diff --git a/Dockerfile b/Dockerfile index 29acc9e2dc5..a06f5b23909 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -FROM docker.io/library/golang:1.16-alpine3.13 AS builder +FROM docker.io/library/golang:1.17-alpine3.14 AS builder RUN apk --no-cache add make gcc g++ linux-headers git bash ca-certificates libgcc libstdc++ @@ -9,7 +9,7 @@ ADD . . # expect that host run `git submodule update --init` RUN make erigon rpcdaemon integration sentry -FROM docker.io/library/alpine:3.13 +FROM docker.io/library/alpine:3.14 RUN apk add --no-cache ca-certificates libgcc libstdc++ tzdata COPY --from=builder /app/build/bin/* /usr/local/bin/ diff --git a/accounts/abi/argument.go b/accounts/abi/argument.go index e6d52455965..2a0559a6fc3 100644 --- a/accounts/abi/argument.go +++ b/accounts/abi/argument.go @@ -46,7 +46,7 @@ func (argument *Argument) UnmarshalJSON(data []byte) error { var arg ArgumentMarshaling err := json.Unmarshal(data, &arg) if err != nil { - return fmt.Errorf("argument json err: %v", err) + return fmt.Errorf("argument json err: %w", err) } argument.Type, err = NewType(arg.Type, arg.InternalType, arg.Components) diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index 6c545cff39b..7a97115ae70 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -673,7 +673,7 @@ func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx types.Transac signer := types.MakeSigner(b.m.ChainConfig, b.pendingBlock.NumberU64()) sender, senderErr := tx.Sender(*signer) if senderErr != nil { - return fmt.Errorf("invalid transaction: %v", senderErr) + return fmt.Errorf("invalid transaction: %w", senderErr) } nonce := b.pendingState.GetNonce(sender) if tx.GetNonce() != nonce { diff --git a/accounts/abi/bind/base.go b/accounts/abi/bind/base.go index b25221cf430..2b30bf7ad68 100644 --- a/accounts/abi/bind/base.go +++ b/accounts/abi/bind/base.go @@ -221,7 +221,7 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i if opts.Nonce == nil { nonce, err = c.transactor.PendingNonceAt(ensureContext(opts.Context), opts.From) if err != nil { - return nil, fmt.Errorf("failed to retrieve account nonce: %v", err) + return nil, fmt.Errorf("failed to retrieve account nonce: %w", err) } } else { nonce = opts.Nonce.Uint64() @@ -252,7 +252,7 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i msg := ethereum.CallMsg{From: opts.From, To: contract, GasPrice: gasPrice, Value: value, Data: input} gasLimit, err = c.transactor.EstimateGas(ensureContext(opts.Context), msg) if err != nil { - return nil, fmt.Errorf("failed to estimate gas needed: %v", err) + return nil, fmt.Errorf("failed to estimate gas needed: %w", err) } } // Create the transaction, sign it and schedule it for execution diff --git a/accounts/abi/bind/bind.go b/accounts/abi/bind/bind.go index 9befda58edc..0e6e832ed1b 100644 --- a/accounts/abi/bind/bind.go +++ b/accounts/abi/bind/bind.go @@ -240,7 +240,7 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string] if lang == LangGo { code, err := format.Source(buffer.Bytes()) if err != nil { - return "", fmt.Errorf("%v\n%s", err, buffer) + return "", fmt.Errorf("%w\n%s", err, buffer) } return string(code), nil } diff --git a/accounts/abi/type.go b/accounts/abi/type.go index 7272b9440bf..199410da840 100644 --- a/accounts/abi/type.go +++ b/accounts/abi/type.go @@ -103,7 +103,7 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty typ.Elem = &embeddedType typ.Size, err = strconv.Atoi(intz[0]) if err != nil { - return Type{}, fmt.Errorf("abi: error parsing variable size: %v", err) + return Type{}, fmt.Errorf("abi: error parsing variable size: %w", err) } typ.stringKind = embeddedType.stringKind + sliced } else { @@ -124,7 +124,7 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty var err error varSize, err = strconv.Atoi(parsedType[2]) if err != nil { - return Type{}, fmt.Errorf("abi: error parsing variable size: %v", err) + return Type{}, fmt.Errorf("abi: error parsing variable size: %w", err) } } else { if parsedType[0] == "uint" || parsedType[0] == "int" { diff --git a/accounts/abi/unpack_test.go b/accounts/abi/unpack_test.go index cc617254c04..2d169d65f96 100644 --- a/accounts/abi/unpack_test.go +++ b/accounts/abi/unpack_test.go @@ -66,9 +66,9 @@ type unpackTest struct { func (test unpackTest) checkError(err error) error { if err != nil { if len(test.err) == 0 { - return fmt.Errorf("expected no err but got: %v", err) + return fmt.Errorf("expected no err but got: %w", err) } else if err.Error() != test.err { - return fmt.Errorf("expected err: '%v' got err: %q", test.err, err) + return fmt.Errorf("expected err: '%v' got err: %w", test.err, err) } } else if len(test.err) > 0 { return fmt.Errorf("expected err: %v but got none", test.err) diff --git a/cmd/hack/db/lmdb.go b/cmd/hack/db/lmdb.go index 39bed92d1d9..395da6a05e3 100644 --- a/cmd/hack/db/lmdb.go +++ b/cmd/hack/db/lmdb.go @@ -945,13 +945,13 @@ func TextInfo(chaindata string, visStream io.Writer) error { f, err := os.Open(datafile) if err != nil { - return fmt.Errorf("opening %v: %v", MdbxDataFile, err) + return fmt.Errorf("opening %v: %w", MdbxDataFile, err) } defer f.Close() var meta [PageSize]byte // Read meta page 0 if _, err = f.ReadAt(meta[:], 0*PageSize); err != nil { - return fmt.Errorf("reading meta page 0: %v", err) + return fmt.Errorf("reading meta page 0: %w", err) } header1 := new(header) @@ -967,12 +967,12 @@ func TextInfo(chaindata string, visStream io.Writer) error { // meta1.print() if err != nil { - return fmt.Errorf("reading meta page 0: %v", err) + return fmt.Errorf("reading meta page 0: %w", err) } // Read meta page 1 if _, err = f.ReadAt(meta[:], 1*PageSize); err != nil { - return fmt.Errorf("reading meta page 1: %v", err) + return fmt.Errorf("reading meta page 1: %w", err) } header2 := new(header) @@ -988,7 +988,7 @@ func TextInfo(chaindata string, visStream io.Writer) error { // meta2.print() if err != nil { - return fmt.Errorf("reading meta page 1: %v", err) + return fmt.Errorf("reading meta page 1: %w", err) } var freeRoot, mainRoot uint32 @@ -1115,7 +1115,7 @@ func _conditions(f io.ReaderAt, visStream io.Writer, node *mdbx_node, _header *h func readPages(f io.ReaderAt, visStream io.Writer, pgno uint32, blockID *int, parentBlock int, level *int) error { var page [PageSize]byte if _, err := f.ReadAt(page[:], int64(pgno*PageSize)); err != nil { - return fmt.Errorf("reading page: %v, error: %v", pgno, err) + return fmt.Errorf("reading page: %v, error: %w", pgno, err) } _header := new(header) @@ -1193,7 +1193,7 @@ func readPages(f io.ReaderAt, visStream io.Writer, pgno uint32, blockID *int, pa func freeDBPages(f io.ReaderAt, visStream io.Writer, freeRoot uint32) error { var page [PageSize]byte if _, err := f.ReadAt(page[:], int64(freeRoot*PageSize)); err != nil { - return fmt.Errorf("reading page: %v, error: %v", freeRoot, err) + return fmt.Errorf("reading page: %v, error: %w", freeRoot, err) } _header := new(header) diff --git a/cmd/hack/hack.go b/cmd/hack/hack.go index d7f302ba3e9..51ba7935a55 100644 --- a/cmd/hack/hack.go +++ b/cmd/hack/hack.go @@ -13,6 +13,7 @@ import ( "io" "io/ioutil" "math/big" + "net/http" "os" "os/signal" "runtime" @@ -21,7 +22,6 @@ import ( "strconv" "strings" "sync" - "sync/atomic" "syscall" "time" @@ -30,6 +30,7 @@ import ( "github.com/ledgerwatch/erigon-lib/etl" "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon-lib/kv/mdbx" + "github.com/ledgerwatch/erigon-lib/patricia" "github.com/ledgerwatch/erigon-lib/recsplit" "github.com/ledgerwatch/erigon/consensus/ethash" "github.com/ledgerwatch/erigon/consensus/misc" @@ -38,7 +39,6 @@ import ( "github.com/ledgerwatch/erigon/params" "github.com/wcharczuk/go-chart/v2" - ahocorasick "github.com/BobuSumisu/aho-corasick" "github.com/flanglet/kanzi-go/transform" hackdb "github.com/ledgerwatch/erigon/cmd/hack/db" @@ -1191,7 +1191,7 @@ func mphf(chaindata string, block uint64) error { statefile := "statedump.dat" if _, err := os.Stat(statefile); err != nil { if !os.IsNotExist(err) { - return fmt.Errorf("not sure if statedump.dat exists: %v", err) + return fmt.Errorf("not sure if statedump.dat exists: %w", err) } if err = dumpState(chaindata, statefile); err != nil { return err @@ -1425,12 +1425,17 @@ func processSuperstring(superstringCh chan []byte, dictCollector *etl.Collector, } j := i for l := int(lcp[i]); l > int(lcp[i+1]); l-- { - if l < 2 { + if l < 5 { continue } // Go back + var new bool for j > 0 && int(lcp[j-1]) >= l { j-- + new = true + } + if !new { + break } window := i - j + 2 for len(b) < window { @@ -1446,19 +1451,19 @@ func processSuperstring(superstringCh chan []byte, dictCollector *etl.Collector, lastK = k } } - //if repeats > 1 { - score := uint64(repeats * int(l-1)) - // Dictionary key is the concatenation of the score and the dictionary word (to later aggregate the scores from multiple chunks) - dictKey := make([]byte, l) - for s := 0; s < l; s++ { - dictKey[s] = superstring[(filtered[i]+s)*2+1] - } - var dictVal [8]byte - binary.BigEndian.PutUint64(dictVal[:], score) - if err = dictCollector.Collect(dictKey, dictVal[:]); err != nil { - log.Error("processSuperstring", "collect", err) + if repeats > 128 { + score := uint64(repeats * int(l-4)) + // Dictionary key is the concatenation of the score and the dictionary word (to later aggregate the scores from multiple chunks) + dictKey := make([]byte, l) + for s := 0; s < l; s++ { + dictKey[s] = superstring[(filtered[i]+s)*2+1] + } + var dictVal [8]byte + binary.BigEndian.PutUint64(dictVal[:], score) + if err = dictCollector.Collect(dictKey, dictVal[:]); err != nil { + log.Error("processSuperstring", "collect", err) + } } - //} } } } @@ -1567,21 +1572,6 @@ func (da *DictAggregator) finish() error { return nil } -// MatchSorter is helper type to sort matches by their end position -type MatchSorter []*ahocorasick.Match - -func (ms MatchSorter) Len() int { - return len(ms) -} - -func (ms MatchSorter) Less(i, j int) bool { - return ms[i].Pos() < ms[j].Pos() -} - -func (ms *MatchSorter) Swap(i, j int) { - (*ms)[i], (*ms)[j] = (*ms)[j], (*ms)[i] -} - const CompressLogPrefix = "compress" func compress(chaindata string, block uint64) error { @@ -1589,7 +1579,7 @@ func compress(chaindata string, block uint64) error { statefile := "statedump.dat" if _, err := os.Stat(statefile); err != nil { if !os.IsNotExist(err) { - return fmt.Errorf("not sure if statedump.dat exists: %v", err) + return fmt.Errorf("not sure if statedump.dat exists: %w", err) } if err = dumpState(chaindata, statefile); err != nil { return err @@ -1671,7 +1661,7 @@ func compress(chaindata string, block uint64) error { } // Aggregate the dictionary and build Aho-Corassick matcher defer dictCollector.Close(CompressLogPrefix) - db := &DictionaryBuilder{limit: 16_000_000} // Only collect 16m words with highest scores + db := &DictionaryBuilder{limit: 1_000_000} // Only collect 1m words with highest scores if err = dictCollector.Load(CompressLogPrefix, nil /* db */, "" /* toBucket */, db.compressLoadFunc, etl.TransformArgs{}); err != nil { return err } @@ -1694,442 +1684,405 @@ func compress(chaindata string, block uint64) error { return nil } -func encodeWithoutDictionary(buf []byte, encodedPos, limit int, w *bufio.Writer, setTerminal bool) error { - for encodedPos < limit { - codingLen := limit - encodedPos - var header byte = 0x00 // No dictionary bit set - if codingLen > 64 { - codingLen = 64 - } else if setTerminal { - header |= 0x80 // Terminal bit set - } - header |= byte(codingLen - 1) - if err := w.WriteByte(header); err != nil { - return err - } - if _, err := w.Write(buf[encodedPos : encodedPos+codingLen]); err != nil { - return err - } - encodedPos += codingLen - } - return nil +type DictEntry struct { + score uint64 + code uint64 } -// DynamicCell is cell for dynamic programming +// DynamicCell represents result of dynamic programming for certain starting position type DynamicCell struct { - scores int64 - compression int - lastCompressed int // position of last compressed word - words [][]byte // dictionary words used for this cell -} - -func reduceDictWorker(inputCh chan []byte, dict map[string]int64, usedDict map[string]int, totalCompression *uint64, completion *sync.WaitGroup) { - for input := range inputCh { - l := len(input) - // Dynamic programming. We use 2 programs - one always ending with a compressed word (if possible), another - without - compressedEnd := make(map[int]DynamicCell) - simpleEnd := make(map[int]DynamicCell) - compressedEnd[0] = DynamicCell{scores: 0, compression: 0, lastCompressed: 0, words: nil} - simpleEnd[0] = DynamicCell{scores: 0, compression: 0, lastCompressed: 0, words: nil} - for k := 1; k <= l; k++ { - var maxC, maxS int - var wordsC, wordsS [][]byte - var scoresC, scoresS int64 - var lastC, lastS int - for j := 0; j < k; j++ { - cc := compressedEnd[j] - sc := simpleEnd[j] - // First assume we are not compressing slice [j:k] - ccCompression := ((j - cc.lastCompressed + 63) / 64) - ((k - cc.lastCompressed + 63) / 64) + cc.compression - scCompression := ((j - sc.lastCompressed + 63) / 64) - ((k - sc.lastCompressed + 63) / 64) + sc.compression - var compression int - var words [][]byte - var scores int64 - var lastCompressed int - if (ccCompression == scCompression && cc.scores > sc.scores) || ccCompression > scCompression { - compression = ccCompression - words = cc.words - scores = cc.scores - lastCompressed = cc.lastCompressed - } else { - compression = scCompression - words = sc.words - scores = sc.scores - lastCompressed = sc.lastCompressed - } - if j == 0 || (compression == maxS && scores > scoresS) || compression > maxS { - maxS = compression - wordsS = words - scoresS = scores - lastS = lastCompressed - } - // Now try to apply compression, if possible - if dictScore, ok := dict[string(input[j:k])]; ok { - words = append(append([][]byte{}, words...), input[j:k]) - lastCompressed = k - if (cc.compression == sc.compression && cc.scores > sc.scores) || cc.compression > sc.compression { - compression = cc.compression + (k - j) - 3 - scores = cc.scores + dictScore - } else { - compression = sc.compression + (k - j) - 3 - scores = sc.scores + dictScore - } - } - if j == 0 || compression > maxC { - maxC = compression - wordsC = words - scoresC = scores - lastC = lastCompressed - } - } - compressedEnd[k] = DynamicCell{scores: scoresC, compression: maxC, lastCompressed: lastC, words: wordsC} - simpleEnd[k] = DynamicCell{scores: scoresS, compression: maxS, lastCompressed: lastS, words: wordsS} - } - if (compressedEnd[l].compression == simpleEnd[l].compression && compressedEnd[l].scores > simpleEnd[l].scores) || compressedEnd[l].compression > simpleEnd[l].compression { - atomic.AddUint64(totalCompression, uint64(compressedEnd[l].compression)) - for _, word := range compressedEnd[int(l)].words { - usedDict[string(word)]++ - } - } else { - atomic.AddUint64(totalCompression, uint64(simpleEnd[l].compression)) - for _, word := range simpleEnd[int(l)].words { - usedDict[string(word)]++ - } - } + optimStart int + coverStart int + compression int + score uint64 + patternIdx int // offset of the last element in the pattern slice +} +type Ring struct { + cells []DynamicCell + head, tail, count int +} + +func NewRing() *Ring { + return &Ring{ + cells: make([]DynamicCell, 16), + head: 0, + tail: 0, + count: 0, } - completion.Done() } -// reduceDict reduces the dictionary by trying the substitutions and counting frequency for each word -func reducedict() error { - // Read up the dictionary - df, err := os.Open("dictionary.txt") - if err != nil { - return err +func (r *Ring) Reset() { + r.count = 0 + r.head = 0 + r.tail = 0 +} + +func (r *Ring) ensureSize() { + if r.count < len(r.cells) { + return } - defer df.Close() - // DictonaryBuilder is for sorting words by their freuency (to assign codes) - dict := make(map[string]int64) - ds := bufio.NewScanner(df) - for ds.Scan() { - tokens := strings.Split(ds.Text(), " ") - var score int64 - if score, err = strconv.ParseInt(tokens[0], 10, 64); err != nil { - return err - } - var word []byte - if word, err = hex.DecodeString(tokens[1]); err != nil { - return err - } - dict[string(word)] = score + newcells := make([]DynamicCell, r.count*2) + if r.tail > r.head { + copy(newcells, r.cells[r.head:r.tail]) + } else { + n := copy(newcells, r.cells[r.head:]) + copy(newcells[n:], r.cells[:r.tail]) } - df.Close() - log.Info("dictionary file parsed", "entries", len(dict)) - statefile := "statedump.dat" - f, err := os.Open(statefile) - if err != nil { - return err + r.head = 0 + r.tail = r.count + r.cells = newcells +} + +func (r *Ring) PushFront() *DynamicCell { + r.ensureSize() + if r.head == 0 { + r.head = len(r.cells) } - defer f.Close() - if _, err = f.Seek(8, 0); err != nil { - return err + r.head-- + r.count++ + return &r.cells[r.head] +} + +func (r *Ring) PushBack() *DynamicCell { + r.ensureSize() + if r.tail == len(r.cells) { + r.tail = 0 } + result := &r.cells[r.tail] + r.tail++ + r.count++ + return result +} - var usedDicts []map[string]int - var totalCompression uint64 - inputCh := make(chan []byte, 10000) - var completion sync.WaitGroup - for p := 0; p < runtime.NumCPU(); p++ { - usedDict := make(map[string]int) - usedDicts = append(usedDicts, usedDict) - completion.Add(1) - go reduceDictWorker(inputCh, dict, usedDict, &totalCompression, &completion) +func (r Ring) Len() int { + return r.count +} + +func (r *Ring) Get(i int) *DynamicCell { + if i < 0 || i >= r.count { + return nil } - r := bufio.NewReader(f) - var buf [256]byte - l, e := r.ReadByte() - i := 0 - for ; e == nil; l, e = r.ReadByte() { - if _, e = io.ReadFull(r, buf[:l]); e != nil { - return e + return &r.cells[(r.head+i)&(len(r.cells)-1)] +} + +// Truncate removes all items starting from i +func (r *Ring) Truncate(i int) { + r.count = i + r.tail = (r.head + i) & (len(r.cells) - 1) +} + +func optimiseCluster(trace bool, numBuf []byte, input []byte, inputLen int, output []byte, matches []patricia.Match, cover []bool, patterns []int, cellRing *Ring, dict map[string]DictEntry, usedDict map[string]int) ([]byte, []int) { + if trace { + fmt.Printf("Cluster | input = %x\n", input) + for _, match := range matches { + fmt.Printf(" [%x %d-%d]", input[match.Start:match.End], match.Start, match.End) + } + } + cellRing.Reset() + patterns = patterns[:0] + patterns = append(patterns, 0) + patterns = append(patterns, 0) // Sentinel entry - no meaning + lastF := matches[len(matches)-1] + for j := lastF.Start; j < lastF.End; j++ { + d := cellRing.PushBack() + d.optimStart = j + 1 + d.coverStart = inputLen + d.compression = 0 + d.patternIdx = 0 + d.score = 0 + } + // Starting from the last match + for i := len(matches); i > 0; i-- { + f := matches[i-1] + firstCell := cellRing.Get(0) + if firstCell == nil { + fmt.Printf("cellRing.Len() = %d\n", cellRing.Len()) + } + maxCompression := firstCell.compression + maxScore := firstCell.score + maxCell := firstCell + var maxInclude bool + for e := 0; e < cellRing.Len(); e++ { + cell := cellRing.Get(e) + comp := cell.compression - 4 + if cell.coverStart >= f.End { + comp += f.End - f.Start + } else { + comp += cell.coverStart - f.Start + } + score := cell.score + binary.BigEndian.Uint64(f.Vals[0]) + if comp > maxCompression || (comp == maxCompression && score > maxScore) { + maxCompression = comp + maxScore = score + maxInclude = true + maxCell = cell + } + if cell.optimStart > f.End { + cellRing.Truncate(e) + break + } } - inputCh <- common.CopyBytes(buf[:l]) - i++ - if i%2_000_000 == 0 { - log.Info("Replacement preprocessing", "key/value pairs", i/2, "estimated saving", common.StorageSize(atomic.LoadUint64(&totalCompression))) + d := cellRing.PushFront() + d.optimStart = f.Start + d.score = maxScore + d.compression = maxCompression + if maxInclude { + if trace { + fmt.Printf("[include] cell for %d: with patterns", f.Start) + fmt.Printf(" [%x %d-%d]", input[f.Start:f.End], f.Start, f.End) + patternIdx := maxCell.patternIdx + for patternIdx != 0 { + pattern := patterns[patternIdx] + fmt.Printf(" [%x %d-%d]", input[matches[pattern].Start:matches[pattern].End], matches[pattern].Start, matches[pattern].End) + patternIdx = patterns[patternIdx+1] + } + fmt.Printf("\n\n") + } + d.coverStart = f.Start + d.patternIdx = len(patterns) + patterns = append(patterns, i-1) + patterns = append(patterns, maxCell.patternIdx) + } else { + if trace { + fmt.Printf("cell for %d: with patterns", f.Start) + patternIdx := maxCell.patternIdx + for patternIdx != 0 { + pattern := patterns[patternIdx] + fmt.Printf(" [%x %d-%d]", input[matches[pattern].Start:matches[pattern].End], matches[pattern].Start, matches[pattern].End) + patternIdx = patterns[patternIdx+1] + } + fmt.Printf("\n\n") + } + d.coverStart = maxCell.coverStart + d.patternIdx = maxCell.patternIdx + } + } + optimCell := cellRing.Get(0) + if trace { + fmt.Printf("optimal =") + } + // Count number of patterns + var patternCount uint64 + patternIdx := optimCell.patternIdx + for patternIdx != 0 { + patternCount++ + patternIdx = patterns[patternIdx+1] + } + p := binary.PutUvarint(numBuf, patternCount) + output = append(output, numBuf[:p]...) + patternIdx = optimCell.patternIdx + for patternIdx != 0 { + pattern := patterns[patternIdx] + if trace { + fmt.Printf(" [%x %d-%d]", input[matches[pattern].Start:matches[pattern].End], matches[pattern].Start, matches[pattern].End) + } + for j := matches[pattern].Start; j < matches[pattern].End; j++ { + cover[j] = true + } + // Starting position + p := binary.PutUvarint(numBuf, uint64(matches[pattern].Start)) + output = append(output, numBuf[:p]...) + // Code + p = binary.PutUvarint(numBuf, uint64(dict[string(input[matches[pattern].Start:matches[pattern].End])].code)) + output = append(output, numBuf[:p]...) + usedDict[string(input[matches[pattern].Start:matches[pattern].End])]++ + patternIdx = patterns[patternIdx+1] + } + if trace { + fmt.Printf("\n\n") + } + return output, patterns +} + +func reduceDictWorker(numBuf []byte, input []byte, output []byte, cover []bool, patterns []int, cellRing *Ring, trie *patricia.PatriciaTree, mf *patricia.MatchFinder, dict map[string]DictEntry, usedDict map[string]int) ([]byte, []bool, []int) { + // Write length of the string + p := binary.PutUvarint(numBuf, uint64(len(input))) + output = append(output, numBuf[:p]...) + matches := mf.FindLongestMatches(trie, input) + if len(matches) > 0 { + for i := 0; i < len(input); i++ { + if i == len(cover) { + cover = append(cover, false) + } else { + cover[i] = false + } + } + output, patterns = optimiseCluster(false, numBuf, input, len(input), output, matches, cover, patterns, cellRing, dict, usedDict) + // Add uncoded input + for i := 0; i < len(input); i++ { + if !cover[i] { + output = append(output, input[i]) + } + } + } else { + if len(input) > 0 { + p := binary.PutUvarint(numBuf, 0) + output = append(output, numBuf[:p]...) + output = append(output, input...) } } - if e != nil && !errors.Is(e, io.EOF) { - return e + return output, cover, patterns +} + +func decode(output []byte, invDict map[uint64][]byte) ([]byte, error) { + r := bytes.NewReader(output) + var l uint64 + var err error + if l, err = binary.ReadUvarint(r); err != nil { + return nil, err } - close(inputCh) - completion.Wait() - usedDict := make(map[string]int) - for _, d := range usedDicts { - for word, r := range d { - usedDict[word] += r - } + input := make([]byte, l) + if l == 0 { + return input, nil } - log.Info("Done", "estimated saving", common.StorageSize(totalCompression), "effective dict size", len(usedDict)) - var rf *os.File - rf, err = os.Create("reduced_dictionary.txt") - if err != nil { - return err + cover := make([]bool, l) // Which characters are covered by the pattens + var p uint64 // Number of patterns + if p, err = binary.ReadUvarint(r); err != nil { + return nil, err } - rw := bufio.NewWriter(rf) - for word, used := range usedDict { - fmt.Fprintf(rw, "%d %x\n", used, word) + // Now reading patterns one by one + for i := 0; i < int(p); i++ { + var pos uint64 // Starting position for pattern + if pos, err = binary.ReadUvarint(r); err != nil { + return nil, err + } + var code uint64 // Code of the pattern + if code, err = binary.ReadUvarint(r); err != nil { + return nil, err + } + word := invDict[code] + for j := 0; j < len(word); j++ { + input[int(pos)+j] = word[j] + cover[int(pos)+j] = true + } } - if err = rw.Flush(); err != nil { - return err + // Read uncovered characters + for i := 0; i < int(l); i++ { + if !cover[i] { + if input[i], err = r.ReadByte(); err != nil { + return nil, err + } + } } - rf.Close() - return nil + return input, nil } -// trueCompress compresses statedump.dat using dictionary in reduced_dictionary.txt -func truecompress() error { - // Read up the reduced dictionary +// reduceDict reduces the dictionary by trying the substitutions and counting frequency for each word +func reducedict(block int) error { + go func() { + if err := http.ListenAndServe("localhost:6060", nil); err != nil { + log.Error("Failure in running pprof server", "err", err) + } + }() + // Read up the dictionary df, err := os.Open("reduced_dictionary.txt") if err != nil { return err } defer df.Close() // DictonaryBuilder is for sorting words by their freuency (to assign codes) - db := DictionaryBuilder{} + var pt patricia.PatriciaTree + dict := make(map[string]DictEntry) + invDict := make(map[uint64][]byte) ds := bufio.NewScanner(df) for ds.Scan() { tokens := strings.Split(ds.Text(), " ") - var freq int64 - if freq, err = strconv.ParseInt(tokens[0], 10, 64); err != nil { + var score int64 + if score, err = strconv.ParseInt(tokens[0], 10, 64); err != nil { return err } var word []byte if word, err = hex.DecodeString(tokens[1]); err != nil { return err } - db.items = append(db.items, DictionaryItem{score: uint64(freq), word: word}) + var scoreBuf [8]byte + binary.BigEndian.PutUint64(scoreBuf[:], uint64(score)) + pt.Insert(word, scoreBuf[:]) + code := uint64(uint64(len(dict))) + dict[string(word)] = DictEntry{score: uint64(score), code: code} + invDict[code] = word } df.Close() - log.Info("Loaded dictionary", "items", len(db.items)) - sort.Sort(&db) - // Matcher - trieBuilder := ahocorasick.NewTrieBuilder() - for _, item := range db.items { - trieBuilder.AddPattern(item.word) - } - trie := trieBuilder.Build() - // Assign codewords to dictionary items - word2code := make(map[string][]byte) - code2word := make(map[string][]byte) - word2codeTerm := make(map[string][]byte) - code2wordTerm := make(map[string][]byte) - lastw := len(db.items) - 1 - // One byte codewords - for c1 := 0; c1 < 32 && lastw >= 0; c1++ { - code := []byte{0x80 | 0x40 | byte(c1)} // 0x40 is "dictionary encoded" flag, and 0x20 is flag meaning "last term of the key or value", 0x80 means "last byte of codeword" - codeTerm := []byte{0x80 | 0x40 | 0x20 | byte(c1)} - word := db.items[lastw].word - code2word[string(code)] = word - word2code[string(word)] = code - code2wordTerm[string(codeTerm)] = word - word2codeTerm[string(word)] = codeTerm - lastw-- - } - // Two byte codewords - for c1 := 0; c1 < 32 && lastw >= 0; c1++ { - for c2 := 0; c2 < 128 && lastw >= 0; c2++ { - code := []byte{0x40 | byte(c1), 0x80 | byte(c2)} // 0x40 is "dictionary encoded" flag, and 0x20 is flag meaning "last term of the key or value", 0x80 means "last byte of codeword" - codeTerm := []byte{0x40 | 0x20 | byte(c1), 0x80 | byte(c2)} - word := db.items[lastw].word - code2word[string(code)] = word - word2code[string(word)] = code - code2wordTerm[string(codeTerm)] = word - word2codeTerm[string(word)] = codeTerm - lastw-- - } - } - // Three byte codewords - for c1 := 0; c1 < 32 && lastw >= 0; c1++ { - for c2 := 0; c2 < 128 && lastw >= 0; c2++ { - for c3 := 0; c3 < 128 && lastw >= 0; c3++ { - code := []byte{0x40 | byte(c1), byte(c2), 0x80 | byte(c3)} // 0x40 is "dictionary encoded" flag, and 0x20 is flag meaning "last term of the key or value", 0x80 means "last byte of codeword" - codeTerm := []byte{0x40 | 0x20 | byte(c1), byte(c2), 0x80 | byte(c3)} - word := db.items[lastw].word - code2word[string(code)] = word - word2code[string(word)] = code - code2wordTerm[string(codeTerm)] = word - word2codeTerm[string(word)] = codeTerm - lastw-- - } - } - } + log.Info("dictionary file parsed", "entries", len(dict)) statefile := "statedump.dat" f, err := os.Open(statefile) if err != nil { return err } defer f.Close() - // File to output the compression - var cf *os.File - if cf, err = os.Create("compressed.dat"); err != nil { - return err - } - w := bufio.NewWriter(cf) - if _, err = f.Seek(0, 0); err != nil { + if _, err = f.Seek(8, 0); err != nil { return err } + + usedDict := make(map[string]int) + var inputSize int + var outputSize int r := bufio.NewReader(f) - // Copy key count - if _, err = io.CopyN(w, r, 8); err != nil { - return err - } var buf [256]byte + var output []byte = make([]byte, 0, 256) + var cover []bool = make([]bool, 256) + var patterns []int = make([]int, 0, 256) + cellRing := NewRing() + numBuf := make([]byte, binary.MaxVarintLen64) l, e := r.ReadByte() i := 0 - output := 0 + var mf patricia.MatchFinder for ; e == nil; l, e = r.ReadByte() { if _, e = io.ReadFull(r, buf[:l]); e != nil { return e } - encodedPos := 0 - matches := MatchSorter(trie.Match(buf[:l])) - if matches.Len() > 0 { - sort.Sort(&matches) - lastMatch := matches[0] - for j := 1; j < matches.Len(); j++ { - match := matches[j] - // check overlap with lastMatch - if int(match.Pos()) < int(lastMatch.Pos())+len(lastMatch.Match()) { - // match with the highest pattern ID (corresponds to pattern with higher score) wins - if match.Pattern() > lastMatch.Pattern() { - // Replace the last match - lastMatch = match - } - } else { - // No overlap, make substituion - // Encode any leading characters - if err = encodeWithoutDictionary(buf[:], encodedPos, int(lastMatch.Pos()), w, false /* setTerminal */); err != nil { - return err - } - if encodedPos < int(lastMatch.Pos()) { - output += 1 + int(lastMatch.Pos()) - encodedPos - } - if int(l) == int(lastMatch.Pos())+len(lastMatch.Match()) { - if _, err = w.Write(word2codeTerm[lastMatch.MatchString()]); err != nil { - return err - } - output += len(word2codeTerm[lastMatch.MatchString()]) - } else { - if _, err = w.Write(word2code[lastMatch.MatchString()]); err != nil { - return err - } - output += len(word2code[lastMatch.MatchString()]) - } - encodedPos = int(lastMatch.Pos()) + len(lastMatch.Match()) - lastMatch = match - } - } - // Encode any leading characters - if err = encodeWithoutDictionary(buf[:], encodedPos, int(lastMatch.Pos()), w, false /* setTerminal */); err != nil { - return err + output, cover, patterns = reduceDictWorker(numBuf, buf[:l], output[:0], cover, patterns, cellRing, &pt, &mf, dict, usedDict) + /* + var input []byte + if input, err = decode(output, invDict); err != nil { + return fmt.Errorf("decoding compression output %x for input %x: %v", output, buf[:l], err) } - if encodedPos < int(lastMatch.Pos()) { - output += 1 + int(lastMatch.Pos()) - encodedPos + if !bytes.Equal(input, buf[:l]) { + return fmt.Errorf("decoded %x, expected %x", input, buf[:l]) } - if int(l) == int(lastMatch.Pos())+len(lastMatch.Match()) { - if _, err = w.Write(word2codeTerm[lastMatch.MatchString()]); err != nil { - return err - } - output += len(word2codeTerm[lastMatch.MatchString()]) - } else { - if _, err = w.Write(word2code[lastMatch.MatchString()]); err != nil { - return err - } - output += len(word2code[lastMatch.MatchString()]) - } - encodedPos = int(lastMatch.Pos()) + len(lastMatch.Match()) - } - // Encode any remaining things - if err = encodeWithoutDictionary(buf[:], encodedPos, int(l), w, true /* setTerminal */); err != nil { - return err - } - if encodedPos < int(l) { - output += 1 + int(l) - encodedPos - } + */ + inputSize += 1 + int(l) + outputSize += len(output) i++ + if block > 1 && i == block { + break + } if i%2_000_000 == 0 { - log.Info("Replacement", "key/value pairs", i/2, "output", common.StorageSize(output)) + var m runtime.MemStats + runtime.ReadMemStats(&m) + log.Info("Replacement preprocessing", "key/value pairs", i/2, "output", common.StorageSize(outputSize), "input", common.StorageSize(inputSize), "alloc", common.StorageSize(m.Alloc), "sys", common.StorageSize(m.Sys)) } } if e != nil && !errors.Is(e, io.EOF) { return e } - f.Close() - w.Flush() - cf.Close() - // Decompress - if cf, err = os.Open("compressed.dat"); err != nil { - return err - } - if f, err = os.Create("decompressed.dat"); err != nil { + var m runtime.MemStats + runtime.ReadMemStats(&m) + log.Info("Done", "output", common.StorageSize(outputSize), "input", common.StorageSize(inputSize), "effective dict size", len(usedDict), "alloc", common.StorageSize(m.Alloc), "sys", common.StorageSize(m.Sys)) + var rf *os.File + rf, err = os.Create("reduced_dictionary.txt") + if err != nil { return err } - r = bufio.NewReader(cf) - w = bufio.NewWriter(f) - // Copy key count - if _, err = io.CopyN(w, r, 8); err != nil { - return err + rw := bufio.NewWriter(rf) + // Optimise the dictionary + var db DictionaryBuilder + for word, used := range usedDict { + db.items = append(db.items, DictionaryItem{word: []byte(word), score: uint64(used)}) } - var readBuf [256]byte - var decodeBuf = make([]byte, 0, 256) - h, e := r.ReadByte() - for ; e == nil; h, e = r.ReadByte() { - var term bool - if h&0x40 == 0 { - term = h&0x80 != 0 - l := h&63 + 1 - if _, err = io.ReadFull(r, readBuf[:l]); err != nil { - return err - } - decodeBuf = append(decodeBuf, readBuf[:l]...) - } else { - term = h&0x20 != 0 - readBuf[0] = h - j := 0 - for readBuf[j]&0x80 == 0 { - j++ - if readBuf[j], e = r.ReadByte(); e != nil { - return e - } - } - if term { - decodeBuf = append(decodeBuf, code2wordTerm[string(readBuf[:j+1])]...) - } else { - decodeBuf = append(decodeBuf, code2word[string(readBuf[:j+1])]...) - } - } - if term { - if err = w.WriteByte(byte(len(decodeBuf))); err != nil { - return err - } - if len(decodeBuf) > 0 { - if _, err = w.Write(decodeBuf); err != nil { - return err - } - } - decodeBuf = decodeBuf[:0] + sort.Sort(&db) + for i := len(db.items); i > 0; i-- { + if db.items[i-1].score < 128 { + break } + fmt.Fprintf(rw, "%d %x\n", db.items[i-1].score, db.items[i-1].word) } - if e != nil && !errors.Is(e, io.EOF) { - return e - } - cf.Close() - if err = w.Flush(); err != nil { + if err = rw.Flush(); err != nil { return err } - f.Close() + rf.Close() + return nil } @@ -2490,7 +2443,7 @@ func extractHeaders(chaindata string, block uint64) error { blockHash := common.BytesToHash(k[8:]) var header types.Header if err = rlp.DecodeBytes(v, &header); err != nil { - return fmt.Errorf("decoding header from %x: %v", v, err) + return fmt.Errorf("decoding header from %x: %w", v, err) } fmt.Printf("Header %d %x: stateRoot %x, parentHash %x, diff %d\n", blockNumber, blockHash, header.Root, header.ParentHash, header.Difficulty) } @@ -2664,7 +2617,7 @@ func fixTd(chaindata string) error { fmt.Printf("Missing TD record for %x, fixing\n", k) var header types.Header if err = rlp.DecodeBytes(v, &header); err != nil { - return fmt.Errorf("decoding header from %x: %v", v, err) + return fmt.Errorf("decoding header from %x: %w", v, err) } if header.Number.Uint64() == 0 { continue @@ -2674,17 +2627,17 @@ func fixTd(chaindata string) error { copy(parentK[8:], header.ParentHash[:]) var parentTdRec []byte if parentTdRec, err = tx.GetOne(kv.HeaderTD, parentK[:]); err != nil { - return fmt.Errorf("reading parentTd Rec for %d: %v", header.Number.Uint64(), err) + return fmt.Errorf("reading parentTd Rec for %d: %w", header.Number.Uint64(), err) } var parentTd big.Int if err = rlp.DecodeBytes(parentTdRec, &parentTd); err != nil { - return fmt.Errorf("decoding parent Td record for block %d, from %x: %v", header.Number.Uint64(), parentTdRec, err) + return fmt.Errorf("decoding parent Td record for block %d, from %x: %w", header.Number.Uint64(), parentTdRec, err) } var td big.Int td.Add(&parentTd, header.Difficulty) var newHv []byte if newHv, err = rlp.EncodeToBytes(&td); err != nil { - return fmt.Errorf("encoding td record for block %d: %v", header.Number.Uint64(), err) + return fmt.Errorf("encoding td record for block %d: %w", header.Number.Uint64(), err) } if err = tx.Put(kv.HeaderTD, k, newHv); err != nil { return err @@ -2781,7 +2734,7 @@ func fixState(chaindata string) error { } var header types.Header if err = rlp.DecodeBytes(hv, &header); err != nil { - return fmt.Errorf("decoding header from %x: %v", v, err) + return fmt.Errorf("decoding header from %x: %w", v, err) } if header.Number.Uint64() > 1 { var parentK [40]byte @@ -3142,10 +3095,10 @@ func scanReceipts(chaindata string, block uint64) error { buf.Reset() err := cbor.Marshal(&buf, receipts1) if err != nil { - return fmt.Errorf("encode block receipts for block %d: %v", blockNum, err) + return fmt.Errorf("encode block receipts for block %d: %w", blockNum, err) } if err = tx.Put(kv.Receipts, key[:], buf.Bytes()); err != nil { - return fmt.Errorf("writing receipts for block %d: %v", blockNum, err) + return fmt.Errorf("writing receipts for block %d: %w", blockNum, err) } if _, err = w.Write([]byte(fmt.Sprintf("%d\n", blockNum))); err != nil { return err @@ -3172,7 +3125,7 @@ func runBlock(ibs *state.IntraBlockState, txnWriter state.StateWriter, blockWrit ibs.Prepare(tx.Hash(), block.Hash(), i) receipt, _, err := core.ApplyTransaction(chainConfig, getHeader, engine, nil, gp, ibs, txnWriter, header, tx, usedGas, vmConfig, contractHasTEVM) if err != nil { - return nil, fmt.Errorf("could not apply tx %d [%x] failed: %v", i, tx.Hash(), err) + return nil, fmt.Errorf("could not apply tx %d [%x] failed: %w", i, tx.Hash(), err) } receipts = append(receipts, receipt) //fmt.Printf("%d, cumulative gas: %d\n", i, receipt.CumulativeGasUsed) @@ -3181,11 +3134,11 @@ func runBlock(ibs *state.IntraBlockState, txnWriter state.StateWriter, blockWrit if !vmConfig.ReadOnly { // Finalize the block, applying any consensus engine specific extras (e.g. block rewards) if _, err := engine.FinalizeAndAssemble(chainConfig, header, ibs, block.Transactions(), block.Uncles(), receipts, nil, nil, nil, nil); err != nil { - return nil, fmt.Errorf("finalize of block %d failed: %v", block.NumberU64(), err) + return nil, fmt.Errorf("finalize of block %d failed: %w", block.NumberU64(), err) } if err := ibs.CommitBlock(rules, blockWriter); err != nil { - return nil, fmt.Errorf("committing block %d failed: %v", block.NumberU64(), err) + return nil, fmt.Errorf("committing block %d failed: %w", block.NumberU64(), err) } } @@ -3375,9 +3328,7 @@ func main() { case "compress": err = compress(*chaindata, uint64(*block)) case "reducedict": - err = reducedict() - case "truecompress": - err = truecompress() + err = reducedict(*block) case "genstate": err = genstate() } diff --git a/cmd/integration/commands/stages.go b/cmd/integration/commands/stages.go index 650acd64cf1..eb6949e378e 100644 --- a/cmd/integration/commands/stages.go +++ b/cmd/integration/commands/stages.go @@ -15,6 +15,7 @@ import ( "github.com/ledgerwatch/erigon/cmd/sentry/download" "github.com/ledgerwatch/erigon/cmd/utils" "github.com/ledgerwatch/erigon/common" + "github.com/ledgerwatch/erigon/common/dbutils" "github.com/ledgerwatch/erigon/consensus" "github.com/ledgerwatch/erigon/consensus/ethash" "github.com/ledgerwatch/erigon/core" @@ -38,6 +39,23 @@ import ( "github.com/spf13/cobra" ) +var cmdStageHeaders = &cobra.Command{ + Use: "stage_headers", + Short: "", + RunE: func(cmd *cobra.Command, args []string) error { + ctx, _ := utils.RootContext() + logger := log.New() + db := openDB(chaindata, logger, true) + defer db.Close() + + if err := stageHeaders(db, ctx); err != nil { + log.Error("Error", "err", err) + return err + } + return nil + }, +} + var cmdStageBodies = &cobra.Command{ Use: "stage_bodies", Short: "", @@ -276,6 +294,12 @@ func init() { rootCmd.AddCommand(cmdStageSenders) + withDatadir(cmdStageHeaders) + withUnwind(cmdStageHeaders) + withChain(cmdStageHeaders) + + rootCmd.AddCommand(cmdStageHeaders) + withDatadir(cmdStageBodies) withUnwind(cmdStageBodies) withChain(cmdStageBodies) @@ -376,6 +400,54 @@ func init() { rootCmd.AddCommand(cmdSetPrune) } +func stageHeaders(db kv.RwDB, ctx context.Context) error { + return db.Update(ctx, func(tx kv.RwTx) error { + if unwind > 0 { + progress, err := stages.GetStageProgress(tx, stages.Headers) + if err != nil { + return fmt.Errorf("read Bodies progress: %w", err) + } + if unwind > progress { + return fmt.Errorf("cannot unwind past 0") + } + if err = stages.SaveStageProgress(tx, stages.Headers, progress-unwind); err != nil { + return fmt.Errorf("saving Bodies progress failed: %w", err) + } + progress, err = stages.GetStageProgress(tx, stages.Headers) + if err != nil { + return fmt.Errorf("re-read Bodies progress: %w", err) + } + // remove all canonical markers from this point + if err := tx.ForEach(kv.HeaderCanonical, dbutils.EncodeBlockNumber(progress+1), func(k, v []byte) error { + return tx.Delete(kv.HeaderCanonical, k, nil) + }); err != nil { + return err + } + if err := tx.ForEach(kv.Headers, dbutils.EncodeBlockNumber(progress+1), func(k, v []byte) error { + return tx.Delete(kv.Headers, k, nil) + }); err != nil { + return err + } + if err := tx.ForEach(kv.HeaderTD, dbutils.EncodeBlockNumber(progress+1), func(k, v []byte) error { + return tx.Delete(kv.HeaderTD, k, nil) + }); err != nil { + return err + } + hash, err := rawdb.ReadCanonicalHash(tx, progress-1) + if err != nil { + return err + } + if err = tx.Put(kv.HeadHeaderKey, []byte(kv.HeadHeaderKey), hash[:]); err != nil { + log.Error("ReadHeadHeaderHash failed", "err", err) + } + log.Info("Progress", "headers", progress) + return nil + } + log.Info("This command only works with --unwind option") + return nil + }) +} + func stageBodies(db kv.RwDB, ctx context.Context) error { return db.Update(ctx, func(tx kv.RwTx) error { if unwind > 0 { @@ -405,6 +477,8 @@ func stageSenders(db kv.RwDB, ctx context.Context) error { tmpdir := path.Join(datadir, etl.TmpDirName) _, _, chainConfig, _, _, sync, _, _ := newSync(ctx, db, nil) + must(sync.SetCurrentStage(stages.Senders)) + tx, err := db.BeginRw(ctx) if err != nil { return err @@ -481,6 +555,7 @@ func stageSenders(db kv.RwDB, ctx context.Context) error { func stageExec(db kv.RwDB, ctx context.Context) error { pm, engine, chainConfig, vmConfig, _, sync, _, _ := newSync(ctx, db, nil) + must(sync.SetCurrentStage(stages.Execution)) if reset { genesis, _ := byChain() @@ -539,6 +614,7 @@ func stageExec(db kv.RwDB, ctx context.Context) error { func stageTrie(db kv.RwDB, ctx context.Context) error { pm, _, _, _, _, sync, _, _ := newSync(ctx, db, nil) + must(sync.SetCurrentStage(stages.IntermediateHashes)) tmpdir := path.Join(datadir, etl.TmpDirName) tx, err := db.BeginRw(ctx) @@ -594,6 +670,7 @@ func stageHashState(db kv.RwDB, ctx context.Context) error { tmpdir := path.Join(datadir, etl.TmpDirName) pm, _, _, _, _, sync, _, _ := newSync(ctx, db, nil) + must(sync.SetCurrentStage(stages.HashState)) tx, err := db.BeginRw(ctx) if err != nil { @@ -647,6 +724,7 @@ func stageLogIndex(db kv.RwDB, ctx context.Context) error { tmpdir := path.Join(datadir, etl.TmpDirName) pm, _, _, _, _, sync, _, _ := newSync(ctx, db, nil) + must(sync.SetCurrentStage(stages.LogIndex)) tx, err := db.BeginRw(ctx) if err != nil { return err @@ -701,6 +779,7 @@ func stageCallTraces(kv kv.RwDB, ctx context.Context) error { tmpdir := path.Join(datadir, etl.TmpDirName) pm, _, _, _, _, sync, _, _ := newSync(ctx, kv, nil) + must(sync.SetCurrentStage(stages.CallTraces)) tx, err := kv.BeginRw(ctx) if err != nil { return err @@ -760,6 +839,8 @@ func stageCallTraces(kv kv.RwDB, ctx context.Context) error { func stageHistory(db kv.RwDB, ctx context.Context) error { tmpdir := path.Join(datadir, etl.TmpDirName) pm, _, _, _, _, sync, _, _ := newSync(ctx, db, nil) + must(sync.SetCurrentStage(stages.AccountHistoryIndex)) + tx, err := db.BeginRw(ctx) if err != nil { return err @@ -828,6 +909,7 @@ func stageTxLookup(db kv.RwDB, ctx context.Context) error { tmpdir := path.Join(datadir, etl.TmpDirName) pm, _, _, _, _, sync, _, _ := newSync(ctx, db, nil) + must(sync.SetCurrentStage(stages.TxLookup)) tx, err := db.BeginRw(ctx) if err != nil { diff --git a/cmd/prometheus/dashboards/erigon.json b/cmd/prometheus/dashboards/erigon.json index 4b0562176fa..041d528c576 100644 --- a/cmd/prometheus/dashboards/erigon.json +++ b/cmd/prometheus/dashboards/erigon.json @@ -22,7 +22,7 @@ "gnetId": null, "graphTooltip": 0, "id": 1, - "iteration": 1632801657282, + "iteration": 1633497111542, "links": [], "panels": [ { @@ -3070,7 +3070,7 @@ } ] }, - "unit": "s" + "unit": "reqps" }, "overrides": [] }, @@ -3097,13 +3097,21 @@ "targets": [ { "exemplar": true, - "expr": "rpc_duration_seconds{quantile=\"$quantile\",instance=~\"$instance\"}", + "expr": "rate(rpc_duration_seconds_count{instance=~\"$instance\",success=\"success\"}[1m])", "interval": "", - "legendFormat": "rpc_duration_seconds: {{ method }} {{ instance }}", + "legendFormat": "success {{ method }} {{ instance }} ", "refId": "A" + }, + { + "exemplar": true, + "expr": "rate(rpc_duration_seconds_count{instance=~\"$instance\",success=\"failure\"}[1m])", + "hide": false, + "interval": "", + "legendFormat": "failure {{ method }} {{ instance }} ", + "refId": "B" } ], - "title": "Timings", + "title": "RPS", "transformations": [], "type": "timeseries" }, @@ -3155,7 +3163,8 @@ "value": 80 } ] - } + }, + "unit": "s" }, "overrides": [] }, @@ -3165,6 +3174,294 @@ "x": 12, "y": 80 }, + "id": 186, + "options": { + "legend": { + "calcs": [ + "mean", + "last" + ], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single" + } + }, + "targets": [ + { + "exemplar": true, + "expr": "db_begin_seconds{quantile=\"$quantile\",instance=~\"$instance\"}", + "interval": "", + "legendFormat": "db_begin_seconds: {{ method }} {{ instance }}", + "refId": "A" + } + ], + "title": "DB begin", + "transformations": [], + "type": "timeseries" + }, + { + "datasource": null, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [ + { + "__systemRef": "hideSeriesFrom", + "matcher": { + "id": "byNames", + "options": { + "mode": "exclude", + "names": [ + " eth_call turbogeth16c.weblogix.it:6060 success" + ], + "prefix": "All except:", + "readOnly": true + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": false, + "tooltip": false, + "viz": true + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 88 + }, + "id": 187, + "options": { + "legend": { + "calcs": [ + "mean", + "last" + ], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single" + } + }, + "targets": [ + { + "exemplar": true, + "expr": "rpc_duration_seconds{quantile=\"$quantile\",instance=~\"$instance\"}", + "interval": "", + "legendFormat": " {{ method }} {{ instance }} {{ success }}", + "refId": "A" + } + ], + "title": "Timings", + "transformations": [], + "type": "timeseries" + }, + { + "datasource": "Prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 88 + }, + "id": 188, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.0.6", + "targets": [ + { + "expr": "go_goroutines{instance=~\"$instance\"}", + "instant": false, + "interval": "", + "legendFormat": "go/goroutines: {{instance}}", + "refId": "A" + }, + { + "expr": "go_threads{instance=~\"$instance\"}", + "instant": false, + "interval": "", + "legendFormat": "go/threads: {{instance}}", + "refId": "B" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "GO Goroutines and Threads", + "type": "timeseries" + }, + { + "datasource": null, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 8, + "x": 16, + "y": 96 + }, "id": 184, "options": { "legend": { @@ -3199,7 +3496,7 @@ "h": 1, "w": 24, "x": 0, - "y": 88 + "y": 102 }, "id": 146, "panels": [ @@ -3898,7 +4195,7 @@ "h": 1, "w": 24, "x": 0, - "y": 89 + "y": 103 }, "id": 75, "panels": [], @@ -3962,7 +4259,7 @@ "h": 6, "w": 12, "x": 0, - "y": 90 + "y": 104 }, "id": 96, "links": [], @@ -4065,7 +4362,7 @@ "h": 6, "w": 12, "x": 12, - "y": 90 + "y": 104 }, "id": 77, "links": [], @@ -4123,7 +4420,7 @@ "h": 1, "w": 24, "x": 0, - "y": 96 + "y": 110 }, "id": 4, "panels": [], @@ -4167,7 +4464,7 @@ "h": 3, "w": 4, "x": 0, - "y": 97 + "y": 111 }, "id": 108, "interval": null, @@ -4246,7 +4543,7 @@ "h": 3, "w": 4, "x": 4, - "y": 97 + "y": 111 }, "id": 111, "interval": null, @@ -4326,7 +4623,7 @@ "h": 3, "w": 4, "x": 8, - "y": 97 + "y": 111 }, "id": 109, "interval": null, @@ -4406,7 +4703,7 @@ "h": 3, "w": 4, "x": 12, - "y": 97 + "y": 111 }, "id": 113, "interval": null, @@ -4485,7 +4782,7 @@ "h": 3, "w": 4, "x": 16, - "y": 97 + "y": 111 }, "id": 114, "interval": null, @@ -4564,7 +4861,7 @@ "h": 3, "w": 4, "x": 20, - "y": 97 + "y": 111 }, "id": 115, "interval": null, @@ -4664,7 +4961,7 @@ "h": 6, "w": 12, "x": 0, - "y": 100 + "y": 114 }, "id": 110, "links": [], @@ -4768,7 +5065,7 @@ "h": 6, "w": 12, "x": 12, - "y": 100 + "y": 114 }, "id": 116, "links": [], @@ -4872,7 +5169,7 @@ "h": 7, "w": 24, "x": 0, - "y": 106 + "y": 120 }, "id": 117, "links": [], @@ -5000,7 +5297,7 @@ "h": 1, "w": 24, "x": 0, - "y": 113 + "y": 127 }, "id": 138, "panels": [ @@ -5110,7 +5407,7 @@ "type": "row" } ], - "refresh": "30s", + "refresh": false, "schemaVersion": 30, "style": "dark", "tags": [], @@ -5165,14 +5462,12 @@ { "allValue": null, "current": { - "selected": true, + "selected": false, "text": [ - "turbogeth16c.weblogix.it:6060", - "turbogeth16c.weblogix.it:6061" + "turbogeth16c.weblogix.it:6060" ], "value": [ - "turbogeth16c.weblogix.it:6060", - "turbogeth16c.weblogix.it:6061" + "turbogeth16c.weblogix.it:6060" ] }, "datasource": "Prometheus", @@ -5203,7 +5498,7 @@ "auto_count": 30, "auto_min": "10s", "current": { - "selected": false, + "selected": true, "text": "1m", "value": "1m" }, @@ -5278,8 +5573,8 @@ ] }, "time": { - "from": "now-2m", - "to": "now" + "from": "2021-10-06T03:54:19.826Z", + "to": "2021-10-06T04:08:12.196Z" }, "timepicker": { "refresh_intervals": [ @@ -5308,5 +5603,5 @@ "timezone": "", "title": "Erigon Prometheus", "uid": "FPpjH6Hik", - "version": 45 + "version": 50 } \ No newline at end of file diff --git a/cmd/rpcdaemon/README.md b/cmd/rpcdaemon/README.md index 45e6a2dce06..30818275266 100644 --- a/cmd/rpcdaemon/README.md +++ b/cmd/rpcdaemon/README.md @@ -13,7 +13,7 @@ * [Trace transactions progress](#trace-transactions-progress) * [Clients getting timeout, but server load is low](#clients-getting-timeout--but-server-load-is-low) * [Server load too high](#server-load-too-high) - * [Batch requests](#batch-requests) + * [Faster Batch requests](#faster-batch-requests) - [For Developers](#for-developers) * [Code generation](#code-generation) @@ -66,8 +66,7 @@ INFO [date-time] HTTP endpoint opened url=localhost:8545... ### Healthcheck -Running the daemon also opens an endpoint `/health` that provides a basic -health check. +Running the daemon also opens an endpoint `/health` that provides a basic health check. If the health check is successful it returns 200 OK. @@ -90,9 +89,10 @@ Not adding a check disables that. **`known_block`** -- sets up the block that node has to know about. Requires `eth` namespace to be listed in `http.api`. -Example request +Example request ```http POST http://localhost:8545/health --raw '{"min_peer_count": 3, "known_block": "0x1F"}'``` Example response + ``` { "check_block": "HEALTHY", @@ -101,7 +101,6 @@ Example response } ``` - ### Testing By default, the `rpcdaemon` serves data from `localhost:8545`. You may send `curl` commands to see if things are @@ -449,10 +448,10 @@ Reduce `--private.api.ratelimit` [./docs/programmers_guide/db_faq.md](./docs/programmers_guide/db_faq.md) -### Batch requests +### Faster Batch requests Currently batch requests are spawn multiple goroutines and process all sub-requests in parallel. To limit impact of 1 -huge batch to other users - added flag `--rpc.batch.concurrency` (default: 50). Increase it to process large batches +huge batch to other users - added flag `--rpc.batch.concurrency` (default: 2). Increase it to process large batches faster. Known Issue: if at least 1 request is "stremable" (has parameter of type *jsoniter.Stream) - then whole batch will diff --git a/cmd/rpcdaemon/cli/config.go b/cmd/rpcdaemon/cli/config.go index ef376835c83..f39e68e2691 100644 --- a/cmd/rpcdaemon/cli/config.go +++ b/cmd/rpcdaemon/cli/config.go @@ -57,6 +57,7 @@ type Flags struct { TraceCompatibility bool // Bug for bug compatibility for trace_ routines with OpenEthereum TxPoolV2 bool TxPoolApiAddr string + TevmEnabled bool StateCache kvcache.CoherentConfig } @@ -93,10 +94,11 @@ func RootCommand() (*cobra.Command, *Flags) { rootCmd.PersistentFlags().BoolVar(&cfg.WebsocketEnabled, "ws", false, "Enable Websockets") rootCmd.PersistentFlags().BoolVar(&cfg.WebsocketCompression, "ws.compression", false, "Enable Websocket compression (RFC 7692)") rootCmd.PersistentFlags().StringVar(&cfg.RpcAllowListFilePath, "rpc.accessList", "", "Specify granular (method-by-method) API allowlist") - rootCmd.PersistentFlags().UintVar(&cfg.RpcBatchConcurrency, "rpc.batch.concurrency", 50, "Does limit amount of goroutines to process 1 batch request. Means 1 bach request can't overload server. 1 batch still can have unlimited amount of request") + rootCmd.PersistentFlags().UintVar(&cfg.RpcBatchConcurrency, "rpc.batch.concurrency", 2, "Does limit amount of goroutines to process 1 batch request. Means 1 bach request can't overload server. 1 batch still can have unlimited amount of request") rootCmd.PersistentFlags().BoolVar(&cfg.TraceCompatibility, "trace.compat", false, "Bug for bug compatibility with OE for trace_ routines") rootCmd.PersistentFlags().BoolVar(&cfg.TxPoolV2, "txpool.v2", false, "experimental external txpool") - rootCmd.PersistentFlags().StringVar(&cfg.TxPoolApiAddr, "txpool.api.addr", "127.0.0.1:9094", "txpool api network address, for example: 127.0.0.1:9094") + rootCmd.PersistentFlags().StringVar(&cfg.TxPoolApiAddr, "txpool.api.addr", "127.0.0.1:9090", "txpool api network address, for example: 127.0.0.1:9090") + rootCmd.PersistentFlags().BoolVar(&cfg.TevmEnabled, "tevm", false, "Enables Transpiled EVM experiment") if err := rootCmd.MarkPersistentFlagFilename("rpc.accessList", "json"); err != nil { panic(err) @@ -240,6 +242,7 @@ func RemoteServices(ctx context.Context, cfg Flags, logger log.Logger, rootCance db = rwKv stateCache = kvcache.NewDummy() } else { + stateCache = kvcache.New(cfg.StateCache) log.Info("if you run RPCDaemon on same machine with Erigon add --datadir option") } @@ -262,7 +265,6 @@ func RemoteServices(ctx context.Context, cfg Flags, logger log.Logger, rootCance return nil, nil, nil, nil, nil, fmt.Errorf("could not connect to remoteKv: %w", err) } - stateCache = kvcache.New(cfg.StateCache) subscribeToStateChangesLoop(ctx, kvClient, stateCache) remoteEth := services.NewRemoteBackend(conn) diff --git a/cmd/rpcdaemon/commands/daemon.go b/cmd/rpcdaemon/commands/daemon.go index bb55ce7c783..67ae90a4c34 100644 --- a/cmd/rpcdaemon/commands/daemon.go +++ b/cmd/rpcdaemon/commands/daemon.go @@ -20,6 +20,9 @@ func APIList(ctx context.Context, db kv.RoDB, var defaultAPIList []rpc.API base := NewBaseApi(filters, stateCache, cfg.SingleNodeMode) + if cfg.TevmEnabled { + base.EnableTevmExperiment() + } ethImpl := NewEthAPI(base, db, eth, txPool, mining, cfg.Gascap) erigonImpl := NewErigonAPI(base, db) txpoolImpl := NewTxPoolAPI(base, db, txPool) diff --git a/cmd/rpcdaemon/commands/debug_api.go b/cmd/rpcdaemon/commands/debug_api.go index c161779e32e..eb3d4814dcf 100644 --- a/cmd/rpcdaemon/commands/debug_api.go +++ b/cmd/rpcdaemon/commands/debug_api.go @@ -72,7 +72,12 @@ func (api *PrivateDebugAPIImpl) StorageRangeAt(ctx context.Context, blockHash co getHeader := func(hash common.Hash, number uint64) *types.Header { return rawdb.ReadHeader(tx, hash, number) } - contractHasTEVM := ethdb.GetHasTEVM(tx) + + contractHasTEVM := func(contractHash common.Hash) (bool, error) { return false, nil } + if api.TevmEnabled { + contractHasTEVM = ethdb.GetHasTEVM(tx) + } + _, _, _, _, stateReader, err := transactions.ComputeTxEnv(ctx, block, chainConfig, getHeader, contractHasTEVM, ethash.NewFaker(), tx, blockHash, txIndex) if err != nil { return StorageRangeResult{}, err @@ -235,7 +240,10 @@ func (api *PrivateDebugAPIImpl) AccountAt(ctx context.Context, blockHash common. getHeader := func(hash common.Hash, number uint64) *types.Header { return rawdb.ReadHeader(tx, hash, number) } - contractHasTEVM := ethdb.GetHasTEVM(tx) + contractHasTEVM := func(contractHash common.Hash) (bool, error) { return false, nil } + if api.TevmEnabled { + contractHasTEVM = ethdb.GetHasTEVM(tx) + } _, _, _, ibs, _, err := transactions.ComputeTxEnv(ctx, block, chainConfig, getHeader, contractHasTEVM, ethash.NewFaker(), tx, blockHash, txIndex) if err != nil { return nil, err diff --git a/cmd/rpcdaemon/commands/erigon_receipts.go b/cmd/rpcdaemon/commands/erigon_receipts.go index b014b1e30e6..b8d4ead38c6 100644 --- a/cmd/rpcdaemon/commands/erigon_receipts.go +++ b/cmd/rpcdaemon/commands/erigon_receipts.go @@ -30,7 +30,7 @@ func (api *ErigonImpl) GetLogsByHash(ctx context.Context, hash common.Hash) ([][ } receipts, err := getReceipts(ctx, tx, chainConfig, block, block.Body().SendersFromTxs()) if err != nil { - return nil, fmt.Errorf("getReceipts error: %v", err) + return nil, fmt.Errorf("getReceipts error: %w", err) } logs := make([][]*types.Log, len(receipts)) @@ -55,7 +55,7 @@ func (api *ErigonImpl) GetLogsByHash(ctx context.Context, hash common.Hash) ([][ // receipts, err := getReceipts(ctx, tx, *number, hash) // if err != nil { -// return nil, fmt.Errorf("getReceipts error: %v", err) +// return nil, fmt.Errorf("getReceipts error: %w", err) // } // logs := make([][]*types.Log, len(receipts)) diff --git a/cmd/rpcdaemon/commands/eth_accounts.go b/cmd/rpcdaemon/commands/eth_accounts.go index f0dd9f2aa4f..d0089389e05 100644 --- a/cmd/rpcdaemon/commands/eth_accounts.go +++ b/cmd/rpcdaemon/commands/eth_accounts.go @@ -17,7 +17,7 @@ import ( func (api *APIImpl) GetBalance(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (*hexutil.Big, error) { tx, err1 := api.db.BeginRo(ctx) if err1 != nil { - return nil, fmt.Errorf("getBalance cannot open tx: %v", err1) + return nil, fmt.Errorf("getBalance cannot open tx: %w", err1) } defer tx.Rollback() blockNumber, _, err := rpchelper.GetBlockNumber(blockNrOrHash, tx, api.filters) @@ -41,7 +41,7 @@ func (api *APIImpl) GetBalance(ctx context.Context, address common.Address, bloc func (api *APIImpl) GetTransactionCount(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (*hexutil.Uint64, error) { tx, err1 := api.db.BeginRo(ctx) if err1 != nil { - return nil, fmt.Errorf("getTransactionCount cannot open tx: %v", err1) + return nil, fmt.Errorf("getTransactionCount cannot open tx: %w", err1) } defer tx.Rollback() blockNumber, _, err := rpchelper.GetBlockNumber(blockNrOrHash, tx, api.filters) @@ -61,7 +61,7 @@ func (api *APIImpl) GetTransactionCount(ctx context.Context, address common.Addr func (api *APIImpl) GetCode(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) { tx, err1 := api.db.BeginRo(ctx) if err1 != nil { - return nil, fmt.Errorf("getCode cannot open tx: %v", err1) + return nil, fmt.Errorf("getCode cannot open tx: %w", err1) } defer tx.Rollback() blockNumber, _, err := rpchelper.GetBlockNumber(blockNrOrHash, tx, api.filters) diff --git a/cmd/rpcdaemon/commands/eth_api.go b/cmd/rpcdaemon/commands/eth_api.go index 5eb8bb2b32b..78c03e05587 100644 --- a/cmd/rpcdaemon/commands/eth_api.go +++ b/cmd/rpcdaemon/commands/eth_api.go @@ -105,6 +105,8 @@ type BaseAPI struct { _chainConfig *params.ChainConfig _genesis *types.Block _genesisLock sync.RWMutex + + TevmEnabled bool // experiment } func NewBaseApi(f *filters.Filters, stateCache kvcache.Cache, singleNodeMode bool) *BaseAPI { @@ -120,6 +122,8 @@ func (api *BaseAPI) chainConfig(tx kv.Tx) (*params.ChainConfig, error) { return cfg, err } +func (api *BaseAPI) EnableTevmExperiment() { api.TevmEnabled = true } + // nolint:unused func (api *BaseAPI) genesis(tx kv.Tx) (*types.Block, error) { _, genesis, err := api.chainConfigWithGenesis(tx) diff --git a/cmd/rpcdaemon/commands/eth_block.go b/cmd/rpcdaemon/commands/eth_block.go index ba875f24235..b48398ea56f 100644 --- a/cmd/rpcdaemon/commands/eth_block.go +++ b/cmd/rpcdaemon/commands/eth_block.go @@ -51,7 +51,7 @@ func (api *APIImpl) CallBundle(ctx context.Context, txHashes []common.Hash, stat } txs = append(txs, txn) } - defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now()) + defer func(start time.Time) { log.Trace("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now()) stateBlockNumber, hash, err := rpchelper.GetBlockNumber(stateBlockNumberOrHash, tx, api.filters) if err != nil { @@ -96,7 +96,12 @@ func (api *APIImpl) CallBundle(ctx context.Context, txHashes []common.Hash, stat return nil, err } - blockCtx, txCtx := transactions.GetEvmContext(firstMsg, header, stateBlockNumberOrHash.RequireCanonical, tx, ethdb.GetHasTEVM(tx)) + contractHasTEVM := func(contractHash common.Hash) (bool, error) { return false, nil } + if api.TevmEnabled { + contractHasTEVM = ethdb.GetHasTEVM(tx) + } + + blockCtx, txCtx := transactions.GetEvmContext(firstMsg, header, stateBlockNumberOrHash.RequireCanonical, tx, contractHasTEVM) evm := vm.NewEVM(blockCtx, txCtx, st, chainConfig, vm.Config{Debug: false}) timeoutMilliSeconds := int64(5000) diff --git a/cmd/rpcdaemon/commands/eth_call.go b/cmd/rpcdaemon/commands/eth_call.go index 13ee8509e02..57052c7e19b 100644 --- a/cmd/rpcdaemon/commands/eth_call.go +++ b/cmd/rpcdaemon/commands/eth_call.go @@ -39,8 +39,10 @@ func (api *APIImpl) Call(ctx context.Context, args ethapi.CallArgs, blockNrOrHas args.Gas = (*hexutil.Uint64)(&api.GasCap) } - contractHasTEVM := ethdb.GetHasTEVM(tx) - + contractHasTEVM := func(contractHash common.Hash) (bool, error) { return false, nil } + if api.TevmEnabled { + contractHasTEVM = ethdb.GetHasTEVM(tx) + } result, err := transactions.DoCall(ctx, args, tx, blockNrOrHash, overrides, api.GasCap, chainConfig, api.filters, api.stateCache, contractHasTEVM) if err != nil { return nil, err @@ -170,7 +172,10 @@ func (api *APIImpl) EstimateGas(ctx context.Context, args ethapi.CallArgs, block return 0, err } - contractHasTEVM := ethdb.GetHasTEVM(dbtx) + contractHasTEVM := func(contractHash common.Hash) (bool, error) { return false, nil } + if api.TevmEnabled { + contractHasTEVM = ethdb.GetHasTEVM(dbtx) + } // Create a helper to check if a gas allowance results in an executable transaction executable := func(gas uint64) (bool, *core.ExecutionResult, error) { diff --git a/cmd/rpcdaemon/commands/eth_receipts.go b/cmd/rpcdaemon/commands/eth_receipts.go index 1f0e281d793..6910b7004ac 100644 --- a/cmd/rpcdaemon/commands/eth_receipts.go +++ b/cmd/rpcdaemon/commands/eth_receipts.go @@ -262,7 +262,7 @@ func (api *APIImpl) GetTransactionReceipt(ctx context.Context, hash common.Hash) } receipts, err := getReceipts(ctx, tx, cc, block, block.Body().SendersFromTxs()) if err != nil { - return nil, fmt.Errorf("getReceipts error: %v", err) + return nil, fmt.Errorf("getReceipts error: %w", err) } if len(receipts) <= int(txIndex) { return nil, fmt.Errorf("block has less receipts than expected: %d <= %d, block: %d", len(receipts), int(txIndex), blockNumber) @@ -295,7 +295,7 @@ func (api *APIImpl) GetBlockReceipts(ctx context.Context, number rpc.BlockNumber } receipts, err := getReceipts(ctx, tx, chainConfig, block, block.Body().SendersFromTxs()) if err != nil { - return nil, fmt.Errorf("getReceipts error: %v", err) + return nil, fmt.Errorf("getReceipts error: %w", err) } result := make([]map[string]interface{}, 0, len(receipts)) for _, receipt := range receipts { diff --git a/cmd/rpcdaemon/commands/eth_uncles.go b/cmd/rpcdaemon/commands/eth_uncles.go index c0dcfeebae3..5e52baa8151 100644 --- a/cmd/rpcdaemon/commands/eth_uncles.go +++ b/cmd/rpcdaemon/commands/eth_uncles.go @@ -41,7 +41,7 @@ func (api *APIImpl) GetUncleByBlockNumberAndIndex(ctx context.Context, number rp uncles := block.Uncles() if index >= hexutil.Uint(len(uncles)) { - log.Debug("Requested uncle not found", "number", block.Number(), "hash", hash, "index", index) + log.Trace("Requested uncle not found", "number", block.Number(), "hash", hash, "index", index) return nil, nil } uncle := types.NewBlockWithHeader(uncles[index]) @@ -73,7 +73,7 @@ func (api *APIImpl) GetUncleByBlockHashAndIndex(ctx context.Context, hash common uncles := block.Uncles() if index >= hexutil.Uint(len(uncles)) { - log.Debug("Requested uncle not found", "number", block.Number(), "hash", hash, "index", index) + log.Trace("Requested uncle not found", "number", block.Number(), "hash", hash, "index", index) return nil, nil } uncle := types.NewBlockWithHeader(uncles[index]) diff --git a/cmd/rpcdaemon/commands/rpc_block.go b/cmd/rpcdaemon/commands/rpc_block.go index 2465831c01e..b24451c538b 100644 --- a/cmd/rpcdaemon/commands/rpc_block.go +++ b/cmd/rpcdaemon/commands/rpc_block.go @@ -28,7 +28,7 @@ func getBlockNumber(number rpc.BlockNumber, tx kv.Tx) (uint64, error) { func getLatestBlockNumber(tx kv.Tx) (uint64, error) { blockNum, err := stages.GetStageProgress(tx, stages.Execution) if err != nil { - return 0, fmt.Errorf("getting latest block number: %v", err) + return 0, fmt.Errorf("getting latest block number: %w", err) } return blockNum, nil diff --git a/cmd/rpcdaemon/commands/storage_range.go b/cmd/rpcdaemon/commands/storage_range.go index 69d8f0f0025..141be618bbc 100644 --- a/cmd/rpcdaemon/commands/storage_range.go +++ b/cmd/rpcdaemon/commands/storage_range.go @@ -36,7 +36,7 @@ func StorageRangeAt(stateReader *state.PlainState, contractAddress common.Addres resultCount++ return resultCount <= maxResult }, maxResult+1); err != nil { - return StorageRangeResult{}, fmt.Errorf("error walking over storage: %v", err) + return StorageRangeResult{}, fmt.Errorf("error walking over storage: %w", err) } return result, nil } diff --git a/cmd/rpcdaemon/commands/trace_adhoc.go b/cmd/rpcdaemon/commands/trace_adhoc.go index 2efe0f821cd..8207edafa43 100644 --- a/cmd/rpcdaemon/commands/trace_adhoc.go +++ b/cmd/rpcdaemon/commands/trace_adhoc.go @@ -930,7 +930,11 @@ func (api *TraceAPIImpl) Call(ctx context.Context, args TraceCallParam, traceTyp return nil, err } - blockCtx, txCtx := transactions.GetEvmContext(msg, header, blockNrOrHash.RequireCanonical, tx, ethdb.GetHasTEVM(tx)) + contractHasTEVM := func(contractHash common.Hash) (bool, error) { return false, nil } + if api.TevmEnabled { + contractHasTEVM = ethdb.GetHasTEVM(tx) + } + blockCtx, txCtx := transactions.GetEvmContext(msg, header, blockNrOrHash.RequireCanonical, tx, contractHasTEVM) blockCtx.GasLimit = math.MaxUint64 blockCtx.MaxGasLimit = true @@ -1070,11 +1074,11 @@ func (api *TraceAPIImpl) doCallMany(ctx context.Context, dbtx kv.Tx, msgs []type if err != nil { return nil, err } - stateReader = state.NewCachedReader2(cacheView, dbtx) + stateReader = state.NewCachedReader2(cacheView, dbtx) // this cache stays between RPC calls } else { stateReader = state.NewPlainState(dbtx, blockNumber) } - stateCache := shards.NewStateCache(32, 0 /* no limit */) + stateCache := shards.NewStateCache(32, 0 /* no limit */) // this cache living only during current RPC call, but required to store state writes cachedReader := state.NewCachedReader(stateReader, stateCache) noop := state.NewNoopWriter() cachedWriter := state.NewCachedWriter(noop, stateCache) @@ -1103,6 +1107,12 @@ func (api *TraceAPIImpl) doCallMany(ctx context.Context, dbtx kv.Tx, msgs []type header = parentHeader useParent = true } + + contractHasTEVM := func(contractHash common.Hash) (bool, error) { return false, nil } + if api.TevmEnabled { + contractHasTEVM = ethdb.GetHasTEVM(dbtx) + } + for txIndex, msg := range msgs { if err := libcommon.Stopped(ctx.Done()); err != nil { return nil, err @@ -1139,7 +1149,7 @@ func (api *TraceAPIImpl) doCallMany(ctx context.Context, dbtx kv.Tx, msgs []type } // Get a new instance of the EVM. - blockCtx, txCtx := transactions.GetEvmContext(msg, header, parentNrOrHash.RequireCanonical, dbtx, ethdb.GetHasTEVM(dbtx)) + blockCtx, txCtx := transactions.GetEvmContext(msg, header, parentNrOrHash.RequireCanonical, dbtx, contractHasTEVM) if useParent { blockCtx.GasLimit = math.MaxUint64 blockCtx.MaxGasLimit = true diff --git a/cmd/rpcdaemon/commands/trace_filtering.go b/cmd/rpcdaemon/commands/trace_filtering.go index ed7388f3c5a..05a24c5791c 100644 --- a/cmd/rpcdaemon/commands/trace_filtering.go +++ b/cmd/rpcdaemon/commands/trace_filtering.go @@ -199,7 +199,7 @@ func (api *TraceAPIImpl) Filter(ctx context.Context, req TraceFilterRequest, str dbtx, err1 := api.kv.BeginRo(ctx) if err1 != nil { stream.WriteNil() - return fmt.Errorf("traceFilter cannot open tx: %v", err1) + return fmt.Errorf("traceFilter cannot open tx: %w", err1) } defer dbtx.Rollback() diff --git a/cmd/rpcdaemon/commands/tracing.go b/cmd/rpcdaemon/commands/tracing.go index fe082919d7b..c2b5fdac65f 100644 --- a/cmd/rpcdaemon/commands/tracing.go +++ b/cmd/rpcdaemon/commands/tracing.go @@ -54,7 +54,10 @@ func (api *PrivateDebugAPIImpl) TraceTransaction(ctx context.Context, hash commo getHeader := func(hash common.Hash, number uint64) *types.Header { return rawdb.ReadHeader(tx, hash, number) } - contractHasTEVM := ethdb.GetHasTEVM(tx) + contractHasTEVM := func(contractHash common.Hash) (bool, error) { return false, nil } + if api.TevmEnabled { + contractHasTEVM = ethdb.GetHasTEVM(tx) + } msg, blockCtx, txCtx, ibs, _, err := transactions.ComputeTxEnv(ctx, block, chainConfig, getHeader, contractHasTEVM, ethash.NewFaker(), tx, blockHash, txIndex) if err != nil { stream.WriteNil() @@ -113,7 +116,11 @@ func (api *PrivateDebugAPIImpl) TraceCall(ctx context.Context, args ethapi.CallA return err } - blockCtx, txCtx := transactions.GetEvmContext(msg, header, blockNrOrHash.RequireCanonical, dbtx, ethdb.GetHasTEVM(dbtx)) + contractHasTEVM := func(contractHash common.Hash) (bool, error) { return false, nil } + if api.TevmEnabled { + contractHasTEVM = ethdb.GetHasTEVM(dbtx) + } + blockCtx, txCtx := transactions.GetEvmContext(msg, header, blockNrOrHash.RequireCanonical, dbtx, contractHasTEVM) // Trace the transaction and return return transactions.TraceTx(ctx, msg, blockCtx, txCtx, ibs, config, chainConfig, stream) } diff --git a/cmd/rpcdaemon/test.http b/cmd/rpcdaemon/test.http index 41e780cb183..be0cbe9cfe4 100644 --- a/cmd/rpcdaemon/test.http +++ b/cmd/rpcdaemon/test.http @@ -4,21 +4,46 @@ POST localhost:8545 Content-Type: application/json -{ "jsonrpc": "2.0", "method": "eth_syncing", "params": [], "id":1} +{ + "jsonrpc": "2.0", + "method": "eth_syncing", + "params": [], + "id": 1 +} ### POST localhost:8545 Content-Type: application/json -{"jsonrpc":"2.0","method":"eth_getBalance","params": ["0xfffa4763f94f7ad191b366a343092a5d1a47ed08", "0xde84"],"id":1} +{ + "jsonrpc": "2.0", + "method": "eth_getBalance", + "params": [ + "0xfffa4763f94f7ad191b366a343092a5d1a47ed08", + "0xde84" + ], + "id": 1 +} ### POST localhost:8545 Content-Type: application/json -{ "jsonrpc": "2.0", "method": "debug_accountRange", "params": ["0x1e8480", "", 256, false, false, false], "id":1} +{ + "jsonrpc": "2.0", + "method": "debug_accountRange", + "params": [ + "0x1e8480", + "", + 256, + false, + false, + false + ], + "id": 1 +} ### @@ -30,7 +55,7 @@ Content-Type: application/json "jsonrpc": "2.0", "method": "eth_getBlockByNumber", "params": [ - "0x1b4", + "0x0", true ], "id": 1 @@ -54,7 +79,15 @@ Content-Type: application/json POST localhost:8545 Content-Type: application/json -{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0xf4240",true],"id":2} +{ + "jsonrpc": "2.0", + "method": "eth_getBlockByNumber", + "params": [ + "0xf4240", + true + ], + "id": 2 +} ### @@ -73,6 +106,7 @@ Content-Type: application/json ], "id": 537758 } + ### > 60 ### >20 diff --git a/cmd/rpctest/rpctest/utils.go b/cmd/rpctest/rpctest/utils.go index 7bade8a5161..bec1c14690f 100644 --- a/cmd/rpctest/rpctest/utils.go +++ b/cmd/rpctest/rpctest/utils.go @@ -223,7 +223,7 @@ func requestAndCompare(request string, methodName string, errCtx string, reqGen oeRespFile, _ := os.Create("oe-response.json") //nolint:errcheck oeRespFile.Write(resg.Response) //nolint:errcheck oeRespFile.Close() //nolint:errcheck - return fmt.Errorf("different results for method %s, errCtx %s: %v\nRequest in file request.json, Erigon response in file erigon-response.json, Geth/OE response in file oe-response.json", methodName, errCtx, err) + return fmt.Errorf("different results for method %s, errCtx %s: %w\nRequest in file request.json, Erigon response in file erigon-response.json, Geth/OE response in file oe-response.json", methodName, errCtx, err) } } } diff --git a/cmd/sentry/download/downloader.go b/cmd/sentry/download/downloader.go index 9e30c1a5266..dbf5203aa82 100644 --- a/cmd/sentry/download/downloader.go +++ b/cmd/sentry/download/downloader.go @@ -210,7 +210,7 @@ func RecvUploadHeadersMessage(ctx context.Context, if rlp.IsDecodeError(err) { log.Debug("[RecvUploadHeadersMessage] Handling incoming message", "error", err) } else { - log.Error("[RecvUploadHeadersMessage] Handling incoming message", "error", err) + log.Warn("[RecvUploadHeadersMessage] Handling incoming message", "error", err) } } if wg != nil { @@ -312,7 +312,7 @@ func RecvMessage( if rlp.IsDecodeError(err) { log.Debug("[RecvMessage] Handling incoming message", "error", err) } else { - log.Error("[RecvMessage] Handling incoming message", "error", err) + log.Warn("[RecvMessage] Handling incoming message", "error", err) } } @@ -519,7 +519,7 @@ func (cs *ControlServerImpl) blockHeaders66(ctx context.Context, in *proto_sentr if req != nil { if peer := cs.SendHeaderRequest(ctx, req); peer != nil { cs.Hd.SentRequest(req, currentTime, 5 /* timeout */) - log.Debug("Sent request", "height", req.Number) + log.Trace("Sent request", "height", req.Number) } } cs.Penalize(ctx, penalties) @@ -594,7 +594,7 @@ func (cs *ControlServerImpl) blockHeaders65(ctx context.Context, in *proto_sentr if req != nil { if peer := cs.SendHeaderRequest(ctx, req); peer != nil { cs.Hd.SentRequest(req, currentTime, 5 /* timeout */) - log.Debug("Sent request", "height", req.Number) + log.Trace("Sent request", "height", req.Number) } } cs.Penalize(ctx, penalties) @@ -673,7 +673,7 @@ func (cs *ControlServerImpl) newBlock65(ctx context.Context, inreq *proto_sentry if _, err1 := sentry.PeerMinBlock(ctx, &outreq, &grpc.EmptyCallOption{}); err1 != nil { log.Error("Could not send min block for peer", "err", err1) } - log.Debug(fmt.Sprintf("NewBlockMsg{blockNumber: %d} from [%s]", request.Block.NumberU64(), gointerfaces.ConvertH512ToBytes(inreq.PeerId))) + log.Trace(fmt.Sprintf("NewBlockMsg{blockNumber: %d} from [%s]", request.Block.NumberU64(), gointerfaces.ConvertH512ToBytes(inreq.PeerId))) return nil } diff --git a/cmd/sentry/download/sentry.go b/cmd/sentry/download/sentry.go index 8bef6da82a1..a3639f3c2c2 100644 --- a/cmd/sentry/download/sentry.go +++ b/cmd/sentry/download/sentry.go @@ -17,15 +17,10 @@ import ( "syscall" "time" - "github.com/golang/protobuf/ptypes/empty" - "github.com/ledgerwatch/erigon-lib/gointerfaces/grpcutil" - "github.com/ledgerwatch/log/v3" - "google.golang.org/protobuf/types/known/emptypb" - - //grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" "github.com/holiman/uint256" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/gointerfaces" + "github.com/ledgerwatch/erigon-lib/gointerfaces/grpcutil" proto_sentry "github.com/ledgerwatch/erigon-lib/gointerfaces/sentry" proto_types "github.com/ledgerwatch/erigon-lib/gointerfaces/types" "github.com/ledgerwatch/erigon/common" @@ -37,7 +32,9 @@ import ( "github.com/ledgerwatch/erigon/p2p/enode" "github.com/ledgerwatch/erigon/params" "github.com/ledgerwatch/erigon/rlp" + "github.com/ledgerwatch/log/v3" "google.golang.org/grpc" + "google.golang.org/protobuf/types/known/emptypb" ) const ( @@ -270,13 +267,13 @@ func runPeer( default: } if peerPrinted { - log.Debug("Peer disconnected", "id", peerID, "name", peerInfo.peer.Fullname()) + log.Trace("Peer disconnected", "id", peerID, "name", peerInfo.peer.Fullname()) } }() for { if !peerPrinted { if time.Now().After(printTime) { - log.Debug("Peer stable", "id", peerID, "name", peerInfo.peer.Fullname()) + log.Trace("Peer stable", "id", peerID, "name", peerInfo.peer.Fullname()) peerPrinted = true } } @@ -472,10 +469,10 @@ func NewSentryServer(ctx context.Context, dialCandidates enode.Iterator, readNod Run: func(peer *p2p.Peer, rw p2p.MsgReadWriter) error { peerID := peer.ID().String() if _, ok := ss.GoodPeers.Load(peerID); ok { - log.Debug(fmt.Sprintf("[%s] Peer already has connection", peerID)) + log.Trace(fmt.Sprintf("[%s] Peer already has connection", peerID)) return nil } - log.Debug(fmt.Sprintf("[%s] Start with peer", peerID)) + log.Trace(fmt.Sprintf("[%s] Start with peer", peerID)) peerInfo := &PeerInfo{ peer: peer, @@ -491,7 +488,7 @@ func NewSentryServer(ctx context.Context, dialCandidates enode.Iterator, readNod if err != nil { return fmt.Errorf("handshake to peer %s: %w", peerID, err) } - log.Debug(fmt.Sprintf("[%s] Received status message OK", peerID), "name", peer.Name()) + log.Trace(fmt.Sprintf("[%s] Received status message OK", peerID), "name", peer.Name()) if err := runPeer( ctx, @@ -502,7 +499,7 @@ func NewSentryServer(ctx context.Context, dialCandidates enode.Iterator, readNod ss.send, ss.hasSubscribers, ); err != nil { - log.Debug(fmt.Sprintf("[%s] Error while running peer: %v", peerID, err)) + log.Trace(fmt.Sprintf("[%s] Error while running peer: %v", peerID, err)) } return nil }, @@ -608,7 +605,7 @@ func (ss *SentryServerImpl) startSync(ctx context.Context, bestHash common.Hash, return nil } -func (ss *SentryServerImpl) PenalizePeer(_ context.Context, req *proto_sentry.PenalizePeerRequest) (*empty.Empty, error) { +func (ss *SentryServerImpl) PenalizePeer(_ context.Context, req *proto_sentry.PenalizePeerRequest) (*emptypb.Empty, error) { //log.Warn("Received penalty", "kind", req.GetPenalty().Descriptor().FullName, "from", fmt.Sprintf("%s", req.GetPeerId())) strId := string(gointerfaces.ConvertH512ToBytes(req.PeerId)) if x, ok := ss.GoodPeers.Load(strId); ok { @@ -618,20 +615,20 @@ func (ss *SentryServerImpl) PenalizePeer(_ context.Context, req *proto_sentry.Pe } } ss.GoodPeers.Delete(strId) - return &empty.Empty{}, nil + return &emptypb.Empty{}, nil } -func (ss *SentryServerImpl) PeerMinBlock(_ context.Context, req *proto_sentry.PeerMinBlockRequest) (*empty.Empty, error) { +func (ss *SentryServerImpl) PeerMinBlock(_ context.Context, req *proto_sentry.PeerMinBlockRequest) (*emptypb.Empty, error) { peerID := string(gointerfaces.ConvertH512ToBytes(req.PeerId)) x, _ := ss.GoodPeers.Load(peerID) peerInfo, _ := x.(*PeerInfo) if peerInfo == nil { - return &empty.Empty{}, nil + return &emptypb.Empty{}, nil } if req.MinBlock > peerInfo.Height() { peerInfo.SetHeight(req.MinBlock) } - return &empty.Empty{}, nil + return &emptypb.Empty{}, nil } func (ss *SentryServerImpl) findPeer(minBlock uint64) (string, *PeerInfo, bool) { @@ -892,7 +889,7 @@ func (ss *SentryServerImpl) send(msgID proto_sentry.MessageId, peerID string, b ch := ss.messageStreams[msgID][i] ch <- req if len(ch) > MessagesQueueSize/2 { - log.Debug("[sentry] consuming is slow", "msgID", msgID.String()) + log.Warn("[sentry] consuming is slow", "msgID", msgID.String()) // evict old messages from channel for j := 0; j < MessagesQueueSize/4; j++ { select { @@ -940,7 +937,7 @@ func (ss *SentryServerImpl) addMessagesStream(ids []proto_sentry.MessageId, ch c const MessagesQueueSize = 1024 // one such queue per client of .Messages stream func (ss *SentryServerImpl) Messages(req *proto_sentry.MessagesRequest, server proto_sentry.Sentry_MessagesServer) error { - log.Debug("[Messages] new subscriber", "to", req.Ids) + log.Trace("[Messages] new subscriber", "to", req.Ids) ch := make(chan *proto_sentry.InboundMessage, MessagesQueueSize) defer close(ch) clean := ss.addMessagesStream(req.Ids, ch) diff --git a/cmd/snapshots/downloader/commands/root.go b/cmd/snapshots/downloader/commands/root.go index 9ebd244fa4c..1028ba7787c 100644 --- a/cmd/snapshots/downloader/commands/root.go +++ b/cmd/snapshots/downloader/commands/root.go @@ -12,6 +12,7 @@ import ( grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware" grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery" + proto_snap "github.com/ledgerwatch/erigon-lib/gointerfaces/snapshotsync" "github.com/ledgerwatch/erigon/cmd/utils" "github.com/ledgerwatch/erigon/internal/debug" "github.com/ledgerwatch/erigon/params" @@ -159,7 +160,7 @@ func runDownloader(cmd *cobra.Command, args []string) error { if mainNetPreDownload { log.Info("Predownload mainnet snapshots") go func() { - _, err := bittorrentServer.Download(context.Background(), &snapshotsync.DownloadSnapshotRequest{ + _, err := bittorrentServer.Download(context.Background(), &proto_snap.DownloadSnapshotRequest{ NetworkId: params.MainnetChainConfig.ChainID.Uint64(), Type: snapshotsync.GetAvailableSnapshotTypes(params.MainnetChainConfig.ChainID.Uint64()), }) @@ -176,7 +177,7 @@ func runDownloader(cmd *cobra.Command, args []string) error { default: } - snapshots, err := bittorrentServer.Snapshots(context.Background(), &snapshotsync.SnapshotsRequest{ + snapshots, err := bittorrentServer.Snapshots(context.Background(), &proto_snap.SnapshotsRequest{ NetworkId: params.MainnetChainConfig.ChainID.Uint64(), }) if err != nil { @@ -191,7 +192,7 @@ func runDownloader(cmd *cobra.Command, args []string) error { time.Sleep(time.Minute) } }() - snapshotsync.RegisterDownloaderServer(grpcServer, bittorrentServer) + proto_snap.RegisterDownloaderServer(grpcServer, bittorrentServer) go func() { log.Info("Starting grpc") err := grpcServer.Serve(lis) diff --git a/cmd/snapshots/generator/commands/generate_body_snapshot.go b/cmd/snapshots/generator/commands/generate_body_snapshot.go index 8a601488c09..ced7d4c7a17 100644 --- a/cmd/snapshots/generator/commands/generate_body_snapshot.go +++ b/cmd/snapshots/generator/commands/generate_body_snapshot.go @@ -61,7 +61,7 @@ func BodySnapshot(ctx context.Context, logger log.Logger, dbPath, snapshotPath s hash, err = rawdb.ReadCanonicalHash(tx, i) if err != nil { - return fmt.Errorf("getting canonical hash for block %d: %v", i, err) + return fmt.Errorf("getting canonical hash for block %d: %w", i, err) } body := rawdb.ReadBodyRLP(tx, hash, i) if err = sntx.Put(kv.BlockBody, dbutils.BlockBodyKey(i, hash), body); err != nil { diff --git a/cmd/snapshots/generator/commands/generate_header_snapshot.go b/cmd/snapshots/generator/commands/generate_header_snapshot.go index 750e3d66ab8..4f15f42cc7a 100644 --- a/cmd/snapshots/generator/commands/generate_header_snapshot.go +++ b/cmd/snapshots/generator/commands/generate_header_snapshot.go @@ -77,7 +77,7 @@ func HeaderSnapshot(ctx context.Context, logger log.Logger, dbPath, snapshotPath hash, err = rawdb.ReadCanonicalHash(tx, i) if err != nil { - return fmt.Errorf("getting canonical hash for block %d: %v", i, err) + return fmt.Errorf("getting canonical hash for block %d: %w", i, err) } header = rawdb.ReadHeaderRLP(tx, hash, i) if len(header) == 0 { diff --git a/cmd/snapshots/generator/commands/generate_state_snapshot.go b/cmd/snapshots/generator/commands/generate_state_snapshot.go index 45490e8c475..d3566c8a991 100644 --- a/cmd/snapshots/generator/commands/generate_state_snapshot.go +++ b/cmd/snapshots/generator/commands/generate_state_snapshot.go @@ -96,7 +96,7 @@ func GenerateStateSnapshot(ctx context.Context, logger log.Logger, dbPath, snaps var acc accounts.Account if err = acc.DecodeForStorage(v); err != nil { - return false, fmt.Errorf("decoding %x for %x: %v", v, k, err) + return false, fmt.Errorf("decoding %x for %x: %w", v, k, err) } if acc.Incarnation > 0 { @@ -125,7 +125,7 @@ func GenerateStateSnapshot(ctx context.Context, logger log.Logger, dbPath, snaps if acc.IsEmptyCodeHash() { codeHash, err1 := tx2.GetOne(kv.PlainContractCode, storagePrefix) if err1 != nil && errors.Is(err1, ethdb.ErrKeyNotFound) { - return false, fmt.Errorf("getting code hash for %x: %v", k, err1) + return false, fmt.Errorf("getting code hash for %x: %w", k, err1) } if len(codeHash) > 0 { code, err1 := tx2.GetOne(kv.Code, codeHash) diff --git a/cmd/snapshots/tracker/commands/root.go b/cmd/snapshots/tracker/commands/root.go index 6c443015e41..268c3f8ca1f 100644 --- a/cmd/snapshots/tracker/commands/root.go +++ b/cmd/snapshots/tracker/commands/root.go @@ -104,7 +104,7 @@ var rootCmd = &cobra.Command{ return true, nil } if time.Since(a.UpdatedAt) > 24*time.Hour { - log.Debug("Skipped", "k", common.Bytes2Hex(k), "last updated", a.UpdatedAt) + log.Trace("Skipped", "k", common.Bytes2Hex(k), "last updated", a.UpdatedAt) return true, nil } if a.Left == 0 { @@ -268,7 +268,7 @@ func (t *Tracker) ServeHTTP(w http.ResponseWriter, r *http.Request) { return nil } if time.Since(a.UpdatedAt) > 5*DisconnectInterval { - log.Debug("Skipped requset", "peer", common.Bytes2Hex(a.PeerID), "last updated", a.UpdatedAt, "now", time.Now()) + log.Trace("Skipped requset", "peer", common.Bytes2Hex(a.PeerID), "last updated", a.UpdatedAt, "now", time.Now()) return nil } if a.Left == 0 { @@ -343,7 +343,7 @@ func ParseRequest(r *http.Request) (AnnounceReq, error) { } port, err := strconv.Atoi(q.Get("port")) if err != nil { - return AnnounceReq{}, fmt.Errorf("port: %v - %w", q.Get("port"), err) + return AnnounceReq{}, fmt.Errorf("port: %v - %w", q.Get("port"), err) } res := AnnounceReq{ diff --git a/cmd/state/commands/opcode_tracer.go b/cmd/state/commands/opcode_tracer.go index 379140c96d6..557ee5b7cea 100644 --- a/cmd/state/commands/opcode_tracer.go +++ b/cmd/state/commands/opcode_tracer.go @@ -681,7 +681,7 @@ func runBlock(ibs *state.IntraBlockState, txnWriter state.StateWriter, blockWrit ibs.Prepare(tx.Hash(), block.Hash(), i) receipt, _, err := core.ApplyTransaction(chainConfig, getHeader, engine, nil, gp, ibs, txnWriter, header, tx, usedGas, vmConfig, contractHasTEVM) if err != nil { - return nil, fmt.Errorf("could not apply tx %d [%x] failed: %v", i, tx.Hash(), err) + return nil, fmt.Errorf("could not apply tx %d [%x] failed: %w", i, tx.Hash(), err) } receipts = append(receipts, receipt) } @@ -689,11 +689,11 @@ func runBlock(ibs *state.IntraBlockState, txnWriter state.StateWriter, blockWrit if !vmConfig.ReadOnly { // Finalize the block, applying any consensus engine specific extras (e.g. block rewards) if _, err := engine.FinalizeAndAssemble(chainConfig, header, ibs, block.Transactions(), block.Uncles(), receipts, nil, nil, nil, nil); err != nil { - return nil, fmt.Errorf("finalize of block %d failed: %v", block.NumberU64(), err) + return nil, fmt.Errorf("finalize of block %d failed: %w", block.NumberU64(), err) } if err := ibs.CommitBlock(rules, blockWriter); err != nil { - return nil, fmt.Errorf("committing block %d failed: %v", block.NumberU64(), err) + return nil, fmt.Errorf("committing block %d failed: %w", block.NumberU64(), err) } } diff --git a/cmd/txpool/main.go b/cmd/txpool/main.go index 114b39f0129..cf71f9d903b 100644 --- a/cmd/txpool/main.go +++ b/cmd/txpool/main.go @@ -38,6 +38,8 @@ var ( pendingPoolLimit int baseFeePoolLimit int queuedPoolLimit int + + priceLimit uint64 ) func init() { @@ -56,6 +58,8 @@ func init() { rootCmd.PersistentFlags().IntVar(&pendingPoolLimit, "txpool.globalslots", txpool.DefaultConfig.PendingSubPoolLimit, "Maximum number of executable transaction slots for all accounts") rootCmd.PersistentFlags().IntVar(&baseFeePoolLimit, "txpool.globalbasefeeeslots", txpool.DefaultConfig.BaseFeeSubPoolLimit, "Maximum number of non-executable transactions where only not enough baseFee") rootCmd.PersistentFlags().IntVar(&queuedPoolLimit, "txpool.globalqueue", txpool.DefaultConfig.QueuedSubPoolLimit, "Maximum number of non-executable transaction slots for all accounts") + rootCmd.PersistentFlags().Uint64Var(&priceLimit, "txpool.pricelimit", txpool.DefaultConfig.MinFeeCap, "Minimum gas price (fee cap) limit to enforce for acceptance into the pool") + rootCmd.PersistentFlags().Uint64Var(&priceLimit, "txpool.accountslots", txpool.DefaultConfig.AccountSlots, "Minimum number of executable transaction slots guaranteed per account") } var rootCmd = &cobra.Command{ @@ -107,6 +111,7 @@ var rootCmd = &cobra.Command{ cfg.PendingSubPoolLimit = pendingPoolLimit cfg.BaseFeeSubPoolLimit = baseFeePoolLimit cfg.QueuedSubPoolLimit = queuedPoolLimit + cfg.MinFeeCap = priceLimit cacheConfig := kvcache.DefaultCoherentConfig cacheConfig.MetricsLabel = "txpool" diff --git a/cmd/txpool/readme.md b/cmd/txpool/readme.md index 116d15b3e0c..5218c5cea6e 100644 --- a/cmd/txpool/readme.md +++ b/cmd/txpool/readme.md @@ -47,8 +47,8 @@ Will add this part soon [tbd] [x] Notify about new pending transactions - we sending more than need [x] Handle "NewBlock" message with 200K transactions re-calculation - in under 50ms [x] Add --txpool.globalslots, --txpool.globalqueue,--txpool.globalbasefeeeslots -[] Add --txpool.accountslots -[] Add --txpool.pricelimit +[x] Add --txpool.accountslots +[x] Add --txpool.pricelimit [] Add way for simple introspection - where is tx and why [] Hard-forks support (now rules are parsed ones on txPool start) [] Add pool to docker-compose diff --git a/cmd/utils/diskusage_windows.go b/cmd/utils/diskusage_windows.go index 9bf7740b994..75e76500ded 100644 --- a/cmd/utils/diskusage_windows.go +++ b/cmd/utils/diskusage_windows.go @@ -26,12 +26,12 @@ func getFreeDiskSpace(path string) (uint64, error) { cwd, err := windows.UTF16PtrFromString(path) if err != nil { - return 0, fmt.Errorf("failed to call UTF16PtrFromString: %v", err) + return 0, fmt.Errorf("failed to call UTF16PtrFromString: %w", err) } var freeBytesAvailableToCaller, totalNumberOfBytes, totalNumberOfFreeBytes uint64 if err := windows.GetDiskFreeSpaceEx(cwd, &freeBytesAvailableToCaller, &totalNumberOfBytes, &totalNumberOfFreeBytes); err != nil { - return 0, fmt.Errorf("failed to call GetDiskFreeSpaceEx: %v", err) + return 0, fmt.Errorf("failed to call GetDiskFreeSpaceEx: %w", err) } return freeBytesAvailableToCaller, nil diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 607fd4e2063..3ffb1ccaca3 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -179,7 +179,7 @@ var ( } TxPoolPriceLimitFlag = cli.Uint64Flag{ Name: "txpool.pricelimit", - Usage: "Minimum gas price limit to enforce for acceptance into the pool", + Usage: "Minimum gas price (fee cap) limit to enforce for acceptance into the pool", Value: ethconfig.Defaults.TxPool.PriceLimit, } TxPoolPriceBumpFlag = cli.Uint64Flag{ @@ -732,7 +732,7 @@ func NewP2PConfig(nodiscover bool, datadir, netRestrict, natSetting, nodeName st } natif, err := nat.Parse(natSetting) if err != nil { - return nil, fmt.Errorf("invalid nat option %s: %v", natSetting, err) + return nil, fmt.Errorf("invalid nat option %s: %w", natSetting, err) } cfg.NAT = natif return cfg, nil diff --git a/common/compiler/solidity.go b/common/compiler/solidity.go index 3e457cbd5f5..0e50cd18a86 100644 --- a/common/compiler/solidity.go +++ b/common/compiler/solidity.go @@ -137,7 +137,7 @@ func (s *Solidity) run(cmd *exec.Cmd, source string) (map[string]*Contract, erro cmd.Stderr = &stderr cmd.Stdout = &stdout if err := cmd.Run(); err != nil { - return nil, fmt.Errorf("solc: %v\n%s", err, stderr.Bytes()) + return nil, fmt.Errorf("solc: %w\n%s", err, stderr.Bytes()) } return ParseCombinedJSON(stdout.Bytes(), source, s.Version, s.Version, strings.Join(s.makeArgs(), " ")) } @@ -163,7 +163,7 @@ func ParseCombinedJSON(combinedJSON []byte, source string, languageVersion strin // Parse the individual compilation results. var abi interface{} if err := json.Unmarshal([]byte(info.Abi), &abi); err != nil { - return nil, fmt.Errorf("solc: error reading abi definition (%v)", err) + return nil, fmt.Errorf("solc: error reading abi definition (%w)", err) } var userdoc, devdoc interface{} json.Unmarshal([]byte(info.Userdoc), &userdoc) diff --git a/common/compiler/vyper.go b/common/compiler/vyper.go index fb1f98d863e..dd588260b09 100644 --- a/common/compiler/vyper.go +++ b/common/compiler/vyper.go @@ -92,7 +92,7 @@ func (s *Vyper) run(cmd *exec.Cmd, source string) (map[string]*Contract, error) cmd.Stderr = &stderr cmd.Stdout = &stdout if err := cmd.Run(); err != nil { - return nil, fmt.Errorf("vyper: %v\n%s", err, stderr.Bytes()) + return nil, fmt.Errorf("vyper: %w\n%s", err, stderr.Bytes()) } return ParseVyperJSON(stdout.Bytes(), source, s.Version, s.Version, strings.Join(s.makeArgs(), " ")) diff --git a/common/test_utils.go b/common/test_utils.go index a848642f77f..8e182792b94 100644 --- a/common/test_utils.go +++ b/common/test_utils.go @@ -31,9 +31,9 @@ func LoadJSON(file string, val interface{}) error { if err := json.Unmarshal(content, val); err != nil { if syntaxerr, ok := err.(*json.SyntaxError); ok { line := findLine(content, syntaxerr.Offset) - return fmt.Errorf("JSON syntax error at %v:%v: %v", file, line, err) + return fmt.Errorf("JSON syntax error at %v:%v: %w", file, line, err) } - return fmt.Errorf("JSON unmarshal error in %v: %v", file, err) + return fmt.Errorf("JSON unmarshal error in %v: %w", file, err) } return nil } diff --git a/consensus/aura/aura.go b/consensus/aura/aura.go index b08f1073a27..83238f94d4a 100644 --- a/consensus/aura/aura.go +++ b/consensus/aura/aura.go @@ -231,7 +231,7 @@ func (e *EpochManager) zoomToAfter(chain consensus.ChainHeaderReader, er consens panic(fmt.Errorf("proof produced by this engine is invalid: %w", err)) } epochSet := list.validators - log.Debug("[aura] Updating finality checker with new validator set extracted from epoch", "num", lastTransition.BlockNumber) + log.Trace("[aura] Updating finality checker with new validator set extracted from epoch", "num", lastTransition.BlockNumber) e.finalityChecker = NewRollingFinality(epochSet) if proof.SignalNumber >= DEBUG_LOG_FROM { fmt.Printf("new rolling finality: %d\n", proof.SignalNumber) @@ -564,7 +564,7 @@ func (c *AuRa) verifyFamily(chain consensus.ChainHeaderReader, e consensus.Epoch //nolint if step == parentStep || (header.Number.Uint64() >= c.cfg.ValidateStepTransition && step <= parentStep) { - log.Debug("[engine] Multiple blocks proposed for step", "num", parentStep) + log.Trace("[aura] Multiple blocks proposed for step", "num", parentStep) _ = setNumber /* self.validators.report_malicious( @@ -1096,7 +1096,7 @@ func (c *AuRa) GenerateSeal(chain consensus.ChainHeaderReader, current, parent * // first check to avoid generating signature most of the time // (but there's still a race to the `compare_exchange`) if !c.step.canPropose.Load() { - log.Trace("[engine] Aborting seal generation. Can't propose.") + log.Trace("[aura] Aborting seal generation. Can't propose.") return nil } parentStep, err := headerStep(parent) @@ -1108,24 +1108,24 @@ func (c *AuRa) GenerateSeal(chain consensus.ChainHeaderReader, current, parent * // filter messages from old and future steps and different parents expectedDiff := calculateScore(parentStep, step, 0) if current.Difficulty.Cmp(expectedDiff.ToBig()) != 0 { - log.Debug(fmt.Sprintf("[engine] Aborting seal generation. The step or empty_steps have changed in the meantime. %d != %d", current.Difficulty, expectedDiff)) + log.Trace(fmt.Sprintf("[aura] Aborting seal generation. The step or empty_steps have changed in the meantime. %d != %d", current.Difficulty, expectedDiff)) return nil } if parentStep > step { - log.Warn(fmt.Sprintf("[engine] Aborting seal generation for invalid step: %d > %d", parentStep, step)) + log.Warn(fmt.Sprintf("[aura] Aborting seal generation for invalid step: %d > %d", parentStep, step)) return nil } validators, setNumber, err := c.epochSet(chain, nil, current, nil) if err != nil { - log.Warn("[engine] Unable to generate seal", "err", err) + log.Warn("[aura] Unable to generate seal", "err", err) return nil } stepProposerAddr, err := stepProposer(validators, current.ParentHash, step, call) if err != nil { - log.Warn("[engine] Unable to get stepProposer", "err", err) + log.Warn("[aura] Unable to get stepProposer", "err", err) return nil } if stepProposerAddr != current.Coinbase { @@ -1143,7 +1143,7 @@ func (c *AuRa) GenerateSeal(chain consensus.ChainHeaderReader, current, parent * /* signature, err := c.sign(current.bareHash()) if err != nil { - log.Warn("[engine] generate_seal: FAIL: Accounts secret key unavailable.", "err", err) + log.Warn("[aura] generate_seal: FAIL: Accounts secret key unavailable.", "err", err) return nil } */ diff --git a/consensus/ethash/algorithm.go b/consensus/ethash/algorithm.go index cc423ad4300..2847d482048 100644 --- a/consensus/ethash/algorithm.go +++ b/consensus/ethash/algorithm.go @@ -168,8 +168,8 @@ func generateCache(dest []uint32, epoch uint64, seed []byte) { defer func() { elapsed := time.Since(start) - logFn := logger.Debug - if elapsed > 3*time.Second { + logFn := logger.Trace + if elapsed > 5*time.Second { logFn = logger.Info } logFn("Generated ethash verification cache", "elapsed", common.PrettyDuration(elapsed)) diff --git a/consensus/ethash/sealer.go b/consensus/ethash/sealer.go index bed0649f755..ce143340ba3 100644 --- a/consensus/ethash/sealer.go +++ b/consensus/ethash/sealer.go @@ -283,7 +283,7 @@ func (s *remoteSealer) sendNotification(ctx context.Context, url string, json [] // any other error, like no pending work or stale mining result). func (s *remoteSealer) submitWork(nonce types.BlockNonce, mixDigest common.Hash, sealhash common.Hash) bool { if s.currentBlock == nil { - s.ethash.config.Log.Error("Pending work without block", "sealhash", sealhash) + s.ethash.config.Log.Warn("Pending work without block", "sealhash", sealhash) return false } // Make sure the work submitted is present @@ -318,7 +318,7 @@ func (s *remoteSealer) submitWork(nonce types.BlockNonce, mixDigest common.Hash, if solution.NumberU64()+staleThreshold > s.currentBlock.NumberU64() { select { case s.results <- solution: - s.ethash.config.Log.Debug("Work submitted is acceptable", "number", solution.NumberU64(), "sealhash", sealhash, "hash", solution.Hash()) + s.ethash.config.Log.Trace("Work submitted is acceptable", "number", solution.NumberU64(), "sealhash", sealhash, "hash", solution.Hash()) return true default: s.ethash.config.Log.Warn("Sealing result is not read by miner", "mode", "remote", "sealhash", sealhash) diff --git a/consensus/result.go b/consensus/result.go index a1e3dfa7436..ccde2333c6b 100644 --- a/consensus/result.go +++ b/consensus/result.go @@ -19,7 +19,7 @@ type Cancel struct { } func (c *Cancel) CancelFunc() { - log.Debug("cancel mining task", "callers", debug.Callers(10)) + log.Trace("Cancel mining task", "callers", debug.Callers(10)) c.cancel() } diff --git a/core/allocs/fermion.json b/core/allocs/fermion.json index 1821842a563..8ee158b6a06 100644 --- a/core/allocs/fermion.json +++ b/core/allocs/fermion.json @@ -11,7 +11,28 @@ "0x0000000000000000000000000000000000000004": { "balance": "0x1" }, - "0x00521965e7bd230323c423d96c657db5b79d099f": { - "balance": "1606938044258990275541962092341162602522202993782792835301376" + "0x0000000000000000000000000000000000000005": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000006": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000007": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000008": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000009": { + "balance": "0x1" + }, + "0x42D5d120aD9c1692c5Fa72DcA20657254bbAa08D": { + "balance": "1000000000000000000000000" + }, + "0x3EC60Da1858eC7fA8EDD0dc736611Dba9ab43999": { + "balance": "1000000000000000000000000" + }, + "0x3a03F6D88437328CE8623EF5e80C67383704eBc1": { + "balance": "1000000000000000000000000" } } \ No newline at end of file diff --git a/core/blockchain.go b/core/blockchain.go index b8f99ad8550..fdc2e0a4115 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -266,7 +266,7 @@ func FinalizeBlockExecution(engine consensus.Engine, stateReader state.StateRead } if err := ibs.CommitBlock(cc.Rules(header.Number.Uint64()), stateWriter); err != nil { - return fmt.Errorf("committing block %d failed: %v", header.Number.Uint64(), err) + return fmt.Errorf("committing block %d failed: %w", header.Number.Uint64(), err) } if originalSystemAcc != nil { // hack for Sokol - don't understand why eip158 is enabled, but OE still save SystemAddress with nonce=0 @@ -278,7 +278,7 @@ func FinalizeBlockExecution(engine consensus.Engine, stateReader state.StateRead } if err := stateWriter.WriteChangeSets(); err != nil { - return fmt.Errorf("writing changesets for block %d failed: %v", header.Number.Uint64(), err) + return fmt.Errorf("writing changesets for block %d failed: %w", header.Number.Uint64(), err) } return nil } diff --git a/core/genesis.go b/core/genesis.go index fd4f5893838..65f7fb03443 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -429,13 +429,13 @@ func (g *Genesis) WriteGenesisState(tx kv.RwTx) (*types.Block, *state.IntraBlock blockWriter := state.NewPlainStateWriter(tx, tx, 0) if err := statedb.CommitBlock(params.Rules{}, blockWriter); err != nil { - return nil, statedb, fmt.Errorf("cannot write state: %v", err) + return nil, statedb, fmt.Errorf("cannot write state: %w", err) } if err := blockWriter.WriteChangeSets(); err != nil { - return nil, statedb, fmt.Errorf("cannot write change sets: %v", err) + return nil, statedb, fmt.Errorf("cannot write change sets: %w", err) } if err := blockWriter.WriteHistory(); err != nil { - return nil, statedb, fmt.Errorf("cannot write history: %v", err) + return nil, statedb, fmt.Errorf("cannot write history: %w", err) } return block, statedb, nil } diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go index 71db385d8d3..66da8212bf2 100644 --- a/core/rawdb/accessors_chain.go +++ b/core/rawdb/accessors_chain.go @@ -641,22 +641,22 @@ func WriteReceipts(tx kv.Putter, number uint64, receipts types.Receipts) error { buf.Reset() err := cbor.Marshal(buf, r.Logs) if err != nil { - return fmt.Errorf("encode block logs for block %d: %v", number, err) + return fmt.Errorf("encode block logs for block %d: %w", number, err) } if err = tx.Put(kv.Log, dbutils.LogKey(number, uint32(txId)), buf.Bytes()); err != nil { - return fmt.Errorf("writing logs for block %d: %v", number, err) + return fmt.Errorf("writing logs for block %d: %w", number, err) } } buf.Reset() err := cbor.Marshal(buf, receipts) if err != nil { - return fmt.Errorf("encode block receipts for block %d: %v", number, err) + return fmt.Errorf("encode block receipts for block %d: %w", number, err) } if err = tx.Put(kv.Receipts, dbutils.EncodeBlockNumber(number), buf.Bytes()); err != nil { - return fmt.Errorf("writing receipts for block %d: %v", number, err) + return fmt.Errorf("writing receipts for block %d: %w", number, err) } return nil } @@ -673,22 +673,22 @@ func AppendReceipts(tx kv.RwTx, blockNumber uint64, receipts types.Receipts) err buf.Reset() err := cbor.Marshal(buf, r.Logs) if err != nil { - return fmt.Errorf("encode block receipts for block %d: %v", blockNumber, err) + return fmt.Errorf("encode block receipts for block %d: %w", blockNumber, err) } if err = tx.Append(kv.Log, dbutils.LogKey(blockNumber, uint32(txId)), buf.Bytes()); err != nil { - return fmt.Errorf("writing receipts for block %d: %v", blockNumber, err) + return fmt.Errorf("writing receipts for block %d: %w", blockNumber, err) } } buf.Reset() err := cbor.Marshal(buf, receipts) if err != nil { - return fmt.Errorf("encode block receipts for block %d: %v", blockNumber, err) + return fmt.Errorf("encode block receipts for block %d: %w", blockNumber, err) } if err = tx.Append(kv.Receipts, dbutils.EncodeBlockNumber(blockNumber), buf.Bytes()); err != nil { - return fmt.Errorf("writing receipts for block %d: %v", blockNumber, err) + return fmt.Errorf("writing receipts for block %d: %w", blockNumber, err) } return nil } @@ -779,7 +779,7 @@ func ReadBlockWithSenders(db kv.Tx, hash common.Hash, number uint64) (*types.Blo return nil, nil, err } if len(senders) != block.Transactions().Len() { - return nil, nil, nil + return block, senders, nil // no senders is fine - will recover them on the fly } block.SendersToTxs(senders) return block, senders, nil diff --git a/core/skip_analysis.go b/core/skip_analysis.go index c78b9af5932..ede5367a18c 100644 --- a/core/skip_analysis.go +++ b/core/skip_analysis.go @@ -21,7 +21,7 @@ import ( ) // MainnetNotCheckedFrom is the first block number not yet checked for invalid jumps -const MainnetNotCheckedFrom uint64 = 13325400 +const MainnetNotCheckedFrom uint64 = 13370300 // SkipAnalysis function tells us whether we can skip performing jumpdest analysis // for the historical blocks (on mainnet now but perhaps on the testsnets diff --git a/core/state/database_test.go b/core/state/database_test.go index 905461901b2..0a1068f8cca 100644 --- a/core/state/database_test.go +++ b/core/state/database_test.go @@ -1296,7 +1296,7 @@ func TestChangeAccountCodeBetweenBlocks(t *testing.T) { intraBlockState.SetCode(contract, oldCode) intraBlockState.AddBalance(contract, uint256.NewInt(1000000000)) if err := intraBlockState.FinalizeTx(params.Rules{}, tsw); err != nil { - t.Errorf("error finalising 1st tx: %w", err) + t.Errorf("error finalising 1st tx: %v", err) } _, err := trie.CalcRoot("test", tx) require.NoError(t, err) diff --git a/core/state/dump.go b/core/state/dump.go index c0427f56564..e46f25593be 100644 --- a/core/state/dump.go +++ b/core/state/dump.go @@ -155,7 +155,7 @@ func (d *Dumper) DumpToCollector(c DumpCollector, excludeCode, excludeStorage bo return true, nil } if e := acc.DecodeForStorage(v); e != nil { - return false, fmt.Errorf("decoding %x for %x: %v", v, k, e) + return false, fmt.Errorf("decoding %x for %x: %w", v, k, e) } account := DumpAccount{ Balance: acc.Balance.ToBig().String(), @@ -181,7 +181,7 @@ func (d *Dumper) DumpToCollector(c DumpCollector, excludeCode, excludeStorage bo if incarnation > 0 { codeHash, err := d.db.GetOne(kv.PlainContractCode, storagePrefix) if err != nil { - return nil, fmt.Errorf("getting code hash for %x: %v", addr, err) + return nil, fmt.Errorf("getting code hash for %x: %w", addr, err) } if codeHash != nil { account.CodeHash = codeHash @@ -211,7 +211,7 @@ func (d *Dumper) DumpToCollector(c DumpCollector, excludeCode, excludeStorage bo t.Update(h.Bytes(), common.CopyBytes(vs)) return true, nil }); err != nil { - return nil, fmt.Errorf("walking over storage for %x: %v", addr, err) + return nil, fmt.Errorf("walking over storage for %x: %w", addr, err) } account.Root = t.Hash().Bytes() } diff --git a/core/state/intra_block_state_test.go b/core/state/intra_block_state_test.go index 3b6c0b4be75..8074095c3d3 100644 --- a/core/state/intra_block_state_test.go +++ b/core/state/intra_block_state_test.go @@ -248,7 +248,7 @@ func (test *snapshotTest) run() bool { } state.RevertToSnapshot(snapshotRevs[sindex]) if err := test.checkEqual(state, checkstate); err != nil { - test.err = fmt.Errorf("state mismatch after revert to snapshot %d\n%v", sindex, err) + test.err = fmt.Errorf("state mismatch after revert to snapshot %d\n%w", sindex, err) return false } } diff --git a/core/state/state_object.go b/core/state/state_object.go index d6617d17701..55d416d0a1a 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -328,7 +328,7 @@ func (so *stateObject) Code() []byte { } code, err := so.db.stateReader.ReadAccountCode(so.Address(), so.data.Incarnation, common.BytesToHash(so.CodeHash())) if err != nil { - so.setError(fmt.Errorf("can't load code hash %x: %v", so.CodeHash(), err)) + so.setError(fmt.Errorf("can't load code hash %x: %w", so.CodeHash(), err)) } so.code = code return code diff --git a/core/tx_journal.go b/core/tx_journal.go index 8631058c641..c1b753df094 100644 --- a/core/tx_journal.go +++ b/core/tx_journal.go @@ -83,7 +83,7 @@ func (journal *txJournal) load(add func([]types.Transaction) []error) error { loadBatch := func(txs types.Transactions) { for _, err := range add(txs) { if err != nil { - log.Debug("Failed to add journaled transaction", "err", err) + log.Trace("Failed to add journaled transaction", "err", err) dropped++ } } diff --git a/core/tx_pool.go b/core/tx_pool.go index af2515dca06..81ae7fcdf3c 100644 --- a/core/tx_pool.go +++ b/core/tx_pool.go @@ -366,7 +366,7 @@ func (pool *TxPool) loop() { pool.mu.RUnlock() if pending != prevPending || queued != prevQueued || stales != prevStales { - log.Debug("Transaction pool status report", "executable", pending, "queued", queued, "stales", stales) + log.Trace("Transaction pool status report", "executable", pending, "queued", queued, "stales", stales) prevPending, prevQueued, prevStales = pending, queued, stales } diff --git a/core/types/receipt.go b/core/types/receipt.go index 6392dd17077..68dc6ab98bf 100644 --- a/core/types/receipt.go +++ b/core/types/receipt.go @@ -38,8 +38,6 @@ var ( receiptStatusSuccessfulRLP = []byte{0x01} ) -var errEmptyTypedReceipt = errors.New("empty typed receipt bytes") - const ( // ReceiptStatusFailed is the status code of a transaction if execution failed. ReceiptStatusFailed = uint64(0) @@ -244,7 +242,7 @@ func (r *Receipt) DecodeRLP(s *rlp.Stream) error { return fmt.Errorf("read TxType: %w", err) } if len(b) != 1 { - return fmt.Errorf("only 1-byte tx type prefix is supported, got %d bytes: %w", len(b), errEmptyTypedReceipt) + return fmt.Errorf("%w, got %d bytes", rlp.ErrWrongTxTypePrefix, len(b)) } r.Type = b[0] switch r.Type { diff --git a/core/types/transaction.go b/core/types/transaction.go index 75808a6247d..4dfc74f262c 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -122,7 +122,7 @@ func DecodeTransaction(s *rlp.Stream) (Transaction, error) { return nil, err } if len(b) != 1 { - return nil, fmt.Errorf("only 1-byte tx type prefix is supported, got %d bytes", len(b)) + return nil, fmt.Errorf("%w, got %d bytes", rlp.ErrWrongTxTypePrefix, len(b)) } var tx Transaction switch b[0] { @@ -139,7 +139,7 @@ func DecodeTransaction(s *rlp.Stream) (Transaction, error) { } tx = t default: - return nil, fmt.Errorf("unknown tx type prefix: %d", b[0]) + return nil, fmt.Errorf("%w, got: %d", rlp.ErrUnknownTxTypePrefix, b[0]) } if kind == rlp.String { if err = s.ListEnd(); err != nil { diff --git a/docker-compose.yml b/docker-compose.yml index e224d238a7d..d7d1cb389d8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,7 +16,7 @@ services: restart: unless-stopped prometheus: - image: prom/prometheus:v2.29.1 + image: prom/prometheus:v2.30.2 user: 1000:1000 # Uses erigon user from Dockerfile command: --log.level=warn --config.file=/etc/prometheus/prometheus.yml --storage.tsdb.path=/prometheus --web.console.libraries=/usr/share/prometheus/console_libraries --web.console.templates=/usr/share/prometheus/consoles ports: @@ -27,7 +27,7 @@ services: restart: unless-stopped grafana: - image: grafana/grafana:8.1.5 + image: grafana/grafana:8.1.6 user: 1000:1000 # Uses erigon user from Dockerfile ports: - "3000:3000" @@ -40,7 +40,7 @@ services: rpcdaemon: image: thorax/erigon:latest - command: rpcdaemon --datadir=/home/erigon/.local/share/erigon --private.api.addr=erigon:9090 --http.addr=0.0.0.0 --http.vhosts=* --http.corsdomain=* --http.api=eth,debug,net + command: rpcdaemon --datadir=/home/erigon/.local/share/erigon --private.api.addr=erigon:9090 --http.addr=0.0.0.0 --http.vhosts=* --http.corsdomain=* --http.api=eth,debug,net --ws pid: service:erigon # Use erigon's PID namespace. It's required to open Erigon's DB from another process (RPCDaemon local-mode) volumes: - ${XDG_DATA_HOME:-~/.local/share}/erigon:/home/erigon/.local/share/erigon diff --git a/eth/api_backend.go b/eth/api_backend.go index 9ee6f233a29..d1c055c8de3 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -191,7 +191,7 @@ func (b *EthAPIBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*typ } receipts, err := b.GetReceipts(ctx, hash) if err != nil { - return nil, fmt.Errorf("getReceipt error: %v", err) + return nil, fmt.Errorf("getReceipt error: %w", err) } if receipts == nil { return nil, nil diff --git a/eth/backend.go b/eth/backend.go index bfb5011bec1..bde8a588b7b 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -369,6 +369,8 @@ func New(stack *node.Node, config *ethconfig.Config, logger log.Logger) (*Ethere cfg.PendingSubPoolLimit = int(config.TxPool.GlobalSlots) cfg.BaseFeeSubPoolLimit = int(config.TxPool.GlobalBaseFeeQueue) cfg.QueuedSubPoolLimit = int(config.TxPool.GlobalQueue) + cfg.MinFeeCap = config.TxPool.PriceLimit + cfg.AccountSlots = config.TxPool.AccountSlots cfg.LogEvery = 1 * time.Minute //5 * time.Minute cfg.CommitEvery = 1 * time.Minute //5 * time.Minute @@ -510,8 +512,10 @@ func New(stack *node.Node, config *ethconfig.Config, logger log.Logger) (*Ethere return nil, err } } else { - if err := backend.txPool.Start(hh.GasLimit, execution); err != nil { - return nil, err + if hh != nil { + if err := backend.txPool.Start(hh.GasLimit, execution); err != nil { + return nil, err + } } } } @@ -661,12 +665,12 @@ func (s *Ethereum) StartMining(ctx context.Context, db kv.RwDB, mining *stagedsy eb, err := s.Etherbase() if err != nil { log.Error("Cannot start mining without etherbase", "err", err) - return fmt.Errorf("etherbase missing: %v", err) + return fmt.Errorf("etherbase missing: %w", err) } if clique, ok := s.engine.(*clique.Clique); ok { if cfg.SigKey == nil { log.Error("Etherbase account unavailable locally", "err", err) - return fmt.Errorf("signer missing: %v", err) + return fmt.Errorf("signer missing: %w", err) } clique.Authorize(eb, func(_ common.Address, mimeType string, message []byte) ([]byte, error) { diff --git a/eth/fetcher/block_fetcher.go b/eth/fetcher/block_fetcher.go index 3388009dd38..ee2a4f4d52a 100644 --- a/eth/fetcher/block_fetcher.go +++ b/eth/fetcher/block_fetcher.go @@ -381,14 +381,14 @@ func (f *BlockFetcher) loop() { count := f.announces[notification.origin] + 1 if count > hashLimit { - log.Debug("Peer exceeded outstanding announces", "peer", notification.origin, "limit", hashLimit) + log.Trace("Peer exceeded outstanding announces", "peer", notification.origin, "limit", hashLimit) //blockAnnounceDOSMeter.Mark(1) break } // If we have a valid block number, check that it's potentially useful if notification.number > 0 { if dist := int64(notification.number) - int64(f.chainHeight()); dist < -maxUncleDist || dist > maxQueueDist { - log.Debug("Peer discarded announcement", "peer", notification.origin, "number", notification.number, "hash", notification.hash, "distance", dist) + log.Trace("Peer discarded announcement", "peer", notification.origin, "number", notification.number, "hash", notification.hash, "distance", dist) //blockAnnounceDropMeter.Mark(1) break } @@ -689,14 +689,14 @@ func (f *BlockFetcher) enqueue(peer string, header *types.Header, block *types.B // Ensure the peer isn't DOSing us count := f.queues[peer] + 1 if count > blockLimit { - log.Debug("Discarded delivered header or block, exceeded allowance", "peer", peer, "number", number, "hash", hash, "limit", blockLimit) + log.Trace("Discarded delivered header or block, exceeded allowance", "peer", peer, "number", number, "hash", hash, "limit", blockLimit) //blockBroadcastDOSMeter.Mark(1) f.forgetHash(hash) return } // Discard any past or too distant blocks if dist := int64(number) - int64(f.chainHeight()); dist < -maxUncleDist || dist > maxQueueDist { - log.Debug("Discarded delivered header or block, too far away", "peer", peer, "number", number, "hash", hash, "distance", dist) + log.Trace("Discarded delivered header or block, too far away", "peer", peer, "number", number, "hash", hash, "distance", dist) //blockBroadcastDropMeter.Mark(1) f.forgetHash(hash) return @@ -715,7 +715,7 @@ func (f *BlockFetcher) enqueue(peer string, header *types.Header, block *types.B if f.queueChangeHook != nil { f.queueChangeHook(hash, true) } - log.Debug("Queued delivered header or block", "peer", peer, "number", number, "hash", hash, "queued", f.queue.Size()) + log.Trace("Queued delivered header or block", "peer", peer, "number", number, "hash", hash, "queued", f.queue.Size()) } } @@ -726,7 +726,7 @@ func (f *BlockFetcher) importBlocks(peer string, block *types.Block) { hash := block.Hash() // Run the import on a new thread - log.Debug("Importing propagated block", "peer", peer, "number", block.Number(), "hash", hash) + log.Trace("Importing propagated block", "peer", peer, "number", block.Number(), "hash", hash) defer func() { f.forgetHash(hash) f.forgetBlock(hash) @@ -735,7 +735,7 @@ func (f *BlockFetcher) importBlocks(peer string, block *types.Block) { // If the parent's unknown, abort insertion parent := f.getBlock(block.ParentHash()) if parent == nil { - log.Debug("Unknown parent of propagated block", "peer", peer, "number", block.Number(), "hash", hash, "parent", block.ParentHash()) + log.Trace("Unknown parent of propagated block", "peer", peer, "number", block.Number(), "hash", hash, "parent", block.ParentHash()) return } // Quickly validate the header and propagate the block if it passes @@ -750,13 +750,13 @@ func (f *BlockFetcher) importBlocks(peer string, block *types.Block) { default: // Something went very wrong, drop the peer - log.Debug("Propagated block verification failed", "peer", peer, "number", block.Number(), "hash", hash, "err", err) + log.Trace("Propagated block verification failed", "peer", peer, "number", block.Number(), "hash", hash, "err", err) f.dropPeer(peer) return } // Run the actual import and log any issues if _, err := f.insertChain(types.Blocks{block}); err != nil { - log.Debug("Propagated block import failed", "peer", peer, "number", block.Number(), "hash", hash, "err", err) + log.Trace("Propagated block import failed", "peer", peer, "number", block.Number(), "hash", hash, "err", err) return } // If import succeeded, broadcast the block diff --git a/eth/filters/api.go b/eth/filters/api.go index aa5d851dbc0..81325f650e9 100644 --- a/eth/filters/api.go +++ b/eth/filters/api.go @@ -504,7 +504,7 @@ func (args *FilterCriteria) UnmarshalJSON(data []byte) error { if strAddr, ok := addr.(string); ok { addr, err := decodeAddress(strAddr) if err != nil { - return fmt.Errorf("invalid address at index %d: %v", i, err) + return fmt.Errorf("invalid address at index %d: %w", i, err) } args.Addresses = append(args.Addresses, addr) } else { @@ -514,7 +514,7 @@ func (args *FilterCriteria) UnmarshalJSON(data []byte) error { case string: addr, err := decodeAddress(rawAddr) if err != nil { - return fmt.Errorf("invalid address: %v", err) + return fmt.Errorf("invalid address: %w", err) } args.Addresses = []common.Address{addr} default: diff --git a/eth/protocols/eth/peer.go b/eth/protocols/eth/peer.go index e8c986fa653..9d77725af11 100644 --- a/eth/protocols/eth/peer.go +++ b/eth/protocols/eth/peer.go @@ -213,7 +213,7 @@ func (p *Peer) AsyncSendTransactions(hashes []common.Hash) { p.knownTxs.Add(hash) } case <-p.term: - p.Log().Debug("Dropping transaction propagation", "count", len(hashes)) + p.Log().Trace("Dropping transaction propagation", "count", len(hashes)) } } @@ -248,7 +248,7 @@ func (p *Peer) AsyncSendPooledTransactionHashes(hashes []common.Hash) { p.knownTxs.Add(hash) } case <-p.term: - p.Log().Debug("Dropping transaction announcement", "count", len(hashes)) + p.Log().Trace("Dropping transaction announcement", "count", len(hashes)) } } @@ -314,7 +314,7 @@ func (p *Peer) AsyncSendNewBlockHash(block *types.Block) { } p.knownBlocks.Add(block.Hash()) default: - p.Log().Debug("Dropping block announcement", "number", block.NumberU64(), "hash", block.Hash()) + p.Log().Trace("Dropping block announcement", "number", block.NumberU64(), "hash", block.Hash()) } } @@ -342,7 +342,7 @@ func (p *Peer) AsyncSendNewBlock(block *types.Block, td *big.Int) { } p.knownBlocks.Add(block.Hash()) default: - p.Log().Debug("Dropping block propagation", "number", block.NumberU64(), "hash", block.Hash()) + p.Log().Trace("Dropping block propagation", "number", block.NumberU64(), "hash", block.Hash()) } } @@ -405,7 +405,7 @@ func (p *Peer) ReplyReceiptsRLP(id uint64, receipts []rlp.RawValue) error { // RequestOneHeader is a wrapper around the header query functions to fetch a // single header. It is used solely by the fetcher. func (p *Peer) RequestOneHeader(hash common.Hash) error { - p.Log().Debug("Fetching single header", "hash", hash) + p.Log().Trace("Fetching single header", "hash", hash) query := GetBlockHeadersPacket{ Origin: HashOrNumber{Hash: hash}, Amount: uint64(1), @@ -424,7 +424,7 @@ func (p *Peer) RequestOneHeader(hash common.Hash) error { // RequestHeadersByHash fetches a batch of blocks' headers corresponding to the // specified header query, based on the hash of an origin block. func (p *Peer) RequestHeadersByHash(origin common.Hash, amount int, skip int, reverse bool) error { - p.Log().Debug("Fetching batch of headers", "count", amount, "fromhash", origin, "skip", skip, "reverse", reverse) + p.Log().Trace("Fetching batch of headers", "count", amount, "fromhash", origin, "skip", skip, "reverse", reverse) query := GetBlockHeadersPacket{ Origin: HashOrNumber{Hash: origin}, Amount: uint64(amount), @@ -443,7 +443,7 @@ func (p *Peer) RequestHeadersByHash(origin common.Hash, amount int, skip int, re // RequestHeadersByNumber fetches a batch of blocks' headers corresponding to the // specified header query, based on the number of an origin block. func (p *Peer) RequestHeadersByNumber(origin uint64, amount int, skip int, reverse bool) error { - p.Log().Debug("Fetching batch of headers", "count", amount, "fromnum", origin, "skip", skip, "reverse", reverse) + p.Log().Trace("Fetching batch of headers", "count", amount, "fromnum", origin, "skip", skip, "reverse", reverse) query := GetBlockHeadersPacket{ Origin: HashOrNumber{Number: origin}, Amount: uint64(amount), @@ -474,7 +474,7 @@ func (p *Peer) ExpectRequestHeadersByNumber(origin uint64, amount int, skip int, // RequestBodies fetches a batch of blocks' bodies corresponding to the hashes // specified. func (p *Peer) RequestBodies(hashes []common.Hash) error { - p.Log().Debug("Fetching batch of block bodies", "count", len(hashes)) + p.Log().Trace("Fetching batch of block bodies", "count", len(hashes)) if p.Version() >= ETH66 { return p2p.Send(p.rw, GetBlockBodiesMsg, &GetBlockBodiesPacket66{ RequestId: rand.Uint64(), //nolint:gosec @@ -487,7 +487,7 @@ func (p *Peer) RequestBodies(hashes []common.Hash) error { // RequestNodeData fetches a batch of arbitrary data from a node's known state // data, corresponding to the specified hashes. func (p *Peer) RequestNodeData(hashes []common.Hash) error { - p.Log().Debug("Fetching batch of state data", "count", len(hashes)) + p.Log().Trace("Fetching batch of state data", "count", len(hashes)) if p.Version() >= ETH66 { return p2p.Send(p.rw, GetNodeDataMsg, &GetNodeDataPacket66{ RequestId: rand.Uint64(), //nolint:gosec @@ -499,7 +499,7 @@ func (p *Peer) RequestNodeData(hashes []common.Hash) error { // RequestReceipts fetches a batch of transaction receipts from a remote node. func (p *Peer) RequestReceipts(hashes []common.Hash) error { - p.Log().Debug("Fetching batch of receipts", "count", len(hashes)) + p.Log().Trace("Fetching batch of receipts", "count", len(hashes)) if p.Version() >= ETH66 { return p2p.Send(p.rw, GetReceiptsMsg, &GetReceiptsPacket66{ RequestId: rand.Uint64(), //nolint:gosec @@ -511,7 +511,7 @@ func (p *Peer) RequestReceipts(hashes []common.Hash) error { // RequestTxs fetches a batch of transactions from a remote node. func (p *Peer) RequestTxs(hashes []common.Hash) error { - p.Log().Debug("Fetching batch of transactions", "count", len(hashes)) + p.Log().Trace("Fetching batch of transactions", "count", len(hashes)) if p.Version() >= ETH66 { return p2p.Send(p.rw, GetPooledTransactionsMsg, &GetPooledTransactionsPacket66{ RequestId: rand.Uint64(), //nolint:gosec diff --git a/eth/stagedsync/stage_bodies.go b/eth/stagedsync/stage_bodies.go index 6002d1bc711..b2fdc1cfdf0 100644 --- a/eth/stagedsync/stage_bodies.go +++ b/eth/stagedsync/stage_bodies.go @@ -200,7 +200,7 @@ Loop: case <-timer.C: log.Trace("RequestQueueTime (bodies) ticked") case <-cfg.bd.DeliveryNotify: - log.Debug("bodyLoop woken up by the incoming request") + log.Trace("bodyLoop woken up by the incoming request") } d6 += time.Since(start) } diff --git a/eth/stagedsync/stage_finish.go b/eth/stagedsync/stage_finish.go index 39560402703..61aaaa59e04 100644 --- a/eth/stagedsync/stage_finish.go +++ b/eth/stagedsync/stage_finish.go @@ -1,14 +1,18 @@ package stagedsync import ( + "bytes" "context" - "fmt" + "encoding/binary" + "reflect" "github.com/ledgerwatch/erigon/params" + "github.com/ledgerwatch/erigon/rlp" + libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon/core/rawdb" - "github.com/ledgerwatch/erigon/eth/stagedsync/stages" + "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/turbo/snapshotsync" "github.com/ledgerwatch/log/v3" ) @@ -124,29 +128,46 @@ func PruneFinish(u *PruneState, tx kv.RwTx, cfg FinishCfg, ctx context.Context) return nil } -func NotifyNewHeaders(ctx context.Context, finishStageBeforeSync uint64, unwindTo *uint64, notifier ChainEventNotifier, tx kv.Tx) error { - notifyTo, err := stages.GetStageProgress(tx, stages.Finish) // because later stages can be disabled - if err != nil { - return err - } - notifyFrom := finishStageBeforeSync - if unwindTo != nil && *unwindTo != 0 && (*unwindTo) < finishStageBeforeSync { - notifyFrom = *unwindTo + 1 - } +func NotifyNewHeaders(ctx context.Context, finishStageBeforeSync uint64, finishStageAfterSync uint64, unwindTo *uint64, notifier ChainEventNotifier, tx kv.Tx) error { + if notifier == nil { - log.Warn("rpc notifier is not set, rpc daemon won't be updated about headers") + log.Trace("RPC Daemon notification channel not set. No headers notifications will be sent") return nil } - for i := notifyFrom; i <= notifyTo; i++ { - header := rawdb.ReadHeaderByNumber(tx, i) - if header == nil { - return fmt.Errorf("could not find canonical header for number: %d", i) + // Notify all headers we have (either canonical or not) in a maximum range span of 1024 + var notifyFrom uint64 + if unwindTo != nil && *unwindTo != 0 && (*unwindTo) < finishStageBeforeSync { + notifyFrom = *unwindTo + } else { + heightSpan := finishStageAfterSync - finishStageBeforeSync + if heightSpan > 1024 { + heightSpan = 1024 } - notifier.OnNewHeader(header) + notifyFrom = finishStageAfterSync - heightSpan } - log.Info("Updated current block for the RPC API", "from", notifyFrom, "to", notifyTo) + startKey := make([]byte, reflect.TypeOf(notifyFrom).Size()+32) + var notifyTo uint64 + binary.BigEndian.PutUint64(startKey, notifyFrom) + if err := tx.ForEach(kv.Headers, startKey, func(k, headerRLP []byte) error { + if len(headerRLP) == 0 { + return nil + } + header := new(types.Header) + if err := rlp.Decode(bytes.NewReader(headerRLP), header); err != nil { + log.Error("Invalid block header RLP", "err", err) + return err + } + notifyTo = header.Number.Uint64() + notifier.OnNewHeader(header) + return libcommon.Stopped(ctx.Done()) + }); err != nil { + log.Error("RPC Daemon notification failed", "error", err) + return err + } + log.Info("RPC Daemon notified of new headers", "from", notifyFrom, "to", notifyTo) return nil + } diff --git a/eth/stagedsync/stage_hashstate.go b/eth/stagedsync/stage_hashstate.go index 5d6d3621851..b0f221ee328 100644 --- a/eth/stagedsync/stage_hashstate.go +++ b/eth/stagedsync/stage_hashstate.go @@ -304,18 +304,19 @@ func getExtractCode(db kv.Tx, changeSetBucket string) etl.ExtractFunc { if len(value) == 0 { return nil } - var a accounts.Account - if err = a.DecodeForStorage(value); err != nil { + + incarnation, err := accounts.DecodeIncarnationFromStorage(value) + if err != nil { return err } - if a.Incarnation == 0 { + if incarnation == 0 { return nil } - plainKey := dbutils.PlainGenerateStoragePrefix(k, a.Incarnation) + plainKey := dbutils.PlainGenerateStoragePrefix(k, incarnation) var codeHash []byte codeHash, err = db.GetOne(kv.PlainContractCode, plainKey) if err != nil { - return fmt.Errorf("getFromPlainCodesAndLoad for %x, inc %d: %w", plainKey, a.Incarnation, err) + return fmt.Errorf("getFromPlainCodesAndLoad for %x, inc %d: %w", plainKey, incarnation, err) } if codeHash == nil { return nil @@ -379,18 +380,18 @@ func getCodeUnwindExtractFunc(db kv.Tx, changeSetBucket string) etl.ExtractFunc return nil } var ( - a accounts.Account newK []byte codeHash []byte err error ) - if err = a.DecodeForStorage(v); err != nil { + incarnation, err := accounts.DecodeIncarnationFromStorage(v) + if err != nil { return err } - if a.Incarnation == 0 { + if incarnation == 0 { return nil } - plainKey := dbutils.PlainGenerateStoragePrefix(k, a.Incarnation) + plainKey := dbutils.PlainGenerateStoragePrefix(k, incarnation) codeHash, err = db.GetOne(kv.PlainContractCode, plainKey) if err != nil { return fmt.Errorf("getCodeUnwindExtractFunc: %w, key=%x", err, plainKey) diff --git a/eth/stagedsync/stage_headers.go b/eth/stagedsync/stage_headers.go index fb6069dadfb..08699082578 100644 --- a/eth/stagedsync/stage_headers.go +++ b/eth/stagedsync/stage_headers.go @@ -128,7 +128,7 @@ Loop: peer = cfg.headerReqSend(ctx, req) if peer != nil { cfg.hd.SentRequest(req, currentTime, 5 /* timeout */) - log.Debug("Sent request", "height", req.Number) + log.Trace("Sent request", "height", req.Number) } } cfg.penalize(ctx, penalties) @@ -139,7 +139,7 @@ Loop: peer = cfg.headerReqSend(ctx, req) if peer != nil { cfg.hd.SentRequest(req, currentTime, 5 /*timeout */) - log.Debug("Sent request", "height", req.Number) + log.Trace("Sent request", "height", req.Number) } } cfg.penalize(ctx, penalties) @@ -151,7 +151,7 @@ Loop: if req != nil { peer = cfg.headerReqSend(ctx, req) if peer != nil { - log.Debug("Sent skeleton request", "height", req.Number) + log.Trace("Sent skeleton request", "height", req.Number) } } // Load headers into the database @@ -195,7 +195,7 @@ Loop: case <-timer.C: log.Trace("RequestQueueTime (header) ticked") case <-cfg.hd.DeliveryNotify: - log.Debug("headerLoop woken up by the incoming request") + log.Trace("headerLoop woken up by the incoming request") case <-cfg.hd.SkipCycleHack: break Loop } @@ -216,7 +216,7 @@ Loop: if stopped { return libcommon.ErrStopped } - // We do not print the followin line if the stage was interrupted + // We do not print the following line if the stage was interrupted log.Info(fmt.Sprintf("[%s] Processed", logPrefix), "highest inserted", headerInserter.GetHighest(), "age", common.PrettyAge(time.Unix(int64(headerInserter.GetHighestTimestamp()), 0))) return nil } diff --git a/eth/stagedsync/stage_indexes.go b/eth/stagedsync/stage_indexes.go index 2d600d3bf87..78d75163910 100644 --- a/eth/stagedsync/stage_indexes.go +++ b/eth/stagedsync/stage_indexes.go @@ -313,9 +313,9 @@ func unwindHistory(logPrefix string, db kv.RwTx, csBucket string, to uint64, cfg func needFlush64(bitmaps map[string]*roaring64.Bitmap, memLimit datasize.ByteSize) bool { sz := uint64(0) for _, m := range bitmaps { - sz += m.GetSizeInBytes() + sz += m.GetSizeInBytes() * 2 // for golang's overhead } - const memoryNeedsForKey = 32 * 2 // each key stored in RAM: as string ang slice of bytes + const memoryNeedsForKey = 32 * 2 * 2 // len(key) * (string and bytes) overhead * go's map overhead return uint64(len(bitmaps)*memoryNeedsForKey)+sz > uint64(memLimit) } diff --git a/eth/stagedsync/stage_interhashes.go b/eth/stagedsync/stage_interhashes.go index e1200485ed9..81f44946633 100644 --- a/eth/stagedsync/stage_interhashes.go +++ b/eth/stagedsync/stage_interhashes.go @@ -77,7 +77,8 @@ func SpawnIntermediateHashesStage(s *StageState, u Unwinder, tx kv.RwTx, cfg Tri log.Info(fmt.Sprintf("[%s] Generating intermediate hashes", logPrefix), "from", s.BlockNumber, "to", to) } var root common.Hash - if s.BlockNumber == 0 { + tooBigJump := to > s.BlockNumber && to-s.BlockNumber > 100_000 // RetainList is in-memory structure and it will OOM if jump is too big, such big jump anyway invalidate most of existing Intermediate hashes + if s.BlockNumber == 0 || tooBigJump { if root, err = RegenerateIntermediateHashes(logPrefix, tx, cfg, expectedRootHash, quit); err != nil { return trie.EmptyRoot, err } @@ -171,7 +172,7 @@ func (p *HashPromoter) Promote(logPrefix string, s *StageState, from, to uint64, } else { changeSetBucket = kv.AccountChangeSet } - log.Debug(fmt.Sprintf("[%s] Incremental state promotion of intermediate hashes", logPrefix), "from", from, "to", to, "csbucket", changeSetBucket) + log.Trace(fmt.Sprintf("[%s] Incremental state promotion of intermediate hashes", logPrefix), "from", from, "to", to, "csbucket", changeSetBucket) startkey := dbutils.EncodeBlockNumber(from + 1) diff --git a/eth/stagedsync/stage_log_index.go b/eth/stagedsync/stage_log_index.go index ed368bf10ae..caa9b9628b8 100644 --- a/eth/stagedsync/stage_log_index.go +++ b/eth/stagedsync/stage_log_index.go @@ -294,9 +294,9 @@ func unwindLogIndex(logPrefix string, db kv.RwTx, to uint64, cfg LogIndexCfg, qu func needFlush(bitmaps map[string]*roaring.Bitmap, memLimit datasize.ByteSize) bool { sz := uint64(0) for _, m := range bitmaps { - sz += m.GetSizeInBytes() + sz += m.GetSizeInBytes() * 2 // for golang's overhead } - const memoryNeedsForKey = 32 * 2 // each key stored in RAM: as string ang slice of bytes + const memoryNeedsForKey = 32 * 2 * 2 // len(key) * (string and bytes) overhead * go's map overhead return uint64(len(bitmaps)*memoryNeedsForKey)+sz > uint64(memLimit) } diff --git a/eth/stagedsync/stage_mining_create_block.go b/eth/stagedsync/stage_mining_create_block.go index 76c9555d7ed..0588ff8b762 100644 --- a/eth/stagedsync/stage_mining_create_block.go +++ b/eth/stagedsync/stage_mining_create_block.go @@ -14,6 +14,7 @@ import ( "github.com/ledgerwatch/erigon/common" "github.com/ledgerwatch/erigon/common/debug" "github.com/ledgerwatch/erigon/consensus" + "github.com/ledgerwatch/erigon/consensus/misc" "github.com/ledgerwatch/erigon/core" "github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/core/types" @@ -210,11 +211,19 @@ func SpawnMiningCreateBlockStage(s *StageState, tx kv.RwTx, cfg MiningCreateBloc header := &types.Header{ ParentHash: parent.Hash(), Number: num.Add(num, common.Big1), - GasLimit: core.CalcGasLimit(parent.GasUsed, parent.GasLimit, cfg.miner.MiningConfig.GasFloor, cfg.miner.MiningConfig.GasCeil), Extra: cfg.miner.MiningConfig.ExtraData, Time: uint64(timestamp), } + // Set baseFee and GasLimit if we are on an EIP-1559 chain + if cfg.chainConfig.IsLondon(header.Number.Uint64()) { + header.BaseFee = misc.CalcBaseFee(&cfg.chainConfig, parent) + if !cfg.chainConfig.IsLondon(parent.Number.Uint64()) { + parentGasLimit := parent.GasLimit * params.ElasticityMultiplier + header.GasLimit = core.CalcGasLimit(parent.GasUsed, parentGasLimit, cfg.miner.MiningConfig.GasFloor, cfg.miner.MiningConfig.GasCeil) + } + } + // Only set the coinbase if our consensus engine is running (avoid spurious block rewards) //if w.isRunning() { header.Coinbase = coinbase @@ -310,7 +319,7 @@ func SpawnMiningCreateBlockStage(s *StageState, tx kv.RwTx, cfg MiningCreateBloc if err = commitUncle(env, uncle); err != nil { log.Trace("Possible uncle rejected", "hash", hash, "reason", err) } else { - log.Debug("Committing new uncle to block", "hash", hash) + log.Trace("Committing new uncle to block", "hash", hash) uncles = append(uncles, uncle) } } diff --git a/eth/stagedsync/stage_mining_exec.go b/eth/stagedsync/stage_mining_exec.go index 1061932c620..7566c7afdd7 100644 --- a/eth/stagedsync/stage_mining_exec.go +++ b/eth/stagedsync/stage_mining_exec.go @@ -251,7 +251,7 @@ func addTransactionsToMiningBlock(current *MiningBlock, chainConfig params.Chain default: // Strange error, discard the transaction and get the next in line (note, the // nonce-too-high clause will prevent us from executing in vain). - log.Debug("Transaction failed, account skipped", "hash", txn.Hash(), "err", err) + log.Trace("Transaction failed, account skipped", "hash", txn.Hash(), "err", err) txs.Shift() } } diff --git a/eth/stagedsync/stage_senders.go b/eth/stagedsync/stage_senders.go index 8786a04f2fc..6c71c6030a0 100644 --- a/eth/stagedsync/stage_senders.go +++ b/eth/stagedsync/stage_senders.go @@ -115,7 +115,7 @@ func SpawnRecoverSendersStage(cfg SendersCfg, s *StageState, u Unwinder, tx kv.R log.Info(fmt.Sprintf("[%s] Preload headers", logPrefix), "block_number", binary.BigEndian.Uint64(k)) } } - log.Debug(fmt.Sprintf("[%s] Read canonical hashes", logPrefix), "amount", len(canonical)) + log.Trace(fmt.Sprintf("[%s] Read canonical hashes", logPrefix), "amount", len(canonical)) jobs := make(chan *senderRecoveryJob, cfg.batchSize) out := make(chan *senderRecoveryJob, cfg.batchSize) diff --git a/eth/stagedsync/stage_txpool.go b/eth/stagedsync/stage_txpool.go index 74803f0e8d0..0c55b7a4117 100644 --- a/eth/stagedsync/stage_txpool.go +++ b/eth/stagedsync/stage_txpool.go @@ -118,7 +118,7 @@ func incrementalTxPoolUpdate(logPrefix string, from, to uint64, pool *core.TxPoo currentHeaderIdx++ } - log.Debug(fmt.Sprintf("[%s] Read canonical hashes", logPrefix), "hashes", len(canonical)) + log.Trace(fmt.Sprintf("[%s] Read canonical hashes", logPrefix), "hashes", len(canonical)) bodies, err := tx.Cursor(kv.BlockBody) if err != nil { return err @@ -213,7 +213,7 @@ func unwindTxPoolUpdate(logPrefix string, from, to uint64, pool *core.TxPool, tx copy(canonical[blockNumber-from-1][:], v) } - log.Debug(fmt.Sprintf("[%s] Read canonical hashes", logPrefix), "hashes", len(canonical)) + log.Trace(fmt.Sprintf("[%s] Read canonical hashes", logPrefix), "hashes", len(canonical)) senders := make([][]common.Address, to-from+1) sendersC, err := tx.Cursor(kv.Senders) if err != nil { diff --git a/eth/stagedsync/sync.go b/eth/stagedsync/sync.go index ad4c188aada..cc6705ace1c 100644 --- a/eth/stagedsync/sync.go +++ b/eth/stagedsync/sync.go @@ -219,12 +219,12 @@ func (s *Sync) Run(db kv.RwDB, tx kv.RwTx, firstCycle bool) error { stage := s.stages[s.currentStage] if string(stage.ID) == debug.StopBeforeStage() { // stop process for debugging reasons - log.Error("STOP_BEFORE_STAGE env flag forced to stop app") + log.Warn("STOP_BEFORE_STAGE env flag forced to stop app") os.Exit(1) } if stage.Disabled || stage.Forward == nil { - log.Debug(fmt.Sprintf("%s disabled. %s", stage.ID, stage.DisabledDescription)) + log.Trace(fmt.Sprintf("%s disabled. %s", stage.ID, stage.DisabledDescription)) s.NextStage() continue @@ -327,7 +327,7 @@ func (s *Sync) runStage(stage *Stage, db kv.RwDB, tx kv.RwTx, firstCycle bool, b func (s *Sync) unwindStage(firstCycle bool, stage *Stage, db kv.RwDB, tx kv.RwTx) error { t := time.Now() - log.Debug("Unwind...", "stage", stage.ID) + log.Trace("Unwind...", "stage", stage.ID) stageState, err := s.StageState(stage.ID, tx, db) if err != nil { return err @@ -360,7 +360,7 @@ func (s *Sync) unwindStage(firstCycle bool, stage *Stage, db kv.RwDB, tx kv.RwTx func (s *Sync) pruneStage(firstCycle bool, stage *Stage, db kv.RwDB, tx kv.RwTx) error { t := time.Now() - log.Debug("Prune...", "stage", stage.ID) + log.Trace("Prune...", "stage", stage.ID) stageState, err := s.StageState(stage.ID, tx, db) if err != nil { diff --git a/eth/tracers/internal/tracers/assets.go b/eth/tracers/internal/tracers/assets.go index 7f45ab286e7..fa4e2df9433 100644 --- a/eth/tracers/internal/tracers/assets.go +++ b/eth/tracers/internal/tracers/assets.go @@ -265,7 +265,7 @@ func Asset(name string) ([]byte, error) { if f, ok := _bindata[canonicalName]; ok { a, err := f() if err != nil { - return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) + return nil, fmt.Errorf("Asset %s can't read by error: %w", name, err) } return a.bytes, nil } @@ -303,7 +303,7 @@ func AssetInfo(name string) (os.FileInfo, error) { if f, ok := _bindata[canonicalName]; ok { a, err := f() if err != nil { - return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) + return nil, fmt.Errorf("AssetInfo %s can't read by error: %w", name, err) } return a.info, nil } @@ -317,7 +317,7 @@ func AssetDigest(name string) ([sha256.Size]byte, error) { if f, ok := _bindata[canonicalName]; ok { a, err := f() if err != nil { - return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err) + return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %w", name, err) } return a.digest, nil } diff --git a/ethdb/privateapi/ethbackend.go b/ethdb/privateapi/ethbackend.go index fab2878ce53..c9967323fa9 100644 --- a/ethdb/privateapi/ethbackend.go +++ b/ethdb/privateapi/ethbackend.go @@ -71,7 +71,7 @@ func (s *EthBackendServer) NetPeerCount(_ context.Context, _ *remote.NetPeerCoun } func (s *EthBackendServer) Subscribe(r *remote.SubscribeRequest, subscribeServer remote.ETHBACKEND_SubscribeServer) error { - log.Debug("establishing event subscription channel with the RPC daemon") + log.Trace("Establishing event subscription channel with the RPC daemon ...") s.events.AddHeaderSubscription(func(h *types.Header) error { select { case <-s.ctx.Done(): diff --git a/ethdb/privateapi/mining.go b/ethdb/privateapi/mining.go index a0f34875393..ed480e17b05 100644 --- a/ethdb/privateapi/mining.go +++ b/ethdb/privateapi/mining.go @@ -166,7 +166,7 @@ func (s *MinedBlockStreams) Broadcast(reply *proto_txpool.OnMinedBlockReply) { for id, stream := range s.chans { err := stream.Send(reply) if err != nil { - log.Debug("failed send to mined block stream", "err", err) + log.Trace("failed send to mined block stream", "err", err) select { case <-stream.Context().Done(): delete(s.chans, id) @@ -211,7 +211,7 @@ func (s *PendingBlockStreams) Broadcast(reply *proto_txpool.OnPendingBlockReply) for id, stream := range s.chans { err := stream.Send(reply) if err != nil { - log.Debug("failed send to mined block stream", "err", err) + log.Trace("failed send to mined block stream", "err", err) select { case <-stream.Context().Done(): delete(s.chans, id) @@ -256,7 +256,7 @@ func (s *PendingLogsStreams) Broadcast(reply *proto_txpool.OnPendingLogsReply) { for id, stream := range s.chans { err := stream.Send(reply) if err != nil { - log.Debug("failed send to mined block stream", "err", err) + log.Trace("failed send to mined block stream", "err", err) select { case <-stream.Context().Done(): delete(s.chans, id) diff --git a/go.mod b/go.mod index 4c9e97172a9..4c2c24f0190 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,8 @@ module github.com/ledgerwatch/erigon go 1.16 require ( - github.com/BobuSumisu/aho-corasick v1.0.3 github.com/RoaringBitmap/roaring v0.9.4 - github.com/VictoriaMetrics/fastcache v1.6.0 + github.com/VictoriaMetrics/fastcache v1.7.0 github.com/VictoriaMetrics/metrics v1.18.0 github.com/anacrolix/log v0.8.0 github.com/anacrolix/torrent v1.25.1 @@ -14,7 +13,7 @@ require ( github.com/consensys/gnark-crypto v0.4.0 github.com/davecgh/go-spew v1.1.1 github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea - github.com/dlclark/regexp2 v1.2.0 // indirect + github.com/dlclark/regexp2 v1.4.0 // indirect github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498 github.com/edsrzf/mmap-go v1.0.0 @@ -25,7 +24,6 @@ require ( github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect github.com/goccy/go-json v0.7.4 github.com/gofrs/flock v0.8.1 - github.com/golang/protobuf v1.5.2 github.com/golang/snappy v0.0.4 github.com/google/btree v1.0.1 github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa @@ -35,14 +33,14 @@ require ( github.com/holiman/uint256 v1.2.0 github.com/huin/goupnp v1.0.1-0.20210626160114-33cdcbb30dda github.com/jackpal/go-nat-pmp v1.0.2 - github.com/json-iterator/go v1.1.11 + github.com/json-iterator/go v1.1.12 github.com/julienschmidt/httprouter v1.3.0 github.com/kevinburke/go-bindata v3.21.0+incompatible - github.com/ledgerwatch/erigon-lib v0.0.0-20210930024651-a59261cb3242 + github.com/ledgerwatch/erigon-lib v0.0.0-20211006142856-240f7f121273 github.com/ledgerwatch/log/v3 v3.3.1 github.com/ledgerwatch/secp256k1 v0.0.0-20210626115225-cd5cd00ed72d github.com/logrusorgru/aurora/v3 v3.0.0 - github.com/pelletier/go-toml v1.9.3 + github.com/pelletier/go-toml v1.9.4 github.com/petar/GoLLRB v0.0.0-20190514000832-33fb24c13b99 github.com/quasilyte/go-ruleguard/dsl v0.3.6 github.com/rs/cors v1.8.0 @@ -57,12 +55,12 @@ require ( github.com/valyala/fastjson v1.6.3 github.com/wcharczuk/go-chart/v2 v2.1.0 go.uber.org/atomic v1.9.0 - golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e + golang.org/x/crypto v0.0.0-20210813211128-0a44fdfbc16e golang.org/x/sync v0.0.0-20210220032951-036812b2e83c - golang.org/x/sys v0.0.0-20210917161153-d61c044b1678 - golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 - golang.org/x/tools v0.1.6 - google.golang.org/grpc v1.39.1 + golang.org/x/sys v0.0.0-20211002104244-808efd93c36d + golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac + golang.org/x/tools v0.1.7 + google.golang.org/grpc v1.41.0 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 google.golang.org/protobuf v1.27.1 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 diff --git a/go.sum b/go.sum index dbf2d6f5bbb..4bceb95dbde 100644 --- a/go.sum +++ b/go.sum @@ -51,8 +51,6 @@ dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBr dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= -github.com/BobuSumisu/aho-corasick v1.0.3 h1:uuf+JHwU9CHP2Vx+wAy6jcksJThhJS9ehR8a+4nPE9g= -github.com/BobuSumisu/aho-corasick v1.0.3/go.mod h1:hm4jLcvZKI2vRF2WDU1N4p/jpWtpOzp3nLmi9AzX/XE= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/RoaringBitmap/roaring v0.4.7/go.mod h1:8khRDP4HmeXns4xIj9oGrKSz7XTQiJx2zgh7AcNke4w= @@ -67,8 +65,8 @@ github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWX github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= -github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= -github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= +github.com/VictoriaMetrics/fastcache v1.7.0 h1:E6GibaGI685TafrI7E/QqZPkMsOzRw+3gpICQx08ISg= +github.com/VictoriaMetrics/fastcache v1.7.0/go.mod h1:n7Sl+ioh/HlWeYHLSIBIE8TcZFHg/+xgvomWSS5xuEE= github.com/VictoriaMetrics/metrics v1.18.0 h1:vov5NxDHRSXFbdiH4dYLYEjKLoAXXSQ7hcnG8TSD9JQ= github.com/VictoriaMetrics/metrics v1.18.0/go.mod h1:ArjwVz7WpgpegX/JpB0zpNF2h2232kErkEnzH1sxMmA= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= @@ -202,8 +200,9 @@ github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7 github.com/c2h5oh/datasize v0.0.0-20200825124411-48ed595a09d2 h1:t8KYCwSKsOEZBFELI4Pn/phbp38iJ1RRAkDFNin1aak= github.com/c2h5oh/datasize v0.0.0-20200825124411-48ed595a09d2/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -213,7 +212,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/consensys/bavard v0.1.8-0.20210329205436-c3e862ba4e5f/go.mod h1:Bpd0/3mZuaj6Sj+PqrmIquiOKy397AKGThQPaGzNXAQ= github.com/consensys/gnark-crypto v0.4.0 h1:KHf7Ta876Ys6L8+i0DLRRKOAa3PfJ8oobAX1CEeIa4A= github.com/consensys/gnark-crypto v0.4.0/go.mod h1:wK/gpXP9B06qTzTVML71GhKD1ygP9xOzukbI68NJqsQ= @@ -230,8 +229,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea h1:j4317fAZh7X6GqbFowYdYdI0L9bwxL07jyPZIdepyZ0= github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= -github.com/dlclark/regexp2 v1.2.0 h1:8sAhBGEM0dRWogWqWyQeIJnxjWO6oIjl8FKqREDsGfk= -github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E= +github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf h1:sh8rkQZavChcmakYiSlqu2425CHyFXLZZnvm7PDpU8M= github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= @@ -257,7 +256,7 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -353,7 +352,6 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -468,8 +466,9 @@ github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlT github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= @@ -498,8 +497,8 @@ github.com/kylelemons/godebug v0.0.0-20170224010052-a616ab194758 h1:0D5M2HQSGD3P github.com/kylelemons/godebug v0.0.0-20170224010052-a616ab194758/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= -github.com/ledgerwatch/erigon-lib v0.0.0-20210930024651-a59261cb3242 h1:AZOJc/5E0shui7SjmaqT4kiBV4kdUDdIjYaIYnRtIyY= -github.com/ledgerwatch/erigon-lib v0.0.0-20210930024651-a59261cb3242/go.mod h1:uiu+QBxRM78KOlqI7P9kiMefN6BTBsHykEbyNgloC9k= +github.com/ledgerwatch/erigon-lib v0.0.0-20211006142856-240f7f121273 h1:89Wd0zCGUBRlz+8/uA/pgBOiOIqbK2sjJiomDSxUYcI= +github.com/ledgerwatch/erigon-lib v0.0.0-20211006142856-240f7f121273/go.mod h1:R65M7eqckpbB9f4+WG6ftXVgPX2U1RhgrKE8lYgLzPI= github.com/ledgerwatch/log/v3 v3.3.1 h1:HmvLeTEvtCtqSvtu4t/a5MAdcLfeBcbIeowXbLYuzLc= github.com/ledgerwatch/log/v3 v3.3.1/go.mod h1:S3VJqhhVX32rbp1JyyvhJou12twtFwNEPESBgpbNkRk= github.com/ledgerwatch/secp256k1 v0.0.0-20210626115225-cd5cd00ed72d h1:/IKMrJdfRsoYNc36PXqP4xMH3vhW/8IQyBKGQbKZUno= @@ -554,8 +553,9 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM= github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw= @@ -579,8 +579,9 @@ github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFSt github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM= +github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/petar/GoLLRB v0.0.0-20190514000832-33fb24c13b99 h1:KcEvVBAvyHkUdFAygKAzwB6LAcZ6LS32WHmRD2VyXMI= github.com/petar/GoLLRB v0.0.0-20190514000832-33fb24c13b99/go.mod h1:HUpKUBZnpzkdx0kD/+Yfuft+uD3zHGtXF/XJB14TUr4= github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= @@ -837,8 +838,9 @@ golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210813211128-0a44fdfbc16e h1:VvfwVmMH40bpMeizC9/K7ipM5Qjucuu16RWfneFPyhQ= +golang.org/x/crypto v0.0.0-20210813211128-0a44fdfbc16e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1022,7 +1024,6 @@ golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210326220804-49726bf1d181/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1031,8 +1032,10 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210917161153-d61c044b1678 h1:J27LZFQBFoihqXoegpscI10HpjZ7B5WQLLKL2FZXQKw= +golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211002104244-808efd93c36d h1:SABT8Vei3iTiu+Gy8KOzpSNz+W1EQ5YBCRtiEETxF+0= +golang.org/x/sys v0.0.0-20211002104244-808efd93c36d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1048,8 +1051,9 @@ golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 h1:Hir2P/De0WpUhtrKGGjvSb2YxUgyZ7EFOSLIcSSpiwE= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1107,8 +1111,8 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.6 h1:SIasE1FVIQOWz2GEAHFOmoW7xchJcqlucjSULTL0Ag4= -golang.org/x/tools v0.1.6/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ= +golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1219,8 +1223,8 @@ google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.1 h1:f37vZbBVTiJ6jKG5mWz8ySOBxNqy6ViPgyhSdVnxF3E= -google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= +google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 h1:M1YKkFIboKNieVO5DLUEVzQfGwJD30Nv2jfUgzb5UcE= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= diff --git a/internal/build/archive.go b/internal/build/archive.go index 8b3ac23d1d8..6db519bd2af 100644 --- a/internal/build/archive.go +++ b/internal/build/archive.go @@ -122,13 +122,13 @@ func (a *ZipArchive) Directory(name string) error { func (a *ZipArchive) Header(fi os.FileInfo) (io.Writer, error) { head, err := zip.FileInfoHeader(fi) if err != nil { - return nil, fmt.Errorf("can't make zip header: %v", err) + return nil, fmt.Errorf("can't make zip header: %w", err) } head.Name = a.dir + head.Name head.Method = zip.Deflate w, err := a.zipw.CreateHeader(head) if err != nil { - return nil, fmt.Errorf("can't add zip header: %v", err) + return nil, fmt.Errorf("can't add zip header: %w", err) } return w, nil } @@ -165,11 +165,11 @@ func (a *TarballArchive) Directory(name string) error { func (a *TarballArchive) Header(fi os.FileInfo) (io.Writer, error) { head, err := tar.FileInfoHeader(fi, "") if err != nil { - return nil, fmt.Errorf("can't make tar header: %v", err) + return nil, fmt.Errorf("can't make tar header: %w", err) } head.Name = a.dir + head.Name if err := a.tarw.WriteHeader(head); err != nil { - return nil, fmt.Errorf("can't add tar header: %v", err) + return nil, fmt.Errorf("can't add tar header: %w", err) } return a.tarw, nil } @@ -226,7 +226,7 @@ func extractTarball(ar io.Reader, dest string) error { armode := header.FileInfo().Mode() err := extractFile(header.Name, armode, tr, dest) if err != nil { - return fmt.Errorf("extract %s: %v", header.Name, err) + return fmt.Errorf("extract %s: %w", header.Name, err) } } } @@ -255,7 +255,7 @@ func extractZip(ar *os.File, dest string) error { err = extractFile(zf.Name, zf.Mode(), data, dest) data.Close() if err != nil { - return fmt.Errorf("extract %s: %v", zf.Name, err) + return fmt.Errorf("extract %s: %w", zf.Name, err) } } return nil diff --git a/internal/build/download.go b/internal/build/download.go index abdc60b2401..c25cefa93bd 100644 --- a/internal/build/download.go +++ b/internal/build/download.go @@ -84,7 +84,7 @@ func (db *ChecksumDB) DownloadFile(url, dstPath string) error { resp, respErr := http.Get(url) if respErr != nil { - return fmt.Errorf("download error: %v", respErr) + return fmt.Errorf("download error: %w", respErr) } else if resp.StatusCode != http.StatusOK { return fmt.Errorf("download error: status %d", resp.StatusCode) } diff --git a/internal/build/util.go b/internal/build/util.go index 1f8d3a0d1ed..07da06b594a 100644 --- a/internal/build/util.go +++ b/internal/build/util.go @@ -154,7 +154,7 @@ func UploadSFTP(identityFile, host, dir string, files []string) error { stdin, err := sftp.StdinPipe() if err != nil { - return fmt.Errorf("can't create stdin pipe for sftp: %v", err) + return fmt.Errorf("can't create stdin pipe for sftp: %w", err) } if err := sftp.Start(); err != nil { return err diff --git a/internal/debug/signal_windows.go b/internal/debug/signal_windows.go index 7148167a315..78f6700fd53 100644 --- a/internal/debug/signal_windows.go +++ b/internal/debug/signal_windows.go @@ -9,12 +9,11 @@ import ( _debug "github.com/ledgerwatch/erigon/common/debug" "github.com/ledgerwatch/log/v3" - "golang.org/x/sys/windows" ) func ListenSignals(stack io.Closer) { sigc := make(chan os.Signal, 1) - signal.Notify(sigc, windows.SIGINT, windows.SIGTERM) + signal.Notify(sigc, os.Interrupt) _debug.GetSigC(&sigc) defer signal.Stop(sigc) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index b2181e2d9b1..8ee4192e528 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -252,7 +252,7 @@ func (s *PublicBlockChainAPI) GetUncleByBlockNumberAndIndex(ctx context.Context, if block != nil { uncles := block.Uncles() if index >= hexutil.Uint(len(uncles)) { - log.Debug("Requested uncle not found", "number", blockNr, "hash", block.Hash(), "index", index) + log.Trace("Requested uncle not found", "number", blockNr, "hash", block.Hash(), "index", index) return nil, nil } block = types.NewBlockWithHeader(uncles[index]) @@ -268,7 +268,7 @@ func (s *PublicBlockChainAPI) GetUncleByBlockHashAndIndex(ctx context.Context, b if block != nil { uncles := block.Uncles() if index >= hexutil.Uint(len(uncles)) { - log.Debug("Requested uncle not found", "number", block.Number(), "hash", blockHash, "index", index) + log.Trace("Requested uncle not found", "number", block.Number(), "hash", blockHash, "index", index) return nil, nil } block = types.NewBlockWithHeader(uncles[index]) diff --git a/internal/jsre/deps/bindata.go b/internal/jsre/deps/bindata.go index a6545b7140d..f8883aaea2e 100644 --- a/internal/jsre/deps/bindata.go +++ b/internal/jsre/deps/bindata.go @@ -19,7 +19,7 @@ import ( func bindataRead(data []byte, name string) ([]byte, error) { gz, err := gzip.NewReader(bytes.NewBuffer(data)) if err != nil { - return nil, fmt.Errorf("read %q: %v", name, err) + return nil, fmt.Errorf("read %q: %w", name, err) } var buf bytes.Buffer @@ -27,7 +27,7 @@ func bindataRead(data []byte, name string) ([]byte, error) { clErr := gz.Close() if err != nil { - return nil, fmt.Errorf("read %q: %v", name, err) + return nil, fmt.Errorf("read %q: %w", name, err) } if clErr != nil { return nil, err @@ -126,7 +126,7 @@ func Asset(name string) ([]byte, error) { if f, ok := _bindata[canonicalName]; ok { a, err := f() if err != nil { - return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) + return nil, fmt.Errorf("Asset %s can't read by error: %w", name, err) } return a.bytes, nil } @@ -152,7 +152,7 @@ func AssetInfo(name string) (os.FileInfo, error) { if f, ok := _bindata[canonicalName]; ok { a, err := f() if err != nil { - return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) + return nil, fmt.Errorf("AssetInfo %s can't read by error: %w", name, err) } return a.info, nil } diff --git a/internal/jsre/jsre.go b/internal/jsre/jsre.go index aa6f1afac08..9fb2257d6a1 100644 --- a/internal/jsre/jsre.go +++ b/internal/jsre/jsre.go @@ -295,11 +295,11 @@ func (re *JSRE) loadScript(call Call) (goja.Value, error) { file = common.AbsolutePath(re.assetPath, file) source, err := ioutil.ReadFile(file) if err != nil { - return nil, fmt.Errorf("could not read file %s: %v", file, err) + return nil, fmt.Errorf("could not read file %s: %w", file, err) } value, err := compileAndRun(re.vm, file, string(source)) if err != nil { - return nil, fmt.Errorf("error while compiling or running script: %v", err) + return nil, fmt.Errorf("error while compiling or running script: %w", err) } return value, nil } diff --git a/migrations/receipt_repair.go b/migrations/receipt_repair.go index 8cf8055c6ff..d1ee62d594d 100644 --- a/migrations/receipt_repair.go +++ b/migrations/receipt_repair.go @@ -133,10 +133,10 @@ var ReceiptRepair = Migration{ buf.Reset() err := cbor.Marshal(&buf, receipts1) if err != nil { - return fmt.Errorf("encode block receipts for block %d: %v", blockNum, err) + return fmt.Errorf("encode block receipts for block %d: %w", blockNum, err) } if err = tx.Put(kv.Receipts, key[:], buf.Bytes()); err != nil { - return fmt.Errorf("writing receipts for block %d: %v", blockNum, err) + return fmt.Errorf("writing receipts for block %d: %w", blockNum, err) } fixedCount++ } @@ -163,7 +163,7 @@ func runBlock(ibs *state.IntraBlockState, txnWriter state.StateWriter, blockWrit ibs.Prepare(tx.Hash(), block.Hash(), i) receipt, _, err := core.ApplyTransaction(chainConfig, getHeader, engine, nil, gp, ibs, txnWriter, header, tx, usedGas, vmConfig, contractHasTEVM) if err != nil { - return nil, fmt.Errorf("could not apply tx %d [%x] failed: %v", i, tx.Hash(), err) + return nil, fmt.Errorf("could not apply tx %d [%x] failed: %w", i, tx.Hash(), err) } receipts = append(receipts, receipt) } @@ -171,11 +171,11 @@ func runBlock(ibs *state.IntraBlockState, txnWriter state.StateWriter, blockWrit if !vmConfig.ReadOnly { // Finalize the block, applying any consensus engine specific extras (e.g. block rewards) if _, err := engine.FinalizeAndAssemble(chainConfig, header, ibs, block.Transactions(), block.Uncles(), receipts, nil, nil, nil, nil); err != nil { - return nil, fmt.Errorf("finalize of block %d failed: %v", block.NumberU64(), err) + return nil, fmt.Errorf("finalize of block %d failed: %w", block.NumberU64(), err) } if err := ibs.CommitBlock(chainConfig.Rules(header.Number.Uint64()), blockWriter); err != nil { - return nil, fmt.Errorf("committing block %d failed: %v", block.NumberU64(), err) + return nil, fmt.Errorf("committing block %d failed: %w", block.NumberU64(), err) } } diff --git a/node/api.go b/node/api.go index 46241c8abee..cf529e2f639 100644 --- a/node/api.go +++ b/node/api.go @@ -72,7 +72,7 @@ func (api *privateAdminAPI) AddPeer(url string) (bool, error) { // Try to add the url as a static peer and return node, err := enode.Parse(enode.ValidSchemes, url) if err != nil { - return false, fmt.Errorf("invalid enode: %v", err) + return false, fmt.Errorf("invalid enode: %w", err) } server.AddPeer(node) return true, nil @@ -88,7 +88,7 @@ func (api *privateAdminAPI) RemovePeer(url string) (bool, error) { // Try to remove the url as a static peer and return node, err := enode.Parse(enode.ValidSchemes, url) if err != nil { - return false, fmt.Errorf("invalid enode: %v", err) + return false, fmt.Errorf("invalid enode: %w", err) } server.RemovePeer(node) return true, nil @@ -103,7 +103,7 @@ func (api *privateAdminAPI) AddTrustedPeer(url string) (bool, error) { } node, err := enode.Parse(enode.ValidSchemes, url) if err != nil { - return false, fmt.Errorf("invalid enode: %v", err) + return false, fmt.Errorf("invalid enode: %w", err) } server.AddTrustedPeer(node) return true, nil @@ -119,7 +119,7 @@ func (api *privateAdminAPI) RemoveTrustedPeer(url string) (bool, error) { } node, err := enode.Parse(enode.ValidSchemes, url) if err != nil { - return false, fmt.Errorf("invalid enode: %v", err) + return false, fmt.Errorf("invalid enode: %w", err) } server.RemoveTrustedPeer(node) return true, nil diff --git a/p2p/dial.go b/p2p/dial.go index cf40c7ed0ad..d15458f4d35 100644 --- a/p2p/dial.go +++ b/p2p/dial.go @@ -240,7 +240,7 @@ loop: for { // Launch new dials if slots are available. slots := d.freeDialSlots() - slots -= d.startStaticDials(slots) + d.startStaticDials() if slots > 0 { nodesCh = d.nodesIn } else { @@ -421,14 +421,13 @@ func (d *dialScheduler) checkDial(n *enode.Node) error { } // startStaticDials starts n static dial tasks. -func (d *dialScheduler) startStaticDials(n int) (started int) { - for started = 0; started < n && len(d.staticPool) > 0; started++ { +func (d *dialScheduler) startStaticDials() { + for len(d.staticPool) > 0 { idx := d.rand.Intn(len(d.staticPool)) task := d.staticPool[idx] d.startDial(task) d.removeFromStaticPool(idx) } - return started } // updateStaticPool attempts to move the given static dial back into staticPool. @@ -534,13 +533,13 @@ func (t *dialTask) resolve(d *dialScheduler) bool { if t.resolveDelay > maxResolveDelay { t.resolveDelay = maxResolveDelay } - d.log.Debug("Resolving node failed", "id", t.dest.ID(), "newdelay", t.resolveDelay) + d.log.Warn("Resolving node failed", "id", t.dest.ID(), "newdelay", t.resolveDelay) return false } // The node was found. t.resolveDelay = initialResolveDelay t.dest = resolved - d.log.Debug("Resolved node", "id", t.dest.ID(), "addr", &net.TCPAddr{IP: t.dest.IP(), Port: t.dest.TCP()}) + d.log.Trace("Resolved node", "id", t.dest.ID(), "addr", &net.TCPAddr{IP: t.dest.IP(), Port: t.dest.TCP()}) return true } diff --git a/p2p/dial_test.go b/p2p/dial_test.go index 99c54bfe4c0..c6746861f60 100644 --- a/p2p/dial_test.go +++ b/p2p/dial_test.go @@ -179,19 +179,22 @@ func TestDialSchedStaticDial(t *testing.T) { d.addStatic(newNode(uintID(0x05), "127.0.0.5:30303")) d.addStatic(newNode(uintID(0x06), "127.0.0.6:30303")) d.addStatic(newNode(uintID(0x07), "127.0.0.7:30303")) - d.addStatic(newNode(uintID(0x08), "127.0.0.8:30303")) - d.addStatic(newNode(uintID(0x09), "127.0.0.9:30303")) }, wantNewDials: []*enode.Node{ newNode(uintID(0x03), "127.0.0.3:30303"), newNode(uintID(0x04), "127.0.0.4:30303"), newNode(uintID(0x05), "127.0.0.5:30303"), newNode(uintID(0x06), "127.0.0.6:30303"), + newNode(uintID(0x07), "127.0.0.7:30303"), }, }, // Dial to 0x03 completes, filling a peer slot. One slot remains, // two dials are launched to attempt to fill it. { + update: func(d *dialScheduler) { + d.addStatic(newNode(uintID(0x08), "127.0.0.8:30303")) + d.addStatic(newNode(uintID(0x09), "127.0.0.9:30303")) + }, succeeded: []enode.ID{ uintID(0x03), }, @@ -235,7 +238,7 @@ func TestDialSchedRemoveStatic(t *testing.T) { maxDialPeers: 1, } runDialTest(t, config, []dialTestRound{ - // Add static nodes. + // Add static nodes. Ignore maxActiveDials config { update: func(d *dialScheduler) { d.addStatic(newNode(uintID(0x01), "127.0.0.1:30303")) @@ -244,10 +247,15 @@ func TestDialSchedRemoveStatic(t *testing.T) { }, wantNewDials: []*enode.Node{ newNode(uintID(0x01), "127.0.0.1:30303"), + newNode(uintID(0x02), "127.0.0.2:30303"), + newNode(uintID(0x03), "127.0.0.3:30303"), }, }, // Dial to 0x01 fails. { + update: func(d *dialScheduler) { + d.addStatic(newNode(uintID(0x04), "127.0.0.4:30303")) + }, failed: []enode.ID{ uintID(0x01), }, @@ -255,7 +263,7 @@ func TestDialSchedRemoveStatic(t *testing.T) { uintID(0x01): nil, }, wantNewDials: []*enode.Node{ - newNode(uintID(0x02), "127.0.0.2:30303"), + newNode(uintID(0x04), "127.0.0.4:30303"), }, }, // All static nodes are removed. 0x01 is in history, 0x02 is being @@ -265,6 +273,7 @@ func TestDialSchedRemoveStatic(t *testing.T) { d.removeStatic(newNode(uintID(0x01), "127.0.0.1:30303")) d.removeStatic(newNode(uintID(0x02), "127.0.0.2:30303")) d.removeStatic(newNode(uintID(0x03), "127.0.0.3:30303")) + d.removeStatic(newNode(uintID(0x04), "127.0.0.4:30303")) }, failed: []enode.ID{ uintID(0x02), @@ -278,39 +287,6 @@ func TestDialSchedRemoveStatic(t *testing.T) { }) } -// This test checks that static dials are selected at random. -func TestDialSchedManyStaticNodes(t *testing.T) { - t.Parallel() - - config := dialConfig{maxDialPeers: 2} - runDialTest(t, config, []dialTestRound{ - { - peersAdded: []*conn{ - {flags: dynDialedConn, node: newNode(uintID(0xFFFE), "")}, - {flags: dynDialedConn, node: newNode(uintID(0xFFFF), "")}, - }, - update: func(d *dialScheduler) { - for id := uint16(0); id < 2000; id++ { - n := newNode(uintID(id), "127.0.0.1:30303") - d.addStatic(n) - } - }, - }, - { - peersRemoved: []enode.ID{ - uintID(0xFFFE), - uintID(0xFFFF), - }, - wantNewDials: []*enode.Node{ - newNode(uintID(0x0085), "127.0.0.1:30303"), - newNode(uintID(0x02dc), "127.0.0.1:30303"), - newNode(uintID(0x0285), "127.0.0.1:30303"), - newNode(uintID(0x00cb), "127.0.0.1:30303"), - }, - }, - }) -} - // This test checks that past dials are not retried for some time. func TestDialSchedHistory(t *testing.T) { t.Parallel() diff --git a/p2p/discover/ntp.go b/p2p/discover/ntp.go index 1615313f27c..dbcd1108c96 100644 --- a/p2p/discover/ntp.go +++ b/p2p/discover/ntp.go @@ -54,7 +54,7 @@ func checkClockDrift() { log.Warn(fmt.Sprintf("System clock seems off by %v, which can prevent network connectivity", drift)) log.Warn("Please enable network time synchronisation in system settings.") } else { - log.Debug("NTP sanity check done", "drift", drift) + log.Trace("NTP sanity check done", "drift", drift) } } diff --git a/p2p/discover/table.go b/p2p/discover/table.go index 549daa373b9..4374f290970 100644 --- a/p2p/discover/table.go +++ b/p2p/discover/table.go @@ -188,7 +188,7 @@ func (tab *Table) close() { func (tab *Table) setFallbackNodes(nodes []*enode.Node) error { for _, n := range nodes { if err := n.ValidateComplete(); err != nil { - return fmt.Errorf("bad bootstrap node %q: %v", n, err) + return fmt.Errorf("bad bootstrap node %q: %w", n, err) } } tab.nursery = wrapNodes(nodes) @@ -332,7 +332,7 @@ func (tab *Table) doRevalidate(done chan<- struct{}) { // Also fetch record if the node replied and returned a higher sequence number. if last.Seq() < remoteSeq { if n, err := tab.net.RequestENR(unwrapNode(last)); err != nil { - tab.log.Debug("ENR request failed", "id", last.ID(), "addr", last.addr(), "err", err) + tab.log.Trace("ENR request failed", "id", last.ID(), "addr", last.addr(), "err", err) } else { last = &node{Node: *n, addedAt: last.addedAt, livenessChecks: last.livenessChecks} } @@ -344,16 +344,16 @@ func (tab *Table) doRevalidate(done chan<- struct{}) { if rErr == nil { // The node responded, move it to the front. last.livenessChecks++ - tab.log.Debug("Revalidated node", "b", bi, "id", last.ID(), "checks", last.livenessChecks) + tab.log.Trace("Revalidated node", "b", bi, "id", last.ID(), "checks", last.livenessChecks) tab.bumpInBucket(b, last) return } // No reply received, pick a replacement or delete the node if there aren't // any replacements. if r := tab.replace(b, last); r != nil { - tab.log.Debug("Replaced dead node", "b", bi, "id", last.ID(), "ip", last.IP(), "checks", last.livenessChecks, "r", r.ID(), "rip", r.IP()) + tab.log.Trace("Replaced dead node", "b", bi, "id", last.ID(), "ip", last.IP(), "checks", last.livenessChecks, "r", r.ID(), "rip", r.IP()) } else { - tab.log.Debug("Removed dead node", "b", bi, "id", last.ID(), "ip", last.IP(), "checks", last.livenessChecks) + tab.log.Trace("Removed dead node", "b", bi, "id", last.ID(), "ip", last.IP(), "checks", last.livenessChecks) } } @@ -552,11 +552,11 @@ func (tab *Table) addIP(b *bucket, ip net.IP) bool { return true } if !tab.ips.Add(ip) { - tab.log.Debug("IP exceeds table limit", "ip", ip) + tab.log.Trace("IP exceeds table limit", "ip", ip) return false } if !b.ips.Add(ip) { - tab.log.Debug("IP exceeds bucket limit", "ip", ip) + tab.log.Trace("IP exceeds bucket limit", "ip", ip) tab.ips.Remove(ip) return false } diff --git a/p2p/discover/v4_udp.go b/p2p/discover/v4_udp.go index e084e9064f6..e5255ef223b 100644 --- a/p2p/discover/v4_udp.go +++ b/p2p/discover/v4_udp.go @@ -385,7 +385,7 @@ func (t *UDPv4) RequestENR(n *enode.Node) (*enode.Node, error) { return n, nil // response record is older } if err := netutil.CheckRelayIP(addr.IP, respN.IP()); err != nil { - return nil, fmt.Errorf("invalid IP in response record: %v", err) + return nil, fmt.Errorf("invalid IP in response record: %w", err) } return respN, nil } @@ -540,12 +540,12 @@ func (t *UDPv4) readLoop(unhandled chan<- ReadPacket) { nbytes, from, err := t.conn.ReadFromUDP(buf) if netutil.IsTemporaryError(err) { // Ignore temporary read errors. - t.log.Debug("Temporary UDP read error", "err", err) + t.log.Trace("Temporary UDP read error", "err", err) continue } else if err != nil { // Shut down the loop for permament errors. if err != io.EOF { - t.log.Debug("UDP read error", "err", err) + t.log.Trace("UDP read error", "err", err) } return } @@ -561,7 +561,7 @@ func (t *UDPv4) readLoop(unhandled chan<- ReadPacket) { func (t *UDPv4) handlePacket(from *net.UDPAddr, buf []byte) error { rawpacket, fromKey, hash, err := v4wire.Decode(buf) if err != nil { - t.log.Debug("Bad discv4 packet", "addr", from, "err", err) + t.log.Trace("Bad discv4 packet", "addr", from, "err", err) return err } packet := t.wrapPacket(rawpacket) diff --git a/p2p/discover/v4_udp_test.go b/p2p/discover/v4_udp_test.go index 1ddf728c6a4..834608e5e2b 100644 --- a/p2p/discover/v4_udp_test.go +++ b/p2p/discover/v4_udp_test.go @@ -102,7 +102,7 @@ func (test *udpTest) packetInFrom(wantError error, key *ecdsa.PrivateKey, addr * enc, _, err := v4wire.Encode(key, data) if err != nil { - test.t.Errorf("%s encode error: %v", data.Name(), err) + test.t.Errorf("%s encode error: %w", data.Name(), err) } test.sent = append(test.sent, enc) if err = test.udp.handlePacket(addr, enc); err != wantError { @@ -124,7 +124,7 @@ func (test *udpTest) waitPacketOut(validate interface{}) (closed bool) { } p, _, hash, err := v4wire.Decode(dgram.data) if err != nil { - test.t.Errorf("sent packet decode error: %v", err) + test.t.Errorf("sent packet decode error: %w", err) return false } fn := reflect.ValueOf(validate) diff --git a/p2p/discover/v5_udp.go b/p2p/discover/v5_udp.go index 5f11efa03a3..711966a789e 100644 --- a/p2p/discover/v5_udp.go +++ b/p2p/discover/v5_udp.go @@ -382,7 +382,7 @@ func (t *UDPv5) waitForNodes(c *callV5, distances []uint) ([]*enode.Node, error) for _, record := range response.Nodes { node, err := t.verifyResponseNode(c, record, distances, seen) if err != nil { - t.log.Debug("Invalid record in "+response.Name(), "id", c.node.ID(), "err", err) + t.log.Trace("Invalid record in "+response.Name(), "id", c.node.ID(), "err", err) continue } nodes = append(nodes, node) @@ -622,12 +622,12 @@ func (t *UDPv5) readLoop() { nbytes, from, err := t.conn.ReadFromUDP(buf) if netutil.IsTemporaryError(err) { // Ignore temporary read errors. - t.log.Debug("Temporary UDP read error", "err", err) + t.log.Trace("Temporary UDP read error", "err", err) continue } else if err != nil { // Shut down the loop for permament errors. if err != io.EOF { - t.log.Debug("UDP read error", "err", err) + t.log.Trace("UDP read error", "err", err) } return } @@ -650,7 +650,7 @@ func (t *UDPv5) handlePacket(rawpacket []byte, fromAddr *net.UDPAddr) error { addr := fromAddr.String() fromID, fromNode, packet, err := t.codec.Decode(rawpacket, addr) if err != nil { - t.log.Debug("Bad discv5 packet", "id", fromID, "addr", addr, "err", err) + t.log.Trace("Bad discv5 packet", "id", fromID, "addr", addr, "err", err) return err } if fromNode != nil { @@ -669,15 +669,15 @@ func (t *UDPv5) handlePacket(rawpacket []byte, fromAddr *net.UDPAddr) error { func (t *UDPv5) handleCallResponse(fromID enode.ID, fromAddr *net.UDPAddr, p v5wire.Packet) bool { ac := t.activeCallByNode[fromID] if ac == nil || !bytes.Equal(p.RequestID(), ac.reqid) { - t.log.Debug(fmt.Sprintf("Unsolicited/late %s response", p.Name()), "id", fromID, "addr", fromAddr) + t.log.Trace(fmt.Sprintf("Unsolicited/late %s response", p.Name()), "id", fromID, "addr", fromAddr) return false } if !fromAddr.IP.Equal(ac.node.IP()) || fromAddr.Port != ac.node.UDP() { - t.log.Debug(fmt.Sprintf("%s from wrong endpoint", p.Name()), "id", fromID, "addr", fromAddr) + t.log.Trace(fmt.Sprintf("%s from wrong endpoint", p.Name()), "id", fromID, "addr", fromAddr) return false } if p.Kind() != ac.responseType { - t.log.Debug(fmt.Sprintf("Wrong discv5 response type %s", p.Name()), "id", fromID, "addr", fromAddr) + t.log.Trace(fmt.Sprintf("Wrong discv5 response type %s", p.Name()), "id", fromID, "addr", fromAddr) return false } t.startResponseTimeout(ac) diff --git a/p2p/discover/v5_udp_test.go b/p2p/discover/v5_udp_test.go index 369078118a4..5d132e6fe20 100644 --- a/p2p/discover/v5_udp_test.go +++ b/p2p/discover/v5_udp_test.go @@ -688,7 +688,7 @@ func (c *testCodec) Decode(input []byte, addr string) (enode.ID, *enode.Node, v5 func (c *testCodec) decodeFrame(input []byte) (frame testCodecFrame, p v5wire.Packet, err error) { if err = rlp.DecodeBytes(input, &frame); err != nil { - return frame, nil, fmt.Errorf("invalid frame: %v", err) + return frame, nil, fmt.Errorf("invalid frame: %w", err) } switch frame.Ptype { case v5wire.UnknownPacket: @@ -755,7 +755,7 @@ func (test *udpV5Test) packetInFrom(key *ecdsa.PrivateKey, addr *net.UDPAddr, pa codec := &testCodec{test: test, id: ln.ID()} enc, _, err := codec.Encode(test.udp.Self().ID(), addr.String(), packet, nil) if err != nil { - test.t.Errorf("%s encode error: %v", packet.Name(), err) + test.t.Errorf("%s encode error: %w", packet.Name(), err) } if test.udp.dispatchReadPacket(addr, enc) { <-test.udp.readNextCh // unblock UDPv5.dispatch @@ -807,7 +807,7 @@ func (test *udpV5Test) waitPacketOut(validate interface{}) (closed bool) { codec := &testCodec{test: test, id: ln.ID()} frame, p, err := codec.decodeFrame(dgram.data) if err != nil { - test.t.Errorf("sent packet decode error: %v", err) + test.t.Errorf("sent packet decode error: %w", err) return false } if !reflect.TypeOf(p).AssignableTo(exptype) { diff --git a/p2p/discover/v5wire/crypto.go b/p2p/discover/v5wire/crypto.go index 18c68fab183..bb3bbefa21a 100644 --- a/p2p/discover/v5wire/crypto.go +++ b/p2p/discover/v5wire/crypto.go @@ -154,11 +154,11 @@ func ecdh(privkey *ecdsa.PrivateKey, pubkey *ecdsa.PublicKey) []byte { func encryptGCM(dest, key, nonce, plaintext, authData []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { - panic(fmt.Errorf("can't create block cipher: %v", err)) + panic(fmt.Errorf("can't create block cipher: %w", err)) } aesgcm, err := cipher.NewGCMWithNonceSize(block, gcmNonceSize) if err != nil { - panic(fmt.Errorf("can't create GCM: %v", err)) + panic(fmt.Errorf("can't create GCM: %w", err)) } return aesgcm.Seal(dest, nonce, plaintext, authData), nil } diff --git a/p2p/discover/v5wire/encoding.go b/p2p/discover/v5wire/encoding.go index 9ba8c69b894..5e983d0b9a3 100644 --- a/p2p/discover/v5wire/encoding.go +++ b/p2p/discover/v5wire/encoding.go @@ -188,7 +188,7 @@ func (c *Codec) Encode(id enode.ID, addr string, packet Packet, challenge *Whoar // Generate masking IV. if err = c.sc.maskingIVGen(head.IV[:]); err != nil { - return nil, Nonce{}, fmt.Errorf("can't generate masking IV: %v", err) + return nil, Nonce{}, fmt.Errorf("can't generate masking IV: %w", err) } // Encode header data. @@ -266,7 +266,7 @@ func (c *Codec) encodeRandom(toID enode.ID) (Header, []byte, error) { // Encode auth data. auth := messageAuthData{SrcID: c.localnode.ID()} if _, err := crand.Read(head.Nonce[:]); err != nil { - return head, nil, fmt.Errorf("can't get random data: %v", err) + return head, nil, fmt.Errorf("can't get random data: %w", err) } c.headbuf.Reset() binary.Write(&c.headbuf, binary.BigEndian, auth) //nolint:errcheck @@ -318,7 +318,7 @@ func (c *Codec) encodeHandshakeHeader(toID enode.ID, addr string, challenge *Who // Generate nonce for message. nonce, err := c.sc.nextNonce(session) if err != nil { - return Header{}, nil, fmt.Errorf("can't generate nonce: %v", err) + return Header{}, nil, fmt.Errorf("can't generate nonce: %w", err) } // TODO: this should happen when the first authenticated message is received @@ -363,7 +363,7 @@ func (c *Codec) makeHandshakeAuth(toID enode.ID, addr string, challenge *Whoarey cdata := challenge.ChallengeData idsig, err := makeIDSignature(c.sha256, c.privkey, cdata, ephpubkey, toID) if err != nil { - return nil, nil, fmt.Errorf("can't sign: %v", err) + return nil, nil, fmt.Errorf("can't sign: %w", err) } auth.signature = idsig auth.h.SigSize = byte(len(auth.signature)) @@ -389,7 +389,7 @@ func (c *Codec) encodeMessageHeader(toID enode.ID, s *session) (Header, error) { // Create the header. nonce, err := c.sc.nextNonce(s) if err != nil { - return Header{}, fmt.Errorf("can't generate nonce: %v", err) + return Header{}, fmt.Errorf("can't generate nonce: %w", err) } auth := messageAuthData{SrcID: c.localnode.ID()} c.buf.Reset() @@ -572,7 +572,7 @@ func (c *Codec) decodeHandshakeRecord(local *enode.Node, wantID enode.ID, remote if local == nil || local.Seq() < record.Seq() { n, err := enode.New(enode.ValidSchemes, &record) if err != nil { - return nil, fmt.Errorf("invalid node record: %v", err) + return nil, fmt.Errorf("invalid node record: %w", err) } if n.ID() != wantID { return nil, fmt.Errorf("record in handshake has wrong ID: %v", n.ID()) diff --git a/p2p/discover/v5wire/encoding_test.go b/p2p/discover/v5wire/encoding_test.go index 26b9293dc1e..a4764dc2497 100644 --- a/p2p/discover/v5wire/encoding_test.go +++ b/p2p/discover/v5wire/encoding_test.go @@ -546,7 +546,7 @@ func (n *handshakeTestNode) encodeWithChallenge(t testing.TB, to handshakeTestNo // Encode to destination. enc, nonce, err := n.c.Encode(to.id(), to.addr(), p, challenge) if err != nil { - t.Fatal(fmt.Errorf("(%s) %v", n.ln.ID().TerminalString(), err)) + t.Fatal(fmt.Errorf("(%s) %w", n.ln.ID().TerminalString(), err)) } t.Logf("(%s) -> (%s) %s\n%s", n.ln.ID().TerminalString(), to.id().TerminalString(), p.Name(), hex.Dump(enc)) return enc, nonce @@ -557,7 +557,7 @@ func (n *handshakeTestNode) expectDecode(t *testing.T, ptype byte, p []byte) Pac dec, err := n.decode(p) if err != nil { - t.Fatal(fmt.Errorf("(%s) %v", n.ln.ID().TerminalString(), err)) + t.Fatal(fmt.Errorf("(%s) %w", n.ln.ID().TerminalString(), err)) } t.Logf("(%s) %#v", n.ln.ID().TerminalString(), pp.NewFormatter(dec)) if dec.Kind() != ptype { diff --git a/p2p/dnsdisc/client.go b/p2p/dnsdisc/client.go index 1005980e2de..9424a4052c2 100644 --- a/p2p/dnsdisc/client.go +++ b/p2p/dnsdisc/client.go @@ -105,7 +105,7 @@ func NewClient(cfg Config) *Client { func (c *Client) SyncTree(url string) (*Tree, error) { le, err := parseLink(url) if err != nil { - return nil, fmt.Errorf("invalid enrtree URL: %v", err) + return nil, fmt.Errorf("invalid enrtree URL: %w", err) } ct := newClientTree(c, new(linkCache), le) t := &Tree{entries: make(map[string]entry)} @@ -258,7 +258,7 @@ func (it *randomIterator) Next() bool { func (it *randomIterator) addTree(url string) error { le, err := parseLink(url) if err != nil { - return fmt.Errorf("invalid enrtree URL: %v", err) + return fmt.Errorf("invalid enrtree URL: %w", err) } it.lc.addLink("", le.str) return nil @@ -276,7 +276,7 @@ func (it *randomIterator) nextNode() *enode.Node { if err == it.ctx.Err() { return nil // context canceled. } - it.c.cfg.Logger.Debug("Error in DNS random node sync", "tree", ct.loc.domain, "err", err) + it.c.cfg.Logger.Trace("Error in DNS random node sync", "tree", ct.loc.domain, "err", err) continue } if n != nil { @@ -349,7 +349,7 @@ func (it *randomIterator) waitForRootUpdates(trees []*clientTree) bool { } sleep := nextCheck.Sub(it.c.clock.Now()) - it.c.cfg.Logger.Debug("DNS iterator waiting for root updates", "sleep", sleep, "tree", minTree.loc.domain) + it.c.cfg.Logger.Trace("DNS iterator waiting for root updates", "sleep", sleep, "tree", minTree.loc.domain) timeout := it.c.clock.NewTimer(sleep) defer timeout.Stop() select { diff --git a/p2p/enode/localnode.go b/p2p/enode/localnode.go index 187d47f3cd0..d5faf8b47fb 100644 --- a/p2p/enode/localnode.go +++ b/p2p/enode/localnode.go @@ -274,14 +274,14 @@ func (ln *LocalNode) sign() { ln.bumpSeq() r.SetSeq(ln.seq) if err := SignV4(&r, ln.key); err != nil { - panic(fmt.Errorf("enode: can't sign record: %v", err)) + panic(fmt.Errorf("enode: can't sign record: %w", err)) } n, err := New(ValidSchemes, &r) if err != nil { - panic(fmt.Errorf("enode: can't verify local record: %v", err)) + panic(fmt.Errorf("enode: can't verify local record: %w", err)) } ln.cur.Store(n) - log.Debug("New local node record", "seq", ln.seq, "id", n.ID(), "ip", n.IP(), "udp", n.UDP(), "tcp", n.TCP()) + log.Trace("New local node record", "seq", ln.seq, "id", n.ID(), "ip", n.IP(), "udp", n.UDP(), "tcp", n.TCP()) } func (ln *LocalNode) bumpSeq() { diff --git a/p2p/enode/nodedb_test.go b/p2p/enode/nodedb_test.go index e76729e5a3d..0ca44575f90 100644 --- a/p2p/enode/nodedb_test.go +++ b/p2p/enode/nodedb_test.go @@ -273,10 +273,10 @@ func testSeedQuery() error { // Insert a batch of nodes for querying for i, seed := range nodeDBSeedQueryNodes { if err := db.UpdateNode(seed.node); err != nil { - return fmt.Errorf("node %d: failed to insert: %v", i, err) + return fmt.Errorf("node %d: failed to insert: %w", i, err) } if err := db.UpdateLastPongReceived(seed.node.ID(), seed.node.IP(), seed.pong); err != nil { - return fmt.Errorf("node %d: failed to insert bondTime: %v", i, err) + return fmt.Errorf("node %d: failed to insert bondTime: %w", i, err) } } diff --git a/p2p/enr/enr.go b/p2p/enr/enr.go index 5c005209a09..10f2f79c528 100644 --- a/p2p/enr/enr.go +++ b/p2p/enr/enr.go @@ -131,7 +131,7 @@ func (r *Record) Load(e Entry) error { func (r *Record) Set(e Entry) { blob, err := rlp.EncodeToBytes(e) if err != nil { - panic(fmt.Errorf("enr: can't encode %s: %v", e.ENRKey(), err)) + panic(fmt.Errorf("enr: can't encode %s: %w", e.ENRKey(), err)) } r.invalidate() diff --git a/p2p/nat/nat.go b/p2p/nat/nat.go index 19daacfa48b..1fe06b97da4 100644 --- a/p2p/nat/nat.go +++ b/p2p/nat/nat.go @@ -102,7 +102,7 @@ func Map(m Interface, c <-chan struct{}, protocol string, extport, intport int, refresh := time.NewTimer(mapTimeout) defer func() { refresh.Stop() - log.Debug("Deleting port mapping") + log.Trace("Deleting port mapping") m.DeleteMapping(protocol, extport, intport) }() if err := m.AddMapping(protocol, extport, intport, name, mapTimeout); err != nil { diff --git a/p2p/rlpx/rlpx.go b/p2p/rlpx/rlpx.go index c6137f47d67..b1dc199d34c 100644 --- a/p2p/rlpx/rlpx.go +++ b/p2p/rlpx/rlpx.go @@ -139,7 +139,7 @@ func (c *Conn) Read() (code uint64, data []byte, wireSize int, err error) { } code, data, err = rlp.SplitUint64(frame) if err != nil { - return 0, nil, 0, fmt.Errorf("invalid message code: %v", err) + return 0, nil, 0, fmt.Errorf("invalid message code: %w", err) } wireSize = len(data) diff --git a/p2p/server.go b/p2p/server.go index c6723b90501..0b2461115c0 100644 --- a/p2p/server.go +++ b/p2p/server.go @@ -576,7 +576,7 @@ func (srv *Server) setupDiscovery() error { return err } realaddr := conn.LocalAddr().(*net.UDPAddr) - srv.log.Debug("UDP listener up", "addr", realaddr) + srv.log.Trace("UDP listener up", "addr", realaddr) if srv.NAT != nil { if !realaddr.IP.IsLoopback() { srv.loopWG.Add(1) @@ -789,7 +789,7 @@ running: // The handshakes are done and it passed all checks. p := srv.launchPeer(c) peers[c.node.ID()] = p - srv.log.Debug("Adding p2p peer", "peercount", len(peers), "id", p.ID(), "conn", c.flags, "addr", p.RemoteAddr(), "name", p.Name()) + srv.log.Trace("Adding p2p peer", "peercount", len(peers), "id", p.ID(), "conn", c.flags, "addr", p.RemoteAddr(), "name", p.Name()) srv.dialsched.peerAdded(c) if p.Inbound() { inboundCount++ @@ -801,7 +801,7 @@ running: // A peer disconnected. d := common.PrettyDuration(mclock.Now() - pd.created) delete(peers, pd.ID()) - srv.log.Debug("Removing p2p peer", "peercount", len(peers), "id", pd.ID(), "duration", d, "req", pd.requested, "err", pd.err) + srv.log.Trace("Removing p2p peer", "peercount", len(peers), "id", pd.ID(), "duration", d, "req", pd.requested, "err", pd.err) srv.dialsched.peerRemoved(pd.rw) if pd.Inbound() { inboundCount-- @@ -861,7 +861,7 @@ func (srv *Server) addPeerChecks(peers map[enode.ID]*Peer, inboundCount int, c * // inbound connections. func (srv *Server) listenLoop() { defer debug.LogPanic() - srv.log.Debug("TCP listener up", "addr", srv.listener.Addr()) + srv.log.Trace("TCP listener up", "addr", srv.listener.Addr()) // The slots channel limits accepts of new connections. tokens := defaultMaxPendingPeers @@ -895,13 +895,13 @@ func (srv *Server) listenLoop() { fd, err = srv.listener.Accept() if netutil.IsTemporaryError(err) { if time.Since(lastLog) > 1*time.Second { - srv.log.Debug("Temporary read error", "err", err) + srv.log.Trace("Temporary read error", "err", err) lastLog = time.Now() } time.Sleep(time.Millisecond * 200) continue } else if err != nil { - srv.log.Debug("Read error", "err", err) + srv.log.Trace("Read error", "err", err) slots <- struct{}{} return } @@ -910,7 +910,7 @@ func (srv *Server) listenLoop() { remoteIP := netutil.AddrIP(fd.RemoteAddr()) if err := srv.checkInboundConn(fd, remoteIP); err != nil { - srv.log.Debug("Rejected inbound connnection", "addr", fd.RemoteAddr(), "err", err) + srv.log.Trace("Rejected inbound connnection", "addr", fd.RemoteAddr(), "err", err) fd.Close() slots <- struct{}{} continue diff --git a/p2p/simulations/adapters/exec.go b/p2p/simulations/adapters/exec.go index 924fcf651be..5b09d2b446c 100644 --- a/p2p/simulations/adapters/exec.go +++ b/p2p/simulations/adapters/exec.go @@ -224,7 +224,7 @@ func (n *ExecNode) Start(snapshots map[string][]byte) error { } client, err := rpc.DialWebsocket(ctx, status.WSEndpoint, "") if err != nil { - return fmt.Errorf("can't connect to RPC server: %v", err) + return fmt.Errorf("can't connect to RPC server: %w", err) } // Node ready :) @@ -472,7 +472,7 @@ func startExecNodeStack() (*node.Node, error) { } var conf execNodeConfig if err := json.Unmarshal([]byte(confEnv), &conf); err != nil { - return nil, fmt.Errorf("error decoding %s: %v", envNodeConfig, err) + return nil, fmt.Errorf("error decoding %s: %w", envNodeConfig, err) } // create enode record @@ -487,7 +487,7 @@ func startExecNodeStack() (*node.Node, error) { // initialize the devp2p stack stack, err := node.New(&conf.Stack) if err != nil { - return nil, fmt.Errorf("error creating node stack: %v", err) + return nil, fmt.Errorf("error creating node stack: %w", err) } // Register the services, collecting them into a map so they can @@ -520,7 +520,7 @@ func startExecNodeStack() (*node.Node, error) { }}) if err = stack.Start(); err != nil { - err = fmt.Errorf("error starting stack: %v", err) + err = fmt.Errorf("error starting stack: %w", err) } return stack, err } diff --git a/p2p/simulations/mocker.go b/p2p/simulations/mocker.go index a3328e0cb55..9c3f76d2e28 100644 --- a/p2p/simulations/mocker.go +++ b/p2p/simulations/mocker.go @@ -76,18 +76,18 @@ func startStop(net *Network, quit chan struct{}, nodeCount int) { id := nodes[rand.Intn(len(nodes))] log.Info("stopping node", "id", id) if err := net.Stop(id); err != nil { - log.Error("error stopping node", "id", id, "err", err) + log.Error("Error stopping node", "id", id, "err", err) return } select { case <-quit: - log.Info("Terminating simulation loop") + log.Info("Terminating simulation loop ...") return case <-time.After(3 * time.Second): } - log.Debug("starting node", "id", id) + log.Trace("Starting node ...", "id", id) if err := net.Start(id); err != nil { log.Error("error starting node", "id", id, "err", err) return @@ -147,7 +147,7 @@ func probabilistic(net *Network, quit chan struct{}, nodeCount int) { return case <-time.After(randWait): } - log.Debug(fmt.Sprintf("node %v shutting down", nodes[i])) + log.Trace(fmt.Sprintf("Node %v shutting down ...", nodes[i])) err := net.Stop(nodes[i]) if err != nil { log.Error("Error stopping node", "node", nodes[i]) @@ -186,7 +186,7 @@ func connectNodesInRing(net *Network, nodeCount int) ([]enode.ID, error) { log.Error("Error starting a node!", "err", err) return nil, err } - log.Debug(fmt.Sprintf("node %v starting up", id)) + log.Trace(fmt.Sprintf("Node %v starting up", id)) } for i, id := range ids { peerID := ids[(i+1)%len(ids)] diff --git a/p2p/simulations/network.go b/p2p/simulations/network.go index 47458664fc9..68e3c40bb00 100644 --- a/p2p/simulations/network.go +++ b/p2p/simulations/network.go @@ -199,12 +199,12 @@ func (net *Network) startWithSnapshots(id enode.ID, snapshots map[string][]byte) // subscribe to peer events client, err := node.Client() if err != nil { - return fmt.Errorf("error getting rpc client for node %v: %s", id, err) + return fmt.Errorf("error getting rpc client for node %v: %w", id, err) } events := make(chan *p2p.PeerEvent) sub, err := client.Subscribe(context.Background(), "admin", events, "peerEvents") if err != nil { - return fmt.Errorf("error getting peer events for node %v: %s", id, err) + return fmt.Errorf("error getting peer events for node %v: %w", id, err) } go net.watchPeerEvents(id, events, sub) return nil @@ -311,7 +311,7 @@ func (net *Network) Connect(oneID, otherID enode.ID) error { } func (net *Network) connect(oneID, otherID enode.ID) error { - log.Debug("Connecting nodes with addPeer", "id", oneID, "other", otherID) + log.Trace("Connecting nodes with addPeer", "id", oneID, "other", otherID) conn, err := net.initConn(oneID, otherID) if err != nil { return err @@ -683,7 +683,7 @@ func (net *Network) initConn(oneID, otherID enode.ID) (*Conn, error) { log.Trace("Nodes not up", "err", err) return nil, fmt.Errorf("nodes not up: %v", err) } - log.Debug("Connection initiated", "id", oneID, "other", otherID) + log.Trace("Connection initiated", "id", oneID, "other", otherID) conn.initiated = time.Now() return conn, nil } @@ -691,7 +691,7 @@ func (net *Network) initConn(oneID, otherID enode.ID) (*Conn, error) { // Shutdown stops all nodes in the network and closes the quit channel func (net *Network) Shutdown() { for _, node := range net.Nodes { - log.Debug("Stopping node", "id", node.ID()) + log.Trace("Stopping node", "id", node.ID()) if err := node.Stop(); err != nil { log.Warn("Can't stop node", "id", node.ID(), "err", err) } diff --git a/p2p/simulations/network_test.go b/p2p/simulations/network_test.go index b780226cc9d..98fb7a6bdfc 100644 --- a/p2p/simulations/network_test.go +++ b/p2p/simulations/network_test.go @@ -118,7 +118,7 @@ OUTER: checkIds[ev.Conn.One] = append(checkIds[ev.Conn.One], ev.Conn.Other) checkIds[ev.Conn.Other] = append(checkIds[ev.Conn.Other], ev.Conn.One) connEventCount-- - log.Debug("ev", "count", connEventCount) + log.Trace("ev", "count", connEventCount) if connEventCount == 0 { break OUTER } @@ -135,7 +135,7 @@ OUTER: if err != nil { t.Fatal(err) } - log.Debug("snapshot taken", "nodes", len(snap.Nodes), "conns", len(snap.Conns), "json", string(j)) + log.Trace("snapshot taken", "nodes", len(snap.Nodes), "conns", len(snap.Conns), "json", string(j)) // verify that the snap element numbers check out if len(checkIds) != len(snap.Conns) || len(checkIds) != len(snap.Nodes) { @@ -214,11 +214,11 @@ OuterTwo: if !ev.Conn.Up { t.Fatalf("unexpected disconnect: %v -> %v", ev.Conn.One, ev.Conn.Other) } - log.Debug("conn", "on", ev.Conn.One, "other", ev.Conn.Other) + log.Trace("conn", "on", ev.Conn.One, "other", ev.Conn.Other) checkIds[ev.Conn.One] = append(checkIds[ev.Conn.One], ev.Conn.Other) checkIds[ev.Conn.Other] = append(checkIds[ev.Conn.Other], ev.Conn.One) connEventCount-- - log.Debug("ev", "count", connEventCount) + log.Trace("ev", "count", connEventCount) if connEventCount == 0 { break OuterTwo } @@ -760,7 +760,7 @@ func benchmarkMinimalServiceTmp(b *testing.B) { defer cancel() for nodid, peers := range protoCMap { for peerid, peerC := range peers { - log.Debug("getting ", "node", nodid, "peer", peerid) + log.Trace("getting ", "node", nodid, "peer", peerid) select { case <-ctx.Done(): b.Fatal(ctx.Err()) diff --git a/p2p/transport.go b/p2p/transport.go index 30dca9417a5..9b28c1d686e 100644 --- a/p2p/transport.go +++ b/p2p/transport.go @@ -150,7 +150,7 @@ func (t *rlpxTransport) doProtoHandshake(our *protoHandshake) (their *protoHands return nil, err } if err := <-werr; err != nil { - return nil, fmt.Errorf("write error: %v", err) + return nil, fmt.Errorf("write error: %w", err) } // If the protocol version supports Snappy encoding, upgrade immediately t.conn.SetSnappy(their.Version >= snappyProtocolVersion) diff --git a/params/config.go b/params/config.go index b925ab130cb..0744e79a669 100644 --- a/params/config.go +++ b/params/config.go @@ -46,7 +46,7 @@ var ( ErigonGenesisHash = common.HexToHash("0xfecd5c85712e36f30f09ba3a42386b42c46b5ba5395a4246b952e655f9aa0f58") SokolGenesisHash = common.HexToHash("0x5b28c1bfd3a15230c9a46b399cd0f9a6920d432e85381cc6a140b06e8410112f") KovanGenesisHash = common.HexToHash("0xa3c565fc15c7478862d50ccd6561e3c06b24cc509bf388941c25ea985ce32cb9") - FermionGenesisHash = common.HexToHash("0xa3c565fc15c7478862d50ccd6561e3c06b24cc509bf388941c25ea985ce32cb9") + FermionGenesisHash = common.HexToHash("0xcb6399165d4b9460d2462a71f4574984df2a92fe513b1ab64d69573426ecc75f") ) var ( @@ -56,7 +56,7 @@ var ( var ( SokolGenesisStateRoot = common.HexToHash("0xfad4af258fd11939fae0c6c6eec9d340b1caac0b0196fd9a1bc3f489c5bf00b3") KovanGenesisStateRoot = common.HexToHash("0x2480155b48a1cea17d67dbfdfaafe821c1d19cdd478c5358e8ec56dec24502b2") - FermionGenesisStateRoot = common.HexToHash("0x2480155b48a1cea17d67dbfdfaafe821c1d19cdd478c5358e8ec56dec24502b2") + FermionGenesisStateRoot = common.HexToHash("0x08982dc16236c51b6d9aff8b76cd0faa7067eb55eba62395d5a82649d8fb73c4") ) var ( diff --git a/params/version.go b/params/version.go index f32b2c68a75..354c84b40bf 100644 --- a/params/version.go +++ b/params/version.go @@ -33,7 +33,7 @@ var ( const ( VersionMajor = 2021 // Major version component of the current release VersionMinor = 10 // Minor version component of the current release - VersionMicro = 1 // Patch version component of the current release + VersionMicro = 2 // Patch version component of the current release VersionModifier = "alpha" // Patch version component of the current release VersionKeyCreated = "ErigonVersionCreated" VersionKeyFinished = "ErigonVersionFinished" diff --git a/rlp/decode.go b/rlp/decode.go index d3022b27301..fefca41ff3c 100644 --- a/rlp/decode.go +++ b/rlp/decode.go @@ -38,13 +38,15 @@ import ( var EOL = errors.New("rlp: end of list") var ( - ErrExpectedString = errors.New("rlp: expected String or Byte") - ErrExpectedList = errors.New("rlp: expected List") - ErrCanonInt = errors.New("rlp: non-canonical integer format") - ErrCanonSize = errors.New("rlp: non-canonical size information") - ErrElemTooLarge = errors.New("rlp: element is larger than containing list") - ErrValueTooLarge = errors.New("rlp: value size exceeds available input length") - ErrMoreThanOneValue = errors.New("rlp: input contains more than one value") + ErrExpectedString = errors.New("rlp: expected String or Byte") + ErrExpectedList = errors.New("rlp: expected List") + ErrCanonInt = errors.New("rlp: non-canonical integer format") + ErrCanonSize = errors.New("rlp: non-canonical size information") + ErrElemTooLarge = errors.New("rlp: element is larger than containing list") + ErrValueTooLarge = errors.New("rlp: value size exceeds available input length") + ErrMoreThanOneValue = errors.New("rlp: input contains more than one value") + ErrWrongTxTypePrefix = errors.New("rlp: only 1-byte tx type prefix is supported") + ErrUnknownTxTypePrefix = errors.New("rlp: unknown tx type prefix") // internal errors errNotInList = errors.New("rlp: call of ListEnd outside of any list") @@ -66,7 +68,9 @@ func IsDecodeError(err error) bool { errors.Is(err, ErrCanonSize) || errors.Is(err, ErrElemTooLarge) || errors.Is(err, ErrValueTooLarge) || - errors.Is(err, ErrMoreThanOneValue) + errors.Is(err, ErrMoreThanOneValue) || + errors.Is(err, ErrWrongTxTypePrefix) || + errors.Is(err, ErrUnknownTxTypePrefix) } // Decoder is implemented by types that require custom RLP decoding rules or need to decode diff --git a/rpc/client.go b/rpc/client.go index bf5a76e050a..172b2d31696 100644 --- a/rpc/client.go +++ b/rpc/client.go @@ -558,19 +558,19 @@ func (c *Client) dispatch(codec ServerCodec) { // Read path: case op := <-c.readOp: if op.batch { - conn.handler.handleBatch(op.msgs, nil) + conn.handler.handleBatch(op.msgs) } else { - conn.handler.handleMsg(op.msgs[0], nil) + conn.handler.handleMsg(op.msgs[0]) } case err := <-c.readErr: - conn.handler.log.Debug("RPC connection read error", "err", err) + conn.handler.log.Trace("RPC connection read error", "err", err) conn.close(err, lastOp) reading = false // Reconnect: case newcodec := <-c.reconnected: - log.Debug("RPC client reconnected", "reading", reading, "conn", newcodec.remoteAddr()) + log.Trace("RPC client reconnected", "reading", reading, "conn", newcodec.remoteAddr()) if reading { // Wait for the previous read loop to exit. This is a rare case which // happens if this loop isn't notified in time after the connection breaks. diff --git a/rpc/client_test.go b/rpc/client_test.go index 0d42347375e..4a009129879 100644 --- a/rpc/client_test.go +++ b/rpc/client_test.go @@ -613,7 +613,7 @@ func (l *flakeyListener) Accept() (net.Conn, error) { if err == nil { timeout := time.Duration(rand.Int63n(int64(l.maxKillTimeout))) time.AfterFunc(timeout, func() { - log.Debug(fmt.Sprintf("killing conn %v after %v", c.LocalAddr(), timeout)) + log.Trace(fmt.Sprintf("killing conn %v after %v", c.LocalAddr(), timeout)) c.Close() }) } diff --git a/rpc/handler.go b/rpc/handler.go index 39784cb60b0..aa0fcf38ded 100644 --- a/rpc/handler.go +++ b/rpc/handler.go @@ -101,7 +101,7 @@ func newHandler(connCtx context.Context, conn jsonWriter, idgen func() ID, reg * } // handleBatch executes all messages in a batch and returns the responses. -func (h *handler) handleBatch(msgs []*jsonrpcMessage, stream *jsoniter.Stream) { +func (h *handler) handleBatch(msgs []*jsonrpcMessage) { // Emit error response for empty batches: if len(msgs) == 0 { h.startCallProc(func(cp *callProc) { @@ -172,26 +172,19 @@ func (h *handler) handleBatch(msgs []*jsonrpcMessage, stream *jsoniter.Stream) { } // handleMsg handles a single message. -func (h *handler) handleMsg(msg *jsonrpcMessage, stream *jsoniter.Stream) { +func (h *handler) handleMsg(msg *jsonrpcMessage) { if ok := h.handleImmediate(msg); ok { return } h.startCallProc(func(cp *callProc) { - needWriteStream := false - if stream == nil { - stream = jsoniter.NewStream(jsoniter.ConfigDefault, nil, 4096) - needWriteStream = true - } + stream := jsoniter.NewStream(jsoniter.ConfigDefault, nil, 4096) answer := h.handleCallMsg(cp, msg, stream) h.addSubscriptions(cp.notifiers) if answer != nil { - buffer, _ := json.Marshal(answer) - stream.Write(json.RawMessage(buffer)) - } - if needWriteStream { - h.conn.writeJSON(cp.ctx, json.RawMessage(stream.Buffer())) + h.conn.writeJSON(cp.ctx, answer) } else { - stream.Write([]byte("\n")) + _ = stream.Flush() + h.conn.writeJSON(cp.ctx, json.RawMessage(stream.Buffer())) } for _, n := range cp.notifiers { n.activate() @@ -303,7 +296,7 @@ func (h *handler) handleImmediate(msg *jsonrpcMessage) bool { func (h *handler) handleSubscriptionResult(msg *jsonrpcMessage) { var result subscriptionResult if err := json.Unmarshal(msg.Params, &result); err != nil { - h.log.Debug("Dropping invalid subscription message") + h.log.Trace("Dropping invalid subscription message") return } if h.clientSubs[result.ID] != nil { @@ -315,7 +308,7 @@ func (h *handler) handleSubscriptionResult(msg *jsonrpcMessage) { func (h *handler) handleResponse(msg *jsonrpcMessage) { op := h.respWait[string(msg.ID)] if op == nil { - h.log.Debug("Unsolicited RPC response", "reqid", idForLog{msg.ID}) + h.log.Trace("Unsolicited RPC response", "reqid", idForLog{msg.ID}) return } delete(h.respWait, string(msg.ID)) @@ -344,7 +337,7 @@ func (h *handler) handleCallMsg(ctx *callProc, msg *jsonrpcMessage, stream *json switch { case msg.isNotification(): h.handleCall(ctx, msg, stream) - h.log.Debug("Served", "t", time.Since(start), "method", msg.Method, "params", string(msg.Params)) + h.log.Trace("Served", "t", time.Since(start), "method", msg.Method, "params", string(msg.Params)) return nil case msg.isCall(): resp := h.handleCall(ctx, msg, stream) @@ -357,7 +350,7 @@ func (h *handler) handleCallMsg(ctx *callProc, msg *jsonrpcMessage, stream *json "err", resp.Error.Message) } } - h.log.Debug("Served", "t", time.Since(start), "method", msg.Method, "reqid", idForLog{msg.ID}, "params", string(msg.Params)) + h.log.Trace("Served", "t", time.Since(start), "method", msg.Method, "reqid", idForLog{msg.ID}, "params", string(msg.Params)) return resp case msg.hasValidID(): return msg.errorResponse(&invalidRequestError{"invalid request"}) diff --git a/rpc/http.go b/rpc/http.go index c1d0ab0ad16..8ffb288c103 100644 --- a/rpc/http.go +++ b/rpc/http.go @@ -29,8 +29,6 @@ import ( "net/url" "sync" "time" - - jsoniter "github.com/json-iterator/go" ) const ( @@ -144,7 +142,7 @@ func (c *Client) sendHTTP(ctx context.Context, op *requestOp, msg interface{}) e if respBody != nil { buf := new(bytes.Buffer) if _, err2 := buf.ReadFrom(respBody); err2 == nil { - return fmt.Errorf("%v: %v", err, buf.String()) + return fmt.Errorf("%w: %v", err, buf.String()) } } return err @@ -253,8 +251,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { w.Header().Set("content-type", contentType) codec := newHTTPServerConn(r, w) defer codec.close() - stream := jsoniter.NewStream(jsoniter.ConfigDefault, w, 4096) - s.serveSingleRequest(ctx, codec, stream) + s.serveSingleRequest(ctx, codec) } // validateRequest returns a non-zero response code and error message if the diff --git a/rpc/json.go b/rpc/json.go index 4d7fdcb31b2..a0d8b5dc6f9 100644 --- a/rpc/json.go +++ b/rpc/json.go @@ -315,7 +315,7 @@ func parseArgumentArray(dec *json.Decoder, types []reflect.Type) ([]reflect.Valu } argval := reflect.New(types[i]) if err := dec.Decode(argval.Interface()); err != nil { - return args, fmt.Errorf("invalid argument %d: %v", i, err) + return args, fmt.Errorf("invalid argument %d: %w", i, err) } if argval.IsNil() && types[i].Kind() != reflect.Ptr { return args, fmt.Errorf("missing value for required argument %d", i) diff --git a/rpc/server.go b/rpc/server.go index bcfcaa9b5a2..b92487bb1d7 100644 --- a/rpc/server.go +++ b/rpc/server.go @@ -22,7 +22,6 @@ import ( "sync/atomic" mapset "github.com/deckarep/golang-set" - jsoniter "github.com/json-iterator/go" "github.com/ledgerwatch/log/v3" ) @@ -100,7 +99,7 @@ func (s *Server) ServeCodec(codec ServerCodec, options CodecOption) { // serveSingleRequest reads and processes a single RPC request from the given codec. This // is used to serve HTTP connections. Subscriptions and reverse calls are not allowed in // this mode. -func (s *Server) serveSingleRequest(ctx context.Context, codec ServerCodec, stream *jsoniter.Stream) { +func (s *Server) serveSingleRequest(ctx context.Context, codec ServerCodec) { // Don't serve if server is stopped. if atomic.LoadInt32(&s.run) == 0 { return @@ -118,9 +117,9 @@ func (s *Server) serveSingleRequest(ctx context.Context, codec ServerCodec, stre return } if batch { - h.handleBatch(reqs, stream) + h.handleBatch(reqs) } else { - h.handleMsg(reqs[0], stream) + h.handleMsg(reqs[0]) } } @@ -129,7 +128,7 @@ func (s *Server) serveSingleRequest(ctx context.Context, codec ServerCodec, stre // subscriptions. func (s *Server) Stop() { if atomic.CompareAndSwapInt32(&s.run, 1, 0) { - log.Debug("RPC server shutting down") + log.Info("RPC server shutting down") s.codecs.Each(func(c interface{}) bool { c.(ServerCodec).close() return true diff --git a/rpc/subscription_test.go b/rpc/subscription_test.go index 066203a66a0..f2474414a35 100644 --- a/rpc/subscription_test.go +++ b/rpc/subscription_test.go @@ -195,13 +195,13 @@ func waitForMessages(in *json.Decoder, successes chan subConfirmation, notificat func readAndValidateMessage(in *json.Decoder) (*subConfirmation, *subscriptionResult, error) { var msg jsonrpcMessage if err := in.Decode(&msg); err != nil { - return nil, nil, fmt.Errorf("decode error: %v", err) + return nil, nil, fmt.Errorf("decode error: %w", err) } switch { case msg.isNotification(): var res subscriptionResult if err := json.Unmarshal(msg.Params, &res); err != nil { - return nil, nil, fmt.Errorf("invalid subscription result: %v", err) + return nil, nil, fmt.Errorf("invalid subscription result: %w", err) } return nil, &res, nil case msg.isResponse(): @@ -209,7 +209,7 @@ func readAndValidateMessage(in *json.Decoder) (*subConfirmation, *subscriptionRe if msg.Error != nil { return nil, nil, msg.Error } else if err := json.Unmarshal(msg.Result, &c.subid); err != nil { - return nil, nil, fmt.Errorf("invalid response: %v", err) + return nil, nil, fmt.Errorf("invalid response: %w", err) } else { json.Unmarshal(msg.ID, &c.reqid) return &c, nil, nil diff --git a/rpc/websocket.go b/rpc/websocket.go index ea6d12f9eb5..f75f16980a1 100644 --- a/rpc/websocket.go +++ b/rpc/websocket.go @@ -57,7 +57,7 @@ func (s *Server) WebsocketHandler(allowedOrigins []string, compression bool) htt return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { conn, err := upgrader.Upgrade(w, r, nil) if err != nil { - log.Debug("WebSocket upgrade failed", "err", err) + log.Warn("WebSocket upgrade failed", "err", err) return } codec := newWebsocketCodec(conn) @@ -87,7 +87,7 @@ func wsHandshakeValidator(allowedOrigins []string) func(*http.Request) bool { origins.Add("http://" + hostname) } } - log.Debug(fmt.Sprintf("Allowed origin(s) for WS RPC interface %v", origins.ToSlice())) + log.Trace(fmt.Sprintf("Allowed origin(s) for WS RPC interface %v", origins.ToSlice())) f := func(req *http.Request) bool { // Skip origin verification if no Origin header is present. The origin check diff --git a/tests/block_test_util.go b/tests/block_test_util.go index 1500c3606da..bdde498575d 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -128,7 +128,7 @@ func (t *BlockTest) Run(tst *testing.T, _ bool) error { tx, err1 := m.DB.BeginRo(context.Background()) if err1 != nil { - return fmt.Errorf("blockTest create tx: %v", err1) + return fmt.Errorf("blockTest create tx: %w", err1) } defer tx.Rollback() cmlast := rawdb.ReadHeadBlockHash(tx) @@ -137,7 +137,7 @@ func (t *BlockTest) Run(tst *testing.T, _ bool) error { } newDB := state.New(state.NewPlainStateReader(tx)) if err = t.validatePostState(newDB); err != nil { - return fmt.Errorf("post state validation failed: %v", err) + return fmt.Errorf("post state validation failed: %w", err) } return t.validateImportedHeaders(tx, validBlocks) } @@ -180,7 +180,7 @@ func (t *BlockTest) insertBlocks(m *stages.MockSentry) ([]btBlock, error) { if b.BlockHeader == nil { continue // OK - block is supposed to be invalid, continue with next block } else { - return nil, fmt.Errorf("block RLP decoding failed when expected to succeed: %v", err) + return nil, fmt.Errorf("block RLP decoding failed when expected to succeed: %w", err) } } // RLP decoding worked, try to insert into chain: @@ -189,7 +189,7 @@ func (t *BlockTest) insertBlocks(m *stages.MockSentry) ([]btBlock, error) { if b.BlockHeader == nil { continue // OK - block is supposed to be invalid, continue with next block } else { - return nil, fmt.Errorf("block #%v insertion into chain failed: %v", cb.Number(), err1) + return nil, fmt.Errorf("block #%v insertion into chain failed: %w", cb.Number(), err1) } } else if b.BlockHeader == nil { if err := m.DB.View(context.Background(), func(tx kv.Tx) error { @@ -210,7 +210,7 @@ func (t *BlockTest) insertBlocks(m *stages.MockSentry) ([]btBlock, error) { } // validate RLP decoding by checking all values against test file JSON if err = validateHeader(b.BlockHeader, cb.Header()); err != nil { - return nil, fmt.Errorf("deserialised block header validation failed: %v", err) + return nil, fmt.Errorf("deserialised block header validation failed: %w", err) } validBlocks = append(validBlocks, b) } @@ -305,7 +305,7 @@ func (t *BlockTest) validateImportedHeaders(tx kv.Tx, validBlocks []btBlock) err // be part of the longest chain until last block is imported. for b := rawdb.ReadCurrentBlock(tx); b != nil && b.NumberU64() != 0; { if err := validateHeader(bmap[b.Hash()].BlockHeader, b.Header()); err != nil { - return fmt.Errorf("imported block header validation failed: %v", err) + return fmt.Errorf("imported block header validation failed: %w", err) } b, _ = rawdb.ReadBlockByHash(tx, b.Header().ParentHash) } diff --git a/tests/init_test.go b/tests/init_test.go index 45bfe1ba2ad..547720a06fc 100644 --- a/tests/init_test.go +++ b/tests/init_test.go @@ -47,12 +47,12 @@ var ( func readJSON(reader io.Reader, value interface{}) error { data, err := ioutil.ReadAll(reader) if err != nil { - return fmt.Errorf("error reading JSON file: %v", err) + return fmt.Errorf("error reading JSON file: %w", err) } if err = json.Unmarshal(data, &value); err != nil { if syntaxerr, ok := err.(*json.SyntaxError); ok { line := findLine(data, syntaxerr.Offset) - return fmt.Errorf("JSON syntax error at line %v: %v", line, err) + return fmt.Errorf("JSON syntax error at line %v: %w", line, err) } return err } diff --git a/tests/rlp_test_util.go b/tests/rlp_test_util.go index 5fc99c63641..553de0f8506 100644 --- a/tests/rlp_test_util.go +++ b/tests/rlp_test_util.go @@ -71,7 +71,7 @@ func (t *RLPTest) Run() error { in := translateJSON(t.In) b, err := rlp.EncodeToBytes(in) if err != nil { - return fmt.Errorf("encode failed: %v", err) + return fmt.Errorf("encode failed: %w", err) } if !bytes.Equal(b, outb) { return fmt.Errorf("encode produced %x, want %x", b, outb) @@ -85,7 +85,7 @@ func checkDecodeInterface(b []byte, isValid bool) error { err := rlp.DecodeBytes(b, new(interface{})) switch { case isValid && err != nil: - return fmt.Errorf("decoding failed: %v", err) + return fmt.Errorf("decoding failed: %w", err) case !isValid && err == nil: return fmt.Errorf("decoding of invalid value succeeded") } diff --git a/tests/state_test_util.go b/tests/state_test_util.go index 82cfd4dc2b7..cc1cbca8897 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -285,7 +285,7 @@ func (t *StateTest) RunNoVerify(rules params.Rules, tx kv.RwTx, subtest StateSub root, err := trie.CalcRoot("", tx) if err != nil { - return nil, common.Hash{}, fmt.Errorf("error calculating state root: %v", err) + return nil, common.Hash{}, fmt.Errorf("error calculating state root: %w", err) } return statedb, root, nil @@ -341,7 +341,7 @@ func (tx *stTransaction) toMessage(ps stPostState, baseFee *big.Int) (core.Messa if len(tx.PrivateKey) > 0 { key, err := crypto.ToECDSA(tx.PrivateKey) if err != nil { - return nil, fmt.Errorf("invalid private key: %v", err) + return nil, fmt.Errorf("invalid private key: %w", err) } from = crypto.PubkeyToAddress(key.PublicKey) } @@ -350,7 +350,7 @@ func (tx *stTransaction) toMessage(ps stPostState, baseFee *big.Int) (core.Messa if tx.To != "" { to = new(common.Address) if err := to.UnmarshalText([]byte(tx.To)); err != nil { - return nil, fmt.Errorf("invalid to address: %v", err) + return nil, fmt.Errorf("invalid to address: %w", err) } } diff --git a/tests/transaction_test_util.go b/tests/transaction_test_util.go index 2d94d10cb1b..9c70b008cd6 100644 --- a/tests/transaction_test_util.go +++ b/tests/transaction_test_util.go @@ -92,7 +92,7 @@ func (tt *TransactionTest) Run(config *params.ChainConfig) error { } // Should resolve the right address if err != nil { - return fmt.Errorf("got error, expected none: %v", err) + return fmt.Errorf("got error, expected none: %w", err) } if sender == nil { return fmt.Errorf("sender was nil, should be %x", common.Address(testcase.fork.Sender)) diff --git a/tests/vm_test_util.go b/tests/vm_test_util.go index 163b1b2f6bc..a2fa376930d 100644 --- a/tests/vm_test_util.go +++ b/tests/vm_test_util.go @@ -83,7 +83,7 @@ type vmExecMarshaling struct { func (t *VMTest) Run(tx kv.RwTx, vmconfig vm.Config, blockNr uint64) error { state, err := MakePreState(params.MainnetChainConfig.Rules(blockNr), tx, t.json.Pre, blockNr) if err != nil { - return fmt.Errorf("error in MakePreState: %v", err) + return fmt.Errorf("error in MakePreState: %w", err) } ret, gasRemaining, err := t.exec(state, vmconfig) // err is not supposed to be checked here, because in VM tests, the failure @@ -117,7 +117,7 @@ func (t *VMTest) Run(tx kv.RwTx, vmconfig vm.Config, blockNr uint64) error { } root, err := trie.CalcRoot("test", tx) if err != nil { - return fmt.Errorf("Error calculating state root: %v", err) + return fmt.Errorf("Error calculating state root: %w", err) } if t.json.PostStateRoot != (common.Hash{}) && root != t.json.PostStateRoot { return fmt.Errorf("post state root mismatch, got %x, want %x", root, t.json.PostStateRoot) diff --git a/turbo/cli/default_flags.go b/turbo/cli/default_flags.go index d6a49857586..3750f55161c 100644 --- a/turbo/cli/default_flags.go +++ b/turbo/cli/default_flags.go @@ -48,7 +48,7 @@ var DefaultFlags = []cli.Flag{ TLSCertFlag, TLSKeyFlag, TLSCACertFlag, - StateStreamFlag, + StateStreamDisableFlag, SyncLoopThrottleFlag, BadBlockFlag, utils.ListenPortFlag, diff --git a/turbo/cli/flags.go b/turbo/cli/flags.go index 575caa22a7b..8918c43d131 100644 --- a/turbo/cli/flags.go +++ b/turbo/cli/flags.go @@ -158,9 +158,9 @@ var ( Usage: "Specify certificate authority", Value: "", } - StateStreamFlag = cli.BoolFlag{ - Name: "state.stream", - Usage: "Enable streaming of state changes from core to RPC daemon", + StateStreamDisableFlag = cli.BoolFlag{ + Name: "state.stream.disable", + Usage: "Disable streaming of state changes from core to RPC daemon", } // Throttling Flags @@ -221,7 +221,7 @@ func ApplyFlagsForEthConfig(ctx *cli.Context, cfg *ethconfig.Config) { } cfg.ExternalSnapshotDownloaderAddr = ctx.GlobalString(ExternalSnapshotDownloaderAddrFlag.Name) - cfg.StateStream = cfg.TxPool.V2 || ctx.GlobalBool(StateStreamFlag.Name) + cfg.StateStream = !ctx.GlobalBool(StateStreamDisableFlag.Name) cfg.BlockDownloaderWindow = ctx.GlobalInt(BlockDownloaderWindowFlag.Name) if ctx.GlobalString(SyncLoopThrottleFlag.Name) != "" { @@ -311,8 +311,9 @@ func ApplyFlagsForEthConfigCobra(f *pflag.FlagSet, cfg *ethconfig.Config) { if v := f.String(ExternalSnapshotDownloaderAddrFlag.Name, ExternalSnapshotDownloaderAddrFlag.Value, ExternalSnapshotDownloaderAddrFlag.Usage); v != nil { cfg.ExternalSnapshotDownloaderAddr = *v } - if v := f.Bool(StateStreamFlag.Name, false, StateStreamFlag.Usage); v != nil { - cfg.StateStream = *v + cfg.StateStream = true + if v := f.Bool(StateStreamDisableFlag.Name, false, StateStreamDisableFlag.Usage); v != nil { + cfg.StateStream = false } } diff --git a/turbo/snapshotsync/client.go b/turbo/snapshotsync/client.go index 597db6056fd..eb3e4a7d889 100644 --- a/turbo/snapshotsync/client.go +++ b/turbo/snapshotsync/client.go @@ -1,11 +1,14 @@ package snapshotsync -import "google.golang.org/grpc" +import ( + "github.com/ledgerwatch/erigon-lib/gointerfaces/snapshotsync" + "google.golang.org/grpc" +) //go:generate ls ./../../interfaces/snapshot_downloader //go:generate protoc --go_out=. --go-grpc_out=. --proto_path=./../../interfaces/snapshot_downloader "external_downloader.proto" -I=. -I=./../../build/include/google -func NewClient(addr string) (DownloaderClient, func() error, error) { +func NewClient(addr string) (snapshotsync.DownloaderClient, func() error, error) { opts := []grpc.DialOption{ grpc.WithInsecure(), } @@ -15,5 +18,5 @@ func NewClient(addr string) (DownloaderClient, func() error, error) { return nil, nil, err } - return NewDownloaderClient(conn), conn.Close, nil + return snapshotsync.NewDownloaderClient(conn), conn.Close, nil } diff --git a/turbo/snapshotsync/const.go b/turbo/snapshotsync/const.go index 349b08e3dc1..699f44c34f8 100644 --- a/turbo/snapshotsync/const.go +++ b/turbo/snapshotsync/const.go @@ -4,6 +4,7 @@ import ( "errors" "github.com/anacrolix/torrent/metainfo" + "github.com/ledgerwatch/erigon-lib/gointerfaces/snapshotsync" "github.com/ledgerwatch/erigon/params" ) @@ -22,19 +23,19 @@ const ( ) var ( - TorrentHashes = map[uint64]map[SnapshotType]metainfo.Hash{ + TorrentHashes = map[uint64]map[snapshotsync.SnapshotType]metainfo.Hash{ params.MainnetChainConfig.ChainID.Uint64(): { - SnapshotType_headers: metainfo.NewHashFromHex(HeadersSnapshotHash), - SnapshotType_bodies: metainfo.NewHashFromHex(BlocksSnapshotHash), - SnapshotType_state: metainfo.NewHashFromHex(StateSnapshotHash), + snapshotsync.SnapshotType_headers: metainfo.NewHashFromHex(HeadersSnapshotHash), + snapshotsync.SnapshotType_bodies: metainfo.NewHashFromHex(BlocksSnapshotHash), + snapshotsync.SnapshotType_state: metainfo.NewHashFromHex(StateSnapshotHash), }, } ErrInvalidSnapshot = errors.New("this snapshot for this chainID not supported ") ) -func GetAvailableSnapshotTypes(chainID uint64) []SnapshotType { +func GetAvailableSnapshotTypes(chainID uint64) []snapshotsync.SnapshotType { v := TorrentHashes[chainID] - res := make([]SnapshotType, 0, len(v)) + res := make([]snapshotsync.SnapshotType, 0, len(v)) for i := range v { res = append(res, i) } diff --git a/turbo/snapshotsync/downloader.go b/turbo/snapshotsync/downloader.go index 9aedb3bf6f5..0d42d0688d6 100644 --- a/turbo/snapshotsync/downloader.go +++ b/turbo/snapshotsync/downloader.go @@ -10,6 +10,7 @@ import ( "time" "github.com/anacrolix/torrent/bencode" + "github.com/ledgerwatch/erigon-lib/gointerfaces/snapshotsync" "github.com/ledgerwatch/erigon-lib/kv" lg "github.com/anacrolix/log" @@ -117,7 +118,7 @@ func (cli *Client) AddTorrentSpec(snapshotName string, snapshotHash metainfo.Has return t, err } -func (cli *Client) AddTorrent(ctx context.Context, db kv.RwTx, snapshotType SnapshotType, networkID uint64) error { //nolint: interfacer +func (cli *Client) AddTorrent(ctx context.Context, db kv.RwTx, snapshotType snapshotsync.SnapshotType, networkID uint64) error { //nolint: interfacer infoHashBytes, infoBytes, err := getTorrentSpec(db, snapshotType.String(), networkID) if err != nil { return err @@ -185,25 +186,25 @@ func (cli *Client) AddSnapshotsTorrents(ctx context.Context, db kv.RwTx, network if mode.Headers { eg.Go(func() error { - return cli.AddTorrent(ctx, db, SnapshotType_headers, networkId) + return cli.AddTorrent(ctx, db, snapshotsync.SnapshotType_headers, networkId) }) } if mode.Bodies { eg.Go(func() error { - return cli.AddTorrent(ctx, db, SnapshotType_bodies, networkId) + return cli.AddTorrent(ctx, db, snapshotsync.SnapshotType_bodies, networkId) }) } if mode.State { eg.Go(func() error { - return cli.AddTorrent(ctx, db, SnapshotType_state, networkId) + return cli.AddTorrent(ctx, db, snapshotsync.SnapshotType_state, networkId) }) } if mode.Receipts { eg.Go(func() error { - return cli.AddTorrent(ctx, db, SnapshotType_receipts, networkId) + return cli.AddTorrent(ctx, db, snapshotsync.SnapshotType_receipts, networkId) }) } err := eg.Wait() @@ -256,8 +257,8 @@ func (cli *Client) Download() { } } -func (cli *Client) GetSnapshots(tx kv.Tx, networkID uint64) (map[SnapshotType]*SnapshotsInfo, error) { - mp := make(map[SnapshotType]*SnapshotsInfo) +func (cli *Client) GetSnapshots(tx kv.Tx, networkID uint64) (map[snapshotsync.SnapshotType]*snapshotsync.SnapshotsInfo, error) { + mp := make(map[snapshotsync.SnapshotType]*snapshotsync.SnapshotsInfo) networkIDBytes := make([]byte, 8) binary.BigEndian.PutUint64(networkIDBytes, networkID) err := tx.ForPrefix(kv.SnapshotInfo, append(networkIDBytes, []byte(SnapshotInfoHashPrefix)...), func(k, v []byte) error { @@ -281,19 +282,19 @@ func (cli *Client) GetSnapshots(tx kv.Tx, networkID uint64) (map[SnapshotType]*S } _, tpStr := ParseInfoHashKey(k) - tp, ok := SnapshotType_value[tpStr] + tp, ok := snapshotsync.SnapshotType_value[tpStr] if !ok { return fmt.Errorf("incorrect type: %v", tpStr) } - val := &SnapshotsInfo{ - Type: SnapshotType(tp), + val := &snapshotsync.SnapshotsInfo{ + Type: snapshotsync.SnapshotType(tp), GotInfoByte: gotInfo, Readiness: readiness, SnapshotBlock: SnapshotBlock, Dbpath: filepath.Join(cli.snapshotsDir, t.Files()[0].Path()), } - mp[SnapshotType(tp)] = val + mp[snapshotsync.SnapshotType(tp)] = val return nil }) if err != nil { diff --git a/turbo/snapshotsync/external_downloader.pb.go b/turbo/snapshotsync/external_downloader.pb.go deleted file mode 100644 index 1b78fb93100..00000000000 --- a/turbo/snapshotsync/external_downloader.pb.go +++ /dev/null @@ -1,474 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.25.0 -// protoc v3.14.0 -// source: external_downloader.proto - -package snapshotsync - -import ( - reflect "reflect" - sync "sync" - - proto "github.com/golang/protobuf/proto" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - emptypb "google.golang.org/protobuf/types/known/emptypb" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// This is a compile-time assertion that a sufficiently up-to-date version -// of the legacy proto package is being used. -const _ = proto.ProtoPackageIsVersion4 - -type SnapshotType int32 - -const ( - SnapshotType_headers SnapshotType = 0 - SnapshotType_bodies SnapshotType = 1 - SnapshotType_state SnapshotType = 2 - SnapshotType_receipts SnapshotType = 3 -) - -// Enum value maps for SnapshotType. -var ( - SnapshotType_name = map[int32]string{ - 0: "headers", - 1: "bodies", - 2: "state", - 3: "receipts", - } - SnapshotType_value = map[string]int32{ - "headers": 0, - "bodies": 1, - "state": 2, - "receipts": 3, - } -) - -func (x SnapshotType) Enum() *SnapshotType { - p := new(SnapshotType) - *p = x - return p -} - -func (x SnapshotType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (SnapshotType) Descriptor() protoreflect.EnumDescriptor { - return file_external_downloader_proto_enumTypes[0].Descriptor() -} - -func (SnapshotType) Type() protoreflect.EnumType { - return &file_external_downloader_proto_enumTypes[0] -} - -func (x SnapshotType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use SnapshotType.Descriptor instead. -func (SnapshotType) EnumDescriptor() ([]byte, []int) { - return file_external_downloader_proto_rawDescGZIP(), []int{0} -} - -type DownloadSnapshotRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - NetworkId uint64 `protobuf:"varint,1,opt,name=network_id,json=networkId,proto3" json:"network_id,omitempty"` - Type []SnapshotType `protobuf:"varint,2,rep,packed,name=type,proto3,enum=snapshotsync.SnapshotType" json:"type,omitempty"` -} - -func (x *DownloadSnapshotRequest) Reset() { - *x = DownloadSnapshotRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_external_downloader_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DownloadSnapshotRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DownloadSnapshotRequest) ProtoMessage() {} - -func (x *DownloadSnapshotRequest) ProtoReflect() protoreflect.Message { - mi := &file_external_downloader_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DownloadSnapshotRequest.ProtoReflect.Descriptor instead. -func (*DownloadSnapshotRequest) Descriptor() ([]byte, []int) { - return file_external_downloader_proto_rawDescGZIP(), []int{0} -} - -func (x *DownloadSnapshotRequest) GetNetworkId() uint64 { - if x != nil { - return x.NetworkId - } - return 0 -} - -func (x *DownloadSnapshotRequest) GetType() []SnapshotType { - if x != nil { - return x.Type - } - return nil -} - -type SnapshotsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - NetworkId uint64 `protobuf:"varint,1,opt,name=network_id,json=networkId,proto3" json:"network_id,omitempty"` -} - -func (x *SnapshotsRequest) Reset() { - *x = SnapshotsRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_external_downloader_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SnapshotsRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SnapshotsRequest) ProtoMessage() {} - -func (x *SnapshotsRequest) ProtoReflect() protoreflect.Message { - mi := &file_external_downloader_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SnapshotsRequest.ProtoReflect.Descriptor instead. -func (*SnapshotsRequest) Descriptor() ([]byte, []int) { - return file_external_downloader_proto_rawDescGZIP(), []int{1} -} - -func (x *SnapshotsRequest) GetNetworkId() uint64 { - if x != nil { - return x.NetworkId - } - return 0 -} - -type SnapshotsInfo struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Type SnapshotType `protobuf:"varint,1,opt,name=type,proto3,enum=snapshotsync.SnapshotType" json:"type,omitempty"` - GotInfoByte bool `protobuf:"varint,2,opt,name=gotInfoByte,proto3" json:"gotInfoByte,omitempty"` - Readiness int32 `protobuf:"varint,3,opt,name=readiness,proto3" json:"readiness,omitempty"` - SnapshotBlock uint64 `protobuf:"varint,4,opt,name=snapshotBlock,proto3" json:"snapshotBlock,omitempty"` - Dbpath string `protobuf:"bytes,5,opt,name=dbpath,proto3" json:"dbpath,omitempty"` -} - -func (x *SnapshotsInfo) Reset() { - *x = SnapshotsInfo{} - if protoimpl.UnsafeEnabled { - mi := &file_external_downloader_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SnapshotsInfo) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SnapshotsInfo) ProtoMessage() {} - -func (x *SnapshotsInfo) ProtoReflect() protoreflect.Message { - mi := &file_external_downloader_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SnapshotsInfo.ProtoReflect.Descriptor instead. -func (*SnapshotsInfo) Descriptor() ([]byte, []int) { - return file_external_downloader_proto_rawDescGZIP(), []int{2} -} - -func (x *SnapshotsInfo) GetType() SnapshotType { - if x != nil { - return x.Type - } - return SnapshotType_headers -} - -func (x *SnapshotsInfo) GetGotInfoByte() bool { - if x != nil { - return x.GotInfoByte - } - return false -} - -func (x *SnapshotsInfo) GetReadiness() int32 { - if x != nil { - return x.Readiness - } - return 0 -} - -func (x *SnapshotsInfo) GetSnapshotBlock() uint64 { - if x != nil { - return x.SnapshotBlock - } - return 0 -} - -func (x *SnapshotsInfo) GetDbpath() string { - if x != nil { - return x.Dbpath - } - return "" -} - -type SnapshotsInfoReply struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Info []*SnapshotsInfo `protobuf:"bytes,1,rep,name=info,proto3" json:"info,omitempty"` -} - -func (x *SnapshotsInfoReply) Reset() { - *x = SnapshotsInfoReply{} - if protoimpl.UnsafeEnabled { - mi := &file_external_downloader_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SnapshotsInfoReply) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SnapshotsInfoReply) ProtoMessage() {} - -func (x *SnapshotsInfoReply) ProtoReflect() protoreflect.Message { - mi := &file_external_downloader_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SnapshotsInfoReply.ProtoReflect.Descriptor instead. -func (*SnapshotsInfoReply) Descriptor() ([]byte, []int) { - return file_external_downloader_proto_rawDescGZIP(), []int{3} -} - -func (x *SnapshotsInfoReply) GetInfo() []*SnapshotsInfo { - if x != nil { - return x.Info - } - return nil -} - -var File_external_downloader_proto protoreflect.FileDescriptor - -var file_external_downloader_proto_rawDesc = []byte{ - 0x0a, 0x19, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x6c, - 0x6f, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x73, 0x6e, 0x61, - 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x79, 0x6e, 0x63, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x68, 0x0a, 0x17, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, - 0x61, 0x64, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x64, - 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x1a, - 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x79, 0x6e, 0x63, 0x2e, 0x53, 0x6e, - 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, - 0x22, 0x31, 0x0a, 0x10, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, - 0x6b, 0x49, 0x64, 0x22, 0xbd, 0x01, 0x0a, 0x0d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, - 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x79, - 0x6e, 0x63, 0x2e, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, - 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x67, 0x6f, 0x74, 0x49, 0x6e, 0x66, 0x6f, - 0x42, 0x79, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x67, 0x6f, 0x74, 0x49, - 0x6e, 0x66, 0x6f, 0x42, 0x79, 0x74, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x61, 0x64, 0x69, - 0x6e, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x72, 0x65, 0x61, 0x64, - 0x69, 0x6e, 0x65, 0x73, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, - 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x73, 0x6e, - 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x64, - 0x62, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x62, 0x70, - 0x61, 0x74, 0x68, 0x22, 0x45, 0x0a, 0x12, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, - 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x2f, 0x0a, 0x04, 0x69, 0x6e, 0x66, - 0x6f, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, - 0x6f, 0x74, 0x73, 0x79, 0x6e, 0x63, 0x2e, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, - 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x2a, 0x40, 0x0a, 0x0c, 0x53, 0x6e, - 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x68, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x73, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x62, 0x6f, 0x64, 0x69, 0x65, - 0x73, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x10, 0x02, 0x12, 0x0c, - 0x0a, 0x08, 0x72, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x73, 0x10, 0x03, 0x32, 0xaa, 0x01, 0x0a, - 0x0a, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x12, 0x4b, 0x0a, 0x08, 0x44, - 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x25, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, - 0x6f, 0x74, 0x73, 0x79, 0x6e, 0x63, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x53, - 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x4f, 0x0a, 0x09, 0x53, 0x6e, 0x61, 0x70, - 0x73, 0x68, 0x6f, 0x74, 0x73, 0x12, 0x1e, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, - 0x73, 0x79, 0x6e, 0x63, 0x2e, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, - 0x73, 0x79, 0x6e, 0x63, 0x2e, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x49, 0x6e, - 0x66, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42, 0x11, 0x5a, 0x0f, 0x2e, 0x2f, 0x3b, - 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x79, 0x6e, 0x63, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_external_downloader_proto_rawDescOnce sync.Once - file_external_downloader_proto_rawDescData = file_external_downloader_proto_rawDesc -) - -func file_external_downloader_proto_rawDescGZIP() []byte { - file_external_downloader_proto_rawDescOnce.Do(func() { - file_external_downloader_proto_rawDescData = protoimpl.X.CompressGZIP(file_external_downloader_proto_rawDescData) - }) - return file_external_downloader_proto_rawDescData -} - -var file_external_downloader_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_external_downloader_proto_msgTypes = make([]protoimpl.MessageInfo, 4) -var file_external_downloader_proto_goTypes = []interface{}{ - (SnapshotType)(0), // 0: snapshotsync.SnapshotType - (*DownloadSnapshotRequest)(nil), // 1: snapshotsync.DownloadSnapshotRequest - (*SnapshotsRequest)(nil), // 2: snapshotsync.SnapshotsRequest - (*SnapshotsInfo)(nil), // 3: snapshotsync.SnapshotsInfo - (*SnapshotsInfoReply)(nil), // 4: snapshotsync.SnapshotsInfoReply - (*emptypb.Empty)(nil), // 5: google.protobuf.Empty -} -var file_external_downloader_proto_depIdxs = []int32{ - 0, // 0: snapshotsync.DownloadSnapshotRequest.type:type_name -> snapshotsync.SnapshotType - 0, // 1: snapshotsync.SnapshotsInfo.type:type_name -> snapshotsync.SnapshotType - 3, // 2: snapshotsync.SnapshotsInfoReply.info:type_name -> snapshotsync.SnapshotsInfo - 1, // 3: snapshotsync.Downloader.Download:input_type -> snapshotsync.DownloadSnapshotRequest - 2, // 4: snapshotsync.Downloader.Snapshots:input_type -> snapshotsync.SnapshotsRequest - 5, // 5: snapshotsync.Downloader.Download:output_type -> google.protobuf.Empty - 4, // 6: snapshotsync.Downloader.Snapshots:output_type -> snapshotsync.SnapshotsInfoReply - 5, // [5:7] is the sub-list for method output_type - 3, // [3:5] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name -} - -func init() { file_external_downloader_proto_init() } -func file_external_downloader_proto_init() { - if File_external_downloader_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_external_downloader_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DownloadSnapshotRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_external_downloader_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SnapshotsRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_external_downloader_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SnapshotsInfo); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_external_downloader_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SnapshotsInfoReply); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_external_downloader_proto_rawDesc, - NumEnums: 1, - NumMessages: 4, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_external_downloader_proto_goTypes, - DependencyIndexes: file_external_downloader_proto_depIdxs, - EnumInfos: file_external_downloader_proto_enumTypes, - MessageInfos: file_external_downloader_proto_msgTypes, - }.Build() - File_external_downloader_proto = out.File - file_external_downloader_proto_rawDesc = nil - file_external_downloader_proto_goTypes = nil - file_external_downloader_proto_depIdxs = nil -} diff --git a/turbo/snapshotsync/external_downloader_grpc.pb.go b/turbo/snapshotsync/external_downloader_grpc.pb.go deleted file mode 100644 index 814d31e01c2..00000000000 --- a/turbo/snapshotsync/external_downloader_grpc.pb.go +++ /dev/null @@ -1,135 +0,0 @@ -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. - -package snapshotsync - -import ( - context "context" - - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" - emptypb "google.golang.org/protobuf/types/known/emptypb" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion7 - -// DownloaderClient is the client API for Downloader service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type DownloaderClient interface { - Download(ctx context.Context, in *DownloadSnapshotRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) - Snapshots(ctx context.Context, in *SnapshotsRequest, opts ...grpc.CallOption) (*SnapshotsInfoReply, error) -} - -type downloaderClient struct { - cc grpc.ClientConnInterface -} - -func NewDownloaderClient(cc grpc.ClientConnInterface) DownloaderClient { - return &downloaderClient{cc} -} - -func (c *downloaderClient) Download(ctx context.Context, in *DownloadSnapshotRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { - out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, "/snapshotsync.Downloader/Download", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *downloaderClient) Snapshots(ctx context.Context, in *SnapshotsRequest, opts ...grpc.CallOption) (*SnapshotsInfoReply, error) { - out := new(SnapshotsInfoReply) - err := c.cc.Invoke(ctx, "/snapshotsync.Downloader/Snapshots", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// DownloaderServer is the server API for Downloader service. -// All implementations must embed UnimplementedDownloaderServer -// for forward compatibility -type DownloaderServer interface { - Download(context.Context, *DownloadSnapshotRequest) (*emptypb.Empty, error) - Snapshots(context.Context, *SnapshotsRequest) (*SnapshotsInfoReply, error) - mustEmbedUnimplementedDownloaderServer() -} - -// UnimplementedDownloaderServer must be embedded to have forward compatible implementations. -type UnimplementedDownloaderServer struct { -} - -func (UnimplementedDownloaderServer) Download(context.Context, *DownloadSnapshotRequest) (*emptypb.Empty, error) { - return nil, status.Errorf(codes.Unimplemented, "method Download not implemented") -} -func (UnimplementedDownloaderServer) Snapshots(context.Context, *SnapshotsRequest) (*SnapshotsInfoReply, error) { - return nil, status.Errorf(codes.Unimplemented, "method Snapshots not implemented") -} -func (UnimplementedDownloaderServer) mustEmbedUnimplementedDownloaderServer() {} - -// UnsafeDownloaderServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to DownloaderServer will -// result in compilation errors. -type UnsafeDownloaderServer interface { - mustEmbedUnimplementedDownloaderServer() -} - -func RegisterDownloaderServer(s grpc.ServiceRegistrar, srv DownloaderServer) { - s.RegisterService(&_Downloader_serviceDesc, srv) -} - -func _Downloader_Download_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(DownloadSnapshotRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(DownloaderServer).Download(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/snapshotsync.Downloader/Download", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(DownloaderServer).Download(ctx, req.(*DownloadSnapshotRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Downloader_Snapshots_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(SnapshotsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(DownloaderServer).Snapshots(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/snapshotsync.Downloader/Snapshots", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(DownloaderServer).Snapshots(ctx, req.(*SnapshotsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -var _Downloader_serviceDesc = grpc.ServiceDesc{ - ServiceName: "snapshotsync.Downloader", - HandlerType: (*DownloaderServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Download", - Handler: _Downloader_Download_Handler, - }, - { - MethodName: "Snapshots", - Handler: _Downloader_Snapshots_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "external_downloader.proto", -} diff --git a/turbo/snapshotsync/postprocessing.go b/turbo/snapshotsync/postprocessing.go index ee6a92b4475..5f2fb6c26d9 100644 --- a/turbo/snapshotsync/postprocessing.go +++ b/turbo/snapshotsync/postprocessing.go @@ -9,6 +9,7 @@ import ( "os" "github.com/ledgerwatch/erigon-lib/etl" + "github.com/ledgerwatch/erigon-lib/gointerfaces/snapshotsync" "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon/common" "github.com/ledgerwatch/erigon/common/dbutils" @@ -41,23 +42,23 @@ var ( Snapshot11kkTD = []byte{138, 3, 199, 118, 5, 203, 95, 162, 81, 64, 161} ) -func PostProcessing(db kv.RwDB, downloadedSnapshots map[SnapshotType]*SnapshotsInfo) error { - if _, ok := downloadedSnapshots[SnapshotType_headers]; ok { +func PostProcessing(db kv.RwDB, downloadedSnapshots map[snapshotsync.SnapshotType]*snapshotsync.SnapshotsInfo) error { + if _, ok := downloadedSnapshots[snapshotsync.SnapshotType_headers]; ok { if err := db.Update(context.Background(), func(tx kv.RwTx) error { return GenerateHeaderIndexes(context.Background(), tx) }); err != nil { return err } } - if _, ok := downloadedSnapshots[SnapshotType_state]; ok { + if _, ok := downloadedSnapshots[snapshotsync.SnapshotType_state]; ok { if err := db.Update(context.Background(), func(tx kv.RwTx) error { - return PostProcessState(tx, downloadedSnapshots[SnapshotType_state]) + return PostProcessState(tx, downloadedSnapshots[snapshotsync.SnapshotType_state]) }); err != nil { return err } } - if _, ok := downloadedSnapshots[SnapshotType_bodies]; ok { + if _, ok := downloadedSnapshots[snapshotsync.SnapshotType_bodies]; ok { if err := db.Update(context.Background(), func(tx kv.RwTx) error { return PostProcessBodies(tx) }); err != nil { @@ -121,7 +122,7 @@ func PostProcessBodies(tx kv.RwTx) error { return tx.Commit() } -func PostProcessState(db kv.RwTx, info *SnapshotsInfo) error { +func PostProcessState(db kv.RwTx, info *snapshotsync.SnapshotsInfo) error { v, err := stages.GetStageProgress(db, stages.Execution) if err != nil { return err diff --git a/turbo/snapshotsync/server.go b/turbo/snapshotsync/server.go index 9aecdd09f32..5be5a839018 100644 --- a/turbo/snapshotsync/server.go +++ b/turbo/snapshotsync/server.go @@ -6,9 +6,10 @@ import ( "fmt" "github.com/anacrolix/torrent" - "github.com/golang/protobuf/ptypes/empty" + "github.com/ledgerwatch/erigon-lib/gointerfaces/snapshotsync" "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon-lib/kv/mdbx" + "google.golang.org/protobuf/types/known/emptypb" ) var ( @@ -16,7 +17,7 @@ var ( ErrNotSupportedSnapshot = errors.New("not supported snapshot for this network id") ) var ( - _ DownloaderServer = &SNDownloaderServer{} + _ snapshotsync.DownloaderServer = &SNDownloaderServer{} ) func NewServer(dir string, seeding bool) (*SNDownloaderServer, error) { @@ -48,18 +49,18 @@ func NewServer(dir string, seeding bool) (*SNDownloaderServer, error) { } type SNDownloaderServer struct { - DownloaderServer + snapshotsync.UnimplementedDownloaderServer t *Client db kv.RwDB } -func (s *SNDownloaderServer) Download(ctx context.Context, request *DownloadSnapshotRequest) (*empty.Empty, error) { +func (s *SNDownloaderServer) Download(ctx context.Context, request *snapshotsync.DownloadSnapshotRequest) (*emptypb.Empty, error) { if err := s.db.Update(ctx, func(tx kv.RwTx) error { return s.t.AddSnapshotsTorrents(ctx, tx, request.NetworkId, FromSnapshotTypes(request.Type)) }); err != nil { return nil, err } - return &empty.Empty{}, nil + return &emptypb.Empty{}, nil } func (s *SNDownloaderServer) Load() error { return s.db.View(context.Background(), func(tx kv.Tx) error { @@ -67,8 +68,8 @@ func (s *SNDownloaderServer) Load() error { }) } -func (s *SNDownloaderServer) Snapshots(ctx context.Context, request *SnapshotsRequest) (*SnapshotsInfoReply, error) { - reply := SnapshotsInfoReply{} +func (s *SNDownloaderServer) Snapshots(ctx context.Context, request *snapshotsync.SnapshotsRequest) (*snapshotsync.SnapshotsInfoReply, error) { + reply := snapshotsync.SnapshotsInfoReply{} tx, err := s.db.BeginRo(ctx) if err != nil { return nil, err diff --git a/turbo/snapshotsync/snapshot_mode.go b/turbo/snapshotsync/snapshot_mode.go index 5d505cb557d..592b56c38fe 100644 --- a/turbo/snapshotsync/snapshot_mode.go +++ b/turbo/snapshotsync/snapshot_mode.go @@ -1,6 +1,10 @@ package snapshotsync -import "fmt" +import ( + "fmt" + + "github.com/ledgerwatch/erigon-lib/gointerfaces/snapshotsync" +) var DefaultSnapshotMode = SnapshotMode{} @@ -28,34 +32,34 @@ func (m SnapshotMode) ToString() string { return mode } -func (m SnapshotMode) ToSnapshotTypes() []SnapshotType { - var types []SnapshotType +func (m SnapshotMode) ToSnapshotTypes() []snapshotsync.SnapshotType { + var types []snapshotsync.SnapshotType if m.Headers { - types = append(types, SnapshotType_headers) + types = append(types, snapshotsync.SnapshotType_headers) } if m.Bodies { - types = append(types, SnapshotType_bodies) + types = append(types, snapshotsync.SnapshotType_bodies) } if m.State { - types = append(types, SnapshotType_state) + types = append(types, snapshotsync.SnapshotType_state) } if m.Receipts { - types = append(types, SnapshotType_receipts) + types = append(types, snapshotsync.SnapshotType_receipts) } return types } -func FromSnapshotTypes(st []SnapshotType) SnapshotMode { +func FromSnapshotTypes(st []snapshotsync.SnapshotType) SnapshotMode { var mode SnapshotMode for i := range st { switch st[i] { - case SnapshotType_headers: + case snapshotsync.SnapshotType_headers: mode.Headers = true - case SnapshotType_bodies: + case snapshotsync.SnapshotType_bodies: mode.Bodies = true - case SnapshotType_state: + case snapshotsync.SnapshotType_state: mode.State = true - case SnapshotType_receipts: + case snapshotsync.SnapshotType_receipts: mode.Receipts = true } } diff --git a/turbo/snapshotsync/wrapdb.go b/turbo/snapshotsync/wrapdb.go index 65d149227d3..781cabd1af5 100644 --- a/turbo/snapshotsync/wrapdb.go +++ b/turbo/snapshotsync/wrapdb.go @@ -6,6 +6,7 @@ import ( "errors" "time" + "github.com/ledgerwatch/erigon-lib/gointerfaces/snapshotsync" "github.com/ledgerwatch/erigon-lib/kv" kv2 "github.com/ledgerwatch/erigon-lib/kv/mdbx" "github.com/ledgerwatch/erigon/ethdb" @@ -14,15 +15,15 @@ import ( ) var ( - BucketConfigs = map[SnapshotType]kv.TableCfg{ - SnapshotType_bodies: { + BucketConfigs = map[snapshotsync.SnapshotType]kv.TableCfg{ + snapshotsync.SnapshotType_bodies: { kv.BlockBody: kv.TableCfgItem{}, kv.EthTx: kv.TableCfgItem{}, }, - SnapshotType_headers: { + snapshotsync.SnapshotType_headers: { kv.Headers: kv.TableCfgItem{}, }, - SnapshotType_state: { + snapshotsync.SnapshotType_state: { kv.PlainState: kv.TableCfgItem{ Flags: kv.DupSort, AutoDupSortKeysConversion: true, @@ -41,7 +42,7 @@ func WrapBySnapshotsFromDir(kv kv.RwDB, snapshotDir string, mode SnapshotMode) ( return nil, errors.New("deprecated") //nolint } -func WrapBySnapshotsFromDownloader(db kv.RwDB, snapshots map[SnapshotType]*SnapshotsInfo) (kv.RwDB, error) { +func WrapBySnapshotsFromDownloader(db kv.RwDB, snapshots map[snapshotsync.SnapshotType]*snapshotsync.SnapshotsInfo) (kv.RwDB, error) { snKV := snapshotdb.NewSnapshotKV().DB(db) for k, v := range snapshots { log.Info("Wrap db by", "snapshot", k.String(), "dir", v.Dbpath) @@ -55,11 +56,11 @@ func WrapBySnapshotsFromDownloader(db kv.RwDB, snapshots map[SnapshotType]*Snaps return nil, err } else { //nolint switch k { - case SnapshotType_headers: + case snapshotsync.SnapshotType_headers: snKV = snKV.HeadersSnapshot(snapshotKV) - case SnapshotType_bodies: + case snapshotsync.SnapshotType_bodies: snKV = snKV.BodiesSnapshot(snapshotKV) - case SnapshotType_state: + case snapshotsync.SnapshotType_state: snKV = snKV.StateSnapshot(snapshotKV) } } @@ -97,7 +98,7 @@ func WrapSnapshots(chainDb kv.RwDB, snapshotsDir string) (kv.RwDB, error) { } func DownloadSnapshots(torrentClient *Client, ExternalSnapshotDownloaderAddr string, networkID uint64, snapshotMode SnapshotMode, chainDb ethdb.Database) error { - var downloadedSnapshots map[SnapshotType]*SnapshotsInfo + var downloadedSnapshots map[snapshotsync.SnapshotType]*snapshotsync.SnapshotsInfo if ExternalSnapshotDownloaderAddr != "" { cli, cl, innerErr := NewClient(ExternalSnapshotDownloaderAddr) if innerErr != nil { @@ -105,7 +106,7 @@ func DownloadSnapshots(torrentClient *Client, ExternalSnapshotDownloaderAddr str } defer cl() //nolint - _, innerErr = cli.Download(context.Background(), &DownloadSnapshotRequest{ + _, innerErr = cli.Download(context.Background(), &snapshotsync.DownloadSnapshotRequest{ NetworkId: networkID, Type: snapshotMode.ToSnapshotTypes(), }) @@ -113,8 +114,8 @@ func DownloadSnapshots(torrentClient *Client, ExternalSnapshotDownloaderAddr str return innerErr } - waitDownload := func() (map[SnapshotType]*SnapshotsInfo, error) { - snapshotReadinessCheck := func(mp map[SnapshotType]*SnapshotsInfo, tp SnapshotType) bool { + waitDownload := func() (map[snapshotsync.SnapshotType]*snapshotsync.SnapshotsInfo, error) { + snapshotReadinessCheck := func(mp map[snapshotsync.SnapshotType]*snapshotsync.SnapshotsInfo, tp snapshotsync.SnapshotType) bool { if mp[tp].Readiness != int32(100) { log.Info("Downloading", "snapshot", tp, "%", mp[tp].Readiness) return false @@ -122,8 +123,8 @@ func DownloadSnapshots(torrentClient *Client, ExternalSnapshotDownloaderAddr str return true } for { - downloadedSnapshots = make(map[SnapshotType]*SnapshotsInfo) - snapshots, err1 := cli.Snapshots(context.Background(), &SnapshotsRequest{NetworkId: networkID}) + downloadedSnapshots = make(map[snapshotsync.SnapshotType]*snapshotsync.SnapshotsInfo) + snapshots, err1 := cli.Snapshots(context.Background(), &snapshotsync.SnapshotsRequest{NetworkId: networkID}) if err1 != nil { return nil, err1 } @@ -135,22 +136,22 @@ func DownloadSnapshots(torrentClient *Client, ExternalSnapshotDownloaderAddr str downloaded := true if snapshotMode.Headers { - if !snapshotReadinessCheck(downloadedSnapshots, SnapshotType_headers) { + if !snapshotReadinessCheck(downloadedSnapshots, snapshotsync.SnapshotType_headers) { downloaded = false } } if snapshotMode.Bodies { - if !snapshotReadinessCheck(downloadedSnapshots, SnapshotType_bodies) { + if !snapshotReadinessCheck(downloadedSnapshots, snapshotsync.SnapshotType_bodies) { downloaded = false } } if snapshotMode.State { - if !snapshotReadinessCheck(downloadedSnapshots, SnapshotType_state) { + if !snapshotReadinessCheck(downloadedSnapshots, snapshotsync.SnapshotType_state) { downloaded = false } } if snapshotMode.Receipts { - if !snapshotReadinessCheck(downloadedSnapshots, SnapshotType_receipts) { + if !snapshotReadinessCheck(downloadedSnapshots, snapshotsync.SnapshotType_receipts) { downloaded = false } } @@ -188,7 +189,7 @@ func DownloadSnapshots(torrentClient *Client, ExternalSnapshotDownloaderAddr str } else { torrentClient.Download() var innerErr error - var downloadedSnapshots map[SnapshotType]*SnapshotsInfo + var downloadedSnapshots map[snapshotsync.SnapshotType]*snapshotsync.SnapshotsInfo if err := chainDb.RwKV().View(context.Background(), func(tx kv.Tx) (err error) { downloadedSnapshots, err = torrentClient.GetSnapshots(tx, networkID) if err != nil { diff --git a/turbo/stages/blockchain_test.go b/turbo/stages/blockchain_test.go index a2e6ae5d628..140053e32b9 100644 --- a/turbo/stages/blockchain_test.go +++ b/turbo/stages/blockchain_test.go @@ -733,7 +733,7 @@ func doModesTest(t *testing.T, pm prune.Mode) error { } }, false /* intemediateHashes */) if err != nil { - return fmt.Errorf("generate blocks: %v", err) + return fmt.Errorf("generate blocks: %w", err) } if err = m.InsertChain(chain); err != nil { diff --git a/turbo/stages/genesis_test.go b/turbo/stages/genesis_test.go index 7c181caf283..a1cbc68c86a 100644 --- a/turbo/stages/genesis_test.go +++ b/turbo/stages/genesis_test.go @@ -44,7 +44,7 @@ func TestDefaultGenesisBlock(t *testing.T) { var err error block, _, err = core.DefaultRopstenGenesisBlock().ToBlock() if err != nil { - t.Errorf("error: %w", err) + t.Errorf("error: %v", err) } if block.Hash() != params.RopstenGenesisHash { t.Errorf("wrong ropsten genesis hash, got %v, want %v", block.Hash(), params.RopstenGenesisHash) @@ -52,7 +52,7 @@ func TestDefaultGenesisBlock(t *testing.T) { block, _, err = core.DefaultSokolGenesisBlock().ToBlock() if err != nil { - t.Errorf("error: %w", err) + t.Errorf("error: %v", err) } if block.Root() != params.SokolGenesisStateRoot { t.Errorf("wrong sokol genesis state root, got %v, want %v", block.Root(), params.SokolGenesisStateRoot) @@ -63,7 +63,7 @@ func TestDefaultGenesisBlock(t *testing.T) { block, _, err = core.DefaultKovanGenesisBlock().ToBlock() if err != nil { - t.Errorf("error: %w", err) + t.Errorf("error: %v", err) } if block.Root() != params.KovanGenesisStateRoot { t.Errorf("wrong kovan genesis state root, got %v, want %v", block.Root(), params.KovanGenesisStateRoot) @@ -74,7 +74,7 @@ func TestDefaultGenesisBlock(t *testing.T) { block, _, err = core.DefaultFermionGenesisBlock().ToBlock() if err != nil { - t.Errorf("error: %w", err) + t.Errorf("error: %v", err) } if block.Root() != params.FermionGenesisStateRoot { t.Errorf("wrong fermion genesis state root, got %v, want %v", block.Root(), params.FermionGenesisStateRoot) diff --git a/turbo/stages/headerdownload/header_algos.go b/turbo/stages/headerdownload/header_algos.go index 5b19b500e5e..6d642ac6808 100644 --- a/turbo/stages/headerdownload/header_algos.go +++ b/turbo/stages/headerdownload/header_algos.go @@ -453,6 +453,10 @@ func (hd *HeaderDownload) SetPreverifiedHashes(preverifiedHashes map[common.Hash func (hd *HeaderDownload) RecoverFromDb(db kv.RoDB) error { hd.lock.Lock() defer hd.lock.Unlock() + + logEvery := time.NewTicker(30 * time.Second) + defer logEvery.Stop() + // Drain persistedLinksQueue and remove links for hd.persistedLinkQueue.Len() > 0 { link := heap.Pop(hd.persistedLinkQueue).(*Link) @@ -473,6 +477,12 @@ func (hd *HeaderDownload) RecoverFromDb(db kv.RoDB) error { return err } hd.addHeaderAsLink(&h, true /* persisted */) + + select { + case <-logEvery.C: + log.Info("recover headers from db", "left", hd.persistedLinkLimit-hd.persistedLinkQueue.Len()) + default: + } } hd.highestInDb, err = stages.GetStageProgress(tx, stages.Headers) if err != nil { @@ -510,7 +520,7 @@ func (hd *HeaderDownload) RequestMoreHeaders(currentTime uint64) (*HeaderRequest defer hd.lock.Unlock() var penalties []PenaltyItem if hd.anchorQueue.Len() == 0 { - log.Debug("Empty anchor queue") + log.Trace("Empty anchor queue") return nil, penalties } for hd.anchorQueue.Len() > 0 { @@ -549,7 +559,7 @@ func (hd *HeaderDownload) SentRequest(req *HeaderRequest, currentTime, timeout u func (hd *HeaderDownload) RequestSkeleton() *HeaderRequest { hd.lock.RLock() defer hd.lock.RUnlock() - log.Debug("Request skeleton", "anchors", len(hd.anchors), "top seen height", hd.topSeenHeight, "highestInDb", hd.highestInDb) + log.Trace("Request skeleton", "anchors", len(hd.anchors), "top seen height", hd.topSeenHeight, "highestInDb", hd.highestInDb) if len(hd.anchors) > 16 { return nil // Need to be below anchor threshold to produce skeleton request } @@ -831,13 +841,13 @@ func (hi *HeaderInserter) BestHeaderChanged() bool { // speeds up visibility of new blocks // It remember peerID - then later - if anchors created from segments will abandoned - this peerID gonna get Penalty func (hd *HeaderDownload) ProcessSegment(segment *ChainSegment, newBlock bool, peerID string) (requestMore bool, penalties []PenaltyItem) { - log.Debug("processSegment", "from", segment.Headers[0].Number.Uint64(), "to", segment.Headers[len(segment.Headers)-1].Number.Uint64()) + log.Trace("processSegment", "from", segment.Headers[0].Number.Uint64(), "to", segment.Headers[len(segment.Headers)-1].Number.Uint64()) hd.lock.Lock() defer hd.lock.Unlock() foundAnchor, start := hd.findAnchors(segment) foundTip, end := hd.findLink(segment, start) // We ignore penalty because we will check it as part of PoW check if end == 0 { - log.Debug("Duplicate segment") + log.Trace("Duplicate segment") return } height := segment.Headers[len(segment.Headers)-1].Number.Uint64() @@ -858,7 +868,7 @@ func (hd *HeaderDownload) ProcessSegment(segment *ChainSegment, newBlock bool, p log.Debug("Connect failed", "error", err) return } - log.Debug("Connected", "start", startNum, "end", endNum) + log.Trace("Connected", "start", startNum, "end", endNum) } else { // ExtendDown var err error @@ -866,7 +876,7 @@ func (hd *HeaderDownload) ProcessSegment(segment *ChainSegment, newBlock bool, p log.Debug("ExtendDown failed", "error", err) return } - log.Debug("Extended Down", "start", startNum, "end", endNum) + log.Trace("Extended Down", "start", startNum, "end", endNum) } } else if foundTip { if end > 0 { @@ -875,7 +885,7 @@ func (hd *HeaderDownload) ProcessSegment(segment *ChainSegment, newBlock bool, p log.Debug("ExtendUp failed", "error", err) return } - log.Debug("Extended Up", "start", startNum, "end", endNum) + log.Trace("Extended Up", "start", startNum, "end", endNum) } } else { // NewAnchor @@ -884,12 +894,12 @@ func (hd *HeaderDownload) ProcessSegment(segment *ChainSegment, newBlock bool, p log.Debug("NewAnchor failed", "error", err) return } - log.Debug("NewAnchor", "start", startNum, "end", endNum) + log.Trace("NewAnchor", "start", startNum, "end", endNum) } //log.Info(hd.anchorState()) - log.Debug("Link queue", "size", hd.linkQueue.Len()) + log.Trace("Link queue", "size", hd.linkQueue.Len()) if hd.linkQueue.Len() > hd.linkLimit { - log.Debug("Too many links, cutting down", "count", hd.linkQueue.Len(), "tried to add", end-start, "limit", hd.linkLimit) + log.Trace("Too many links, cutting down", "count", hd.linkQueue.Len(), "tried to add", end-start, "limit", hd.linkLimit) } for hd.linkQueue.Len() > hd.linkLimit { link := heap.Pop(hd.linkQueue).(*Link) diff --git a/turbo/stages/headerdownload/preverified_hashes_mainnet.go b/turbo/stages/headerdownload/preverified_hashes_mainnet.go index 2f45bedd5d1..58ae801af01 100644 --- a/turbo/stages/headerdownload/preverified_hashes_mainnet.go +++ b/turbo/stages/headerdownload/preverified_hashes_mainnet.go @@ -68460,6 +68460,1185 @@ var mainnetPreverifiedHashes = []string{ "5fe6ee0c730bf06748d3d8fe6d3d8fa8bcf97e90977e66bc8e4275074e0bee27", "c006c792bff3373a23eaeeb151bc6a3f39eadf76c36b16c1d8ab7378e2e96426", "f7075caf26908f5556770acf7e167612e5d20d3008323e0c7b8a03906c083382", + "ab4eff5c17f78da0779d4dad31a06a64d6ffaf97712bae8ad537b39a7ddb3043", + "2bdd7bdbdb384c57293c7f6125321f2dc271bfd2a05215c9a6271cad742e7fdd", + "73fde48cbea6e3826dfa442641c24a08fa3bc11a667d5b5a65a6213baef9a83a", + "abee9d6838a965d7f2b53c2399b43e76a3f8ae6362b27e90ba7d67b640912ac4", + "76589055519d3af635c637236671a0b5bd9228462fffbc858fb8c5eb8df4ec0b", + "653f1a372eb00fbe5f496241e3472ac80d076610a74db44ff30db32f27b3c173", + "e45c7777f67917fb8ccfc03f4031ef948ee1a8576adfdce8a4bc9f3e5d17adac", + "f334f156baee75545337d69a680c1f97c35d44d791dd2405fce8c5c6aa97a226", + "cfe4d1dd19b8b5bbb2048900f403d17102f774e8f36bf828f4d9a6efcbd44f66", + "d6d8d3dc2871488a879da3e9e6e8f9000584ba44d627ed65a3dc935c9022ac3b", + "81a5f16f1778e12c513ef9d51bacf40577ed0c0ae47787ec5bc70ffbfbc4380b", + "167de38bd66db605f65650e95159246b9b96fc4e8e74f16d339090a1851d4dfa", + "91f390af31a9d8db958763e72c7f4e38f25979cfea35903a7eb0c4b2880039c1", + "3c7774232d322be1e82379837a5dfdab573a636ea8851edf102c0f3c6aa51ce4", + "6ca5ea6b5adaf7c1be6b0be5143f6c0eec55de74a5c0b13381d64dbf5ebbc784", + "46a564fdd73e64e41b5fb0bd0248864b22bca128a0ff089cec25ee7136e61238", + "c515c3b0ba9820d0d331723f4a95531e168f3669d9d69ede276ae0782653de79", + "235fc0b6e811d3bb4a3acb1e59f4c74c875154babc692fcd55bb4b251d2a98c4", + "d7c79d6e8daa06e48629fba103711d4756265df3f80bf2cbf9aba2a2a1b57e3b", + "432b3f85ec08b388a21b861286a50daf776ff8d39bcba33b815b7bcfae2bea83", + "4312edef6083e02cfcb1b3f64ebf1bf7b93d9e706973165a36ef983bb30852d6", + "3fde1bdca2432290ba11f6ab4eb1f9ca814b77af33bd41c3570a72ee3010edf0", + "3c75c010ee91d94106d78b995e0e5bac5545a089d7511732e690f832782fe039", + "5fadb3b323c97623b55b99590c184f3ce1b391a91b64161aa6184a29febd75a1", + "22c8bd4e2a803b8059586a5cb4bb91dce3d33e4de64be926b4f4ee8300e8263f", + "15fd7c7385c32387d1943c4eb65670637d019a493310b2b25955973b1920a27d", + "14dffa974fc42067b20c23f44840b62467b245bd3b67563b4c3b6fa3ca0b0dc9", + "fa2871b6d94381c2a7a20dbfc483b4ca2884ca47a71d0d4709394e8c2bf0fd20", + "ca6daa3383f196e3f91bc42cd41d5422907c094e681459b155bb31f0a4850b1b", + "2ed5507e1198a63feab0e444af5832eb7b2f6328706e9833570de4861f2337fe", + "9e52d3b58527ce44380851d8b5e3cac36fbf270ee2c956d85cd077eb08524f8b", + "0946dca6b3400ef4832db275bd6099b9f9ce3391a06b8cf35748535aef8d9aeb", + "d461146307cbfa7b087439c0739e398fd7d259023bc5b7302625bc7d8025937f", + "3a83ad3663f3799606a69b94da9eb989694922bba59e482982a858a7019693bd", + "ef5df3cd2e4e199d2e45cae0aa615afb08a7ed68c9a35d9fe3af3fffc2105763", + "b5eaa80e9208829205e708c2b98348e77ab62c920d14ba8d2983b566e2dc31c9", + "b9e2303006c5e5756818258f81887ac467e2363f01ab1bb09f38f2b52d97e4c3", + "5df5e1c15dd160600b6bd58f04b65ab657707ab979676bb17a0b8e2c3c41a670", + "c8ae4053b5d9ec8dd478a06b0b94c133259a45787dab985dbb7f03d2e402c541", + "0dd4a9ece50df47d44221c8b89c1997b78e360ef67143992b9843783bd4d828c", + "40c8234abf4b3a092ba9eee44e8c2973548136a16287254d9e209a6b48c7c86f", + "7348e7417db5b8f58fdafa15578f9c4987ee125f28cc44d7e8cc413d8d0c5c0b", + "5932dba89cf62dc555144f2839b13f35e622c39b2221ad53133475f8a24b07fa", + "8cf123177692622c11703b77860c678a04a8a34c549da53190e072592cfb59e8", + "d28c5eb7e48492ca07d217a3117f639a110e99751aa0eb302be312db75a73caf", + "2e2fb5f28015848287031489a6c74d767ea98b349867277fec26aab6da4bbce7", + "97ba4d535851b5574e2ae124f303ecc0e8e8fa3d6354328ec14c09a457d715ce", + "1aa408b0dbee55678e4b3cfe6a821f8d13c78d6144bbef6eb1d5e62ad2f64000", + "9fc759a6665624d4930e8376a0a565f9c9b6b9d356c0a394d9c514e9ec378c3b", + "bce759b43ce77c67fad82422ad2adbcb80ce6beb44763d25236b8bcbd7b05096", + "c29613ae071c5fecd94b7b5c8581c06ef754b7be5d7adf806940bfa392724183", + "82db883611476ad456d97b68fc2202d950b36cf54c1216e17b7e3bbd4ee11ea7", + "9c05e6af9108e3be73f5de2c743275a86e3f663c168dec53acb2a7d966aea908", + "0df22f0de22981390a9791a04048c2c3b23a102fb27f1fe034a279bd53041da5", + "8d7907f205fa1237bee3f7f0599c053fec58e31a352f48b9f164237ac832b9ff", + "59efd759284f4d174739d2ed22ab469191fb2e36a83e343a2b8f8d315018f4ef", + "47d3e677185390e5ee823dfe5c38eb5345e01ed732a5acb6e617a4896beca5e7", + "70781d6499d6d9dbcfd9c3e1c5645dd73f9bf24f9707da4eb8a4e0fe8c20ceab", + "fa7ee7aedbfb13a36e6b7aa1568e5e9ccfc67b985f60c8254e0cee7f99150266", + "c280861c15824936645b51fe79800f2ff355eaa73bf7081e68698dbfd01bc2d0", + "c303c59dd92c1064c34578844478ec29d566ba24b949422b5f62e869a63d2608", + "7a9f50cf3dd165fa6d25af1959aebbc8d10af69cbf047b0c6e1ab75435922ddd", + "9589dea6f4fcb9e2f3c725fc85863253a50a6e807ba771db4842227cfbeefee8", + "36e8bbdce65e7da3e968cbee28235fe9659723fde50395287e5cf12ada1b70f1", + "ec64e520fc845e7aeca90676e97c2539784b0c6efc9a26fe3241487cfa9bedd3", + "868fbd607e020b8d94f19004f9ac2a9320033863dd533d6af40e7218e486b97b", + "7d7caa0aa6f76b7c7d2d55226702a45146c718f7731778a761834c080f96603e", + "9c390e75d32f081710c9d3a8eda513e87612bdd4ffccc1d8b15589fc030c7b52", + "33f48e447655decae56c88f70bd08161cc3d68799cd6287f67dc2d2655e49093", + "33196a7f5b09e3e4272e8bc71c4f718255573629aa65c5fc48e3489965b78b6b", + "69d9eb5f28dc8ec00eca2d91d98a0e6e5df0b35712a47b8ac6404d5f6d023bac", + "6e075fad303246daaf2d6e42b0d0423af4e4348f74cb2faa67124e81e0aa86a0", + "dd6cb84d4971d6263c78fa03a1ee8025900fcf2df6d2f425a0f7fd918187d023", + "65733ddd643ae5648d37fe9121db8366bf6905b762b9b392e5140f099890a1f9", + "5290fd20f1adf79c773c7dfe625c240a66871204075fadd13ed572236a578caa", + "9e27f3a85cf79a785781d79937c62d546c32ccf8c2f17d3972d53d2c1fc6a8f2", + "0da9d10560aa816882888b9e73462c580cee06afc07212a85c48bbe39bcad6e4", + "69ef3e61cde1d04146ca95234b81af0a78661342df4b07a1e3588e51b043986a", + "81aa21f14faf74f62a97af81232c8e2c9553eb1d64d62698a4108c6315cd15bb", + "6528359a1f9be8283365aabd1cabdaeebc36fa2d0febde06a21106b03e20cc83", + "b0edacf8d99bf249d0f104e9dfcd7310820148714463be52ac5e329dd8f38ef6", + "e80dc1d6d17dcbc095a7c19926fe0a089e7a528795e36a9f26e4cb903b173b34", + "d846685f77370395a6934d1a22abc9eabb9def59e2915b984fef1a148ff18dc6", + "d81f2e2251bfb3707f0cc3a4216a59ec4448f812a0ce22e0e51bf5df03f59ff7", + "da48ebb9067fbeaeedf7bb260a764cdf19050f10cb56478f6ce724f604af69f3", + "6ea8c088fc5f0b7c0732d9086ee24ffb419e71747cc7fd8c6fe0a388a81ac703", + "829498c3d258b405ecc0000c93b95e3aab23876073570d3bbb8fd74afd58af93", + "ba82e3c88ac7f8bcdf5d2eeeffbe9061803dc33e48063dea7e9410d73fc17228", + "8fd60a04383d5fe0e7df5d5509e9984154829c6031d33124570fbe3c4788d82b", + "be8ab2d9b962a88b64f14cf01c6958e1de21870e423737cdf51377b308309d94", + "2be58b8dfbff9838ed55ae83ba3b9f24be4f6a9a716d89c279c304b4ee5a851a", + "d6335ba14c2b644a6430b7027532521317a8d657f9f814a743a096ec61ac9eb5", + "48df90cb3a5919d22ae252d4bb8f75f88776b13fa6b37e6a2cefdceedcd62ddc", + "fdc1a47db7ad626524b4030be06a34c7e961eb6485f7c2a217ec2ede2c147817", + "6d314457288e05f8f0e91c7edadb00c8525967ccace1154834d185a273d8278b", + "6bc848e217b1d6e19cd806df6241d3fdd192ca20b3e6ed4e642e56c007073a87", + "f5177632f01e5a58c9ee19fde7f3745489bbb5ab736a631340d364e843f7f52d", + "79952b796cf9b6bbcc1c38283f248368037b3d04d2d0efb430f41b1ee6143e97", + "a898a02736628f37689354600c38475bc665df959fb53827988404b1628c76bd", + "c578cf15695c1a9365711fceafbccfe2e7fad9d2af38ced3a6c98e2cdd0caec1", + "479784588e9e870c14e2ccb45af5f117cbc998e4141a485a16d4e27bc40660f5", + "10a863fe5c7ba272e2de38735131114b268369a0cc200af189636bb4bdb4f973", + "dadcb3b76dafcedc0c5dbfbbdfb53de89848989f1691a1d4cd1ef9e8edc7c807", + "29878374766948efea5188ef27c1c4c7113659978fc0971fdd4d4f8405bf250f", + "93447156c46a2a8ddaae80f8ae8ea4356931ef7c51479a3d8e98fc585e931090", + "d1d286911e41e2102c9891bb42d0b9d83356d1e8ccc4abf6d64ab2b419fd32c6", + "e2b4a88dc78ba70d6166b538d71c87a8d55f2c37173397f51d0f12a754544a9b", + "347199eb10f57ec6149e4825d810c9742b9b2373910786e4c047fbfff07e780c", + "660082bcf8c0b07cc15e5fef3f92e6c4913a6a8c91dce9b3dab6ab7e28f5d21e", + "d2f2af59e9e0c64ff6461d02da3f10acf20e47b95719821ff47b609e50560140", + "101d72731aa46ae955370559699175a91d480367e0904752171f94a1a94cce24", + "93c3c24deaff432bd991b57ecb7ce4a441c87ac1ca689b30f0282775983c9075", + "0b82739c73d30af2ab5df5747ac8067590e43470f7db127d978274e1a15ea9dd", + "093303ddfea48b10304df994eeb53ca4c8fc67978f1a81a6558f37527abf1ee9", + "8d94c1f5736b6fb3aa718298c44ea12e4b2eaf99c1a403a4730cc7dcac1ac294", + "2dd100fd619f371e8bc7f2c970993f7f0e9980cfb58f094e4b5abb4e5070bc80", + "5ae20ed3d797885db055169338570d953e710f05ba0b9bda8660b67253240090", + "71560bdfd4755418b3e7bf701a96783cdf52936a67929cf369b58e665b99e880", + "da85407691dcd1000a38e8fb00daac9dcbd811f44b618dc22b41e0abaa624875", + "0556bc8da262dc7e8ba7bf23ea763c15682ca564504f70ecb119df6781d87ae4", + "e2fda4b97c53bacc42f8b9b7310f0917f8f91ce6a505fde6fd6269b6ed8ffa76", + "a7a148239f9db25e45922d4e8e836ba34d8f8808be8d84ce3358befd8d2db048", + "e4ed75dad774bb28bdf86ee0b4d35b3ee84adc28a0369239fd73b9b9215df788", + "84b77ac6088fe88970c567429359d405e58d6e7377eefa45e37854c666c9dd1e", + "601a387df945956895f8df0c66addfb9760d29bc69da1b7e8c7abc4a9bb0bae4", + "cc9adf900b740f3fc07788671f91f7bbea8f57907266d397079ab462c3a326ee", + "79c5a7df204a43ea2f10a34df520cba332846d17ca235f720845bab30d3f253e", + "de6d36cfb2920547d47d7fd2d362cf55d2c847baf648b65b0bd6008faac8de16", + "7e04988e8cc69305f05b0e65af5779805072b2ec519583a2c58ef46d21765175", + "e8fc44b9e0757ca5df50b446bdbb52726261d403af89cee978dbc14fc902e152", + "53aa836a04524ec5b139958d1b408fb63327733aa407cfd5c5fa84b14d7fb2aa", + "9d26393342f0f94a1fe6c8a860819ff1dc7fa32582387ea54153e3e26390377c", + "f72de999fa6c3ccffa9dbc96bf95eb876545ad338fa8b689363f9315f583266f", + "9e452834930583bfe2d25ddbdccabe350e3bdca7cdc2ab5372b9a7fefc6d7754", + "da9d521601aedbf402ac944244419439d082cd1e2b578896b72caef826884252", + "8c31bb754af2a13c3bf6c663b15867db39a714bf5f49e0372265dbc8e52ccc2d", + "95703c29786e5f51d277a68067f94095c6aa84f17def456d20e804f0e26892ef", + "de0e90d32d3e913eb7933128125358df0077fa56cce1feac793d730187e87eff", + "c824a03d6b0dbeb9c3c81af26a50fe947c1a894e3e00250e867ab113c30adef0", + "abe0ceaf7e7df66050ff968d97d3159489eb6a97875ed8efadb5e07445cd8e12", + "4f4ce5effd3003800db874e91d28351781cf5711d3ed10e03dd3680232e95233", + "2c86400827c044629ce9f090b4551188d05bcf71a54c4236b714d27b2a513c13", + "1bc7a23fde632f9bc82a01b06b6946318ce450cb27e69b775b6672039b6e0f5d", + "36c08026b5eac6df3764c72c334367fb6c4f8b56530852edbd5e66c11d36ffca", + "a319a4b569b60387f9d7dbeec5f7d9b789e639b3724b6543e5e712b616fc9488", + "a2f660f788bcc5065640db93904afc4e25f260793d65845778c7a1b8d1490e8e", + "a15b29a501895057c62ee540023daac84241b3fd2bcc8afc79a30908eca0abda", + "15525dcf6ed011ca0af6f0a94fcca2087fa9fe7dfa5fb9227b2c816288c85d3e", + "a1d77606d1217465f53c7b831e5d0b481617d8690794ff1c314d09cc9cc92881", + "dfefccf78bdcc31a012f3ad22832ca6ce569afda1e5a9d58d48f25f992f70b2c", + "cd401b4423cdb2b0f3b92b29708ad52767b36d092698e6317e4e5c0da421bae8", + "e32831a375c10cdfc55852b22d03956236048c3da52fe8d6a3eebf9a59224f83", + "0128e011ee50813ec4f06761a5b33dda967afdee001116bda9195fbf90f00539", + "cf3c0aa03745a3c9abda1cb6082ccc4318257aed22ae0f8c573055cf2ac622a8", + "a4490415417cd8677f6c308ccb75230179015e4268a1bde736fc177d0f8c44a8", + "175210162a0da0969da13ebe709ab98c3908326b2dc14dc5fe0b7882034399bc", + "9cdbc9fbeb818b3c34233d96678e2a9720626b6651de1eebee617e59f9a66c5c", + "a27ea4b279eadb9f3508160d72700d773587473c5762f380198a8a89c6c22141", + "2bbdc32d5f0fd8660ecffd6d45f360ba02e3c3b40ea478906b7b5657ddae68bc", + "804cbd032215730ea5d3d75c29a4bd9d869073685c8b00bfa78f3c77c4b81d5f", + "13a948ecfcee67d6cca47fbc9cdcda059fdf9db3867d10eed695d980acecbbf6", + "ffc85ee938ddac5ae5d4031d12c4d517c07bff3b8aeb5771a8bfcdc940346ea8", + "919d91b848a0c1d12173723b03ec51457471a1f29a67c9fcb2e54c17b3f8001c", + "a32c0b1fdc3f70a2ee6bb8ce7d35894b5de9487a7c935933dad6e3f6791c4d20", + "61b05fe67268119389a5137a77df2b066d7f3492cd3d8f877d35d9a964c68452", + "ac1868c5f1ec6a77132bdf13b7a18e34be4532699e00580043ce5a75b415fbe2", + "462e7d370723a28b88d9e36a3cdecdd7192dfbc2f9e6d059657d8ce170ff668b", + "71f9414d1d671a40730560f9e0e326d255705b81a9ed411c786b00e78ede4f1e", + "9e7f48c4a3098355b3f434ab490c1eeea27b34700dcbe31a3d384d6e039036f6", + "a49b5a0aac636e2666b808ebb39012dad21d39dfbe3b097324cdfb496dc50a52", + "670a928bf1aa2e1b21474c6a7f5b4fef97fc9290f1423d468a8b18ca82520819", + "a5eecf46865e385b3bbeb312af2ae377bf7c520a00d6379de3f3280c433a1913", + "2aa9867ecbbd8c15dd5a82a021785d0bff710bbdddcdddc6499cf35328409578", + "7347e1ced55f779a358e50ba18ad27c4ff25b3893c2287d85d62b33bc8951af3", + "0a5bf094fc2534f121ba3b14ce57eba4db2113f4809001b1b659baa77142f846", + "bbcb5425d648b623dabf2f8ae7e367682bc41643ee10db7eb8a5ee4b7eda16d4", + "bd9504c9c8dfe7a9436b584e61c74d9997479c855e968d3dea545e4a5b693589", + "ac1c6b40a0db3af38370f09fb0a3e60084e868845ad00754f5d85a2834343ad9", + "06e8294cdb53863c48a4cfd95d92c75347dce080b525bc5662304d1a8913f657", + "031de0ecc94b24ed6d6e0c667c7b891727f48f14ab550282e3ab2d22c0d3ba0e", + "67ca0be4ddf96185a8ed3e04894809782a2310e914e18ad2bed549dc1a27c3fe", + "b03ef3682d4e207afee7f5b1a4be0992e3c0b58704d26068dde48b8483695517", + "b77401e79a2e3f16f599c911f7e173cff5b200f204d7091feca2010e91431692", + "6fce7aa4b6fbd9422c8725809f03ebba27046dea5641e074d679b6c6b7057ebf", + "66abb4a5d5342e3d9dd55363fd299954780bf6723d6d7f69930801a9ac1277aa", + "03d72ee745a556d88727ae6797e46dc56b4e2fb482d336bbda8e15fb311c50bd", + "174100710df5346b4a6f665198290fdea6192da55ffe30fe28409e3508848aaa", + "bcce9c5dcdf1c89650a4d612607a071813df980d7105d6b8fd80fa2a06e86a4a", + "8ba5d6a8ee8bceb0cb5f4bcc9c0be362350b093f8e695bcb1692800e08fe8ef4", + "d51caa49c764e2cdbbac5c4afb5ab69f04c637d742ecccb37e85812bf6b71d40", + "91e8aba8041fc299cd89bedae068963f3ed808622322fd3bfc3ecbadc6b6a93b", + "f9a48779983f43559ee169018d86f75c58d40e437b02668f1f6afd4f4e9ab490", + "17a39a1a672a159fe5a88e5cc6ac21a3d080c5a72599a53adaf6945980c3d699", + "99f8b439f0d70d2e3751171a794e04b07400d4fbdac3d8cdb646a627ce90938a", + "1f9f647e8fd44504a9166174f47910b1dcb025154ed76a89d7a5234b17b0c6bf", + "0de42c262b7f43de6c1306d1bb1faee660e3dd68d159a6ce56a2314de396ceed", + "d11e168b811954478dbda2a485d9b50f98a17ccd1a9eb7cde96b6a37d30dd858", + "b72a812efaac79dd5126816c53af4795df3d9a6d2b8571a786e60c138e55d52a", + "bbd13d7db842578b3fb934079e3a49fcf4f506cf0d82e173df7e595cbc856946", + "34cac3fdd9e640110531a6133a9ed288e5ce1305bf7b04092ab38dbdc36aa0fd", + "cd7c48f3c97963392634933fc388dba2c018902dfddb3b694fc98a5b6cbc399c", + "fcb6bfd99e357201730027979b9233280671c9ba852e6fdfb72d904f369b0669", + "2bc3091ec10cfc35dcaae25edff9b3efa8a3268789cb1c98f623e6ad54e768dc", + "96079472691235a8a6193e5efa497c14a4975056e2404a925345ac7899ea4690", + "282b55b54a1316223084bff8d6d546142de77bd6265968c77dba9be9cd6ff0a6", + "e8e6c70a7e56fda300ce4d6d95945c17546ac6428297ea00bc358d0054a3ee31", + "ff712cb3be4d6b41c0511460bf89b14212e884338c7260714370c9b0105db507", + "77ae771cfcf54f59a90f86dad78bf4fab0b8dd042f89834da0469a4cadf22ef1", + "2db343aedc4a0e7e3562b7d2ca4610668b489865daca759d558b2ed2e9f1c89d", + "1ae070001a0b7ae96b2c25dfd1d5789f0030b67f86f9d7cbcb17724cd67930a3", + "f4067c788fc14c1f1c8241d7afc5a058978d7f3268fe642282ffe92c2ba9422e", + "7be6eaf4e78b8be1ef3bc6a129ed474566e0335fa574078e90777f4418e0593c", + "2cdb4fe519cd467fac09701927710622161da3b5e65ed57f725517f847c67fbf", + "0432667a3f9a67c8afd3b253cc3ca50af7d5ce3dfc47bd538a154de44862ba3a", + "74938c36165d6fb84bb8fe756df9a6817916ad6a86cfbca6f193defaea781bdd", + "20b766fec74c0ff92d222185c472634e9771c4045e9d4cf572944b3d9775ad40", + "f2d3ceb76a74ce9fca851c720ba9257b84e79725a3a6f99384a8d3d8bebb4e3b", + "ca63e9002af0bf77e342c6282d3205fb7d44fcedb3af3e38601c4034cf52226a", + "8c341369748ccedfdd1852260525e782cfedf67656562eff662b98cd0120d07e", + "deee275ee3b8f9e7c46e585442179747c7b6d35c7551073fdf0bb8599815427d", + "7ded35e151caff94a770049c7f693b5ef23325e4e31d685cfcda65679bb6c31c", + "54afcd71a02762d4654fc94964dc7918b926a92c8a3cac049472acf696633305", + "b0d89d9bc8597f3585a343c401866f6b75d120893e0c484b9543b9ff2a97a1f4", + "ea4b3be82290bf009b2ebcac9ce360053fecf0eb2cee2a3c9f73167c3937c251", + "b62641ae5d15cbde1cc16aa9c07837670d8a993a0534bba461f13e83a647fb1f", + "c019bfd2c5a9ff64e44c749c970537d49813a7ffed20a3a83d69fad67ee32712", + "7de1043c9cff7249fc071956835843b050b19da47e44035f8d96a9d9aee97727", + "72b170ab1006a30df3b6edb719489550591522c646492905653635204dd54326", + "ce7dba523e894cec785c628af62eca9d180c5f4c46af597fc9554df42cbaaf65", + "e819c828394984a3b0b0c92f9b5da3a504f8aa305a4c782a63c6b3cbeb81a4cb", + "26519d1a6b37109e1d308b71e6a25a8baf1c1021d902bd89e5f43dd7e914638b", + "227ae308b4cd4feb251581c9ea5f53ea50d1466b7512741147579e8d49ea0aed", + "d9ec80c2d9f4ca8049ec60c34b8208b9701ffb13d239cb91589f90ff66c2b014", + "d1df6454f66ccad8a49f2d95955dd6be3164c4f87941c1ca3932029920b4ddf6", + "98cbb24a53761521420514f75fc46b80d82a8bdaa30876696ede98a35ab0230f", + "5709bbcd3cbd9c07e8430c2dd7b305d04d816594e59b9a0db5ab955551d54813", + "aea40ca6da95a000f20919ca15f5dcfa600402e9d992c373c697b3a9d1039e3c", + "87c7ab37f857bed07771e6d60244bd6c961301c96dd61a36666eb90bb7cf38c2", + "e0d7ed99618187e17c5c7016410e6e5691761a3f24f659164e84d60e5b390fe0", + "265237e9ee7cb29199e2ffd0c01f5ca77804aaef961a234c0a54f10388e41251", + "cbc4589bf7b15bc322a09d9752f82ce185664ef8e70df23a7c3780af1fad5ca1", + "7acd7288c765a78309f94d47a073a546452e1da2a63ed0f295a91d7171c71b0e", + "35367baf2e258b6470d3b7ee80bfdde5514a88a68968e6012c200accc5f4e557", + "722542d0fceab5c010efdb003fc0b95f46a250068cd12d642c61584e96c436ad", + "2edbedb2889eda34239b0a6d8cd45a231f536497b827ead9cc095fc9b31bc5e2", + "2d5eb50b99bb94bd347e5e5f9de374887ef8b8e18c84797111d986a0cef7e718", + "d2148c38f79954e06b2a3da0792f4eb1f8cbee47ce0632a2a3092122b5b5dccd", + "adbd1196a22423de7c92157d2bf4652a146686947de174216844bc895050626b", + "317d7a9869c53ccaf902382712eb2f3c577284f718df87c35f4d7b1d49515b08", + "f0f2a3d6a6b57676d2eb449ca568a5f579256677aa4f6bc5588c0fad8a6de51d", + "e0c68a7c6fff0c7e5b1e0c60d250f38c503a038857bd096049a9b77708d32e3f", + "3903eb4bb863771b3c250ef58cf17f20c440662b0a9fca0f77d6fbc5e1b5ce19", + "8ee2270ab1b4295535bac801a655bfc05fbc51ba487917682b2c1db805c9cf6a", + "d9d3956d2241d703424906d0355f492c86fbb33cc19b741fcdd9fd91c88dea1f", + "b4c1d16e2d194c06e0094cf8cacd4e7a3edb586efcda344cf826dd3d392c9c82", + "cd364b1f42c5d227eddf2193171b754621e7b3e9c50a9d839789a2b6c9889673", + "47493e280bd2cc85dc8f2861afbc2e9c7d0c97bdb429f5db9dac430965906f59", + "1f48ff4adeaab5e38084e48d9d98d17dacde5d3e608f222db7cd8d65f1f43177", + "561296618e8bb7473b87b920245eb0fa1d2c4a94102f96476f01a3c0f8fbd652", + "fc58de1804ca746b9416b2c19559a4cc68c9cb9edf532d15a0a8850681e1306e", + "2efcbf6b2d2846343ea8ccc2cc6eac322ac94ed09eb9af5c0fc20abbdacaf0c0", + "d555c6b16b496fd561c44c40e9425fdf15f96e54b3e5a0ed5bd96a598a7866e5", + "b61ab2e8060682fb2bd2789c3ff30ef63abed2b951ef0366403dcae0b3718e05", + "2b6cef38fb89102fc946ed08da675b4eb7e2067a8bd173a3f71665aacc2e88ba", + "c8e6c004fbe0fb2733928ead49ff865580efa57e647d1034c576ff85e88b2e1c", + "8e98ace733e904937e4ea5646be0587b80f45edf52b2f2228f882f314b23c471", + "303b715149991b31ce3da3a1b0b2bc51fac61b093cd432b8d080265c2d766548", + "f614d56881d52b4a7851e370c26b5cb54bba5e7e990514ade5b22bb0d05ff7de", + "22d368ec64c174ba8ee9d6c606054976eda05c2857fd9dfda54efca30622347f", + "da663f8f577257eb645441b13de3a95675b7c75941fbff91cd9d91984373585b", + "5fb3fa26c4073687ab8d9af2df58fa80e28e7bd6993691a1a6d09f543913c98b", + "fe04635d0917b45792c5469b0e846d605f43cdf74ae7932b438889bd1613a3d4", + "ede0c4835266d04a830c3b6fc92de6f1817c4f007040fb92b0219008bdfe3b76", + "d76d1eb375a5eb4f09421e59e3da4ba52f9847a5fa7b9fb04af6719a11c43339", + "0844f1b4bd3cc96fde99f6c12f66949d9c186ba9445fd9809f22c17472237db0", + "70444e4ac910cb28d3bae1f092332df082b17cac6c16af32982bde737bbe1075", + "27ac6cb583fd77a037c629524097163e25995bef85b04d03d9a37d2ff420a2f3", + "973693990a30a666915482637d982477e70cb95d7e0b55d01be71d6d5df1041f", + "ca685f5ba9a1efd428d1e11e7f63288738dc39871869d7bd33b1f7aa024681a0", + "141d7b7df7f31c18f2505b4620aa3d2571d1b5f61867bc1c16b6ed6e8f051d9c", + "3eb7a4a40c46548f31d8c663d535469c5aaa0d61ca8f764d4421af686a8a4b0b", + "3f1c599f175ad7a382a7553c01a4a6bcbef2f2666c9219e43c626a4a5dd765a8", + "03f0cea9efc254d001cb20bb001e2b40174dc9c0a20d557ff3c51b043a499c8d", + "fe5d56166f30c89fb7b15085acf099b2e600335ff8f5f1d39592abb7b86cbe11", + "2a666cf3eb5b5095f1f4d71bd816124b5defe6e7e6f30640c77e05ae0bcc2a2b", + "0fd04eefb4ec2985da437a6a26c5d2231b85149397cf8fb26e8c31d409ef87cf", + "bc2a604809c1a10aae10e6bdce535f1f0135d386bbf9450b79f8d01f1a187c36", + "6c91d789471050700403183f483d979b6c6167a6b07877e07be112fcd298376a", + "8655be2250180fe90b4298979fa55d55fb65a597e36e00fea1f60dfc5ee5f2ce", + "e98f2e8caf6cb7f32680051b8340b1d2e638ace18c15a6986c5fbfb4e15bbb42", + "43d3291e97b5e53cf38078b7fee2e64cd2f7b17dd40565f6d75372e7fc60cf9a", + "70c1bfd672b30b981001ce390bf475ae26c64a875a39ec8b0516695c96f41aa0", + "50599f07766f42b8c1491ffa42fdc93f2577142eb9a710411487d1afdd9eb261", + "6623f0bec5bb2ead29cbf98280a98fefd90f9e09f30fb64012037795a87bb959", + "eb1d855ca5fb5de705062736073ea503b7e5449afdb5128bc4552e0ad89667eb", + "6f3e9a158086fc9b05a12cf4b4fc573cc4e8d7f86456229465f3e6c225b8e956", + "0a312910d4770532fb1d2bd9c8ed47303d23e4f19b48aadb677d8aa93d69175f", + "1e382232eb0044471ac04b6bb42e74d6fbf0550a3dad666c6a9523778165e1fa", + "a67d9271417b8d9677dd1e9f0ac4d7540b9bd367a24c2a9e1a2287728596eb2b", + "bc16c830250f77c0b2a1a0b83a911490096bf9bdc46f2a93c5b094e1553c7f9e", + "379e78140df3c7463ee7225bdee955fee6387532c0a8de1a7956ce349f4fd847", + "63775f87d63c467a830065f5d89ca8ef209fb44e80b954bb846a5e1e61961fa6", + "e823eb15f88c2b04ef216365f044fd0d71976cee57d36fdef6249fc8a4801584", + "433433c89eda585bacfdf089be711e3dd41719c930c8c7006d64523fac69e730", + "ac11b21fbfb8407538c2fd572d7882d116ab3a86601e0cb8e0e5958b744ea6f8", + "4f681fae0baa027242e5ea1bf1e87fbda2d8939913b3b464c6d89ac90b50511a", + "60ef588331270b8a83bf61fd8ba2dedcbc8f51a981579f7eb1961818e51c9cfc", + "7c8cd48aec6dc3ecf5dece739e287335660361298b9200df1d9092934ce2b39a", + "dd7810a05f9b01ac1ebde1b691164c00eafe64eeff749eaa894717e4e121ab0a", + "873269c14659493adc46dc1aa31aa4e663fb6f717a7bcbd90d3a07d6afc44f46", + "a2fa7ab67c309141c8b592f151afcc695b15cc74eff602dd449e495f41fa2684", + "0ff746ed5cf26132835d92c481bc31edcf38cc769ec7655a4cff2c5bf75ab75c", + "e2d34af228c74c15390ee7af98bf83e578717417e174be3be5ef20d69a25307f", + "22543feeff7f8db908a8f5d7ad09c364b26a5b659e31248474d9481550fdc6dd", + "492c2b37b1ec25f3a2ef12de7ec45bac6f3984cced67209a10f2ca5a6ba4e997", + "e18defce11c66a5b54e5bc2984f29f4947c31212df280ec96b46bad707b8094b", + "09078a8215e43952ce36947a1653ec1d5fb0d84d66017b00a1e3528f76e04f21", + "d7f2845e43eee0af82c5672f37f394d44539c1a0dff9e771ab1eed0cd1df3d8c", + "da920a9cae7ba5c99f3138e3dbbf79784eae6ab903d8e87cfd9d08656e954ea4", + "f004f2b461b2d248e755ca458e325ca8b22445897b36684201b5d4840b77e583", + "26a3030e134e27d99d2abf3adb187dfcdeff964c8a28b8460d67c35d76788ef1", + "7200ffc98660ee2a8749018b2229fb3d24564565cf3acc7d1cb870afa5bc0e97", + "5edb33f2c159476dae8256be340dfad8824a7b8c75bbb5a3915209d00e2d87ae", + "c7cb1e2f2c26fa86cefc80b11023028aac069d283f7438eadf33a3dad7932fef", + "ba6de7da2fc3cf0a782e07a1c3b58b2336b02f1fb78f74981478d2ef61ab4b2d", + "c17d0761ce7c7b2a9822d6ad191087d743e41f399496e972208a5615f12b9ce2", + "1cbc7b80e1bf0bdfb0ac0ecce5a2f0e7c11970a9d5d5cd7befe6b00fc47b69dd", + "f87439ca3c692c0c4cf635659883a70562701634cd64096766d81d946a8bb72b", + "3068a1d00ed3e2c2bcad173d7a35b3dc02995f3d0886e37be17016132e25e5a7", + "8f033ad53d3d974de891a4a4a74ff2e3c21d27d95bb3e8a0101e28a63e3668a4", + "4dd75b8320c5c7535676d3e779892b228e7644523ab108b3085506647ef08b37", + "1cbfcc7a1fa183e53c069b0071d18aefbb8e9d863866c39db4d62fcfa01fa159", + "6a05c0eda574e45749561e6713b2ac043043a2c6731e21e1e1262b10810354e0", + "fe92667b024728f406fecd8db30e4421ad65e79fc14b2daaf05054afbf9c9491", + "43e11055e577f1eb8a2a54f72e9e68afb12c235afec8bd364abb8d608c2fb660", + "58dc2c93e7917bd25a99bb1edfc36ee71f35b600a14f9d9460b60122a7f5a0f2", + "146f945faca5539e6ff1015b7d83dc7636216b190c645f4bd77d4b8e35d59612", + "535f39cd7adb916c919217e763549da21aa6dcc75b01068ed8765c7d49bb52c7", + "2c86974dc476c76552f8f205ae18492ea2e4e5c41f92d324d21c64524a721810", + "600e59bfeb06c86d2acbbffb22d5ea905a489503d666fd6dec89a94f85f753b1", + "75badac0ed4d94be0c2b2532c8699fd0fb5f860ec5545c9d95119befdf6100d6", + "943df6d1e4dbb607868c8a372a786f5fd7e85e40375eda98c5e6c1feb9613c02", + "734e4b5e13df7f88fd9ed83288cdfbc38257430361fc89e41f39df35766d5130", + "0c609015fdc5bd54179045e6fab0e0db9e7e7b3be64b8f436b67b03325d6c739", + "c8b4bbf7b7d973232a09d0d279fc5061ca97566bca1750198e798d7fd48178ac", + "ea7cc56418153c90d8667e159f54e631987236829d8b5ef40e5b76ea7836d9b6", + "d9016f28b5f7ad1832854f989af4ed4fd6157c10df8afda75613c0f77c0634f5", + "e8c277ee8879da4b454c00e4c1f4044facc2e9a2253b2bd2d4f9fa82bbcbfad4", + "8ebc7faa232debd15ce110ce299d8905b894d3ffd543544290ae9a73f5d9d601", + "bc6d2d3324244481f96ad8978563099d2652a325dc4fa36485138bd5b4618e66", + "a60c0953099ec7441629bd239955adfb9f9ba31b5014da1ae7f6438159efc01c", + "9266a1fa5102804b4523b00d907a6dd02ae94742f7749f4a010cfe24384793e2", + "949eda89c76a0e33121c735e7e5055389ad97e96e5fbe20f5ad52e49d69354c7", + "de0a337b37d3cbe6b71df7c2df933ae7dcfc4ccfbcc4da22a308712c67058ba0", + "a2a22fa5112ee46ddab4b843672e8b382f86d7e2ccbfac514aa0eaf93c884db5", + "08cc41481465814cdc1e1aa99d72c1ab064dd971e280326c8ab2a25ad42a69df", + "d966cbc74d068a3745a748e1d01a8fc6f9f886d361238ec36d9750bf737cef1b", + "2511a6d4c719c13f01d1d652e81d16d5200ffebf3a116ac4ba81b77f881b4797", + "6ed7d86241afafc1ca461148e35336f74da31ce1444f6ebb2f09b92c0beec194", + "b4bcc8fbff7d0ad525f26faa4952bc5b432565baddcb624c6dbf124b9c526e5c", + "c1e29ad147f99f7056ee3a5797536673a527f72f3935b607c4e093dae998a15a", + "20dc0eeb22948f2b5eee4981a317e5e3ea07a58906eca091ab9764710b12f3d6", + "16bb63c19835525478a5c95e2c81c4133596701688607864bd01af2eeb2be3f2", + "90fde8269e1a5abd4f55b266e33c35eec3c5fcbdfb4e5b5d8106b2d6419cbd10", + "dae1d7d72060de38d8001877947c890e4477b329cad9f90413fa762655a513e6", + "839e3c915ad27d3a0f7fec3863b1cc16f06c340b444b2595e582ec7e4e7a7d2f", + "e0b8add37f4f2844b342fcba255c0785ab3c96af041214c12b92f12881742338", + "b8ed9d7501ca9a5d501dab6ac7a7e24b21d98dd0213e2b1559bce7c2e3f78c9e", + "081e47ec0b3e56b988e558176ff8458ee65ef30e92837350f048d8992ceb5bb0", + "08db7529bb6ce8a9614710d703e9a920b6bba557eb8aaa5a1736f94fb2bba81a", + "ef42fd6fe449f84db934eb70d01709b6dfdc4e9fd818ed10aa797dffb8d09e71", + "7c4074b1a28e70056b89e27144a7c08a23156ac360e9f76c3643e05ef8a6291a", + "334c0329afae0dcd756db2e698a5cf063adfba4729d87c4cbb6ad3de37335b7a", + "53c7bdf8f489dbafec634fcf17bad0720824b96401078623209fe663d0352928", + "df5dcd21deb716ef1a4383cf620c394c738f4dd97101e0fa7c9a9b3029d576ab", + "979d21e09c689e5ed84447ab7b46c0686a75f9b7a68477e838def18e5449f1ff", + "1fcd6a7ab2b98226f7843e5c5d1ab990ffb3af83b37ffc5c40da67ca8090e61b", + "6295c87047d38ecc0ef1252ad47f76ecbdf607a3e559fe263a199906252923ce", + "52213ff1197c44c4341d3609d80dba78e71db1f7087975bd0e184ea9c498b06a", + "5ec143bf8c5ba83effbf92fa30b6e4ff35210cde59d9ccf934de46aa53f5b0c8", + "855a9c12bf86f4ffb2ed4ca61cfbf40e1376a8b67f5745f1edf8eac00f549e26", + "d35dd267b967ed1e66d804ccfbb9ba3e0e3fb3b4c427b0f9e1b90ea54eb62354", + "43e0f96dfa63a116e922169c2cfc82aabd05aa473d24224f164d12259c6688da", + "3638b9dda708f2ddbe49f8e11bbb76e3ad9b6f21e8263c5e1920003e214833f8", + "f6c892440a41ecf811117f294610b37af31af89f3aa50bcf267f4c2bf0405716", + "7dd65c19eff5d01d931bb38dcc46859381c8fbe3bd534cc50ac8521931a8ccbb", + "3e78c6a9e3c32fc6fe8dbd8640bae13f539a7149adcb0e456f3f4e4bc977af42", + "4f0b96a8c67c7ea40f2bbaa7a2ae5f3bb181b83890a6bd57d3c2a560d62c0cfe", + "181ba3d8a3544c6a7be441f7b1066e6116a9f56a2cc27a569aa79faae69290b8", + "09d886073fc5564daa0ee89f24082c51051ffed7b242d3a06a9a7a71c4296a0f", + "66a4c55a278bb6147a67a6e465b01623075a75f22e53ce496ff5c3fded0b2f5a", + "77e3e92e7a7e087b47856cb34fed48834177af47cfd714d4ea4f9ce9c9502bfe", + "b218e81d42a8e4c070215b00234eb00d52d13e68a340858e0a6c3f361f3e1f9b", + "ec0946958939c9b03de3d3aa515d9a2e168f84f576d62c06b56fc82a2f0ac502", + "fdcc1adf001db212b52c6d7fca9de4f503bda61eccbf851d65c538d76ee32a70", + "3ecd4dc2bb6074147df9b59b9d972a5ea187b7056be32d68146c87a84875f10e", + "3dfb267e8c328637b5ce4f88ff254496b4d953856ae83ec00d0f61d581be278a", + "db8854aaf347d1f4e258efff1b43e2d4cc1ef96b3b4270ffad211bd77879a605", + "06de726d0e86117dbff918a23f582cf95ddaa455d172b892b84e6804bfdb9e4a", + "602a4190caf337689ad22ebdee3270edcd9269debbddf4e1b0377ee0ff1efe21", + "695a8f9ee89b5df6eb8902b0bfd27a94ca32c9da117cdbb0a529c4eb18811270", + "fc0fb3f4e089e9f63cabbf851594902f6f0281b4cdfc6e345ec58555db20aafe", + "edebe2cbacb87b303ca0bf458d74cc94ce44b1fe88bd7efc08a503a088a330fc", + "c9c435d7386b913cb5403ef6ad37634968f87adfc1f7cd2d8f237f7fdd825bd3", + "870acbf26f3e5978d247ed7bd3e488d049ea79de9a92d3089942f93f57366dc3", + "e47c9592a46578b5be050585387023b7ed8795a631097037e391f6cbc4a1d394", + "3da3d98a3f02687565bdcd96f4355e3fb2fd335545fd5b85eb814ecb4286b4ce", + "f45c503765254845e9a46661f9ec1c0cea0ebfb58f842553d64fd53c733fe132", + "ccb2e2dbe4e5003076afca8828aa5a4299bf18d607bfc365f1528f28912cc720", + "4a6f7ab02522e7b8b80aac46c32f0d7e64a5389f93ea6084163b59e173742a27", + "08b937805fb5965b0a7f69f6d2327b03d0fd0b052b5e990c7bfb9358e371a425", + "501b1581f2103759184b0f4e51b7fe146784814a23fbb9b7c58f16290bf17461", + "8431b4901e35ad2bbed3a7e7cf32927a5255941d12313158645411cded0d27f9", + "37744ef8564a03632ba6c2ca0eb08f3edd72f07c3482061dc7d189942fba36c9", + "68a7834dfd984f79f2408c55ffb185a4e4ced2775ae21b212c273a43eb4b3239", + "0fd6894a0f363eafb6fd025ded74d4030394bc98428b2235cbd9b10b74a214da", + "292e434703774661aba26a3fb612eeba4ed8532aab00b11ac9877d7f6d85abf3", + "975594edfff43c495618a303f389306d6813d9030170b252b7f009113b07a601", + "4c24bd6246720423c6b1f7ef954e13b18d859bce37ef4e67a3e7b928884f13fa", + "bb625cc66464c530b107edf70347ed2d71879e4623b2fc3b16d5add5d43a136d", + "f0ba3cfdf1f19f1eaf935003dadb8a2319a185ed0151669134093c8a56f2c9b0", + "8d97a044973bc86abd7605d0eff2b1ba563b5c6fc43fd57dc789071cdfc5f5b0", + "fb4837c89fac1de8a503f4a201b419e79f82418e469bda395ac7589651c01900", + "61b330dbc39d2da9bffd7721698758ccc32bf8e1e17f9a29c537a7e5afa8ad3b", + "5781f5445d3ce936964973a7caf89e81a1a517959db9f56027c17e5591d59302", + "e4a3a3ea1e4108df5afe50077adc77f8eadb98a6803912b2a02df702a2537924", + "c7a6e5d3ce64aa78beb81880b5e97db0d113bd18a8979c70e65a8ffb37ef1487", + "af1d8ea4e96cc187768427b89cf2b089df4e5614eeff1a71f2c72524b31e504e", + "b309f0fb738935abdabcc8c345ccfc65095bb3ad9155d56912d64a0eee2af230", + "ef3465e81aea5d61c385934f159c171b6caafbca52e43c4d63ca0e8668ebf27f", + "2d8da3d0a5776534d0842408e762deddf8b8cdd379cc8293771c02508e38884f", + "333afb0941a41fac1d6f77b1640a292dff03e210531667160913a9598c9f738c", + "ed3f97249b970eb09e2b19b75d97fc0ff21fe9fa12818ef8fbaa1dabec9dc616", + "237b447966585434a49e6d9a404982e6b270bdc9db91c4840c0bb15f28b36d02", + "91ffa121b7e21cd52dd6d6f0034d84fafecc41341af6c2267fd7ded1eaf86a37", + "688ba314a5a2368d7cfcb9bcdd630e3a8672b173e013e3f12eda12ca9d2fea5d", + "661018cd853b0b798e8b0c884cec09bc4104972b3a48fa18761c1f769b339d84", + "75e7204f9c96ae5fd66680356989e30f4c053d1ca08a76880eff1a18e47b88e2", + "a8fa9e296de45b271e5e72b3a5eab9a72659ce652e94cb5ad9935fb8875bb885", + "2ea1e851e2453dd657613771d2a223c0cce5a4df052861d8237aef602f872ddf", + "1a4f8e8767b7694d7d7e0e2b12c92ae6b42d1dfa8add4805f6f872d6e35674f5", + "e3437bba79c99f321a19c1aa1b32f37ab6fce0334b25d645a020c1424da1d6a7", + "4ce21fae4cc10b09470877ccf8e49105cbf51da40d01bcf8056183e6a1aae174", + "3d903749656f61a2fbe3a6963f24eb1647349c47682838866903cb49c5b8d212", + "deb74db000900b5f77453c769be9d86d8ae2ff1e33c33b2adacf8d5f917741b6", + "5b64955f30750f051fa69f83d9663fe6e40f167fd90414369f0cc0cd491111d7", + "76ebde73250fc6681d8a9bb56d7e090e3572f6997bb293bce04e6376c26f0881", + "94d12654dd4d414b25c3bca79fff438adb79b215b96921685f4df5fb675715d3", + "cbef00b926662c750f5ef998cd0f95a4742d4705d7f06a1f469918668f9fe265", + "f87188d47c42316bfc8984fd3bc561ded7cd7eb8c18ff520d25676aaa48da49e", + "b5e30cbe14b84b4a9fe6773b70c62a5534733f104f3a6cea9c778e265f071c80", + "2aac1aa64677cd671c4e4598c8e0d46c4a42b7fa856f6f7458dafad326a5e2c2", + "1b7c23db0be31986c5bc9d330ef51cae4fbb9073020f3c7160b3d81e5b350e3a", + "de286540622432014022b5f2dde61cac58a7ce19e205b60e3632a696ca26e5f1", + "94368327a486cb0628aa027cc2de0c08f4f689ac540f50c8fadd04b1e5ed3cbf", + "d19fd0f896e1b5337f481f180019717dce6e3dc82d940fe580ba2f95357ce139", + "5f119517b1ced16b79619cfe96487803cb9a8ca74be819c536eaed8c8a6dc678", + "7b0e032b3cb824ee86c7c9be1b642a1d4160313768764a501fb5fe7ae72aa47b", + "250b2ce88e52d9b3d6906b9b2a39b93b87a523455e7189701e9508d203c1fb40", + "bb97cbdcc39dc6c1e5c6737f3ab8321f9c6091d610d90361f4876d861fff2b3a", + "d3f7226311cefe4c6f64eca55f08dd27dc048ec9e7d03085bd89a3b199f29064", + "c91ba785fab7868063fe4ff4faff378b887131b6dd2ff4c2031f9f6161df0f03", + "cb9f8a032b24ce9d2b1a836b2ccefdad43a3c577bf75d9a035e8863be8c8eeeb", + "86da5d1860d7248b51711fa9479a7faf70ccf181c8e63ff95d8ab7d141efc1fb", + "c472299e94e2c3acaf9db59dc8ccc2fc622d1666984565589bda5e15d21c1f0c", + "2f16bb3467380b7277d54e159a9d9970b2d346a0525b51bf55f0b51ae9ca8204", + "2fa1c04632c21669942bef62fbe2f8f5b06970737df863a823dda9181930300b", + "011737a74aede15c1f397ea182ff70968d3a34891b9f3a9bce282a60f04ae712", + "399bd9bc34101c4e34859cf11ae99f8e5a5e95988cb36f75715159b0821fe711", + "5dcb51391b9c54ae75f17da9708574fb50896b18d4697df4ff8adad943823821", + "0cead0cb83fe0554721ef8039c0b312ce8c5111d43489f4843c921afe1307ad5", + "37bf19fc486486fa9c5978580517738e55355845cf50990b7eaf36cc3f972f3d", + "521e9e6104ecd1b2bae4e739bfc3c88cd58b2bc1310418dd82176cd6105614e2", + "948a4fcce84b1f5997951226e4291dd6fcd375d91cc717e5eded692b83d97529", + "0037b2b0e8a75f4c6c2732069e894dd50c98d28dd3fb107d9d1deed3618fa471", + "b36a8e8bf185d3c936fa0c8b2f40122afb9ca90a148dded54c5c90097aeb394e", + "a1f954e6d4f5da600d041aec3323cfd7c3d54c9aaa37533f320a81564d33d481", + "2fbf90774ad18326abd32131d911e0e60e364f86e56bf5036c50c93c18e2bafd", + "41196c5caa98d98d5679960e49dc5d324411c6eb3272baab2f090f4d5025959d", + "29567109c2b0fdb005bf9482727a6dd7bfc99948fa1dde9a873d0a2dceeb37c5", + "c959fe09a078892f64095797f0054d678bb8171ec7585b67ee761508474b26fd", + "d579953cf950f6f1dc833c41729c22e77f87387f66e7abae7cd129d5b78101ea", + "ceb54847449bc552f877f372ef7f41652e8ff6439ff23625b0d8598c991229f2", + "22d4095c1a48a0e0262b393567d78ed0858a50258af81bc467b6864a97eb8ee1", + "4623ee7e93c2639f76e3ba840da18fa3c0d85716daecfda63e0d1a890b3fee93", + "8c4c1a4f03cce5031faf56a39ac79ba26a8c5b7a75d9d537208260840b193ca9", + "47f5dd4624479ab6d70c32d54691080bf4b306cc7e9037b9a32db359fe7cf05c", + "cfc791128f4b3d5411fdce2f9c95a07b528006036a3672972e8366edf03f95d1", + "99d8106d9b444c31981fe22e03b37454fb493f2b6bae5e94c4cddd33cbfdcdb6", + "21e363d2b91ee584d7c9db34d39397cc5c08c43f8ed01b6211eb212b3b83faed", + "3c4c4de0dc76b300309589d67e075a1b8234852f228a9acbc9d0612cf737c4e3", + "d09d6609f593e591e7cd0e51d72992709d03af0f3e1658fd07c0bb3c40410fe5", + "6c0de6d3a07528fc21b75dd6dd1c95da0dda89dea5d11002ef76d7a4fea38698", + "d70c11dd6ce6605ed44811d075189ab3d8910fe23207edeed485457cb0e9a72f", + "aecb2bf85349b27b0339663d78c7754cef796a16ca94a125536e0b4a04c16ba8", + "5bbb118936cc59977e16b5194069ef11b39c705943fef7ad50ea7e437970ddc1", + "e1a05ff2e78505837489e72c7f3681d640e738b94f4d0fd9698c2492214b91d2", + "5ef171f9085c94c54ee0db4644677d9a7649ec6a2edc9318942fa0b9d518c6e1", + "52645cf7a56d8e9d02cb73a97a4cb6660cb58a4f5a4cf3a2b6772bbc52002f3c", + "d5fdb5548c3d8b36f86274849916278de48b48293908575e34a62667cdcae42e", + "2b1299cb46d1fc94add628e4c79796ef0eefc3ea4aed9524dc9780b16102b43e", + "55c252e02a4e0d6b95d200753a53d05e83954e2cab918681ce6976e82aab7818", + "21d26b3df3ed5e5d4cbe26944d73ffe94728742d54b15dc28760feac6c1e11c0", + "10c2d0b65ef419b74c6cc0881b6ff515fb2ae51858f09f175e78986d2ebae12d", + "9b46c159126659bcb48d3cd8417e5672a66dd417f2d099e0d9069d79c2791116", + "55f0fb1ae65c2008d945e8d95681e0b512189d52f4207410654bcd3d68149e26", + "4fb213f1fa5a696c5932765211a3f3e70c93b2a0eff8787291f1ea7f489b2539", + "855fe7a32a00d81faae702c7ea203d63f47bfbf2ccad3a34fc1458bc05891aed", + "fabf2422e2c09c805e4839f42eeef03eb300e14842d92d4308989dfc294ffd30", + "1b40485d8e11d38c7149176818317918eaf309bfe0078f3c422db5dbfa5a8eca", + "9ecd55bd7337c4d273a4eb56a1fc23e7643d67b589afa4d06fb61b9a81314fe5", + "bb12961f464860b497c47fd0ea3e0917bae8afd37dd0401d806f5b47bc49d26d", + "5d2bb57bb58b60ce4ecdca33d9f9037aec4b59b01f6af65814ebd630d24bb9f1", + "71bcceb7c17a71ab611a676bcd0e71aaf48ebec955503d084d4be562d20975de", + "fb5101c74cc129f8c5baa491ec520ec33898a5ea28f98a3e1afc47bfabaf3bb0", + "b4f1185d96482e3a592401d0a3e1f79efc13edc779928e7f245a62ce85b24477", + "c3cd54c3973a13c04b2e882bd476c473ce9f5a590a6f874561c767d79a15cf0e", + "8ab35018529e6ad70fbb845bc77759b36267ce8b38000ca60864568b209cd896", + "b8ed16402087f91b36cb92bde71115e8ab02c2d9ce748b638944d93f650e3e56", + "b507df2ef6aa651006fbc7b9cc88cd1d8f1bd62346e094e7bff0cd03a75eb11c", + "c55531d52543b431f38fc2ebe78430fc0cc40650fbe94dd44171f5f92e195932", + "828ef0659a66986518c014c2c7e328436aafbedaf568c2b86c48b30aab3c0239", + "be0f5b93e995b1ba1a4d4543b5e62339d4bf85a6a9975ceb655addfb8b6d7843", + "b5bab3259b7c3354dd61a20c6cc33826f70896c03193b285275a9b13734e23a4", + "7c59357b2c5b6dfa91ad15abfff507cee2c80f09c2da592d413b10b00d35e525", + "b47236bbd132fead38e2dc8941f45a99a0da891a841d9732de2167b1a0bd1033", + "46d553e0ec6346c968821c28c25995f50fae6e934c01f60479c12ff497cdbd24", + "ebd647789153d457cc20951ec33fd1e273abe58eebfd56f2715f5ede34419c97", + "1445a9c6e4d0f3780ad25af90a9d65fb6d57d8930ad896cf206871c3acaef7d0", + "982d9caf027540937010c91ecc22fbcd9274acc249a9ab99b78aada97f6ec3cf", + "21bb87e545480f2940131a674dc0083063f3c846d343727d68e53678f69dcdd9", + "49a29d4d113db5b086683732cac310bc1779ef6a0c07119d06f22b4fb97bec3f", + "a3acaa72c5a87ae20f54c23cdd0dc24940f9b89e02c57de790c2167773422cda", + "0321b68fcd2f65aab97ef1823d3e8829f0a5d01c9a5555289330a96919529081", + "d821ab6a213acdd7b16e572dad46a72b6645ad9b2cfc44b4b93756fa27bb59aa", + "7ca1106515f7091016fc8e95a7d65ebaea4036b5dd2260c01e56d608edeee7ad", + "a56d4e030682247074ff029979f65671c0a8c391b2d5c8524f06ce3e0aada8f1", + "23cc197a750d2aba268fc14c6d8e492bb8c0be65eb28e7f4e903d129a030182b", + "c168ce080c17c4f5049479a77dfb71c449f4c191081e5ce868de4665f41f0c75", + "c75caba34e36e7773367509227712a7f34c3876f18a42598025caddb698b4888", + "ae837375d08716a56ce081906477414799c412fbf0caf1f0c0ad2916ba7763d3", + "a5bff1d9fbde392ba43925e88a8c59de8c95cd3839f0382d00ab2b649e011307", + "14c047bd9c0bef73b575244fff0a1d008d1b4caebb899b899c36c293ceedd762", + "2e03807829b7e179336c328941898bfd2ada8d2efadb601645f651f06793da75", + "0966093eed7f53538222e229deff4c4c3429f377cc6635a551d835cde2915714", + "b146e8fd79a4ecd0dfd1822396eb8d3adf114d08e7e4f6370618bae5b878785d", + "47ba2d9f551d47f9e3a7ec76d235286252ffe00bfdcc6bda0f369131560db378", + "9b81f9d92adca9ab9bde67ebff3b9806fc3df2deb05857d75ec6d6cb700eac78", + "ff77f1a1939685aece184de47c9546a9cb9475bdadfaa5bfe34cac3b9dbba59f", + "5df1218116713987d0e6390ba54296e3c065850af3f68b1622b5874b3e621547", + "e8e65adeac21041b67e265b939a5408ae58b1248344b508c1c4d7842197cd7e4", + "44d4c30ecda6149a9af2a23fcfd3440e2f34210ceec8b19124c9cd8e4fef3890", + "3c99eff1a108fc15ec357332a2c97c4252366723aade2fe338f56494bdfc18e2", + "d60e8c215935011c623c09b402fe54f9c0075dee99b981b017aebe70cddd90cd", + "0c8c61e3b5e61963369e02ae11627a8e12bd091d4582552b814d0430d11c64d2", + "bae78d08a540637953c50c7a92c06b7f1c9f4527c4518c7379679e9091d24b6c", + "df5afa66002883892343c3e294a65be803576c243a838cc6ac82b7b5d0d08172", + "f537dc4fb2ddbfab3300767f6ce4a1c1bec95f332d55533e9f44dad5c8e34a7f", + "6fa5d1d73c325aa44284343561bb2faa835581fadd2523d34cacca7d00e80265", + "5e18711b265eee046a65765e6701e9493bfd3badf73fce52fe9e369660e56213", + "5adff756df71f36c146347c69ba82e0aade8c1a8f71d0162efa74d803535fa59", + "7ad65890d54f210831e47e86f71b73abfc16240b7e21d12cd46e53a5d333bc89", + "5f9dd56050c3b3a676101393e39199d2679c081ec6a71e2c634dd5ece25fe3db", + "2542391eeda69bf2f94e4f0f3cd62b008a3bf3c01bd49966ffa6185722c3adda", + "7b7c5e4363aef92e2c9b5626dcce8e9c464c380360076050bca857239c11df24", + "54317d896ac1a71ee6aca2af67571ff667c30dd1ca7694f22ae6dc423e27d98c", + "a30801d4f826cd56e7db56dad9ead3ef0c12f80def3fd4f6367fb4e81fc2b11e", + "e575e49d44d0edc85f4240c2f3dfff909062d0d309fda0d587e157a0a7d073bc", + "a4678562eaaecc14eabbd502cafe27da61e8e1a98545e99d68a39a9189ce7427", + "a6418d932ee4480f232b2a4b56445cbfa9ebcd935acb49e777b062b2a6248621", + "b5b26c5262e58a377733c572437b1e0d09702159e43bea95e352fb46cc5679d4", + "a8fd96e2dcc6ea9757e0de19a992b90ca6ad3017431c5e026172bcd1951fcae5", + "44fdd1ef9927b1321fb5207402dffa317d800cac16e4fa50d95b44de0c98d3db", + "b3912f4bacb07cc8ee0573d1e7482185ba54cb3fcaa5ef3d9e8b69755b823e6f", + "103e3ebf61db7825c2421456ffcb6c1afc0758fc1d3ba8d8084adb56032f2417", + "e9e06e1d3b9b8cdaee6e718135916d0cc5c7328c93794c1a70c84b1a76842c76", + "92c09bc98431f1b4d39ce1b6d82ccc3c159335cd569f34b3dbaaba96d66e8517", + "108829391903d8a146611a5607c0ab45ee60c6403384e626e60260957ed3383b", + "4519f6381edfc97ee7b16aac70ae310c0248df90198613d6e73e955907cc65b9", + "5aba8a19183ef002b7bb2fa3fd0d18df57a74ac9af20b4f2c429e88812f1b82c", + "3d259ed6fa0a323cb1fb352572473b06cf5b77f7f9a9644fa6ed72d23ab4d096", + "0dc6fa4b6c10ae6bac5f0eb3d15adfc56d2ca9e9c7e2305f4d757a6916886734", + "ae870ecde011663337a0d3f363f74f1dced0b0a9607d3165121d0ae034059321", + "e20cb66883af1592ccccd11388686e49266571c84518f7f3f2e3e7dc012f0c13", + "65752eeb395509d168e68e643e69584022df919b341ea5de0da50961c44faae8", + "5842ba8dd3414c43e1f04f39452010d9b968dd748a9d5219bbd03856368637c4", + "c586e7825b26dd14aacea220eeb2530511764139ce83078bb454933684ca3b78", + "eb1410cf82d4ee247f963ee2eb6b14ca968ba00b7fe1d7fc37afaeee156b8097", + "ef90ef3d25cf13158c0f7dfecfd678dedffdda33c3f9eab1f7a00856a1810640", + "457535dbf610635511c75264d70f97ca433a67bcb0aa99215510b92ab51c7ff2", + "1ec64ff6911a86c5e36d90ea5393e98a8c3e1c7b3e094e08794c21b6de455082", + "d2edc6b3a7eee1e15be65131ec136f5e4fb85214852ddfa143d6e66c8c009d6a", + "d628a693b29b3cde9ff5e0fd8278871281ae71f74a0bc7de2b4557036deba817", + "057b32dfff68e55b6b21413c43bf912f288f868a544f3d0b246373bb9128e211", + "592c996f14b465aeb64023c78dc653659395de432d56ca4184637bc2f00f1f39", + "e6d522f8189f467cea3331f9a46561b9744466fbe75ca0cf175f4b098dd70e81", + "fcb7036c783560efe8820573ab170337fc3831c698a500dd749259f57f1e38c0", + "77db507b36919d32c07eb0b321fc065426cdb7dfcda083e9cbe48167a7105b99", + "5f124eec815a97cead9b0a2f38b0639596ada0c40691056aefdc235ed28bc201", + "f2c6f2ff06f28b7bb09a21c17f7bb6446aaecc0b3255059330fd2e830d32517b", + "dae7d633af539b3dcb9594da74fe3fd9c60d30d0b727da114388e9e6b53a8067", + "d6ff243c0658c3b0c4340ed8c560b3d450329ca48a187b89bb56de836b590b3f", + "40f26feed721dd0196f235b687ff48f0c71c2721696c35ca68ff493140b11276", + "29d458f9752b80a589efb5a1769310446e5f1dd1d6bab29084f418fb1828ed07", + "2cdf5ae203e7f8e2023767489da6daf033bb058049dc12670d17f05244a8d8e4", + "cb8d3e1976fa94560d735a3fcf7e45a13245f2b8ce50bb9d013093337b3096ee", + "954cf7068747f3f5b282b99e0c7ba1c854971a494d61f676c5f6e0a63a712bda", + "c1bcdc6f55468c4df2a684604edfa8a2619e954732e07730a59acd884db25c12", + "6e64f2cc1284fcd1159d2978a1d19056cf361b09f76fd938617eaca8c76f7142", + "686c828614fbef92042627c29d135f68072fce939807cc309ff2c58fb267d69c", + "178ec5e1a713feab7b15d830185450676d03647a536dcb53018d68b316fa53f4", + "9f9d37f5be549650cfe5aa6928d0c2a0ade4af6b84e503ed600c5a83401bd282", + "7596baf2d55685e7f0ede60ce9921da914fcfe95d7203e2830b2e40cb2505f8e", + "010d4d116da1905576f3b7eebaa70b0f9c93e4510cc056872f0e4746dc8b269b", + "9ebba358fe4d3034df916900b79a1c1f7b3f6137bb734dad05e0ba63db0f7c5d", + "3b36c0254fc51a14f12ffee78a359093d8a7cd4b09d79bdc7f6135d84e5ea9a5", + "fa8264a74043c990cc79b28bf380e676216f8037f0da7d53184d28f27ced70b3", + "fdf58b0d24c753bcb02b1736e1ebb3490bdd9c27430a4a2e804faa6d59610789", + "baf47ab38ad8cc2da3897662652de9e75e632f7343969fd85d2925e40d362a5d", + "4c756b93d05e7df9610501063445800c56c63a59ca0367c7e0c6fe1690752510", + "4547a155ff821378c243ea0d8438454647b645b2919cc6f61d2aad518e54ed0f", + "bf11f145909f8083b315523125d69d335e391858ac6d3b3ef02dc1cfba67a97d", + "3e63e261263049e664087c49370fe11c0763dd07c54386bf146f8e3133911c78", + "a786da718d320b260df7085e8fb5d823f6e47048d489f6a866fcaeba1b40572e", + "72d22f24700fbfd770ee5788cf3c5e4d90c85d5c516af58858dfb7157524cbcd", + "b8ef43d9afa09681bd78ab4d171e97f92aa79ac35dfaabb29f5a7c17ea8844e2", + "b31d25e540c0173d38e740b216fe71a327a0e8a5ae6846f202a52edeba8608cb", + "b81715b0d7d54b69bf43b41043f19ba0cb5e332d023e84a85c26ad969939df53", + "ad1984d14081cd2be973d1ff9d8c86403a188dc9b802271d72f0127b1b11533d", + "1af7f5036b98f443c2449cb59bab34ecc4af0a2845907d5073051f116ec62e43", + "a29b900c0d7cfdef3f34b0fc4f58ae32cb37c8a7a12d5f4cfc083d26b4b0932f", + "2bc746ac6028b1a92ca53bd80425f31867ccead9ea72f830dd2a6dbfb5a53e77", + "c262950f297727db71c5539667e132c4c1b1e554dbf6b11bd6d1f1cdc04ec04d", + "df1221648bb3072437b39587d30c0d6c482842e8ef44671a45e443f7a0270234", + "a3b8de86d12138fb55f933dfeeb1e4c861a976b9ab5526496df49ebba9985b63", + "e4753fd5f047afcb8786557a9b28d4ea12dac3e1f53889fc0e7135ab4a1efa24", + "0860b25792498a4e93fafa969e8bd5f87df87d1304439ac5eba18dc95b463581", + "d769856d01faa496778ed75c785e191c2ae023e6537ae90d4dc817bb3dcc0c3b", + "5a3dbe0239299833a4d3638d8402c3d7f249fd0a6df34a4c28132548e9911fb5", + "ed5ea6325c265d012a9dd04a77ed7cc2e49572e3c1cefe163a0c7f58f31ca29b", + "f97ddbb15ce25f1aeb2f5d0e6c93fb82d599feae8fb15474b269c54f149e329b", + "73c1e7759af3c9fd978c6bfe18b2f7282c4abdc0d9c8bbeaab472047ad0dc244", + "bacd80acf9f8fea84371fbd12d73a875918a0101ad7fb5dc9639ce22031ced77", + "55b53d55d1f339d10aedabf3af9171b0bd13c7dcf5142da6879f3174203139af", + "75367131ad0c957bdf8476920f6acc57b17fbccbd4712b106bc66f014c18680b", + "fd04754381021796c17a2b87487f334e4c428bd23ce2c7cb4af42d080a5e8d2a", + "e153452a3976f058ca25f6fffd028f8413524cc2f9206b7c1d84ac20fcfecbc9", + "9f5ac15885773831fe697025ecdab00b1fa4d5ebee21ed85c599a37ce888d75e", + "241fd17d33bd00a24685febd1c14181b9f163ebf1722212be92b191f8df77e54", + "9f887f1753ab4655e3c4ea01528f675578578d1597bb2262095d8f86d9f069d4", + "fb173119b291025ddf2f1e15afecafae99983bc55e059d58e135f92278f5dc7c", + "ede6c52220aae03db6afb5c29cf3978f5ca08c1a228726a98070764ae4bdfe22", + "90ae8d9e04fbf5b1adabea3fed5aa3f014c1a4b9d677b1eccb109320139309da", + "64e2a24ba6fce6fbfdeeb8f1850ddf18a1a6b6e9873be3b42ee251dffb1ec2c1", + "e3788d4935e39f6e4e064caa1b81563bd0c017a07773b30c26791357214da1a3", + "1568a1738658c2c358a58d27da48ac147153a9d4aa0ef06b39937316c93dc0cb", + "99e1f96ac284e7675fb83a03eab11319b65f4248916a4612bbf22b8eb8bfd5c8", + "c9fc83c7e47dd9fb4822c1eabd0e1d1e510041bd724502e02b05d748317a1a6a", + "ae5a89de1c5633bfef33053b76a663530680b709e50359cacd6d6ad1ee1ce1ab", + "e6839556343e3640d59d906a75d2a925b649f07120560943e49eb34b5a559e5e", + "10ad9ba6ecc6bdfc32ccc3446a31c470608ca52c63dd13a9f41ed142f4f58ce9", + "6faad489dc651882bb2f01e309c910f18b0f9c2f951165589ac1a408dcd3718a", + "63630405fe909f44a2f1770572fa578ffd739977e88453f48f2657de26782848", + "571e4c4f57aa45ff835fc4e80b1a1d1535954ae81ce8d565247084d00d0ea013", + "73fa10ea9f0d0088c01f878327805e4281f15ea9a6bcdacda77362dbc27d4bf5", + "b5a491339a8641db3de0f1d8da7bea5a99935ed91839c16704a62b7953b7b62f", + "3fa6b174abe9625292c20cade18b0348d049074d51579f4b89df3532b420c594", + "70b541fa77a0f65b581d19a6dce57f074bcafde08c822e7b4a5117d0d655c570", + "f40de3d39e1e39c1a1df4775415d64cec82bc22d537aed37cbf0b77eff08821e", + "8ecf24ec555065fd6e061cda337e0194ea2b032a8b62628d89920ee7ae332fcd", + "112f585c69f3c8327dbdc0a675465c27cbf1efa0eea582d7263cbfa3bf47d490", + "ff50612934c2bf3bea8f72866acd4f733edcd576e4c60a9b6a9636031f67abdc", + "00be29ea23fe65a0935b03f3abcb065837981a09b8469a8f9bbcf347ea5618b7", + "f30b0ddfb0ca510f0808d8b85d43a8c1b549a4df09951b939cd6799f4ac01df9", + "a5dbd6376dd4e0287c51e5ed747a1e9c2757b3b45657e491f28e63c8ceba6f26", + "14efe405870d29fa15232d1c90e214adffccaef884b6e4651a1bb7cb246ecd4c", + "7a6eae663565936217498bddbb46a5ead4a527b66432d4b0d51f4ef606877aaa", + "892fdc0a72941492162acdf717c222738804759b3e5679d177177c9b28c8e2fc", + "f29ff795f71a33f12982da9638eeb8e5b50df09bb0bfca9cfa26215d432bd009", + "4205885a7fbebb05f8fbc74c62305e16e654f0f05e1dcb77d5280ff4783de398", + "7bb28a38f81d00b4ad63a4a4323c545324053ef429401ff22e108a799d3064ff", + "d069e09f2b16eb2f5662c175184903f8aad900bcef07d188a98726ca895879f2", + "d976cb3857e3a446f3ac4f1870990f5c5f0301cd894c63b339d41545255fedac", + "13ba34a6fc3415811470ac14e30220d8918938e042e08bc7066cc306c1c3db65", + "f19166b76f5a23d97e4edbd89093800c1447552724c5e8be934b6328c8ad9d97", + "66176f67bef1429f2872d42b38b245c7308925813bd0606d0e43f35d17f79d4e", + "ad8c6dd604a964ad60caa6d67238c0400a1343a42395480e2a25072e106b6eee", + "466dd5cd9c016e299c7aef6bc1201400b83de1a35af123b2894094e4775844f1", + "5d13f4ff14d88d4bbadf8b08cf446e9cbc5f8894f6ba1dc8379f30902d63a87c", + "e081978627ded2f14196f1820224e6e0230237ea1f910ba5a5bef10d3ca64f64", + "906726e26324ac5478e44375b8a121deb3b9d09c3eb334afc48404ddfd614bb8", + "18c3a6d26c60ef8fbe4737070552f14f37b3f9f2054f35259f8f5a954f00588d", + "46532a9c4712df4e05741205e3f63cd9dc157bf39409b5499a75db174103e456", + "9ac00cdee2f0f0a6341a4e037c50a531fe55b91dfa412bbcefbf7fb84b8ab6fd", + "ee72632290344ca75ecfa083dad8c2d6d377c18bc49482f57c5f16ed66a87b48", + "41eaafbf2e35b66b4d5aa415f66f496e11d838cd1ddebc06fdde124661aa976b", + "ed36ac474e67298b64abeb47f6f03446d679a827396eaee6341d6ca6ab77c3ed", + "eea08b25e98083c5e6eefda37adf832a3790195db8564083be04d12773644251", + "37c44fa6d275f05a16a061d3fcc059ecae5646bb3919e7a1c93e342c6c53e745", + "d3fae34df0e2477253c7d367d18f3d184235c614d1426961e173b930aeab47c4", + "476a7eeccb6ed82fb80cfd9cbc02877c66bf7c6c1ccff4177092b6b9a29b1ae6", + "434e92bbf50aa91e8678481b72ae06633ef705eafb9e71784d8fd83ea63fb0cb", + "5476895715ffbd25934e9c2292d159a124a893ccc5642874ffff2b9491a3b98e", + "4a1d59911d38e7995b899b6abf12ee7d3006cdb658911d03344fba569ff70112", + "fb38885c4122693706b862721117cbad78391c2ca50ef6660e81d8fd8a764a9a", + "700c684a1b6aa282e92fc8e28d413d37ce189e30a106ba768601d0ae2efebc17", + "dc6d5712a64b50c709a14b6822b2fbe4945ffeb2ef2aa6ff7dffdf36ed7d6e4d", + "d3109f9445fca452946f79bb8203c730d644f27d7a68185221359f750acfefbc", + "adae1f7276402592cb11d15a5ee5764601e5afdb93aabc4c5564bf5e0a0dad9d", + "428f6f5837d854e89f874fee59fe4d72a57a338acd8c3ce404bd267943b6bfaa", + "d5c701c60807f3f6149387161ba50c8f4e2c111db6a182047c44b1fe9e262072", + "011761bcadd896a5d81f6eafb57316d68161829a0459d0574490f55b1a26d9f3", + "a1e626eee40faa11c88745d2c7dec2ee79d847cdf80e2bd3a416ffb29027ab8f", + "8fa1a2e037efcc926f7cbd8ef2cd4e2add1731d0fd3dd4429e561ef6cd88fbdb", + "adeb8dc2f6ef3ccbd1a5dc444b9a7f09e691de53a301274d47cd80b932741d13", + "9aae1a272cfa752e8a4b3503a145735405725b176ef954fbb41555097664cb13", + "3db4b312c7214a9f3f307b82b8e8ed5abf96e7ea0a4e9ec6c09c9997599f1b93", + "9e11752f64ae1c1257b2d92e8d8f5e94132692b7b7ebd293dad1765a4777ea05", + "84385e8271995408c0283ab24002efd48cc97d97c0dd47511a3cf744f0aff785", + "abd025aba405821f04719d96294a6591a5108213878ed8b5f9c675e862b82b6f", + "f4845645132ed38d08e9a3ba27af2fccc10358c0773aca0bec43242b99dd472d", + "8601fbdf7387a77910385bf984104141dad83ac277523f1ccc6371b2374c7fb8", + "1f9ef73c79627a1b8ac2dc71353acb01effe74076ee7adea107088fdfd16a4a2", + "6bdbdcfc512cd7d937e90c75e6e8033036c347f9c4434299d5b402622205de1e", + "4e0c95d2171fa86142662dcb5381114e9d09af266ad85085d7e88c31ebed71a4", + "7677a985a102c92cbfbe93a1e1e927eb685bcb2faf9b62a21cfa26b57acf4f04", + "320dcc41110acbbcd6b4018ab6c871c34c169af666184944d05c21b14a16d7ac", + "8f4fd9f751614d968d24ba4e1c22372e09ecae6310ef958362e6d0a0ed022852", + "08d8ab08f41a108cf1b002882ffd36656d09960f6698f68697a93a09e3f3c88a", + "ef9c388e16df8f33fe0b61ca4af72098e0b7b32d09c205050b43f16a809c7db9", + "6a008f76bd546f1cf482c454a111736effd4eb50da4c939131cab557104308f8", + "9d1f7ad5d982215479d6bcd7aca74b15ef3c9b3bef1c27674caef3c3eda4d3a7", + "3d2a849f764f0b642476c2638e54d4c7229d66b5b85f18bd90d9c2a5391d61f9", + "79780db889d7dfd1d999954f195f25dfcdd9771e73715bfdaa122c9829603a27", + "2c8fff69887de1a1e724f481fd8d371e9c0c3341b6ab57e7e4f93d52352c4655", + "adff3583a788bff274e608f78dd121b79758f33545a2fdbf9ddc3f356207f3d5", + "9cf3c7f143f823345f5d0efb71e18c73b693ddfbf2b9f2e36e54d6802c1e49a7", + "afa78ff7215ae99ecafb0e4f51b1cd2fa191a17d1db715edceeaf351ed8f7cce", + "1ac8401c2e3902688e6fa0ac1924134600f89cc553447a1cc5ffb15eb2b1a3e1", + "9d1530e6e89520f79006e8362b89e1457015033475f58e259dae44652fd08cbf", + "fa73158b4548b6aad93852eebdc52f2ea500805d8cd5c08d534160f872993cdd", + "f927da684b637c5dd93dd5463839ffe0f1a15556c02b8ac088f1d92b6fdc897e", + "3ee16901602bee5e30088ba1ae24e0d1c854d4619939ead47ab76a4646a8e130", + "82ea0d469019a6a740386dff92a7723e97327dd2f80fd666eb94acf10d398f63", + "12b006a7f570638cb687ea803f63945e80c64d7b32e81644d08c119673a3b3df", + "f7bca2e2669ff58f8938c6d8350bcc0bd9dd1c197d98471a83b00a763d571713", + "58be4b666a78c6a066044a6384080e32cd62264fa8a6e21b66c94ccf0f40e372", + "9e5225950ac0f66c4142265ed1aaa1273fbf1ebd474deb597edd4180975df027", + "fb3e6bc8a9c11ac0afcffa4772deb48f534106954b924715fea7e3f50cdd534c", + "267b0b8f2017d24f796a7cf1f2b11b74312db98ce7314fb4f0feb97ada4545bc", + "91db31f625a79b87e4f2cf8e360e34e5ab559dd0dedeadc1982e6d4157abca70", + "d285e21928b215a64479d515794a2b271d9ebf7b160165b546606a0d020baea9", + "5d091853ec59ce78ffd650bdecde16a31e318d8f6c1e1e5e8076311bf8b17279", + "57ef15b0dd70972522ce3800b6cbf3432fae5401e387bd0f2464d419d1cb2eaa", + "47842a1b670db73e139ca12747e554a0c194d140c3c6b3df8a5ab76880a24edf", + "858df78e0eefd4a242f26710508029ae0571eb0e39d4f8c4f73d9cfe21856de0", + "a6a07d7d671a3fbb798fbbbcda5e291d3cb50d7e2c737f2f09ec2cf10161057f", + "74ad70260c5cdac2237e7c82b5e8e279f1704560909b88424766d2645f295ea2", + "03e89fc1f7dd1410a4ba48ba8275d1ad514b0a051e3ef09abd28099035ea7c8e", + "022cbd052246a2a8d8dc12c944fdb1219d0ac74792dbae60e0b98f51aa1756a1", + "c72599598005cc5abf8f08e76f2d5dff3cca2f6079181f8a0c9c275e25a45d5e", + "dbc2a44745720a6332556a1be7b06ebdfeed5860a5ead026cfde4a98c25f63e4", + "c1526abe0373a59902e82477b78beb57e0e90c61cc4f2a2b6e1434ab19fe366e", + "82ab1f6644794e97fea8501f397641fdf888e60ae52dd5608a1ac3c03b7e61cd", + "80b805da40a4f7c38386b4abfd080597ea90811106acd9ae7035d6854daf39e1", + "d08431123db52508a83916e506d60994dcc421af1a0d9a5497cee1ecef83afd9", + "77801aa7d57100426e5d3090d8c1b3a06ee7370a2cdb0aeaadcfed417b78597c", + "ea642cc4bcbff804ca06092a4fba73c5a7f8f3f68d0f5dd4992e7e921e0bb0da", + "307f7145bef4aa984d015a7a27630f529b87ce666e0565c401857a6281df375f", + "073f02f8c28474203a5345af457fee09fe5eb4108a1cf075979b1869a1fbac6d", + "3dbe8d1238a4ddd9e2f8e69d245e7eb6e5bd86ac87b2cdd7452e6e1dd02ae53c", + "a84e39ba9ea6a837330b482dab1d5b4ad83656439d7c62fe9773a3b14deb0394", + "9987b015da2c0a54c2e074a7cc60303ec66079f0423207d7075ee83f07867aee", + "95a0b838889b088d4c591d2b5bf5fa283491c28d93dacb1422f176b0dd8eafb8", + "3fd5d94cb2606e1e198835e804c7328f8b0093e7b2ab6c79557aac1fcc9db2e6", + "12adcfa2d16bea9236de86d0897471a1012d213d210fc0758c11355afd80fe53", + "a24ba144e2d30322e72a01da920486b0ebb664d1b731c5f580513c060e5ef3d8", + "098021be4145a1fc74e698e122257bcca952e8a9d4e93cf75232db820cd60a0d", + "54f452219b0ceccf07a50b738b711dd55d8c821b603d60f5b36a55551c8b59dc", + "7699ab14167e607221e713d9923099416f3c804803396091f4acfb6a5f24c9aa", + "a317e7a7a69a3530dceb9a0da962c0427aed30e9acea323f5b1d3be3bc92edf4", + "f3737cd944424ea4ea3c9c6d7f23bbb16b4134af1d49ee6c3bdecc526c9b8119", + "a09ef2e003872100f2ca8e6bfa6515be76b87ad4d060093393c989d039e85b6e", + "a351f410d10ad91a7a955e52e71c8ca4929d15e2690a910ca09429913537fcc5", + "cea1c834397183b3cf22238fb6ed80f4efac9f4e65d9e7ff5dd643dfa9eccc8d", + "f7c2db1715cc5cc636d920794bb89768548ad09eb8f977c195519bb972b4e988", + "8c56df66cc63cdd5d56037afac47ce4357e8594e30630b43eb6154d108a3fcd8", + "acf18e6ab0f273ddfd5c93778b57cbdd854e80014a1a4fb1edbc685617b9c27a", + "2e6d8a5f573ba50c20b28034ffdaab483dc2c73c0c21cbe97ae77e118b510081", + "85d7e7891995759b49e54808381eba37698cb1803d81d00d7d626496256a78a9", + "778ab04e37d45a1bd2983701f740464141ec511ae0ef9faf1d8ed7f75eb8c09f", + "b110e9947e7ecb4504734f3e6f5bc00d653f723021ed4b064486972ad7bc41bb", + "0c5b5bfd0a9e4f2c6f5d1f6ec1165ab75f723ad5babc10cf984b723775eabab9", + "f57780be9d7f204039c573c617a68e69ff98c3fcce8f067da0f23999fad135e0", + "35be02e80d36947d2179e7c2b985dd079e95d6b5063c6a20941f6966719bc40a", + "5136f0399bab61ee1611f9c1da084cf7d1cc87cb861798a2f63f7e61d6242051", + "52791482e04dc95e119973c4634e08d9dfb9253bc57d914cf54d7580738ed9e7", + "7b5761dfb46a4f9462603b6535b7a94fbb4d5c8c9520e7d32a0d92f9572fe010", + "23266e2f3168b1d0d8d40a15570de5641c1671cf7767f1f81941ae4d27f3648e", + "1e94fe530b8c2c4e1bfdf060676f05b061018365fdd72fde7bb7d7182c51fd1a", + "657e8c5af7280941d0a1cd1d96415d938b90d8d0e8a63ea76bc59a0e817df5cd", + "39cf51dae88b456c8d3a56e7e6a7d742ed68993a9c89a7edfca496a75c2a97a5", + "eb90f1234b5281cbfd5e40ac1bb9770765cd2306ab9da906e03c5db5bd447d90", + "de2c1eedf6d9e258a7ca687a955a562b594e1cb7bdb6b169444e32f5205b9b43", + "f605135e997283f161eecb9a4aac59e63a6c61fc973994cff41b5e2c8b97c6db", + "2dc2e6f3705afb495033e926df649ea3378574574b4c888e11161be03e9b6608", + "9ee2b4efa1fd1dbd34c8ed8f57757a0d4f2491c37e5a0786ca917da78ad726db", + "c463130171dfb725400112f60612c5c2ca07f99a1d821cb5603aaae67ce16aea", + "a0d74cc886d2e0c2d61999aca3e2d82c1e36520c7e3371bc01a47d6d15114f5f", + "c5b3651deee538fd4da9bfaf313c8d40d9c1e4d94b4868bc37b043a07b347007", + "c5f87a7417a7bc92678807207802d65fa2b3fecb1bf9474ed70f5c8592fd2a77", + "58b57ed77d4c574b81242f58a3967d0e60835208db372c71dd65efde65e50031", + "30755b9f795522e5cda35985dfa7f2649b2bc269cd15f5f59c9d739cbb574f60", + "a3a9fafce52529e31222860c8f118a13d8cc4bcd2d465cae50b5569d61fd361a", + "48cca23f0a9b9a47374ec1d578dd8a669d858dec3ad85e94928b4ad34594f61a", + "ebacf643894663602385de9ba85372eea17b969359e99cfeebde8d5ac2636da3", + "13f4c66dffaed3e6ca7b245772388fdedfaf111fb201b90ba15048b7362857a1", + "9a9587baacf625f7a6fb77feeade028905b353381b7bef852efdd4b436e277d9", + "c5f5901461c2e46686341fc9cd1228267b55692342a23f600b36a99349fd6ce6", + "17ebc4c1279299bd5039c3b2a8e4f2efff1872d6386fc409a6ccc9f37f19e0a3", + "cdc6b186e2a8b715e4f8d2371cd2ce439140bfc3b4377271a881ce67dc895cbc", + "be965c75b459ebb8028a3431abc70f98246ee235d24d2ae0be56f67069818189", + "a5b36811003efad18a52716e8635e611d539ef79d5262781e890839767aa4296", + "9a89f8fbe0de94b8b5c3f2aeb6f8ab638fa3e1397fa18ec017f1d530c7c305b7", + "18e33a09dfd1d91fad5e5415a5da9ea3754bb72c4b554f80d7b754affe0a2d76", + "4115263e8f024c3eb7caf5d748b7aa9da0deaaabff9b0be0d7482c063f7b60ac", + "151986678989bf8823638cd91dd6eaa602d78e9718a241f851f8d19d5cf5f52d", + "29c3d96ed176e5ccb642dea79b75ee6505555e0b0cbe73afcdaef5289916a39f", + "2efffd99301253716cd710900542fb18caa45768d3df732e1c7a3179e80a4948", + "eb7e81bd8155171250465d615812bd2c0ffc13f1370faf0b184768cb102bf180", + "3c5771e883d67b3734874569535fed6be9c2943121d154666ae38674e63de081", + "adf9de6847f702cb1b0856b7bed02682236c60e0514d451dd5de3e833baaba85", + "2606055a4eb30a3ef8faa8ff0538784ce06bb15a6025e0e3c627d110c3b9775d", + "32e184505bcedc32d47b9ef4ec07c8a77a90a37cb833c96fec51e82b3678dac3", + "ac7e52312693d8de216b283fa1e6479fbe755ac7f6979fdfad8bf9b3cc886930", + "18e1024fe31b956051ebd80be73e155fb2a4e84e56d0ec239af194110e48136b", + "d9562f47dbab1301f4c98a94a1b13732077735fee5807ff04bf00acda87cd643", + "342b7082a72ef740a89f4d269a4b1b6759c46f7c5711211a20cdc74191202e25", + "f848621819b61a1fce458722e91aa0d7f0f44f1bfd26294d6a92930f517f4083", + "01f389fbbaeb4710ddc7889ebc3b75a25aade1da0f43c14cb087a063df2ae066", + "5dd0563a73efa1f5c1620e329092908c1789396147ce68b9e012be0f7470cb22", + "7a8672807853339a4d7d4fc4c6fa0998ccb5bed2b758fd9dbad858b12905a53f", + "6227559183dbf9a6d97a48e958c4527c2e93ba2221044ffd2370cac34c22cdd9", + "1d02365ed39ffa2f36f0156307aca629d576e3f0b08a0c5bab8f35d70099ab8f", + "152bdc0b0c77934e029660dd561abc1471079879d2fa6b3e1c2a16664c85891b", + "7ed238b94ee497f85ebf485bf2af9a908f180c45f9f1b7755fa37106a61ec9be", + "3cccab6ebfbe285645a36327578eb7f1b7007e50b8b766c41fd6d554e6282ca8", + "be10c25a9dc32d8f00b32bf44f8fdac78f3f2261355a421d8a8e124d0f5253e9", + "80d3ae1043ece3cbd31d323e7ef41aa1e60a81b1e8809424a02c51254640ecff", + "21b73209a034d6c6b902ab0f0d124c22b1e556d66366c81cd40a06913fcf3412", + "f35b9b4c904461e66f1552ecc4aa0d7fe294010ae6859a3c3f8a1bbb916ef92d", + "a834a744973c1503e570eb1ea289525307bdd4cab22cc0afe35631f815b68c16", + "d53523e6e0e97e9dfeae3ce4be0247741d40e0d93536de2f91283d3fd6b52e83", + "7a9370e37c0f1e923944a89269d6548c5f99ce192d5693c01df663cd2e4bea48", + "ee60e832cf42fdaf6a62ad5d60ef275e27313bcb4717678583f537d046d01e17", + "4efdb9020e3a0357f45b7dd30ed7cf528e213746fcd5b06b282b1f9506720778", + "285f9432b43741bfac25682f316ea68cabc5d908d68d00102e284c19f96e95cc", + "68b8d64d25bd9cd772f7c5796188e3916391c5cf0bbe1552377a46c3bef29d5d", + "777c84f851ff3e59bcf9f5f621d9cde3f5559e76badf13956eb0eab4dd8819d3", + "1d23f021276179565cdb56bb510070317ffd560d5661a94b58496f2e502b9141", + "63db9f820f6d56300ee5b7eba88e286e859980759c3a6c9351ff0a81462ae59f", + "8cff324b909baf4e8d0938bb2988adcebdab16188f1445ba23f02b42a46c369d", + "8db14b51680b2433cc91b86724b67dcc17a6d7a3bd4f986b2ff28cf2f3c25b0a", + "7a2dbee6f74d54f029d7ad6ddfa68a8bf50c41c024d5591a5bbb8f0a133437c6", + "7cf0d57601f4f3e58cde655312cb31a779693ddf893190f29802fdf2bf67e657", + "931602b3eb1deab71efd1be20fb0bedd6f4025bbcd7889f708706fdb2df43650", + "8a8ddcfdcbabb9902b7986c4ba0ee23ac379b8590453f396028da66b50350251", + "908b2e43264a9923c5ad3094638970ecbeb5c3143101f2e5bf9db99157f92a85", + "48af478d3c8bc9930c8a33b4a98695af9fee9a380540db4227525ecb9b2d36ac", + "d7ecb0189f0b586b5ddc372770089d3f6ab71e26e2e79a0e447cc9262e24a797", + "4a6a46c93fe8badfee43e3dce3f66fbb2fc5dbd71cfb16fd90c411350aba2eae", + "6e8322d2d9ccccb652a019be26947b6eaa8636f507e144e11f379bb369f7b6d8", + "02534f0b6d2a09128ca4ec0fa28559848d3911e488af849a526a56d702973efa", + "f7c5482112fcca69afc02036d0b3b3d0e8aa5194ef96c69af113eef227be4033", + "37a95b3e13282e1ef4aea49af6f5aa3a9008b1b544b963f6899875716e9b5ee4", + "96e4be2a0c8b8bd49dbc3f532a65e3d0add1768c848f1fcc678236bf25dfe2a7", + "ed0a9303c64d3386987a00373bdb200fb9afb62a359fefef2272aff047e7736d", + "546880a5e8dd31cca445dacc10df779218f6f398ba59a0fa7650058e617d4c5e", + "1d458da18180855e36d5e99bf192fb79c630cd18cdfcb99ea64080cabac90ac5", + "5887b85c4c7f1998a412f5a8fbaaf49b1fe81b5071a5db1286bf980a26ca1111", + "b96cc96791a2db45f153f08785d53fb30b54770fe8f1e05e86c538db785d8a4d", + "4789a185889a5157ba40752085af98f050da0daeb5299a3fd21be0383e50f883", + "7611550e9593dbec985ad839cfd3eb518de4a9266570765f271e9f026d43af23", + "7252811838ee4d5632537d8585d3897ad61b07ecc59dfb52f30efa94c5795698", + "ffe3eda10150bad0d7ea98e8abcddff0ea8e1d63f857c0016d7356972b218e49", + "1a3dc859d5ac1b43a2fff37c348248536d45204b1fd28e769ca69e67a0d676ee", + "4918749297a70f8db836dfd9a9410309e021df242d7c2afabf83f26507c687f2", + "dfb2f19361d31993d783a4a83f7d313e032fd9b75333ddb1430943d209231b3d", + "eaebd78b542d51f8fdd0764a38181d163a3fcd9f4a6acbf087d9e1c0ef076ccc", + "53b1f5406af47c634079ee4382d4db91d7516769f0355ac9a19af90209512add", + "3e66dc7ef11ee3e107dee6f5245ed3a8f99440d1abfc7e23611a1a2d1803c34c", + "3f7bc2bef78a84e9d51416b5b69ac6d3cd57e52968bf2dc8ff5de804a24bc6cd", + "b62017360bf8eaecd7d143fbfbe32e0203cd6d6cbfb774a7e2776d62ba103fbe", + "441d28a16d87d2bc0d01b78268197c2e3e63e0ffd5b984572ff5e6eea22dba96", + "6fbf726fb457b027f0293c4f55d0354c9b71649e2752f68c3780777b979dd528", + "1d96fccb9d63a887edeeed516be13d696d45feb1160ac1c73f37529db8fa75d5", + "32f9e43f81848aeb8012886f32a4803268854b2162cf2c3a46a6773d882129a6", + "b0294166b05f7e6b8429da7fceeea3a01a8cda15cc73a8e4477be088e1e7155f", + "b13fecad78f4d9b08b7fd370d2c70f2ca8667bcef89c5988ac4235df427f33f1", + "7097172aa8428b84ef7b486eee287da6edde8eea0b24e2a25306b843819de352", + "a5a177be75f62781daa35382033d15177d86abb38618352c58d1de9addce45f7", + "dea7d6bd35b31055f1075d8382b858c3feb7ee272cf4f0d360fe3b1b3da7b8c7", + "8be65305f60e39d88cee816c5064381ffe71575f3e8f014a77309191de71dee9", + "2599b4cbc0dc94f6de233f638a5f1a4a56c03055b1701390c2444f1a4b415621", + "f1d1dca11f6bfc51a269dbfaa74eabf82fb3cef07f61a400c550e7fa286d9591", + "02e6552991c86017a6c2f88dbb79905e87cf8a19596754815401134c94c18e33", + "27a304ce7c9a1ee1fc91dad986686a28f679b4a71fcf41625c3d4873b48e5527", + "b1d2107cff32f9e31647048eefc6cb2419d32cadfe1af521bd43c269757b63dd", + "ccfb1ebee0dabcc1473a06d6484bb4627de6ed37929bd4d5bf1049fbff866e64", + "a55e7d225528e65043bc51a7a7dd90901ee0e7127479b702163b95556c78686b", + "fcda3628bd286dd53157b3348f3afee5072c758fd91716a2697248100d1bf11a", + "a5360aca848d1ba823e0089fcbe7b470ee5258e7aca010ed7f6f15a8bef5ee7c", + "c2fec48bd5bee43f9b1db7e68bad33b0ef0a832beff3c3b3314b0f3abe19fbfc", + "6d86b864007fc64ed9ec2becb2286eec0ab384756c0f74c45b5dec8bdd0a677e", + "5e0d286ed2e4e2f5b05a61aa4e7d032b1d283438b5ca6e90d86b9136be253931", + "adeec6cd6c97ab2f80f953a3b8f7b21019f0650578044314ac15b91ef050f73b", + "e4a4a657240328751b27c1f4628dc60cd303d13bda369c923b0983a491b659cf", + "d79bcaa8910986e14ef3fe5f4d31295d242824f9fe20f017ca63bfdc3a32e820", + "8bb55701fb09dc78e3c9dd48454327222f3824f5a27feb00afc94587ec4cf4a6", + "26ebae79be6a868ce58e3cddd10b2e35f8b483a86c0dd778cf0b70fa29cd86b4", + "91acaaf48799f0ab3eaf896078f8d111600a8f12c1a0d949aa99c65664b41dca", + "6fdd1b369861e7c6eda4b4e91165da8ff11796b7a690c85486afd68cf9413272", + "ef190dafdeb760f732ca7365c0810e16908bc2c1e90600eafb4d57b33d311b09", + "ce3f57bbfe05571ee4a298f9486abd618e78bbb5d259ad26857a011317ab4311", + "1ec1d9b516b0e67c84ebda32c5999858d18be9c8c0d28b6f5eb19a603c950c5f", + "9ab136b9ec0ecb7c52089eb90a587da148236aabf90501ed30a0fa7f4bf3ea73", + "42e3636f761ad7fc938ef989daa469056ad3d564f67f3ef59e86cfdc113dbbd3", + "22c927f20bed9e6f092c30bb5642cf6f37fdcc1eba2d91928a751ae8ab6c3617", + "7bc3126884528fca75953879cbca151c3c65560358562a061de6763ea0ad9fa2", + "fddabc9d3b82545cf0d80ec646d8b46af0c2a583375f44f16d6bdba86c3df754", + "6ca929bde05fe91eacc7f4f93da0b470b71adf583e7cec4b6793fecbd537df3e", + "20619eda29dcf61ddb9e05e61128e9a5343eadcd9a5bf239ed9b9fad6f52b527", + "74c6784a7075b727272d30b45d684b897be5d723445188c7a6cdcea0e8a2f4a3", + "1549d68007e70f01cce5fb5ef0ad336ba92d81c615bc8b2d58b462e379d0d23e", + "85fa397727fd142615c7b722c33905d92c374929ab9ae41f2d0560206caee2d7", + "34041e48d11ea14eb3c51d2b9699b6ec54618d6fd8d061d65692302dfece1974", + "2935aa6a75fced6dbd56ab987466c0cac5330ce93b4c4699d8526e2b2aa6022a", + "b9585527de9acf601f357ed3e6e071967777ce1a04218633e80e919eca4b40cb", + "33901f8839e240cd9bc9d93eb71cab41e34819dc8bcc0787199f3d57844e703a", + "4b9a88fd416836f5ac2e9a62503b7337625aac8a4dbd8c7d35c6f811e6e0bcd9", + "f45894ebbefc575e79a105ad772f7386d9d3d8e10a5a81713b1b0ff1319195d7", + "b150acdc96642816c87a098b979589a112278742b67a5d85f39c8c8baa38e22f", + "a283da1f98473acee8aba51eedd1ac22ff4cc9864697fc9a82673170da7b84c0", + "77ab60404cc353a9e454946f532e567249f8b979d3ab127401e3145930d3223a", + "0863428beb9fc46d3df348ed73b62e1c0f7a18955fc9dc05a8608289ee83ea02", + "24664bbd69ad4a92fc2f34a1e704c1b5da789792f5c956381c94596c3a726f68", + "f9eee44a56ded01c0ff590c55f79a9d7dc223de2e9f21b9e91670943da529821", + "19f0b0b78075d2057ed7d1190b557bc46ed65c16604f252eb93460f3701f2561", + "57095b17de8859962c78a4b5d8d35aad160c82fc0ceafa77920f721e7be48a95", + "dfeae3bacf46f3b3311ffa10cd1809768d7f98a00ee15db3f44bb532f14c4f43", + "2e8a0e71ff8ebc9bb1e87f17138d4a3bd1e4b58e5520cc0307c14febc59b08aa", + "7c39979798f5fcac8e1dfc32808101eb2bfca23aae95acfcf949f5e7ebefcbc6", + "7f3bfcfff92cc2cb2cef16ced0452c81fb9f2cd58d915759fa45bc57373ee127", + "39050e3079456572e702a4a8bfb34e3c38ebbbf1d1d86a18f794aea93d5f0b88", + "6ae27000c64b4099cac03d3c568b51fae290fb1920f18311c2f75571bbb9299f", + "33a812a96f594359b7b6fba2687b1df026f7bef4589b51bbc19725de3fb8981f", + "2125a7ce2dd30a254f6aac13c62ce64cb98fa29e2799b11429efa33eafa5c55a", + "7a7628375a1562903a0eae53b4fa89541c577803fda24600dbaac70102e1d516", + "8f20761a406e572542da3b00f09426585e31378c4efb9079dc48c7618e0c5161", + "20681d6efb7ab3aad4804e9bccf05ee2cc97b1cddcea73213189d69f2999065c", + "2c10060c80dc82142dcc1c4c26370ae16aab6ec23ae13c782ae351c6bfbf0f41", + "b5b44d6ced0e64ef19265076fcaa26c4a13e537f09055605eb6c38b731ebd77f", + "db6538f68a064df0bb0dd0eeaede7a289181277bd4f4087158395fd03c434b9c", + "186bddb15834bf747eaf0169c4e74d56b0bf649232fbd97972bc0e25cd1638e2", + "57821a3026821ac673afd62823aaf7440fd6bcaa663c85c7d187a51bb9956f48", + "d71efe2fd8de8f03e599690abd9f05708650f7ce0a45725955c8e8b3589678f5", + "7ed0f6b1ea460aa3175300c8d20af7951036edf42cf5967448a5f48298616a0b", + "61be2039c32da527caa286b0ee9a1fc45b2029466095abc1fdbf8a95882c23a6", + "9b0c81d0ea7c55b43a0859d42d5eece3f81d395c55aa6b433097a7b330e6e675", + "e84ebd9c26bb11e8ec5fb186080e1620ebbb12395fe5b344d424fc2b3f492e09", + "c1527f92dace59383374f12838fc3395379781b6403a48e11f5592be482a28f5", + "df6ed5a86bd26322517a7f6e2367d82708be1a49b616946fb4d266f3472f7b9a", + "62ed3ee70a939adb4e4c10b9e0a9aa1b6016abf0166badec305ad62d503d755d", + "45700b68a0d1902c9418e2cc85e7c62f4708559600110fc8fbadd709a165add6", + "66c181fbf9b7e46481fa2f4a099bed4045fd90b543279b1dc81e3967ecd5c1bb", + "ac334b504b76ac0565f82c63c998125c422d20ba920f7ae728d43fcdcea11845", + "a68377ba0538c69f384eb9d3a38896d4dd62cd6c1b3857b82ad543fd61baae55", + "7136e1688c65d0f0424b91f3eddf6eee1ecc0d0a11e6b01ba38e6d243e601aab", + "16a11ac2ff0db370d0ddfb863168010d5403afe530773dcd2fcfbd861cb07bf9", + "8c33209084841e5fae2732abe0132ec71500810571fa9e97780ff51f72587d14", + "cf09d3a1b106934fcb82b6e9406be63b809809f20c0a01f5d0f798f5bf0a0335", + "3b0a71493caaf3ae366555d913f296eb0174aa1207adfc77630d443aa92d29c6", + "1a982030a52a66066ccd3656bb0cb57c554e2cb663435843894b5c9098f2664d", + "3a87e635b1e2319fdee80a777cbf8bdb555e3f81cde29058feaa92b6cb1bb6ba", + "7a369a4dc5a95338ccf089652b5d9c294565a5f95640d906ae63d0ce1f3225b4", + "d89981f06a3f203d36a444c2166063ecd2f02330e08610ddbc8412fc55c8610c", + "71c09269ea98a111a67ba5d71fdef1f827a050c11977003f49c0721b519f706a", + "2ff19d61dc7088868d304dba4da6dcc8946837d9f1798d102285b1a4c69eee7a", + "c8ba0dd4c6e0420033f4cc50874b842ae37b74a322361f273ade2033e766474a", + "7b34622e4918b3c758dec53ccf9374bc80963b5324807564211f87833955e8c0", + "e2f569b37b4b9ff3b15eb364863e03d2912ee9ae0ae250446be431ae2f9c1288", + "439f13a594a287ebcae3f453ce23e35873e7bc7d6686211827998b9b52552430", + "75469cb9a64b87c420933ac5d2a375065be519c61b5b3276ae6a4df43bd21efc", + "8dd11f3f2888a7ebb8875209aa1d7596bc27c37523e8d65b574511da2af0f3b5", + "f1520d534b505adcbb09cd1c932f89bca41e8b41a513e589840daac1f58cccf7", + "231b3ea3a44a677f3440604c80921fa08d94596d8d0a61a383285b7c89ea29f6", + "c2359a42dbe7af090f1427a6bed06a73115bd1025b41f93f49a58dc749d731f5", + "780ea3f4b9ae9e4105c18f501ac67381f271c9ee520e8551cb1431998c67dcb1", + "5e493a87c8e9422b35cbb61a02ba1ef9434bf8369397f30cac5e8079062e35e4", + "c9737a2e93321eef0e3a28956346ac0050b15123ea398be844812975e36fcec5", + "feda071db3f3a69aa86733279895b31a103179de41b59a5d784f92fe6ee3a8ba", + "96c35e96d06ab6649f872d411619691b937b6fa0a92673706d7cb6a157ccf738", + "ae152bf115bc299dcc04146205abb869e4d0abf852cc6f48367cf33031042291", + "114b65ba45bc6de77ff58be661a101bc902bd7cbd41962935711034e66cde276", + "77bbed105ff7531f06d7d628cbe734d4d9511d884d74f99984e788a51e232068", + "6f9688bd5be2fffd0a4b96cf0b36ebcfd2882f2604b27c8dd57fc6e8b2041959", + "d70a97c9c41cd0c87475fbc90372a04ee3eb387dc92033d7660d1d9949a46135", + "2b819fd1ee855f09e8a02a951ff8f3cd880ffb9ce0a9ffa463b5c7b87ae28f86", + "e475e2cdc76ebc46b21f2458116114901cb65893e0ea91ee9b74146e3f929741", + "1dbe80c5592e2639594024666af2382bff41d5d4f35db127956f2d4cb10754d7", + "9bd05234e3990c9ab4ccebf5c3e9a255d202d10aa091e4a169528cb680ea4fa7", + "71017b944fa50fe9f807cd5ad48e1d4764ab671f50aa2694e1bd44d4a1f3bf7a", + "e579256cd8274f8d163f86cdcd8a66f03071d0f21b81d040af175be54a8b4401", + "3fdb8c8d696b98064ffc713eb4361f338c6f99693a91af1d873cd9c716216fd4", + "e279fefc70367dfe2a53154b518ec8cbb9f662bc43adb6e8e72737b2b58527e0", + "33aac91b8e5534a354576f08612a6d4c9fc33b3f34bec85332f80b7e63ae270c", + "d6a568647ac24228ad11845cfed576e7367fb96db48fe3eb657fc9e4566e16ab", + "8b06a2191621a8aef76db7d8ad4a895278a102397ff674b39906d0fc831c8dd8", + "9a188d4f5c7702167ef07c92927dc0148dfdf66d8f8177bdaf92466801af6205", + "d1de700f66f763c459e8d8806a054d57622748ac1db911eebd8704a2fd6933c2", + "5ff11add134530fe227aa0d3af0896bbf349e5b37779e3b34e9f778ecdc87937", + "d38aabb7b09be836d9953e460ccebb61de65afc23c5393b3a3fede33c8bb89e6", + "f8d50d780f0f16508ae407ec8f4db56be2fd84da1ea033acac37b7a33eba996a", + "9dd57fe201cc3c9adeb296c6ca882ec0b4ff7ebc88fac32202d46289a190d4d6", + "9382a699f1f625e2d54050662b74928b383dfecc31c5857a3907fd3ea785b0d9", + "35ba08c85c3eb5ac0e478da6f107f31c46c5b3cb909bed0e6dbe321da931c785", + "062ccb0d50a800dc115134884214816b0bc2ef9f1b29c98a38d7243c01a4f48d", + "ef961f8de571fd942db154b7d17234beb8f0a27d92fce75cbb72e013d5d41923", + "b73de24582a0edce27ec62f1ffa01416a8c886aa578afa95b2a339cafa45d026", + "e2ce2dbd64a953124f47f6bcd3a1ed16c6d879e8916be4707a02e99ac8cbe7f8", + "38160b335134da29729c629d6afd650d0cb5663660aeeee8e2540744e217cbed", + "9c2196dc7e81a1b3ba31bc7e4f75ca8580bbd3cb45f4d7da0f8bc8dd04330a48", + "91d41a2edc9e12e695800d0e390ec816709480fa86f4ea107d25c27b131dba2b", + "babcd22a8092010ac07cf7b38b225081924a9763256ca014086cd7456b0c7877", + "8a9a312c93282c382cff7e9745835f098896b3288da053ddd5cd792c5cf2d35b", + "2c59f4cb840ce89af8f519b9625b5d52bd87411b792847ce8726a45947822587", + "fa439721141524d7b3f549af0d57d1affe5c63acd668a3695ea4292192846544", + "1d5687d942d7b70fa53d0fb05361602f038a6f61ed84126bed3bc9bc98ed2c6d", + "66654ebe8dfcce445d56578d7797ac81bb2b998fefbaaecf9d6ed93752327a0a", + "e0f31be480e4861cbab1e34452855fb88d2d7dc1decd9acc981f90181e951e93", + "d97645fff2793a2f0e57fe39513ebb38de66c4d3e3092d47bdc4259d3557c325", + "9f853fb6ed8a31f9ff977eab156150910e09a332c0896886a07c9eb95d74ba3b", + "76e3cf2fa4c60da7653892cdd15db7224f6fad0d6cb3ed1201eabd59b66a9ba0", + "07c9ef3aa4abb4a491b111f926e0cc1b13bebe9ed7c494f67a0c2f30788a85a5", + "3d96ac93d76626e5da4929ebc052551e3b9504bbc2d62a0d3eb3b78ce208fa29", + "a4d9b095cd67bb899285da12a33b4e14d6082c434d0b0fbf087b5ab9124806d9", + "15854c9f15fdde17af1f2bd3ed0d60c9e8c80cbacde95b050c5eae336cc8cf93", + "923e3833e8d2e17c236c97699033ee42d5e3ea47595aed7c4427a7c73b54e2ca", + "e00c8dd112ec91e5f14826ad9caba518b8c925cbaab3a3eef0486c8909810e03", + "a65a1e64b2889ed789a86c89ff91b9478f60b81b79290ed9bc875a9a51ac5d1b", + "6c9b85eeda1e3692ba2ada105540970416c8faa3f70eaadc6a5ea573c1a97d6c", + "2cc778646516cd5d9410f4d3f84c1795b8061bef58ac143eb98634ef62cae14a", + "6a27813514fa45f8b0ed1acf3b06c534d230073e3a4e6f9795f9c2e771a5a26f", + "5f7600acd161303a9532b669ea09a3aa8041e5e01ac26d1267907593d26d236f", + "45e5a03a9800bafe8d0613d17c8241bfa1d7931b2520ca4ce8a125a745ca3292", + "ad837dc0dbe46c21dba626adfd745252c4d9538e036d6bf87b05a5aca9b60909", + "cf42c511ea7aee2e0f74c41bac196bea1401bb0b15d9d63bf40ef9351892e6df", + "43702b347e3b3cadfbf9711909a1d5b33aca8dfd696d87828b5cbdaf751dcaaa", + "7cb57ddc322b23297a10050bfacc47d7c2dc0f66b11bde351f1f8c177aaa973a", + "9629f645244d82392958d5c44cafc9fdb75860d8097fea369f0e77ee7cb69d1d", + "3d1ad95d705d6daf048258cb749ba218c825d35ff5769473acb57bb9a72afa24", + "04241c22bce5d8e45d51e90d3c3a579b10cc154de20ac23c4ee9a276095c7bb7", + "ef343c6b317e6d17727a1497863cbbfe29126e44acc0ae89052c838010aea09e", + "b2195415d0a0ccea327999f0b6bc0afa89610bb26ba49eac1d6368396ef81d79", + "1dfc95cb2e250f7fb0025cd97a3f6c5c8106babd5ca3ac21558b6a792b95771a", + "008cff50150a877abcfb0334fd91068cdef89d724987e26485d5ed6245c3ee08", + "01106e66a2db14eebea02e118bac85a52646fdc9f0b70f1c04140e09e65b9858", + "41d921ed5fe0b2f2613b295051b7a7ce09e0481cf2a24a25d7db1858a17a3807", + "a221e6205df5efe1b954e3211950f4e19e146963a5bf6203bd5138b2f3a0ca14", + "1d95a68b502ae98693e621686850278b104628f1d8bd6dc20c9b1416e94269b9", + "960b716f6b8149a322fd2dd677c62047a81e20f0a1cba15057dce92ae7b55a47", + "66fafaf8833e1f5cfa148884dcce2290a851a1686c513159dfde78bc51dd58fc", + "02d0eff84b9709997eaa59a6f5c6c23e8b6c71aa1deb600fbd044ec48bcacc19", + "96c52bbd407080c1a2310608bfd48fa9dfb7f30c1f28d01f7ef67a9ad16e4ea2", + "ce4f6e2d6fdd112aa951d96e3c38a286d4b9138c737a5a42d327eb561bfcc8f9", + "f01c68a81f42829c8758f5f8c8629865079ed96a248ef726d93cd55801e710d7", + "70809479ecfa858c3402e8a80753c4f2974baaef31e5d252b28461a5e9733dde", + "62aed40096ffb13ebb4b287312cac14a38fee42f0296de92d8e19eed21b8322f", + "3bda8b712cb1beee6f227dcc41621c707648f73fee6ce75677f52a030e03dafe", + "420c90c4b8a83793610557bdd93f131247d0d2dd3ebfe379948e139db6cd093f", + "1070daef0d50de4b2b99477940a60d6fa3bc4d9b540d79ffb50b6d9113047729", + "5c1f966ec87192309e1317efb6525b9105c3e4cfc49bf1eb374617688c661dbc", + "0a3d6ef178c1e1e05db1e628e6ed9001d76e09b65d18ee0f7e73126aed0864e4", + "24d298f92959078fca9de16490a8fc6707889e29d8b72bb9544a87f365831c85", + "801af0d9aee17c968447fe11555c77cea33348b9faad17d68932c2f4d95cc2b3", + "262bf584a3c7930ff07b05cab334624117a125c3c443e57302966999bdab5d8c", + "b355e4d6ce022d3608d6690783f2faea35005690ac04dc900b5cac60bc20d614", + "4bdb6c93d47878f6ff501a9476e2b3d2adf7163611bc5cba0b908ac79567780d", + "f0df0b78b9ed75165bf633381dfaaba2b174d64bb553de66760d80c525f83aef", + "eae5ee003e80f173f08e384f471d7f2870aa8b4b4c8d820d04eb65bb0bac4cdd", + "18b7b5f87b0b625db5f3101c67706c8af0765f65047255b2a24770cc1c0cc489", + "79ace834e14e14f761a45dfc962ce03c04bdbcdcf9e70bc1d4fdff4d96caff2e", + "11989f30915158174af97f04236905aea5ce6e1c845c0ffae29a2b592cce0c0d", + "5ea509a6c0645133e7618d65d59313980c3ac2a1a53bdb8eafa6d22994ccad7e", + "07990d07113cce49788aa2bf0b4c68ede31488540e2e41fd54144d343f7d5068", + "a0fe43562df46683cd906818ec0b9543aed4c70f6687b344a0ef9057b5801d55", + "6e112e55cf36afd953140125fed9a49d8b6108aaa8c9d399b742610234a196e9", + "810520a289834f79b8ea072e877a6dda874f6b10d4ea103d84f913f76dd1259f", + "a6ca480f8efe11c8135e9f840bf80cb27b64ecf9a0419e74a51b08fa4cceb63c", + "25d2d218e73917a38cf8ef78c3617f6589345aaf369a95079f3bc95777e45fb9", + "0b99cbf7922ba45a728a49f03f2212295becfd6016d8b9518d93217884e9013d", + "1f0b5db83e5cfe546effae51538ac5251b12678bd6fa02c8df1da11b5b34afbe", + "95b29c0d0cd67f9497e2627be6bf2de1c4084f50d7b3b020f332c4dc3c7ea4b8", + "c0c63a7fc61c2cf61b96490e1f57fa51173575cbd39d855e300fff5af17d145f", + "186daa88b72cea8dcf8536a209869beefd186a994b04d79d86ed5f1194e876e5", + "7a2d460e107b39d7b511eea625e2cdb9c9624ee22453697e151173dc9fd17eda", + "c4f667d986a03236131a52cce526629c9f21da13c0d81892d0e063b23789697f", + "c74825d491e813cb4192405f03893e384361aceb82d570ce3e993d455584cc0c", + "d5dd36020c40d660df2a7b3d67d10bd7eb0c5fbd8cbbac1e8c8fb08291064007", + "37205d210ccd6e805057c22efc533b0d2c7e35cd8f771df5ba1c9486d51bf687", + "334507474c2a60779b5c6e0433b02851880031def0ac6dbf367c47fb8a6dd6aa", + "1e151c9201fefe47fe96ffb3a03976631cf9af18a6b9307f54d36e876f6b5478", + "4638254adfce5f120d287ff6b6310116c58e57f5afb724eb46250e8f69d37e4b", + "ec85108b1b31bfe72a3fa15c131843afe74ddf687b33f48f67d75c3bcd4ee96a", + "a20f231a9ccace252bd5376c9e548fc986d5a7ad333454cf6d12a043bb342a54", + "1fbd33b1088a896f7be37ba2e1efa79ed09e1931f3eab026fad1d3eb78634f9b", + "5a1acd66bfbe7acd0b0f961ac10cf0600395ef05189222a4c4515231eb01a189", + "c0ea9a9857a1d8e7b715a58cdc37d011cdb52d9b9772ead5b0415b606b216d6d", + "efc59fdc923bca11f39cc961f6443f4b4aef0c55fd563d5b77a008b8c803ece2", + "ac68a87d5bd1d1db964c58c86f0f6a279a7984cf22414427c444db7f197bbb77", + "86f3f2a7785130ceea52b84909d319e2467ff449184eceb85695bec81251bfb5", + "a0990b4009d6a957655169e4d8826c86bc1569f276158284bd4831759fd9e866", + "ed8fcf85fb6bf9c395ef33f3af4ac28957d5a42f4b141d95c13cdb2c9081ad1d", + "6e12c83efc160d77b05c3d6b6219ed50ffabdf9afb20230d7035c542f33ce290", + "426a1b4ba558358a004f7b88cbcdb105f22d1e5eb3c538189d01b51bff20c735", + "5065603854aca3c8a30de9990cf08e5fa5ccf2624ee94ab087f8a79d302919e3", + "037d6704a5f61abb5f67c0d73a718814db05499916acfd9a128b3289d4c6a32a", + "0ba8d1665d2e68adfa95ce7c91fb40ed4ea518afa1cbe79ec42242134b24b6de", + "95e76596e577cefb032d4e96c62cf0139e4fa179e456175345feaa2269ed68b2", + "57ce04a098e4e316f4b1307a6933b2c34ed2cc02d9c920433d98fce7b163acae", + "9dfee111d5593dfbe6d13c34af179068755badbe15f3b57a49915222b85182ef", + "f385d19ebbc536ce7b8d8bfc80bea617add2da3ae2170a246c58bf95f82712e2", + "b9e0e039dd01592d6f6a47da5ddb2465d096cebc03edb497fa5ddff98b6422ff", + "59eb3060a77dc0e90d7f92d6ec16f439aca1686a592d4cac19c84f81218099b7", + "1e74d3a91eedb61121296490390d3917a10e9b9fc3fedc837ae785e5403602b9", + "fdbbaa6ce952c31e89ae01824c34e07f494fb9447ac708177000fa5cb138770e", + "8fe240aee8012938cb8566d108a6e2e06fa7972b2f36cc77b20fec748b652e1f", + "e86298b974af01610f3b40cb049bae9e3904456a0c01d7df9b46f49ebd850cac", + "bc57c804e11d87d4703ece33c9777bbaea5c9c1cc4f0943e83a6b7e78c8a0bf6", + "51c3bf22b2f2bd20fa279ad54f9794df6b02d4c06e3a50ca4565b5996d81c53a", + "49fd5a9ad3dc8bddebcb6387f311afc53fa08d6fcdd10e4f9ee1e3b4837a06c7", + "4c51f3c1e1bfad63fe1e16b29c46b2ad5149b218d9ad50013efaafc68d0d44c9", + "e382c8f088b974bea64d4baee1769a41391fea29e2f385a773c3b4837a10881c", + "5ea18952cf9ad79d9564b7fab58426bb22d155462f3abcc254b79d40212bb2ab", + "fc8940816a73e8770590828416bc305c271207d75e1b99eec1ff2579b7975f72", + "677b8c66e0cd7a309073d382fb3461ce855b07e678f276cc06d4dd8a8ef3dcde", + "353b532d85f5fdb74d85b6931de7346d442c1b718791e7b2e76dce8a3b420d1e", + "6df796db8e5d6a40406253a732ebdcb655e4ddb2ee155388cedffd033317c445", + "7731c7999e8d7682ff3fc1c665829a88a76f3697170e2bd2dde209387959c6fa", + "c4142aae8a2e966bffddac73ec2fb2538c294669bea6c8f9dbe3d6404016d338", + "4e68a96d662afffc8a6fc1d0dd026044d9c87ee454b86f5bec472e08abcdb5e0", + "da906cb841a2e13353a558791e6eee7dba0a158215d39d4c568c9a3bbf2169fd", + "1ed15f904db82d57da3295d71772da5e8e6bc8582af035e455f6146784fdcc51", + "b14be342ae0975f6141bd6412ec49c39ce30490b60645af4a4ddee0665c522ea", + "a12954eb22167b0ac44bf6080f001f12a90fd85ea6d6f2e0fd7a42c2a3244f84", + "0694aa41fc445f4ad9accab53620cd052cf8ebe37a769caa2a8551df2068166b", + "6a7784007f9f6cf7bddb9bf8c203b3da14e9006fc884e309755a85054269111f", + "01503dcd943274e44915865b6062e36c91a4bfa72d39beadbfa3cb88968449f2", + "3c59803fb30b9ef25595fec8a59b5a4a53e1243a894108bcc2a03d752a94e780", + "2f2e3794bc7af5e0c6e406ca62b80f477af7fa265c61923d079b6248718c297a", + "5815a3b38a18d487cf0e7adf042d421a33a53d7088315b664b7ac4760eda95b7", + "e4c4048080c4309a13e08b92fa24d084188be8194dc749740ffcab42798587c6", + "edf622d2f4ad2f4bdd39dbb37ec09a926f350e17fea29334075a63569519528d", + "f88f6195f306f7f926a60eeda59db249f82f71c7316f6b0fc3da94cf961c4b50", + "b855b9ebeb31271208ad8897f71e635d96d7c4dc36b91530bb35f076210f29da", + "0a44f2f00e8de448d4d9585bbee93a96b97b30311b0ba15ada75c1b54e55f187", + "082775a74ed2033d265042e756c46193fdab71ae2700ebfd035150ec0c95e53a", + "02ab9b6be0c3c9e7203ced84edf47a76b2144adc3e8ba9d7fef2771bc79195a6", + "03811487935492780c1a42af8d7a3a380a403fcba961184a688c561bfd7cc589", + "108e10ae0f42a75c1ad897a9d4cb339f30b7ddc75c540453223dace0b89bbb28", + "192f6680c71e8429235ad6fec9ecc48ceac1c65395a0a63edc5695b700604fee", + "0c6ce91a0e730e8e44b1646c7875df0aab2fb29052ef8efe95be654fe9a8f84a", + "a8032f3ebabdd9079a19730be52604411e98c32fde68b4827e4e1cbe5f4e8589", + "1341ac23110b0abac1b16a04c278f1b55d5c71529ccfd480e5a93ad2d63e5702", + "6b90d054aa440f64f788f49e4768223ec28f7163a4ba9910a9b8066aaa43ef20", + "d689b59988e61698b234079f3731480f6f944fcc95c2b790a4da8888ebb845e2", + "655dd0133997e6dedcbf601c0b8e05b40b7960f04e5add1bbe38fcab4a6406d4", + "f0d5fe79b3e8393c13400de1c5d4b499b1b3aef7eae1aeae3edad970b8c51a47", + "9565598265a144286d9f95a30001f7de07c4562cc757548e9ed0b86f897c9fd9", } -const mainnetPreverifiedHeight uint64 = 13143936 +const mainnetPreverifiedHeight uint64 = 13370304 diff --git a/turbo/stages/headerdownload/preverified_hashes_ropsten.go b/turbo/stages/headerdownload/preverified_hashes_ropsten.go index 9574ad92860..ab032502b95 100644 --- a/turbo/stages/headerdownload/preverified_hashes_ropsten.go +++ b/turbo/stages/headerdownload/preverified_hashes_ropsten.go @@ -57054,6 +57054,1185 @@ var ropstenPreverifiedHashes = []string{ "39e2869f9e719061bc4a27173e642586abf9283390078dd08166754f54bbc704", "402794453e360092651fc1e028bcb751ad9f8afcdebc6a1e2d592f0b32814cb3", "b328f7d545b6ede74b9be9c277131e661570affc9beec67b9ec30733fca0952f", + "1c1c07aa5031b8153c6608ee7d235b5e235b0ab5db4bcf134e0e760270798842", + "df78b3fb09394d9d374df22702a57a864e127df2105a2e05f36219bd166745f9", + "1ede9c8993be5736b077402f6c4d401302236806f7659d77c800405032e49048", + "6c868843c567b63f39a03911f3c278c704024eca2a5093689d6cd1dd3638c0f6", + "8e46a479a039f9b1d3e3387b0fae1331a2cac252dbe5140a3f42c9f921334d5c", + "ff450102f3d2fe452b6d98fb05f17744613c8988c94db17893de485b576b3d81", + "96c90fad2ee7444ab55a7b2bd0335eaaff04e333d11d1bbb34cbf4f192ae1057", + "e3eafe1ad70e726ef38cbfb8b53448db0795131f85a96ee63cf567384e28763a", + "282668d4d8735d81e0c91417efdb8fcee5d5727163d4bc7d6978d2fd59a5b703", + "ca5184403f6c0e858fb15b039193af04790af3d5804501e18514dbd5e3ba5595", + "21eb273137a8134284e667550f7dea32cbd9cd7a72b94cd09836e98dc4a054fb", + "4365bec33d4c999a708b084f6193580c111262266cb26c646bb0a081b06cd176", + "61c76743f72a872616b291cf45628c509fbeb199afc314a1d515a740fa130fae", + "786a5ce0691c1b332edab8c4d36e2836d81b8bc92f456c2c6c21e93ec0669b5a", + "aaa70e8d485f70bda81739a81144c1139312c0bc253d2f0d7b2f44d73802ffc9", + "2d0be4229cc8e60798e53edd3cf00dc4de968d254833c8a41033afce04b5058b", + "28135f4c965801096d679c83076b82f39bcedaa7cfb5657ae691c638ab38cff5", + "bf73b8fedca96dbe318fa64ab9873987b79a3464f9564ddb5048383e073bfd84", + "c8365e6c2e99a20b0c2f12afa99b1aa8c0a0ad9f8c2a041fb1b0c9b3e890047f", + "e795610aa344e11b0d6879070d7ccc5e766899a881dd9450f8d62ee8146e5a3f", + "5de75c3294bea57c729168a78efdbce8d207fc7d5978e5aee7e5fe7971fa09cb", + "89fc8b619e2d2328d8fa1a65f04432c342731e155d476e0e5d5efb3672432115", + "37db99c5557da39cdbd95608947e233094250b19b913a55ec06d7b1f745ab89c", + "3bb303b827dc522c586de6d02ee5f48b2f5c3a8b73990e2f3374230224abb5b9", + "c5816d90da41c97d681590bbce8f8e543d6baf36ff0c233b4dcf648442a0c1af", + "c4d26c4e9ec3e8d236fa32bdf330ef807e4611f62dc78e8d506d4e458a25c024", + "8a5c4511f514cf6a12687ca7f796dd0ba5eaaa6e1079e37d69ba964152da94aa", + "3bf8c86c01d82412c97047b4b2f8206233dcfef18f980ae8c4b6e761c8aab781", + "7b35c250c318034c06da7e8f7e4552e04f94c4e2c52b931d1a517dd68e9edcda", + "9d8758c25ea290c59edcd1e04e44d6538a236641a1b92989b9c964068f1e27f1", + "fc526d1cf09687057a6626ae7e04d9e1bddceef39ae66380bb290f521c0ff3af", + "b94a2d74b70fd110902962c853f3a30f6afd191f9147a35fd99bae4624bfaabd", + "0be0b30706b5a1f0a5b977b637e10d420f4cc1223f19ab3f4fade71e9123eb0d", + "968c01d3413ae373e132e765862d29a9048d12cbb8cbe014f8ce2c9ec52eeb98", + "35782a1c380b38eb1b43766de8846668ec2810b493fa1b957b9f33bb3a016903", + "7a3e8114c0da2535c9296868ca0608f95166b64de5993990b1c53778bf1a9641", + "e6175134a803054b72b8d86fd3a2c684f07f181e21f5f2fe984bd36b3a388095", + "2618adb148e90de7e0ce90b749df76cb40a62086a953c9248bbf6d1f6d2bbebe", + "c39f145719cbf2dd440323a4a48a8c9050225fb6e82939da921d64441ca02029", + "95a604dfb7b7ef3dea4a8845297e420b7ece225cb9a2ca66526620cae6fbd56f", + "4d365f1720450e192f6cd7dc521b8683b636db1d39f812352a55c7d73473b877", + "b018afad4fb9f9cf608c6107ec3b0aa658c476bd03b330a57377a21a5a1b4fb4", + "a1cb828da5f274552566cc77f5c4f96d95186636f6f1a6efab8a070cb0f2e799", + "a3f799bc5d9f79c06c7d4350285790e3dac23e5cc3ef8eb3a980e4cdba849617", + "868d3a0838a1eae153b5eb76456b9e854e112be772dc516bfadcf8bd4c2d8cef", + "c48ef63e3da884646c417e281afeeb874ca2335901cf860d53a8c820898b01fc", + "0956ea7495926194625d6b81e62f06965291d92e87b3e6069464eab7b24dc348", + "019d71507fde7076af1be88f2f5c4ff4b45de1b0bc0e2bfd5e21fcff69ac6ef0", + "31cb4366128932c629397f73374e2f2a0a5bcd1db8a7518c5a34d343e48bbbcc", + "fd621618e9d47dca2f440a3ffe6931c5835b9bc51c78efaa170be2cd507ef383", + "815281a0ab7c6c790a18df03c7997c28610bd67dcb9402b85ea7413aede37e0c", + "26c07e8e9ab7b9c7b3608b92795397e2fd0487ce0a4dd7950530c39759f62ca2", + "7a093052746ff19345a866c57998860bf90ac3c500669e4e586173294a3bd30f", + "02a0d202d35a0aca8e35afecf66e42a9d0d5db8436051b4d2e86b8ecabfafb61", + "ee1fe2c53249be2b66eaa86fae3e9839b076524ceac3dfdacdf95bea60a92760", + "f0abc7aeb5f8cf043018209092e559f93d1b9094a03c065565292bd85548b702", + "0d544ed1dccd7eb52a22b8de7ae3e46351466ad00f872565ac069f4af03f7f33", + "09059c5a3224d659b9795ad00117c2716c74d3a909b050440d6c223a58df14b0", + "e7c566ee668883b346cd2a60ce5a6d97d273f31bd66e05b2d4f30f5eb86c7e83", + "a9d5c559a2bfb75b2aa6ee0061c5133bec0e623b74ee09ce65cb1f23aca26408", + "429091d0c224e4d1b281063bdc9d4b2b00e525a93076ca39af3699983bbae3f0", + "2ac7dd9674a56628c8322762d1b801a69554d8e0e05cada223503e3d7c471920", + "0c87654b9592b67a78eeeae4b97769449da75439ba6853cb7427a9256031e3e7", + "579ed1d18901866e8c01a1c60aef15766ae9cd2ec25c7b3906babea216600a61", + "e6031d1a4b6d08337c86cc25e004f91e266e7d62d4d840bf0dc20f3e921010b0", + "5d3682fae957d7603b48fae3cbe5febbe1aca49e094f474aac8ab9d4d89546b4", + "13d3aac665c7108b3286e9df4caf4c6eec0f42ca5ad30a50a37e0e43231b16f8", + "9b4dc4cf0d600d9d322887b841fe50ebad1deb2cd40cbf2ccc76e15953dc1e29", + "8160b8f7078383275fe62e2e7053118a5e93d0cefa7c41228f102362a3d89d64", + "2ff2e1c853faa44a6345085fcd209b61365e8fc2ab79bf6fb7a3e4ee62a580e7", + "d222dab9ecd07b05b719672e060a5775cc77bb61f962a3244b18574704bdebe8", + "ec5693b1e8a10adb01717c2a6dc25daa9bcfac5a05a35c4030a3ce42ebbaeae0", + "60cb77326e0fc26fe4a3f868b4ea76120131dd51cd325ad4887fc93e83a7dcb2", + "136ff0dc1e162c785c668c94e8e38bbbaec80eb710d160fd0ba45fbae0c3f046", + "1036f02b2f3de63b1eb24e50f8927f13ae123da29acab98504f870fac0e5a2ab", + "6fa543a6678ee104d9be36186e84f70101a81494eb6bf420eaad8a48418e79d0", + "3c5272441e3e2322fc1ab7744fb2c29491bd83b5bced204e19de95cdb98ecb2e", + "b01e6e81702fde272b11ed849b8dd15989c22910235fbd87ea02c1d47c8b4612", + "6c098d04c1a14fdcf8bf3d6b4b1ba299d5538085774f92c7c0245ef98343f92e", + "531a59ee690ed7bed8072c2b250f1c468b198394550f71228f4431a6d4f7c86e", + "39c2388ae70017b8fdcb092c66b4ddc23ac6c126320534a021945fac811c9de3", + "a7bf32ec642f5ffe4de192a7ef55894bcd2a35fc5d2009ce046bda9f3ee4637a", + "094d3a795e3b1a0c5d919623c7a7726af01fabb2b0505d8f757beffc1895997c", + "64b57da509ea2225ec12caec84ebb31ac2a16064346ea2d813c14aa9830dd6d0", + "c03363eb714bb7af213e0e32c43f6d1f79a5475fdc804701c1e68c9def8d8d30", + "80f86a31c165fb02b72d7028477ce316565216b38836e569d727da6a9ac69af3", + "8bd1648c7b5d8183a48355c6613b7ba4d73aa0dd886a63c87eb1fdddfb9e3666", + "2fbdc3cf1f4fc4a8425145e2a0763e578b093e93e82776fcfe8a6f3419c1be7c", + "efe92c46f79e3490941710260af9d34224e39ec9aa620e1496160035203faa6f", + "f46a4617802085c227a2ef98c4a3e536dc5871d0cc6c25f2231ab151f07a62f6", + "984beb438b058d2ef875ee8cc535e860548c6a2af535bad635ad75d468f8e475", + "65b30d0d1dd799f4608551df4ad5ae90e475a2db31c559be0e8379b8d84d549b", + "e83b2c265ff475c58d68c41b1703fbf925705ca9d5d3f7f5cfd92b577d57c5e6", + "6807b8432f4bf6e12002925999926eb22e48f853ddd77972878617a41cbcf84b", + "3a7db8934d4cdec7ca54622ca1b60c103a40fa0234e2ae828111f60b237a2afb", + "6ea7675d6a797ffded7758efd3fb13090db428280c323a8b19de60db7248e5c6", + "4fbcb47feb1433d0eadc6f629df5346460bffb4e59655598bac939e61745a84c", + "7fabf4a58b9c16d98356e84b1237559ec1f31680ff033a6868d1b59fab1a1f78", + "3da68f3c45711387cc167a091e5aca4d5a563896bb188093d17049f0acc5ed39", + "3820cd503adbc2764581bdae3aa7b20a459dfbebb67eaab92cddcc877a34b36a", + "5a8b3c11d921c8dd7897b2e243e0690e6255f7108c70cc7db207bca3a2f56106", + "6d105e7b65c276892c360b00d561d78b9093bccc79259b49b60fc977680085e9", + "cf59530bd698d7e4e0471c435909f90c1b9dff17c593b0e6d6e2fdfd6a3a4c19", + "03725cc5abd7a3dd24802902128d3f8af00da31a3030eadac4c16ecf4292bb76", + "4eb5683fd0dccba90b17eab96e7ca3453997a062cef60435bd2a3101161cdfe7", + "673bc42d244f77de8daf7a6b369854018640bdac9716ec831a99e873869bb561", + "5865cec5b6b6330786637552bf8d641869331e023c03f8e8c34572e17d70b702", + "6db40f4f9be1678a49d000987d39f04e2800bc886aad7d811b07ecaec2de5c6d", + "f4f54f19959b5db26980ef5b4acb1dfd244fbb573f6d4b5e71d075ff6e919de0", + "d6d457596ba3cab110b1f866bbb948467d769565794919487a67fd0e8f2d0de1", + "985b2ef362de59cb9b474ca05e0c64a2c5be9dfad997f7a56e132f1fc0a3ae95", + "cab8915dd21eaf529a457d4686cbb842a7a0945841481e6aec9cda07f35d8942", + "6f831b07d631d7f5cab6b806749e3760e3936448b7197a76bdf9587f78016236", + "36336c8f8a67e02a8a5112e26eddb3d14958d5747ae9a3b816a5b72f81076aa5", + "a317f8f250dc13833c242494928134ef9a1e5566479e23394760012dd751cb46", + "aebb16a449832334a9aa7fd9397415a53846163339d8d69a0ae5e58e238c835c", + "d1f6c2a3135a721f64153da6f14cc18e112b6bdc61319e77844bff733b27388f", + "fdf2df5bbf9c08c7b65ee01ad8ac9515a24bd1d2042dc4a5c38e76dfe063f858", + "e25b1ca3bb20a0fafcde54313dc68325a14b75e836afa00c7963edaeb869fc3f", + "b8d5ebddd37ed8292378f8199f72a9fd0ec4fea34cd25b761c1b5c1bd620e3df", + "e62439e2955d4bc8c83d5f6c73464c7f7d278108c16e16f359548c709d40c958", + "7637b161fdb7fcd621d35c0c56b3f1b15f05a8f83a7ae5122b5781d853d48803", + "22da922971ccdaab496a17ec378fc84b7430a878e5952e0f3b6a5b4965654420", + "c41e6a4f022d5f1f160c5440ce21c0498ab4094f94fa13454ed80fac2870839e", + "7e5c08e2e56f9a8bd6d7c93647f67491cadd5386918b4e57e70f7673b429fc41", + "54a744cca7f4300237bf025bd8c89e15f62ef9b3b52664375bfb2344ea48f28b", + "ca546bdc327e317579fcb97db61ba32d81faf75eeef85069ea7b961c753fa5ed", + "1c352aeff4da7f8cc0c7f937094346c77558dcf3acb841e6996c17a55e020b29", + "31f801079a33b00072ffaf88b3ac1096bf07e0858de916f127344d51f209eee7", + "05116255350786713c4c2538b3f064dc157d2f5a9a9f4d828fa6871ac999b8d0", + "aed6d33950f802f3f3931b513fed912e55ac48092cebed5d87b068577bb1b55b", + "b18d41af42dd850696f5f629e70ffe229affa2515eaf9968dd8c9b28c67dca56", + "2c090fde3ff98792878d65320ce2e5996f0a164806db911ad43086004dfb7782", + "ef050933e06d2468d39675d9d6c3a7970fd5af1d7382874c9989750ddf9d31c8", + "055846ed0620813a850dc5f8042fefecd186d805099b36d9eb682333b029b5dc", + "0e7d1445d8c7e309c7316e5194116d299472048b5aa2d706c77578eefd537e90", + "1eb3e81f5e638b5cdb0383daa9f27b12e3690f4b809580b4d759329228035f45", + "ca37d0b7ec22c3d5656a4e40dc85845c24dd8585e074206d0522304e2a87e291", + "96558b944dd628ffd77b6dbe466cf3c89fb71bc425b78ae8aee15d2d97942c24", + "72cc4c532eedb7cbc791e360ce15d45f918b78f11d309cf508857068ae5a7c59", + "778ba2d93d764cfb26ab734b4afb32414ffbc9e3dde50e63b25326e32a5df0a7", + "2c19032241b96cf054b7882d452caa294bff119eb5e6b5fa4a45fd042b9c7fd4", + "2e47fa5c25fced2a5d531ea2dd91abb7df0584a11e3264b87dfde049ee2195bc", + "218d5aab799921396dfa878f5ccd18e44d0f3e3291deac19c24a32edc5001bfd", + "d7f28e9a4f698b8c36430e9f82dd9601a8e2f1a1de8e49b8294cb51f2ed03280", + "557e62e2765488cc967356d993521ab9f07dc45795c072f51c0e521bbd02bfb3", + "f901479001b63a120d6c64d884705e3368752558a5251aa89ebb58e59946fb3e", + "11b9dc34dba737155e5e11e3909f6bba65209e4fc4d36ea3196b68493c444df2", + "8274023b43903d9139f691cde3797cd5524a5b9c1c53e775dd38ba396e7e7a61", + "4a3e2cf53b076b003338444431593848400570f730c3aea1541dc4fa26624e99", + "71c7608a9c9b23b31a3e0f8f8eb35c9c465d74f26f1cc4fcc4fa71304c59bc78", + "4e6f953f12fdd48cea1bfd36407dfcbe7d9eb146efd7964a191922cdcb7539de", + "3ba1526736b809e58513f7b60366be7fc5866832bc86f91f9a39d8b225e835d0", + "9463db88cb7029994def8217b6c2540786f7ce156e1f1087683ba767e95519fe", + "cf033a6c2b15f91aa36a4d2d2052adeb584aaed2c9f28aa4f70cec21f599a09b", + "8f3837ede58fd5132d8f507a5646db0172d81dd50ba4e60882317e74e25e10ea", + "ba5d53e3192fbc427a6f0fb14bfdf2f2d3db7a521a15bc4ed55aeb1b0e22dce8", + "a991ba4b0470c7742b50fef79cdb16efbb3cec422ee62c2bde7807f12f82425e", + "dada57d8d7975b4985847e04258ebe644409326c89210697ed373aed2170d1bf", + "2b3facc8843c085226ec4ac814a79342a530ac0b4079ca9d7eb2a94ea2c22fb8", + "0fa14f4b99a674f581fc0108347f04a162d418612ccdb57e565b2ae463737eae", + "588f7decdce60bf883b94fc961f0672397ca47f8e156ae3a813b7876e2177998", + "24e95431ac68f157bb186c3f8880566db697b14e8ca3797015ec599b17fffe45", + "e4c41ef328b0dd0fdf23938d2adaabc4d393fce45e6ba9efec28c905f4f10bd3", + "7ba16f42b59d1251ca44e100d819fbebf3a13ff49dc698f27b768994b69854c9", + "2898b8697b50cd9c9b97378e24d0f1c2f0cc1e5d59aacf8896941c4829226b87", + "6ab6adba8185a297d68e07d3755eaa1843a80b3c8b9c5ad4f2d8fb04f97633a2", + "88d78ec6c36337877ede2f7810cdf36cd3e5bb87a32591b5fd9e848bcab4a371", + "0eea223d90e87bafe6638f8d3a01c97327cdadd4e80a0d4fd7f0ed10c5534a7a", + "51341e3edbf350185d820399fa68a553f882a594222b82c078683de93b21a645", + "e2896ce979cec08d856bb29f60dcb66d39dbf0901a15ca1effbded4b3ef262e1", + "865dacf672317b7a8275d5b1ae83a9233c114f63b1a9b3ca1d8b30394902885c", + "ca2ed050f2cbb82324b8917f7916693c1824cc9137520057143e8801c34b7b58", + "9f745ebab94f35f98211c255d616a753291f7b1445d5677981e2399e3e503a16", + "95f1bb7a18a8b086f99d01d0cd6e7cb3dcd676d32758333bce7d8f7ea9ba76b4", + "db44161802fa81ea0a0ae1dee3835fa08b271fc3d4591d9a57043429c0b75cc3", + "d0f409e14cbc2c46ba01cc471ebbf06dae31e3713f44935b4465d08029f66b5e", + "acff9e995cdaf2236f29cb28af62cd08857fb7cfcc03aa6877c3041351411307", + "6c41e5cbcdf3e98aa3387b05c537e1ae8204e1ac360f7a757eed1bc6839935d6", + "542f8374ba00f439020a5165a5a8517e6bf941b472456a41854788e3611e509b", + "cefbfde5fedaa94e8f8d8f6262adcce9a43c38f54af9a7992a122b371c857e9f", + "a62396d37566d3a436d1163ff53fc5f0e467ab57a952f52e9b21d242666ae2f3", + "1f2894e7ba07e390b8fc08dfe35683da64a8387faa76b7a383aa99c028b04f74", + "41f40f0338fa2b5dbefbf16c8b34c04c02eb3ca3e53935925bd0db9d9bdac4e5", + "6b9c07f87f25548fba445a55d7838c9af47f99e2aec2f9968b4ca56b6ca449ae", + "a56dc8928d4091f7d685ef09b1ff7f62e92f28c5a968726463a83b2cd2d825aa", + "13fa7f949fa8ace388042ead48436de3b8645f4e6333a531e0c4b27da214d469", + "099e82a7ae515a9685077dd29934dbb26e8605c634b7a648b7b8261923e2b614", + "75cf92b8998b75cc5adfcc2605cc65aedd58d2ad5eae6839aef3644dadf67131", + "e0a8c810e224b8ed97075d89046f0f39aa46445bdb5fe4f54553e91507bcefc5", + "0fc1701f57fa59fcd92e3851ef371437959e53888475b95f453e86ff071f91fa", + "f9b6a3d9faa7cdcbfcfa8d188956d8fec9c1e8ff3d03d14f372cb14dcff22a23", + "43c1356c02cb1658613facbfe574f686bbb95cc4c715fc7e0fd92fc75823b46a", + "efb9b1edd2632a12dd1db785fba8e7565e945e3d2712462129228c86439eecdb", + "0cad31789e923034956221047eec8073f9814744c3b9aa6e9c0d55a772350296", + "413ddc31dbbfcd9b1ad9326aef24acc2f65d36f93098908615379a937d94af64", + "5624ff6b081a120dc4c9404b6e4c2755bbb281dd781f7a7cfe9df8b045a96d3d", + "8058eb686cdb6e409082b90152effa4b759617b5e12b1a105cf07c9a6fc81242", + "1e858e8cf297debd265d0cc1cea5c75fbe6b2e93868745ec1e1d8d55b8f03659", + "067473d8e48b9e3027c6d095c21705ae5aa25be25e1081fbbc7b4d876bdcde27", + "e6244d9cbca590bb4e7ea0ff9650a617d6bac466ab414c43ad94d5ced8ba3f36", + "99b34694c1ac155f83e0f29166fc4c8c57e77acac3252867ba284daa0e4ca417", + "959784397d2bc71040e409a166bf5ecadd8cdff653dc86ee14142d0d803ec7ab", + "300b1b1a5170d3dda1fd1c8631d8a1578d676612fee0ab5d963fca94e3cabaec", + "6fc66a61e127cf6ad7149b26d15155ad29a372bb26a8baed52ca0410ce104147", + "7f5a2783b92bf5ae82b6eee694a51529b681e58be3f7b00c88a37597984ea144", + "8daff407c73a71665e35035db944a6fd28c05701f4258b236f1507d5f0583ad5", + "20abdfb9ce59b9daf0ec947acdad63407e84d992e9a85a77cad36bd06b1c7bd3", + "43b28670c41b2199835f0d4a2591ededc8f2c3a7d2dc5e587584f1b089bbf256", + "4479da0435140ffb08549308a538a9f956ead0515f5e612083f179d51d2e8c4f", + "c262cdf23b2a916f1d38824a086dd9cf5ecd2f4279bd2b044909778730a5645f", + "376551a7e94ddf5dc1c88f7684c436f9bfddb603cdc5b4d0fadf7999ac25ca68", + "6f47089690cffe8f2bc1f0b377a5c916274f294107667683d373c7af62adcd2a", + "7ce17b3cf35cb5925457f99f49d3ad2860266dcb5fb042d5e3e241ac9831efee", + "1e118493bc480afbe4123f70c11f53720770ad5bd6633682c2bb8c10c479a6af", + "7b231a1ced7a6ff3571d6430e8492d4a675af857c3f54476622ff66006bb46b6", + "c260edc80e36e63947dc4db0fd4678e7258b3ad1b54876d6e7db6254b9a13b37", + "d202e6f525c1e91a1ba0d76f65d12769c90bc78c8bb476b0f1ae47758a704423", + "326c1793235139376c65bae02f34d70fd4de5969f0c71561a90404bde5259e64", + "b6b6e19837fea4d0d61fbe8ebfd30975fa0b953fc32636951d6bed95163db1f0", + "919c4e1421b09ddaea6e0e35ae8897cf497309aee58c0d440e8496d612b11088", + "361721b791031939414e939b8068a2115fd21458beb124721f3c139742ffb7d8", + "8c25009ec2d583c4f07992a636a367f13f04623623c332bc0d108eff0a4299d7", + "c1fba24c420cc9e6fe4a4ebdbf1b3773f31140696fdc533b6fb441027b52ca7e", + "f0666550f595fee32190d3a90a1c1ed323fce179898a999fb2ce438c4055d86e", + "1347cd4d9875d06309062458b45e125cf159158e2a2baca57adebfd0fb6fbfd7", + "fc5f6060e6b30fe79e08a61de125962de22f872d815dff01bf748837fd3c541d", + "afe46196ffec707724a16dcfb4d742a264b8aad2fbae8e8b31056dbaa7454e28", + "a1017580a2fdc0f342954f68062089565620acb8b6096eff5f56a2dde0926139", + "584f25c52f44479391a431962c63d9252afbe120d678ae55f7226efd27a98fda", + "97c60004e93c828b1b7da12f3c9dc235bbddc3bc3da860960bba567c805c3dc7", + "38965c716ea28c12304d767ad385c43e949c622410ea027f5071a0553fef956e", + "4a681c2611be7425cd15e09fa5bf492877e5aa5ce304672a550df13f463db96c", + "0edb8070cd99665d8404c16914eb6d86e15183d26eda2dff38dc4480a46547ab", + "7a34cda5e82a24993437942448731bde308b5130c152a2d09b37e581f8b97520", + "15d3c526fb0fe5ccb913033f274de58021c884f00835e964a77a40be29d4059d", + "a3e2f9eac6b120fd380c93761f72820513f45c9fffdf15e7212c011f8b539fca", + "814adc66930e512139a241fb9a93bb879f5f10e058c913cd03a10d22a1ae3a4d", + "633ebe18ca49653b2b7e405decfdaf8de966ea53596a2c05578cf9b4c6f676fc", + "9541f23bca790ca99f8d59dd05ff77dbc54fb2e764a0fee99c625f24cb9fca6a", + "acbd489a7c16dae88100aa7eb93535e0421c511086e25e7a76bc93fc66e0997b", + "a3b7d786cce750c2d57acb22e09805823889380b51a89e6242a1fe2c8781d5ec", + "3d616e45e4f4ac7387d0746dc55efad795d8972b83d18fdc3bd27541f68c0951", + "3bb6fe19a6c878a274b168dbc5d1e03e336445208cd27c7d650e9d8b4a16cb8c", + "4e9e60407aebdf21613ae2e667ad8866bfcf127b3838f101d90d6a8e14c3c523", + "d67c01748b257d985ad9d65aa88f236a68599156281f2f3a22843d014c19ffeb", + "d338f1b846ceb973e6cb759bcf3d1ba13f6dd678296428bfcdacd121b0337c3d", + "6441d87a15eee0264e029e079d926858fceec8d985b82400860cbb073c66c12d", + "b77809deb9a4883e4e2d93b1683f7f9caf9b6e9b8d80f01037ba146ff2c11a69", + "190125b7a1e1894113973634c7d1f8055fe3c24b784a17e269660a60d15ad5ef", + "2c29eca57821e55b879cb604eadfceb5d0f6a8e2990f467b8230e99796f04831", + "a458f1ec4431e6e0643ff25b263e5a9db6e3db29f892c90dd30aab265398fb4d", + "cb4ed38a347fadbead025a29a1f5f5ae700b36918419b7c51ab7c524ca7b7a28", + "0abe1d4ca0f7127179c39e7fe7ecbdfd47c7aec7ed90dab8422abd3dc02bf570", + "3886b7985a99db76b90d6e980dc9416ebb871267de7454b90a3a5e3190f53094", + "b9992138765ccd3a8f34f66b91e8d6e7593edc7f36ae113aee786c215a01b209", + "943046e577ddf73e51ec4f7522bbedf05d2e6b6006ba14d47a29d8510272db46", + "28cccc9e6c905701817ecd5098788e3a7014ff61ff10051e2c3c705a1b865e1c", + "5052a61ae3c7cf4563fd98ee5ea41076b2ac5498cd7d59dbe70a53171ea86e09", + "6766a08f22eca6655927ed29ae17446f3a62485efb9fe353eea120dcd8207d76", + "615f213723423aa0677b6968b16f38f11fde51572fa9892d17aaa945e4374a15", + "44da23d3b577e70dd12f64bbaab7467e4283106cbdb4af5e08678b5193dd2479", + "68a9681ed3a0d17ec0c873aadedc61ad75f64b8b8333483b525bca97929f6de4", + "7d65d18bdb03b567a2d762b6eb3242abb863bce5492e953a064a582f9796b21d", + "eb765bf3ef743951f8c71141ec8320ce665cd36e8193bcd594b8a01b76f4208b", + "720439540f1b0bca6b5bf0de9c461dfb62db142aa9c195004f2c59d3b2e30daa", + "6c4bb69a941164e2c81b38456a4566adbc8e9b1616590b3a6aa14671a94cd735", + "0da14c26fb28cc3ba919fdaa337d805efe499c427ae7a1ebef18a90a893f1602", + "404afbb54a870ac1b335c61ffab086ab68fb3e024fb5ada9eb40ec48f6404302", + "fa525d4b6d37e5febf39cc214d8b49662e84c803094bf202a1b822b966a7b235", + "b7b0aa19ed90a519a435d5d11279e87a40bb860509e489dbf89ea1fb867f129a", + "87900451edfe61e75fd4ab4f6befd33c37021d43f28f16c395b1d1277dfa6b24", + "e29989bf2cec3261e7eda33f3913e05da95e905d2bae5a9b9925fc54646a2551", + "1e7f18d6ded18d7a5c7dea2e01a75d96b117cadbc870cd20ed9b1d6d55ddcb14", + "8103af04ceeaec5205b4efb2a2573e61ac83d5471530540d30f3dda537738f63", + "7de4046557c876ab914ab7ac1acc9b7e0c4b24f87ffdfe40025189fbaf7f1364", + "d569754e186a5158e4ea7906c5228692a2a346efda1c2ce04bd1c7efee5203c4", + "56f8d65f3a1865f21324512e4072b551470c3600e38303810c61820626493085", + "acf8d559cf206b0571b604191bfccfd90158de57fa61b3add19b275a89d73bcd", + "c09597d29423381fc6a3cf9a83fd521a6e11c9ef467d31962e42b891aea37c26", + "f6cb8960ff1a68ff34a0c8b6fac6fb573cb0073ab8442e9890ce8223af9f1ed7", + "32f7fc5bcc918e43acb917a769a5645776df9df68264112afb90c7f3cc2bc4d1", + "e2be91edaf35857e4547487599e0448dc0cd543fdc7daf7c0f43bba8d11f4cac", + "204593756b0b77ea39a3e10924dc8bd6f0d5a8ee7eaa7cbe6d54617b5a7a5d58", + "9c23690521c381562a28e9531519b2f227a153ac4962a5ed9087023dd622f78d", + "fbb4c068e1ebabbd357296017835757ba1947c367636ab16691f90b5e0993d7b", + "a6796b89adfeac5eaf244ae0c9e6093b4a3dadf571c70bcebf532d7ca598fc2a", + "e013c542f15945205cef9988d3e7487c9df27a5cadc772a311d30a967c1490ff", + "fd92496db203ed6de6d951effb99fc60441923b54e331037df0f34f183b3d3c0", + "ed62fa9d31f811f85005347ebe31576622814e4a62fe6bfc3db7af09572f1b66", + "1ffd714fa21cb800c405f0fc74c17bd3656ec5bb36c6ba928ceaa84329150f05", + "d56bfa87ac774719b5af98d7ade412674bbad448299618a94f9ac0852441138a", + "e577f2778c4bad10b776e718b1d3a16a89f1a254300647cc24c9c1e8104a746a", + "7daddabc548009bcfa4cd91cec68d362d915d7116a5b7fc9472176527d7e0a09", + "ed1483a56215c4d23504604bdf65d5a23b0106b7b21951cd72e7c548be03a002", + "e65fa413be1f9dbca731d1219ee445cd77d4421d0113474926b3c6fe8befcadb", + "ac0db6d10645fb9259187822d0b4e4dd8ad1892bd6869f542bd0ce71f0aaa27d", + "85bf6606f300b813250d012c9167295b9ede6b22171b4af199a8f378319e18e0", + "434006215fb1247f14fde67335f55c698a17268723c1512ad844645491d08209", + "d75a9f1f859d021d857fa45dda69a6954997b3accf3074968c39112612c42a50", + "934ab6fea2b3b35b75c948405c50bafd7d081eb56e4ebd556a83f21897e49189", + "dc370bd31afdbf525b350af40b6cbf7667757e491be74b5da41e514d92b3f320", + "84b53c15a3d8c4560f817c70ab4cad44eb0dddfbea9dee1053ec98eb0c4fbf00", + "2599da57ee9b2d80fc132446cbd90e4792ca753819c715bcbf8316954eb79db2", + "7a96c6748a4b3f0d5637efd10d6995d50a31b3444a277d8b43b4ffd7351e7a14", + "5a824e1dffeae31a80b8967fafc7d36f853f96ce729cdb1f371dc95c9a7e41fa", + "84761fd144997ea62eaa78b44feb25525db42a68adcaa6f56ce5b51f4e93299a", + "ab004e743460613da5199ab0b09f47879f2aa0e2abc6aa7e6a64f6c5a705a53d", + "03c9ecf578b06914e53d2ca768d8f934f19db2cae3a96067be6ebefd41f32374", + "5bf802f9689361586fa02dbe8ccca18b17f1a97267b009f3d2b2b0b85274df2c", + "ce409cafdf6c1239cda9c47e52f33dac4b290ea38e502e77f79d1edf7f8ff14f", + "5eecfef7567f4b06224c04eef97f65a67b793995a8da05ca87bfabc76304bd9a", + "5a5f070c097aab4eba83fbe9e87cc1aa5190fff48cbcf8b39030046575945587", + "46d03388bd6deb53299d93057417df8e101d42436d995482e505b7072b0f98f3", + "2cf1c03f0027ef256017e44f987c6905158ff456345027815390a12d2af6a2b2", + "04e0d68a8e82499983cb7ff78874b8d8cfb9f0e25ab8037cc00365d6ffa78676", + "bf1b34eb460e58639ad9586c922ed13dbcaa6190837f6452b0b718c652028b38", + "fba03a6bcf5e704d795eac957da62d8b8f8d508bd5795b914c2a1f61c2355077", + "5e1f0b92e5af4cf5ad2427e582342f978b26fed944f11f37ad92feaf04625866", + "6da90c67ce894d8a9e717d37aa5b075f733b83725fcbddf0760ea7b6d094f995", + "8a3229b0d5b5fb0664d2eaba70f4b0f3f83c7567786dec259f5ae2b4aa9cad3e", + "d44cb331e6e9a27c6e564846fe2eaa52a2a6683f993ce8212829adc16bc4c7f0", + "e5e017fee59e3f7c33b5eb4493e97ed1bb39277385352bdddd48d6e94beb7c4b", + "697d439a73898faac35575203d7241f7dc4aad422833cb06c1f965c6f6126d00", + "aad929c31b7d86430282b841c76024d34d45d0a7a70cdbfcc9297ab64c98e3ca", + "a93fb78ad56f6b7d80dd45b0dde42bb3a425f78e5968eef662a60af007678992", + "d9cef7c9d227fc4f3893a7ba6deaf2ddd2823ef25661e54557670e8a09e2a8fc", + "73737cb8710ee017be18bcacfb21bc89f1501d948dfff48475078a458e0684c8", + "57e54a9169809bf650cea4e88b84492f85860bc940d91149db759ab4a0b5e1bc", + "7f13ca84d7bd59d90ce308fb34f4365024ea0d194803d9e0d58cd5a11a61c864", + "f31dd7cf6b4e91b915de47b06158de179acaf9181d2abfc18bbc380f87234d9a", + "ca66be884d4fa862b46c92d56726ae8b50d4f8319c35d1bbe2a68334a09c77fd", + "911a9daf7764aca6bbd2464901b0198f72975157c0460d0f038fea660f319165", + "74865ff41dc506b3e8275c2a4d9fc11984cb5bc8de754c832ed98a3b65f7fea5", + "d6b8c4d272960d0858f0579cbc125fae86a9920717da204aa4b48947b2a8459c", + "cfe31929d9683c4f3c8d00b6afa254c43425e25b5dca69bb4166f46db4c01943", + "1311d9229a62fffddbbe7a9bacd996595d0f727cf729a1ac3bb37f1b2a04f4c9", + "01d1d584a80f19b2dab4b93b35e25929a24f122f836455e12ac861a0910c1670", + "e2e78d402297937dee0381d6a4776d06471c3a40c4e4d77b29e0fd5bcbecf452", + "a1fed51a999a6e9ed675621637f526184316d5e085d297dd1103a74b46874678", + "85bee38f0b5016e338869a13db0eb810b04675a5fe71390dc2ea9e4958ef74e9", + "c46e11076d1ccadcff6c2673d316df20382aa9d6bbfe99c9af3ba17056f66265", + "9ec573eefc2ceba8c23caa513a1c005c02cbebf4d7b0d669bf5da26c83b37228", + "f7e14d6aa023691bcb95767ae6a330389c53a627096c76f18a2088abc767ef60", + "b8af30bb054398c60ff8c4335a9aef89d9db8f75396dc299218213de64092767", + "a490689583a71d948b443fef224ac812a0269d9f4b331c90f4f8c5c3a6e0770a", + "e78ccece89dff23b535bf8ccb6d2633aa5aeeb71feaf3b5a87aa4eeb6f6add8a", + "a5c08a83a6b4759350eed2c57d4f412b151c0a8fcfb2a778cbee6c574e090ce9", + "2dcbc7628b400eb91fbc17ce5c7373286fc5e8dc1c8cdd56dcb371a2520c99ba", + "419deb19c0e0ea7cebd02c25887723573076873b7f0a8eac691d6bbc4b172157", + "e9efb9695aebea3be1267921a694b9183c5314347c066980c83e1fc2b7ded694", + "fe65764ae32185c307213f62599ec21a0f49da13aeee97dcfe927fe0e13fb1bd", + "2b1d3711b62c5a10b5093facc34a69ca647cabe7861e2d16338058f89683e971", + "b9ed42cc195beb26d9664c6dfaf4a7cfadcfef4e1088adda9cad327cf9e8b143", + "716026772d595c39f6c9dbe19e92feb1b3556dc59b3defd956a3bc7fc5774eb9", + "675f36275e645166f897306c1ed928a304897775d9c71b6d45a235b54756a25e", + "664c84ef2f294fe38d4ca9c43975c163891a98f89d3e47c95af93f034d01ba33", + "2bebcaa9619327233c446e2c56c65bad91892ef9c7e6c17d8ff7dd0e7d85ed0d", + "ed0f9dcfe211064eb93cb417201e125b0c151f441c8582566810a1132255cab8", + "8b61215a945abb77bb2ff9feb57963298126dd1cf8bf1d5bd7cf4f8a9602d1b3", + "82839ab85485d5ee1704b7247b44169d3f5e41f892afa0410a8138a0d83eb0e8", + "57dacbe7a2f5f0b5848ebfaa762788dba1db64ed956d387298d15972e00f4fb4", + "51dce2efadbc53723b84d22ad01de786b11b225afded9f66bbe6f89658b981d9", + "884821570c35c830592b6513ad8321d96bb553812c9f35344441f7db20527828", + "bfe0ad514414846044e50925a9ca183d3e932fe054932e36eb94b9f79d17e099", + "cf466bc2a2c7f57043804dcbf90dd61b60c8753a749f88e914790bd14a3b5705", + "8a2ff7735799a361096a9c3e07438520ceff562277cbda17bcdd5aac8f5e2477", + "cb0a1a693929daa9d2a59fd73b6ff070323124422794d7f343c725eab57d7189", + "8b5aeceb19eb63492f01abd5d563eb1421b4ae420019ffe93b35fe1056917d31", + "eee3e13fd974095f72b38c1757a153a1d07ddfb7b40fdbc7bf0086a96eab197c", + "1ba7313952b67de5d489153222f6a48fe857c8bd22f0ff71cd2f1c817705b103", + "e6bd26c9232df710ba6f106efa03d8a8ad39e09f6b897fef1795454b4e64b6ed", + "cb5c7e3f76216d45feed602a43c78d7d28b14e8110fc1ce55f07fc40e7e15abc", + "74ae604c0406f2c481de2283b0a494ee6cfb28f8982452b5367f049471b9517e", + "f99b2a451edf21751e6e4d0271e7cc56d6df7b0ce671d9da30482faa18d09c9a", + "7ee02b16c21ba1271363b9b7cdc04a9ffda1794f4ea4eae7de487d8a66c4a829", + "65d27b0b48ac0f7334fbc17d138e7c645abbce67dca608ef94362f00e4172c3f", + "49e7d79ed1cb2c276cb47541c6ce50a16895dca1d7c19906c83ca8cf143ca499", + "653434fc05dba0d11f520faa2a5a4845eec60da1ca7b3f3ebc27b066656a77dd", + "dab90f3a9673774b6442893a9f6279966b1de654925c860c8e5685e07544e9d0", + "33d61ff3805f79dfd319c1f542855ebb25ed297fb06e23e7cea35661cf646f5a", + "27b4f2031fbdcedb6c2a64715aec44394342f4f085a48d338c2cf6edba2f9d8b", + "dd3b24f2759d0c6a508f2975c6365bdd0450525588dab6cb1e92dea2f5f467c8", + "8c5d267e40a09fba91da0c95923529dc605d5b3312dfa0cf27a206bf33909031", + "51ba4794eaababdec249c0dbfd9d2416cb81bf8f3b3fcf8e271103e8ec14ace0", + "e3e344cda765554e41efca7318bb9505d6d605961e5177b632f84e67dfa4bd24", + "1dad2bfed8cfc85edc1a695a30ea192f21bb9981d3d7863ed9b17f768e2f52b7", + "7db39a951b0464aac953112beaa00840707c783fd438e95bcadfbf31a612a83e", + "39853fcb145c1c922b768cf5ce57ca291402c9ea98e587b6313c869084e1579a", + "dd2b33fd6ca03ba87e0e5a28eb17e761004aff438837e30a8dc1814f3da56338", + "af405555d49b09f8f86e739b251e706d86e4a66c87df9df503ee849e10794c4c", + "ca853763762b822c973a4f971ce15bd6cf540b5b51942a7bdb906184684737c1", + "57b85a90ef9195469ca6a6d89e4fa78907ec7024d0a19e68c78ea82752e11f19", + "ae86c7ddfec6a9975133fb3ee0f7237684cab50a5cf2b8bf7da2a81fe1e4bc71", + "891dd4e60e3a56bdbdd0bac1f3eb3aa0fe83c3398a2a8515d78a26631bf52653", + "0cf218d1bd09385e4a6f1753b4a2a1359008a00d9ca6517176e52fa8e89dcbb8", + "93ca68bd573a5d976b9f7e92835f2f3cf9ac68b216f824ae12c5f4fab64cbfbc", + "8e8fa62b9cc2a753f019657cc0a747270bdb0f3617cb4852513f5734573301ea", + "20c75594f306e5ae30164fad8fdcee2136e63c65cad7200645fff49ea6845c0a", + "543498e2dc6ff94401a1a34e52bc1c71d25904ebe1622ec42c5e488889be49bc", + "d85893696e83612f20514c6785b7d59246e3ce7e17c1be4dade7bd145b715cfb", + "2978474d9caf5e8d8911e2100a1dc8c1edfc447ae149f9ad4cae86302a3cfba0", + "6c624a82022ed75fe7bca04ead61020e7ecffbedd6567af6bafcac92e2e25151", + "d72eba1f4a19aa1e5484d9e16f52827d7c15ae14c0c2f012020a56941569e94d", + "46309134583d837a9221a3524258eb1d1e963a985989060559f86feed35d2738", + "dcceb3b071862993c7d4050b01b38b1f7abd82f39e803c1dd95e6384ac583fa5", + "df9f0f3364e87c5b9e0278f2db30bbd92281f6ea2e9c2cd640b46a074c0c8238", + "d5a605ddeab10dfd39cf67ee26d35c2e462b1ffb9a8beb1eb9c5bb860afc7b7c", + "7ad3c09a5a9d4967e65e10657321d71054aa3625d0646a23369b368e17b92771", + "c777ded65357319c542b1dc22f17b29d8c80b804c8230391c8d10160197bc802", + "421bb090756ed6712ba2bb42e995110ec8c6f971e301b918465a1f9b05d6c967", + "b6c942102fce9600f1dd58ea42ed3a989d1e7fe3fb7b43d9e2a264311fc2c63c", + "e4053faa87a84cf96e2c462fc0b4e1aa3045839cf5251d12074228fd0c62662f", + "b34ee1abd4b71983bf2641e8e8e996baaf21c56e133a697b4c4b7a69c7b371c7", + "eef0e80aeb09ffa8116521ce2d38ebf8b9ca3d5353eb81a2dfba74bcdd55c15c", + "1a268d3bad58e0c56b1b2278ffe696bca6afbaab884cf08dc37297f74953143e", + "e11ade7e399268ca93330973d55d15936c42bf88f10723573b5f475a2ed9f82a", + "9ce53e42b4242293e73f791765b606d9eeb6705f934177a034bebdc1f16ec27f", + "af82a5bf5233bf6e2a376404c43ef2ede6ae51986c5fb1318a6f0df3ca4b2ad3", + "c14716e005b7eea9c5ab77bc551304119e7c916922af9cc173dbd0fd18a67023", + "90596c75c0550665eb06656fe50dc71768f11cf93d873c7e11651f8d15689b50", + "d56c4cf11420ce05b0f2ed504d37e17a0dd952469a6b4e908522026a5bf3203c", + "82cdaa07a48193ed782a528b45543bee2607147f94f11291d7c54f6a4c682a3e", + "99186675c10cc8d4607218fa439d7f4056d9bf40bc2e7cc1771da8fc28164258", + "2601cfd83a63e1fd256839fe8998daa810a29d77c85ea9a9f55fd4a12da6809f", + "eb217731c8df7156bfbd2f99b5d104e9ae73aa2aea021b352e2c9dba81bd74e8", + "8fa34bd937af59edae24cf30ee3f6943dd7ddca0ddca535ca24d7ab2af529252", + "a33ebb149cb0124365499c8992fb9de276f736c9cf917e7d1311dd0dfb982d61", + "07f4619f465bd37085152ed7756f25eace6a620449a6179d528f6dc1ef711b54", + "ce54f3d1a04c0be1b4e8d6b2a736f877b6bc3c224d19eaa9b0f29eaff1013166", + "1217c42b7751bd24a08bfedb1d8c987d588be3fbce6dd90b77ac929d989221c8", + "e33c95b8c26658ea4ea2a565d0b1a2d9d4e215e11172b1702b1c4ea771fd9fb1", + "dd324f298dc149a1bd70c93aee3363b1330c6b64f07feddcbf377c52aa1412a7", + "c64c1b9e414f9ce70b89d34e7f8eaf458766ff94191889ad7b8bd695e3f211df", + "4a3bc8647117e6311582dd619d624cb1ff9c9d49ffe2bae3b963fb6065d2f09a", + "c09cfe56a7765b004648742367f66bb43ff5324312f138590d56f33663e8db19", + "54c0f59809e31436f7b37ddbce450d7f63b5b47af1030f55c0b4bf5abdb26712", + "01861832e15b72c97cdec1fb7b7f0e06db5669bead65735dc5d0b159d3f60288", + "1bad30df895ff33338c2d96040d453a1dbfbf2d5a604247598682c977246e35e", + "01f3638fe5b906693cd6e4221c3419b88424fa7a40212d0fd9c85dcdd4e91adc", + "fb0bb3b6507a833dc20e603ccaccf48f956be6c4a57edfdded7ad955dad4acc9", + "4297ea67d7d6d5eb5215edfa3ae8e2485a0cb9a19213d6bb4ecba4cfe6a7328e", + "32a4bd66e4105f66c172b0acfc164289fef83162cfffb6df153da9ac6f1dbcec", + "9723e352e0575f4b8ef22d899e5d3c576cbf529362e6eec7d6fad03fc150ac44", + "df3957a95ebcd9dc3ba5cb9efc6bb731b346772e18510bdfc4ec876f4c2964f0", + "3ce44980b13411cd5a7a637db88dff74c0ba49d618e7f097427e5b7be291427c", + "01e3249402cec48dc77846d7f7d2d21e932284ea37b0b321c20b0a5847340027", + "e9ca8dfeb5e9663a80c62546e874b14f94077aeceb7e4b120757a07099b1cb4d", + "7e2447d96fe11ac7215d8bded824070990c3b2f6f5dcf5e72a3fb380d1eca329", + "03eaa07e5351870434bb87b8b60964642410fc563c080a9ada2f32d38de98963", + "36341d0efd8ddf279371f432540df299bf6c9e556770ada29bc4c9eab45aaf59", + "23e03fc76fca6b0003bda0985951b07590b11129c28f6f8283d035ffdd0c9da8", + "6a41a307bbdd9ca7f7419bcaf98e8e638af0fc25dd90d3aa3abace381729e03e", + "b715c1487c1aa5debe515c1ffbca8c4ef155393a36371f6456df52913d27f850", + "88a99baa790e1b7caff75275570905229a05a0eff3d9d138712c542fc7b724b7", + "2dade93ea7899497c8423d50fec1c273904b7d6d272a859c480c9b4fab921c35", + "beeccb8847a93eb0b9844511c40db8352aff2afd8b06ff10e6a49e34a01dccda", + "40acc6f44c0b74d9dcf018432f97e68f171378ce6337b7565602a9d6b5d62c33", + "628d82753cd728cfb193b0a0daf448cbf791718b92792268e7b74a6efee669a4", + "2668d7ab83cd11cb07782419129b708786dbffa309c4385d6fce089953a63662", + "5ede86093b459602e7db138b55ba1de52b9506b03c87bd22a9a06707bcc5f860", + "372947e2fe254f3823a86c6c1353bbd3a7c2c29a1e6c807214ce11c1fa992882", + "144e3653ff3393928816402cb5993781e4f8e17fe7c4cc3449baed854f0a9429", + "3e8c6106fd318753701fb2725c2099648c851000f6acca116060eab5d0b13929", + "8ea2b947cbc92cde9c479470d92660ded8ad203efb0d427ff4d944b7c8f8ba9f", + "377dcff5814796e29a520c1a7a25ed61a1965bfaba6ff56c19a7c29e9bb5c12e", + "e8f850c7fc11b852fcfd09d39957eeeb238b2e5c0b264935a5dc51ab1278522e", + "9870ad688b6114ffcd0fdbdf0c5c4ec15e04d263c8af432310adb13fb2d43015", + "308a5a504bd6dd923855795f1f2014efbd515dfc5141f7303a66112a81e44f9f", + "aad7dd5db3b62bc4aa79079202c503da551b2dabe565cbe14ace5d8758153df2", + "ffe7e05096a71a1932e53a2db5af2f12683cbb9d98295c42d4aae86c009d7887", + "51fce95f4f9e7e87d3e78b09924f87e85f3916d9757a31874a59565a6f99769a", + "0926b3c69615215e5e2ceee44fd70cfc1dba1ebb2e1c4875c6e48036c0b130c6", + "aa0beb0e4835789c1c650aee3b5c434fc6515779525e6d2bcf7babcf93baa632", + "34716b70e30fb27e53c9c4d0653c4af830f8a2ca2387236efd90aaa4669cae71", + "7e4c9a777372c2b74463982aac328494811e38761df7b5d1fde128a2d729b633", + "58f02d944c6697c3831e8391a205a7ba00293536a6c3f5e97ddf4c9cb0c721a1", + "ec1a8c6e34056ab7d212ad13fb4e4245bdb4f24fa64c041154947d191ca1935d", + "6ab33acf682212e90e99b169080c9c81c7e5db9155579f53f77f097930839906", + "ae01626318b330496625cec54061b1e547ee489ca54f3e992f192079b199775d", + "8727cd578ace92d46caf73803aebe839c8d636a7fce8bb41956dc92abef10fc9", + "975b718ec899151fb633d16d5a56608ff54c06f2f55eed9ef1fe7c0919d161ce", + "66812dfac1f4401564b43d7e2ed3211a7a495106bc075650bbae2c2d71e1d6f7", + "969682d83d6829f5b83b60af8b03c75ec9e0fa0440737cc9c041bd3c7654f1d3", + "0ce05bb1f08b3d54739047ad5e3d51a4a05b8e9d4150776ae6f02cf6cb45bfce", + "f90d8a248c7989d8c02a3cf573aedeee6ba681758e2075971465a958ce35b4e0", + "e0eb5f9f75e2f0f6a0ec38f0216275d2a252278555cc023f082b77f60ce46ad4", + "cb9109f92874e9f6d007f582cc90976ad4c64e803ddcf7a103137b1d07a8fa8d", + "9ee86ccfdd940d4b314d3d0f4af5592968176c5f31da3944865bb017e12902cc", + "84a9412e8267a0c64359aa3be57e54e936669af5ca8b52a4d534d020c7276d06", + "bca041161e0025024b8bc815d17cd038d88014787ba87970736092996a8d4f7b", + "576d66e535f88574b6a999e593e23ef28c0f61149907bea48951faea1fd08cc4", + "a65032ea2c06c9c5f1094cd694aba926fb36f8183eb68a9366df44d11a3495ad", + "391df8484a2f6d46e7556c87000fc628fb208bddfdbf48678f3571b9d70f748c", + "ec20e1785ec8526f386170a59a74ea36b2055bc877cd6c500c00990da584d6df", + "4deb87db7567e74e8dc64e1572ae3195947da7ece1369e67c4c8a7ad954686e0", + "8f84fa73da1e26fd83c9db6f634b10c7aa2b1606b09df98a6b179b993d60c052", + "cdcfd62425bcdd35c28d362aaef7f1ff5d9898d6a788770daa48bcc1a68941b9", + "0eb744b464a44fbea5b6144a5a24cb04827d9d3d46ffacf88f03754b0e0bfbbd", + "ba7bfa7b3facc1ec10ca72e4f9bcc3e304e03219cd4e7c2b1e7812fdb50c491d", + "7f47eb0f534ecf8af8db1ba0ca3f20ec61dd95d79d8b2be17820c7199525f6fa", + "d00184c6062d2d5d19cedc5b406a2993627d4a4849595a3d979ceb7ad17ecc0f", + "5cddf12bf4ba94f6b56b0c61475c9b4a529e5bd67ee6beb23406a5508ade6373", + "f1f62ce2e6b1e5dddeef12ead8c3e7b272a6f12f9730fdbdbcd3af1656dffcb7", + "7406bffc66ec2ec5d499d3054167cf2732b9e74217d6df3115516e2754d9715b", + "15874f0967d1af3dc04fd8cbd0fe393abbd047105cbd898d58fb589e4352d1c1", + "38982aff3e96ec5626a8831d45014699bc28f19bb34ab449ae0363259c0972a8", + "8f34f4b27ead564c13df4a2e1062346e315355216a03a35118d791df6a7195a8", + "e00d3cba869c15d6fede8d7b17bd2222f2aee352ac072d1ca500913f057596bb", + "d1f8b9cf584438352e49b664a83977a2989ac22e03a73e642994665d505b3aaf", + "8bfe0b91335a4912cc4db55130b8d595eec361141f165f09772833149f49cfa9", + "c0ea1d0b0eeaf5f41a378849f137703120fa12330b5cdb71a800b6d5889ad38a", + "fa002d4cfa605d1a435fa12eea0ab1702fc18917efca2e8b035ed4e61e4c978c", + "bfe249fb40efaca1686c4e69fe9a5bc3db9f61c909ed2dfa012e39811de593e4", + "9bd7034f4bb80d89ed6d5bd89af524cbe83458ad2484714da7662fb8e95f23d0", + "68c7f111cd76727b0f6c6deddb8b60f8dabb4c4f940b88e978bb6c938a8ec221", + "4b019818830c2d586ad88452b69bbd4222fc45a742cf314313bfb08a3d5c6c78", + "f3032b05886b5a1bafa1b6d863d259320970354d6fe993500fd87c2e59f4cbbb", + "9e0916c6f843452a210b03953526670a7ec1bd9e6347c1dfe2131be78881cfe6", + "f9e4df42d33881ac6805f6e4b47a29b60e82ec0759ea053ec288de157c106f47", + "5a31b5e8d3364b749176ae00fddcd2e1080f287e059838d27113be6785c657ba", + "fd66ca88787cd62326ff3871b7b0f34d71a2a6640ec79664648c564776ca2e6e", + "bc4566c1ed508c6baff9f59c0b2b534571450e392912aced700eec255c2fdfc7", + "ed575a3502c6a944321373858770b25f4845ddc8c6e412a70539efbde5fe2247", + "8157eaad6604cd082ceaaadf0a114f819b0c131f0972ba1ce94eefe0112befc3", + "089ff93946bda3759b3869b38ca1a9a4119431dc01179a391893057a1d3a6404", + "a5694455b2492f9c878baf87da4e5f896ecfcf106a56497128ba7abbbe9a32d3", + "327c8c06d2df53a95c8a835fc1f4531f332d7a7ceb2fb1addb942ef1eb4df0e7", + "93eac83e87699a4000955f2a996baaa64224649f2c886ba82ecdb782047113bf", + "295508d0e5bad73816ea629a0e1f909305412fa23841ac46bd9ea0d1afb491b0", + "b0faebaf8fcceaf0620c70375dd4eb59c3dbc28f8d9cd9ff10997425b2f61de9", + "617fbc10de9b2065e57947768f9f4648d11410e0e05b9bda9dd7db5a90910ac8", + "4b058f5f38617429dd0c539bff1fe3a76725e916148940ebdc76a1b18e9791af", + "3e5ac21005777b5c810dd21258d8791540c7df1a0ecb99e6e3b35de7477ebbc4", + "23ec6628b9105613ba794771c48bc33196a4b47003cbc1a0735180a9a7e3040d", + "4b1323d869d4cdcbbb24249927e7f3cf639dfdacec9d1fbc39cc6ac849c80eb0", + "0afc65b591974b6ebb1eb6fbf130068878ccebd7396a70d15fd66219d5398dc1", + "94ea7d07ef7a109122694cc9681585cd1466bebb6a16de4d01eb037a0716884e", + "15988fbfce5c1d285a19e5c5b70c531411874d3aa199c420131850b0d5ce78ae", + "e1914c0a4d089c01d54387b99640ed422998fc94abfde1b846f745ea03540845", + "b62ed887419c760f12bf88340ec89cce17da73ae327114f40e43eff29c868467", + "018f824c1a60978c68f5a2d8c21d19f058a18f6a388915d3a9823c2d5b236050", + "52b8d275216abeed7a11ccdacc361735ff01a2644e431a4ebc11c5d95e9879db", + "b276dfb0d9e3aaec2170e935c68ffc14c3bef8b2c13201456310cc0e90d05a22", + "115b3bf761c58f4a0c018f35e1be195d42de853d30c7557961386b8b8abf4255", + "ecf3e976f7ea7b6fd6c9a002fff168893cc012b5f4a0b4f557f02a6703e85e0f", + "2c13c132997d102af8b0f1144d7ab0416807ed1ec1b9d5fd286865a001dad6ec", + "cb4e642ad74481ce6ee4fe7ccf2fd4cabbdfa24392cd3e7ae07c46b12e0b5ba8", + "602692d37edd91225e09cfdec54d7f947f0926d9f95ce8094e76e1987cb553ba", + "196f276eff7efb554dea701e64a842944187c78d1b5e97b6944c30129ab097a5", + "d1287075948a1689535178f124ebafa3c03a36456bf207adf84c50a64376e311", + "f797de6ed2488ad6468260169ce65e03a78f046d8045cf9f5cd0e64d50f1ef8d", + "46d45e0ec0116a9ae96ddcf720d2b8231a2929bfb1b3d66b76e3ed68d6cec3e1", + "a9d5d3edda17f0013bab0c1a5e6d3128d89468e1c5c010f9b95e6a9a8d33212f", + "653a7adf26330bcb7468642159a449c1edb4fcf65afd62e0788829335781df82", + "35d91edfc96cb1d995b51774b2e51c8dc77c7c0f39b21ff483af2f5a64260aad", + "aeb1db154eb3d6432f1d3c9ef2fee74ce25bc4b896b1009ebd9d526799ee72ac", + "f6aa6e775a73e3e622547d32a59675dc356dc8e5457e66959fe07b627f02bf85", + "5181b3e44d1f337406386a664983d4fa3d5998c84b44f24b832e5e6b8b3c0a3b", + "bd549f0234e411db8bd6b32f1adc6eae4ef998e8ec730b80ba0fd1cd8a9c6d21", + "740dc4605778638c7bd4ac8540a3c7999ff27280d81c5ecb93cc9acf53ca42fb", + "deddeb738b37135ad3a4211cb64513c9913dbacfe08dea2c8622a1a97e9df294", + "5404268137fb080baab77f084ee1ba717af487ae9603c9572de728b64f985893", + "7ae27cb872c234086d8290f157b2737069731a2008336da1663f29de3776ea2d", + "29c58631a8fc58e2c5647872406fa10aa6141fa95f194d8adc88019cdb57618e", + "d54e8fe5b4ea103858f6e419474828b2aca547a15f32d3e82832348b7bad3009", + "33ef09341edf1639f77110a510a1cc6c69b7527c0173fd7e9dae7c3474249d05", + "2fe1983e96f3c10a3585dd627df485293b1e2a377b3a795255fbfe781d1e120f", + "c9a6c16b58ea0c030816b5153a4d913299cc44a1190a3300fee5c6d1b742d836", + "55fb5989d7f7f2709d5afb514b57288c140b3d06165f1004a9027d2d8d641e06", + "f09bd3d7e648fb73501e87200630927e913f7eb83e02c084d1f17bdb15d343b9", + "064f5e0a51be727aac0ad1bcb1d40ce5585ae0a3d8e0ecdb49366aecfd826192", + "057879a165afc2847a6cdc0b28108645dcd39c6bc8d267160c44309a2f4e650b", + "16258a97ac54ceef5de74d4fed26719aea5d1c240ae787c8f9afd9d2f63ac429", + "135f6175c39ae5c2ed2f2a211d73f5312a558bfe953027ec7e6b1ba7dd3eff4a", + "5d1ce8de894449de8b424a794bbd92c8f1ca0925d23f6669398eb49193d32865", + "0060bdc49a4621ff6705d3f18a8b848c5e6815f406809548a096a32189d30645", + "e81b2dc5f33e6a5e5045c84abeef908cb7962ecfe1c9addd86d7e4b35b9b9c76", + "9216e3aba03b5f034138ac5a0e9c77e2e297d659d57ca13161454aac03d1890c", + "aa860ac9d8c388b669be5ff2b740e64b8962d4370466ccffc5a284b4349603a0", + "2ebbfa420d7169b15b41d48cfac572ca124468c8316d439486832016c9725856", + "4dbe77def035dd0a3bc053ae6e3d33d76b3542c945301fc9b12b349488b41adf", + "930ecacb65b6beb9e7a7d75d2eb79baa8e3bbb927a1d17e95a247cae549639d1", + "1e4f877cfa8890efc743ef9766170d6af0fbfb382356b90dfa7304041d2dfdfb", + "46c83cbca401d6ccc65d299bd4302ad471e8196423b9bac9c5a6f487689b12b3", + "2565b76148d69d0613dca299549ce6495e5c6277ac01e95336ca47e81735f0fb", + "09f6e7069b2c5337cedef41ef131f58bda36949dc604662e905e8e21db0d2f72", + "d338d4d1d36a5948c55cea60b6950e24faa94e86fd81c53af5323f0924e6a9f7", + "4fd75af3b8c1e05d3b013dbac99f5974e758ddd80a765411e9ddc66f9ad92fc2", + "7ed81ced3e0c02306c16aebed5ae2af582bceafa1388f0b838f261b368fcfebb", + "60cdb72f427edb1c18e405fb600f4b09e33008e1fdffebcc7e6b768648f1da26", + "6ad0004a58abe5c6952636161c38b66b3bb9831a4c5039a9ab292d2b78b542d2", + "3fe92e968522f446e4920751e57310762976156cc785b2e9b531b5b41f0a6845", + "6a7f2c01191a1a2cfc80403713c5e50cec2cfd7b4ea65a52cc80d6b494533915", + "bc81ed8faff56606e13785198ffac5efa92abdb3b5cecd4a8a3c5d71e200929f", + "658278d4cfc322915f829d8d089bb1747bf324d441a16795e558f0910a323e0b", + "ad877daf583914f31ac0ffee5a66b660ad9a74a737ed3cb013ac96756fbe8287", + "3916992389abca3043024a33a1df2d72a21b422edc17c7ba8fc1ab68f2c47bc3", + "b5240dbf8bd30f84cd6ec9d2bf8a461609793510f1031de0893bc09c15a6e8e2", + "6378707e3de025dbac7caaa92affa9fee57606592d731cf51a16dcd1fce92a43", + "ee3f9392e8ad50289e392cda1da5ece5149b3be75afa3ee29fdba57df5728170", + "231f0be5793409298ed48708a929666c01ebd565e1ca2de00607e1e9cae01c5f", + "17e4244826aa147d429d4aa47826fb87f90248d595b4f39a6a8749d5eea9b914", + "de7079e37def69a90b97aac87361f3a8276e499de49fd296866ca4e219b0acd8", + "fce3368cdbb807058ac22b1059dcf40ec55ec1f38558b95e16b6e54b677c6c15", + "9ef8718356c1961c6b05e926731c75294cdc0232c60feda5f487363ceb0c993c", + "64f5877f45fadb2dfc80828722620356c4ff5c7f273b4b2581cb106063744d11", + "ebac3c0c62553f7b7f017f2985ad2e07e7f686aa19f341d69a515d11eb9e8f72", + "65fb0d2dfaec0bd22fa36eab94f99376cf1955b8a1214d15272d3c021750bad6", + "c24b9508d4398c770fba085436b6103a071b9505df8f3de8be10e6fe1e010a77", + "6e8c37ed38521835bbfe4651bcf7672b622e8caed2cbed455ef76ea6354b4177", + "11db1fe32b6864ec1c871c26679d8ffe71aabcd8ee5b2b5f4fc5bb3a7ed41a9e", + "620df17444a1d1ecbf3680cdf2dfe1a4c67d037865e04a1a4dc7df7bc404f25c", + "b17bf8284fe3a82c7d664fec1ee0d0cca6d85a46713f8540b9df25fe7e2e6fca", + "c5ab7d8ebf609267204350cb00ddf1cbabba541666c3dd4f6149eeec7b590894", + "5220c92e0b372e767b8b2354bfed4c508d92ed7b650892e0fd442bb32f403e16", + "cb8dc6118291d330d1456f7871e4b18fa46d8570c211a09584373e0194e45290", + "7373c69e280bed523e13972c31d64f042d96c4a8a9647ec7b5b2f48290848077", + "ba0c13123bcfe29053ad41a399682dd9f85341844aeda1e6b8bd68e51fe95c44", + "7f943d7e63e31cf07716654c8962c6c20bef47f4cb98ccc36e55c02a81166f52", + "6bd6e94191e1862a0b2cbc45dafe1c0f986521e9f3cf237b90314ec94a439af6", + "35510dbd7d93083e6d6089bea394bd42a506c05df1306f898971fefa05cae8c3", + "8551da509762d14a36b87bd6ec2ab4c8d6b728dd6ae5520f1f89facc71907f29", + "64ce0eb0364d6153a65c87c77dd414b13bbebd5bb6acaa013eabf7f4200f8396", + "3281090d0db2957d89240c6950e7ac9db29b1e9c1a1e480aad5f5392be97b49e", + "8a0dc146745d0b9a86314575e940d0986062b2b86ac1540bbb9e9922fe7cfb9d", + "dd5c3bbbada08964b4ba45255bd29eec22272b4145be9c613fd3d8c0b0f8b15e", + "ad5f16fad934b491c51586be867614494b73eeadf387d4f3ceefcf7f8da8c3e5", + "47c8993aaa5a937dc9b037cb7e01961048c026bead2cf30f454575aae7b47120", + "4757bdb46b9e385c9603acab80179e4eb97f0565acd81b893dff5fb3852336ae", + "0441442c8ac58f657154062ad58b9d8e652d3865a5f44a245ebc387412ab6938", + "a370aa027527aabbacd482a92bf8d92c37c9fc82d438911bad5beaab915fe3a8", + "81c3e196dee315ec60dd5af14237debe4c9d60c1836c97afead602c3629208af", + "cca7c6b500178b88ef6c727afd9b617e171c1d53d8cfad5e845c125f2a77d0ac", + "7c29b85fb0debde9bf27aa119c9b15ebf9760b8017c0be5b3b13f75b0d725f88", + "c5823bcb02dc24aa02f52e6686aafde87b105580b12fc581487e04fd21b90f59", + "2a139238f664d2c8fd267203bc3d5dfd71ff03bf3416ed24c38564b9b31b29b6", + "33caab894c8fc6a009d241354b6125c3c932a96e198c0339bf8a9dc7bee6e55c", + "d6eeefa1d74d13e7ff2d49d5fad9fd1cf1b3c6c0cc5aa5e546d6e8237c678be9", + "701105422d178deb8e811ac8514f42fa0449650a35b6803b611cd1b9f3503817", + "ac778829b0e69072005d9587b5c5a06ffd3ef8925123612634e788a94fc926cc", + "313ad527fa8a5ebb96da7b18a6d806e918675ec52c618e9cb9846212dbee67fc", + "7fbf8d1bc5f80f296b7686215fb610ee57da50a08f3d12996472af5d4eee6a9d", + "df81829907a6f19555f03130a63bdaf642b567c4ef9d4ec7b8318887fd15630e", + "4ba28de6319b6f64074ad2c997bd1ed8f43fd92e1880f06c6a2a23f6fd823e7e", + "356ef67eaf85279d7bb2f3cdec24486ec158ca7e15dfa3b19845b3d15052c1f9", + "50a164870b46d7e999bbe7f4d3ed1537f14ea171ec19801708a24644295390b5", + "7ef036f61b1643e3daa37b69837dfee3a8d324b77ffd749e47de043ac46241d6", + "16dc82301f229b130855b12ab640282840c4805cf02b0dd885f63ae3f3b3f440", + "1258bc8508d2723cf31b4882cf83e1ec557fdc25c6618d47fe62ab3915f434d6", + "963e22398c7907b0898d0b429d7e45f9a10a36b4865980694917e590049e9efa", + "f4d7bd26bedf405802806efc99fc7935b0671154b0d0662b3b9f0fb229c8745f", + "56607c08a017b3f95332dda64acce47e129cefec859b9d5ec89eff9aef95ad38", + "7167aa13337e0aed407178786ce8d1b42f4ad33c5f3fe01eade0f98f022cb312", + "4d6f2e9bc5afc4271e5d2b4206cac0494489567568f76598dd7faccddc56889b", + "8382464f3e03c46001bea896890e0af3e472fabf6c4a60ec211aa37e8b767295", + "935aa5b30be546514db748703cbd9db345f7618303a5190e9e9babf6e697ce0c", + "a3f560875df2dbc960c7e4090eb3142d2d5917d0983bc066ce206e7811a5b789", + "029ba3d7bc0138eaff8b4c4242fda85bd0c4a52555d8b8a38947a1773683ae9b", + "fa1b195fe0ce16de9dd852cdc9800215177198813df7e75ed897fe30bf9494f6", + "7f29ea1696467b7946c3e156f298c95bd555d97ceeb4e7c62b10ad6b5c4da861", + "b6ae5e9a916f47e814db7926c2629c7e779daf5586d27869730ecfd667b1f9fb", + "4376b167607b266b0dadb0c45cd5a1762ddb5f00cb7aef138ffdf05ae9bae0fd", + "245fe9a234aacee2e93084acf372e5972a3f3c5a344ab22a2041a6aaf12953dc", + "72d1f87e251c2ace638407f902fc929a702ab7ce7cfd2a0df1f5d15e8df17160", + "0eaf3c54809e151e4a66202606e680a6f54d1c53661802f89469eae9aecfdc8c", + "5cc19063b282ee2e953eeab3c43dd855cb823ec340acde9a5263ffa234f01044", + "20e95f5848dc72a017690cb594e54827bf38c81742a5047eed84553f409c73c6", + "2f9e15e443eda2f9a3553ceb82a3a60be496d5dbe5d34618547100796d5646de", + "d546b10d497bbfd2c57f52a00fc9646c01c8562868ee5f7f85c25762be7785a3", + "15844ff3304d40c25d0939a61d11dffcb6b8b4bc4f7bcea5af0987febeae4732", + "e595f08eb8d58351a827240ba3f250990bdc30e21845bf2814c7a64d1d9df463", + "b54275bb8a0e137d19a33d34fd648a7d62f652ac946ec3699f10d1e4210baeba", + "9ec2bd7e680df20ae4e351d0cd558155a6a045bb9c14ed669671bc6b184622b9", + "e8a42319fa841c47e5973ba219bb7e35ddfda02d9aff926283a601d2d0de6a8c", + "67a0468cecde6437ab5e9293db77c61dfe1b064ebe7b5cca4b053e380edc7590", + "106816fe4b0958544ead37346bdebaf32ae4bab9c48b2948dd09ded42a163fcc", + "0d3fc9415403fdd5053da7530b504c413fac924e4158dbd84c77f1177b8a3119", + "f9cf7ec859b3853e48eb9b5cc4ce46b3dd95b25cd74cd930a10d8ef4c47ca473", + "e5542d0554c2702a4c6cc8d98d334514be19893122eb8758ba55f07da4a1a3da", + "4e4a8018c99e9c8be4b5a15ef27a008ae480235c926ae1884a38d46b8e61c39a", + "294791835f4a8bceb44894e9b19b6f589f7796e52e3e64039c41ab82eb8c1bd2", + "380efd9ffc657c059d3fbb2cf1761e19a8dcbb3be0bdb9f8b1f650c8baef1fd2", + "ba2713ead1548970e5887d6183f82e2dfdc2d8580f2b5300b23608548074a2e0", + "8cf18b645c10b489f90088a7ac0521bf4e0966bc55d66dd5f5e11e5a9429c73c", + "9479ee69fb431c3cbf55a190468cfb790cfb1150c7f02b74ba5e105ae3205d8d", + "dcc5ccb3540f3ea50033001acbbbb0ec71a566401ba395e7fc3d1d11d345fcbe", + "35665159a3ee36b712496af4671b8f1f775a5eed46cb80072773e05090d4be6e", + "1815b003c9840d19506108d9dda5e60c197ab436500a34eee09e560508486740", + "8e88b23d5bdd089f60b3e732bc610ea2273f76a5ba0de7dba9b7c2db3a4bdd37", + "544b3460e1f59b96c5b85e2769b811183d0a46efc1c7282768152e9b53470d07", + "db82b9737571542f3f9bd494e23ac96a56060c074573c4cf497310459a902939", + "c9e4efb04e2cd6207581b8dd4cdf920042242acdf8eeb55092638920aaa0e755", + "47246f5c2701a606b67d8fe95e69649fc6793178fa0b58cc0fc7f54117be602b", + "2d70cb21b593e9d48c528eef8518134f85379f273e00705886da05a0596ae46f", + "ba761bd3a390ada8935b47b0f771c9aff02beb62bd9ffd2cb22b88d6e4fdb40c", + "363ddf297c5dd3066b4794c296d61bb57eb02015912ea3322eeaa1badd28d6cf", + "4263d0a29044d8e56b1a82934dbf1e8c48bb78d3930782c9f3ece60a8ad49d71", + "a7a9368c57da33caf513f5ae255828170bf3147da1cd38f389973f9e5bf92991", + "b82b2dadab25f15096c457f707a14878fec7124947a3250dd490ce5d5ca62ca7", + "417dc712a27ada2f063eb855050a02ad952cdd56897b8d5ff51d2860c70ab380", + "88b64fd049793594511e8294b2621e727bd37f7143cc79ede0c817fe32f10290", + "c1181653033a8501de4ed9f790980d03ecf0d889dfa91def05a552b128d9fbc1", + "1b99ae46629ff543183052fb6d7b95a97f76667dff147ffbf2c319336e3b2fd8", + "1a77b71f0de7313dd6b33f7cefb59adf7054a6c023604dfc44505555a73a2f39", + "51269662b1f43e0586f55e3132c345b30305c285bdae841a6cfb02f7bd1607ef", + "552fb052f35bb05ed1020e2f845a649384b1ffb0959e297b4704c7a81fbb96e0", + "e7c667b6fdcf0ab1f5214b8327c9cef908a3801c9c65106faa794e3d268df1bd", + "7437cd55d6f16c81d52e6d1eba5c1674ba7b74cb5b87f9cdeb1f91d6480cb0a0", + "b5105640dbd67915304d74a0c161bf05b26b4c6c84c841e0acc6b1fad8096860", + "055c2429c3740be1768894d4b06421fbf6c4e3f4782b049639456786d78f4d32", + "5cf62d742134f05ce1b5ab66bcc6fb08daab6e26999be769d6736e1db6f38fc1", + "61ebb1b90863c57512fc361c502f88aafdc5a9fd470e31d400d0077913a226bc", + "5ae1e92583f5f65aaef31919142afaeab432efcfb2249a53c165b2fa17ae57fa", + "f41045d6bf70037793b7eeb79260fca164d6ff25c6eb8079ad7b5ebeb4b58b9b", + "742fd883e80f0d754ec49c8e1280f64b1ec122c7a6d2d7b0ac377fd4fec03418", + "bc3e8f4fba84f268b874ad2f30c1f88582039d588f21b2cbb0f6ec22b95ebfe1", + "e80c13985ed15073612c6f88bf26af16ccfdbc13a2d4dbbad435992b7e51cf94", + "fe06c583a430be09b56c00ab07b8b3550800846974d0952377c08aa82c03ae40", + "c2111662c61d2061bfc9e7b6500105e015c14f04e5f730a1621ad9389ac69982", + "d64dd2b84ec6d8c6e17ee2efad7474dda6a7461a3e5b426ce52e4f39e397272b", + "ed4be0185d6b5874d87cea5663322fbd95ddac671392f775de35a4bf2499049d", + "66a4413210a63f9b12bb172c34bc74d1354521c8233fec0dc4ee20a6a2fc12d2", + "508280bd40186263ac0d5cc7fba1e9018952133f39c2c80532f9d356097a6f0c", + "b85fc2ed68eede72db829353852853386fc0d996d26fe13d000ca7718bf78e7b", + "e2740a48a8179e47a04d30c193770bb6724e88f7f5b3cb8ca67e90eaf7a88bef", + "2e738990cc5553013dc69fa7a7c7f9e47c0da2e2d8ef80c4f3f237211ecdb8e4", + "97fb12574e8c4dd3a63050b8b071c18b8ac44fa83bc8a27df7a3c133e5112614", + "e08089216ed81ac0b9cb05e01cdac52f56990ab374ac5abf40df15805994650e", + "2232b27a480bb8393b1b4f995c472c2de834c3f9181e69a5ea1a9348ece63b52", + "3c1cfafcde7e9483805da75aed260e9c4f8a348963deea1739e5ebecb23d5393", + "99e4c8d0e86bec52e47eb65224f51ae493f837dab468c74bd4c6cad906a508c5", + "c75b6e25aa466132dfced0edf79d95fa8f16c587dfce19c77d109df46a407dce", + "d7b844b299de2eb75b0665a4d2f04d9072b7a814b05e77f086b8a5f72fac33f8", + "1be73c8dbcf4f6b27ee3459567ba8381d8e2d4dc63f90e57a3f6dd2f2231c75c", + "d0bfff2cce77b7a0fed302722d013a5d1789bc3d7e3e320f014bd6f37786ef90", + "a1f576e8448a7e04a4968f953729fd1e9ecd4e44b6e7777d3867a16f85cc5eaa", + "212a9f0d36b9db1b0d16f9677572c7ddc5c8c0fe93fddd6a99551f2eb460cbda", + "7e21f8251136d4f9bdc636a6bcb2c840909970c08a7ceefc4becc34d470b4834", + "bb7992784b13e47f1691954c08dd6fc4d649244058d0d92c8af86ea52e322ea5", + "29bf8d103d5e637d702a045f0d6ad5481c6a91b15515bc9f7540df7d2e734ded", + "41a73a1ca80d155708a3b6ce7ae8fdf4ff9e70dd7a9e35a6f3902cff895fd4b7", + "04b345f4c46d4f202d882242d8b796e32253a0a27c13d459921dadca51fd8a46", + "3477bbdd7f2b99e93f75b90a3ab14723824ae6d575adb7d1a775783e29e6472d", + "1fd4bc7d577671f061b0cc769058b8ed9d29db8f5473967b2ce7e9ddc37123bd", + "2ee790b93edbafe43981420b8880950894878645295174e5c67f763f884a565f", + "79a63478a4f5a80ad9f494b07f4f31f758e0cb6a567a05569fa3c03eba0adc22", + "82eb752de5640e0135ab453520d74c34454b7a48346814dfa097bf74f750c176", + "383d8523db7f464bb82eefe067142403746735e56acfb5fa3060bf5bf78f7351", + "c582302303ce926c2e10e88578dfd30c2475155d79f7dcfc86669c65e2bc1067", + "99ff1b78fbfd8fdb1b38c944f7cbe7e16f72649c89a8eb4adf1d6bdb7e6d525a", + "de98934d1fb463f373b1c731585c5c57a19dff6d4514b127f14208bcc6fa20cd", + "454da0735552acc53200defa4b2bf681ca17d31f07b942c1fd5f95fb280bf2f1", + "5072708300bf4da3fe99413c5f3864d94f0993f485ec37fddef34c528f9fb83b", + "20ca0e3d1516c7818107c0becba32aec929a654b61f2e7d874667c36fe981400", + "4c191cb8168d76034728fb9564b0ec130259945274b2e5eba14bf5bea2201189", + "ac55620f5b0608fb120d1d4555eab995c54ed771ce78224a64913ca5605cf199", + "ba966104706b5fffd00365fd40941f060b990998b76ac2375bcb3e5269746123", + "44f74725d40b24025e47a4f6341e36ec70c86ae46efe3d2c6efbb7fa0bba97c1", + "09c8f283bcfcc01745a5821213db924f9dec444439c07f29652ce0e460128d72", + "f9d6eb98b0298e282251e95f300515a5f6d6ac2d32cdf83c7397cca0ed0ea3d2", + "89d697c683cc51369fc501771e4b47146dfaa1a0f5135b02e181bc1ae50ec9c0", + "bb31c2f2dae5b7f46567fae2ecd0f0293f4549605e1b4ee2643f9e51434c6215", + "b2f549ef0a31783241ef389a58fdbf46d5a8bcfaf3fd4e82dcda23d23601b8d0", + "39571058f6fc0175d2bb0c89b78e938b93ce01fd1fac5e356dd866771008359a", + "f6b13ab271bdb7db04a24ae5a4af91242eb9d6338057b53763a3b7c42132851f", + "d4bb8d36c2cccca86907aa99ed4c5e80e5e529754f209f39e5091b9245e1aa8e", + "2b6fa8770e3dfcc74720b768ab96c7251785a29413331bc1e17986329ccdb53c", + "3ba63591c04b1274d104c797942cdf6bfb83fccd69c1315c49eef5ca8408cbe6", + "a1d3592e76f18a34bfff252ed22ebeba838d68c6a7d31494a080bf8db95501eb", + "eea5e0f2fbf789be1f6f7a06cacde7736d9891939a6cffd0c767ec0a68ec5292", + "99dd13f5b1bb00ecfbaef6e062e83e278e40a29d29b996af1306cdd6e906a0ef", + "f99cc7b4d15f109bd82b9ec3c2fc262d8b4aedd2df861426ff69d01009b2197a", + "8251dfd044766015f06bb9339d17abaa03930ce7c7836d65b2755f0a6645c3d8", + "b44e1c46f29f7cebdf50b355d996b668045a7a5002fe1b736b5d21f63a72756f", + "49a9489baf1ed9417b4eb59ffe74b3e669e2e43f9ec0a77ad2cf2febc5c8c793", + "2dc669c381371a8b1382a23f4a468e0c7773ff50e60835967f419e85fb3d2d98", + "6c376d6dbcc6a4b2b7b169e5d932a18502267f4a7f423e7d2c926e4ac0a2d30d", + "8ddef6208d5fc38c5bd3677710d6f2014888cb24757cd89a775feb8ee65e46d4", + "e8b2e19c3a1e00f3f431cfbb9c661497306fb0cd92d71d3cc052a6e2b87324cf", + "5264ca7f001185c10e5cd0595162db064d6deacab172ae0a6bd51631bc78a65f", + "b87860c28b6bc8136c0c0c206130286afff2e9c10128dda44f619cf30385173e", + "4e25b4cd9d120d577c3fdae719ef067adef62b3e4b611bf3591795c5d22017e5", + "3dbec8db252f6b3cd6347bfc1ed48889be7d843c8a9de7d62de8846048661375", + "c27890de1f7c14623b6fed6f8c4b840e4e46130fd90b6a9f1b7fb401a726cdca", + "a5abfbd5829ebec2a3ea676ead78eb1bff3f0098e2f076a889299b3154211c1a", + "7ee2da29384daf03688407d1e2bbb072c1a312eedb23b60c07fb49aa8cf77b5b", + "018584d55a161c553173f30ac2d256cb039cff17a808f0b98dcc7d472a06becd", + "d39ff8bec92f9fe588dd341ead9e4f44fdcbe330f5cf760147b5969e5f430cad", + "4209765e89aa7813f80e5cc8ea4b6369c7a399556044e17e26e4f5f4dd776ab9", + "0efecb231857f08aeb235f125ecf7ff8c8cbf38fd07bcab12239fd646e9703a0", + "81cafdd94f61c5420a5db9f74f839073cea35c82092a70de356ecf5ebbb51b3c", + "266f7313ff953575ed66341447ea2be6be0e03afbce66704605824f146b344b4", + "0ace8420db1d61ade8332b49581b119ce28fe8d0c650becee1537018df33547f", + "654ee78a14e8deb80993f67b98a01bdbcfbf073db96ce0b363049c9f91e49a62", + "ee9cb5051657f144595a69ba00ebf1b119824e20b3de1e980edc368f1f5b8d9c", + "252adbe1cb8dc207e52a28bf126df459c59ced9a4b560cb3091679b5269ecccb", + "cb9b4d226b2fa35908458439c1b8d943b3b9b72b1a674f0cde384f739b2a6ccf", + "622972e22fc3a6f48c56a132ffaed2e62091597c53d967e956a555cd817bd8f1", + "d10c7d685d4d130ea4ec8ef671da3e849532d6c61b20a78094b20524b99bd2fa", + "ac2052877881fca22f79c7745541ff6b3a470e001d64c282f574d0f4c4fcfd7c", + "adb4fb39091b463ba5aac4d8b5190f5e305e4153ace2f4f1364e8526629e986c", + "c37a87aede5de12b75ebb61fb8fcfc2dd4b2a7838a723ab174d3a2da195f610b", + "12c27256d86e3a0f416430b46525c14e85d2e8252bb4d68082bd5ea54673f690", + "5725726fb0a2e1e3b1c23e651aa910a09eea83fce803baf8135b745fdf7bc563", + "25e91558804af0aeae23fd66ec886f797fa9a477230b8e8ace226f1d2cc82122", + "fdc540e80862748bb6d4bc977284ee58185c57be4251b42667673954631e645a", + "f3602732dd02400efe914c329c2bcb470eaf7b1d0d0d75372afe377482032d5e", + "b088cd8bb44f58e438797dee567e1ed11532a1d1dc8067580fb659b2e8e33423", + "7afa0d8e5b3bb45ca56c1406a22b98473c5f578fcbe56c7659e114a1cc82ae8d", + "406747bf78cb1ead849da7855c41c7c3e1f8be62df82106f06d6420432fbcac8", + "c92258587aa321a55c0226c16d55db2e1c58ed39a967452d6c2df81b9075dcea", + "a6e977fe5d5b76186db7f4c5de0b141a7283430e1108b13feb2e3c9acd488d37", + "8a13709a7e900d2f382647204586f6b324871defc5e65b95cd85b16b5f12924e", + "8d5c0064a1e0d9dc75ae8562bbdb899edc7456e2de95598c2f1bfa19df1d00ad", + "e8ca77de3fa2dab0cb3bae21b31954665f86af6d345b3436bca284bc763aa427", + "1170a26aa5e44642e1c26cfb838a2a7d7af046b3f4acb543b2b36b9880ca162d", + "243ad68b8f0798f21a30d0a1a6d14325424f8abb437118c36fa7448e96946848", + "512d10e3f2967c593d669be169ba788949dc7d715df57edca7db9a3fc86afb98", + "37b800915fad3def1f59d28d50c3c18680dc1cc7c700e8eec6e6c2814f59e664", + "0d2da60d38123f68b21e39bfffb85ae601b0c9edba1f403d160448457336e4c3", + "6dd2cd4d837ce292a2b5a511cc8cfe48cd15f30b2a9aa225b2e5dadd7a2fbec4", + "73012f4f56decf203f0825a493da492601de90fcb80f349b615560c4e1e8b16b", + "a36f3ef0640f694b85b23783647e1abada1c7ecaa10e53101f04c23d99a4f799", + "cdf701ffbf31df96f6ffdf9b1e409abcf80f9250d0e477224dc31ef1aeff381d", + "c7dcd16483fecef11a3fc3822a0d1ed3a903c7c2b2df71bfd65911946ffbae19", + "401d4dd6a072df858c0895236a8332bc8d4c2a67539bb4f44a636d345c05d1f3", + "2b7858df016307781071c02dd673732540bc0f0e92e484b7ba35381b203f667e", + "4d502ce93c82649ae0e4dfc6395b79dba8dfc0e50e9cce6a1fbf4caa65de9206", + "6e55ce3eca7da1530fe5bf9348e6ce9b4394cff90236c2c4ce83c071cbd2faa7", + "61cacadb48aa5b376027a02be7bfdd2005b55ab599a3e8e3031ebfca1a0ecd55", + "881363feca24eab96c86dd14bbf4ca6a391831bb9b3632625a4168254c9ad303", + "8ba91ae5a5c2efdf49a8573acf2a79d17b8c0f8546773d9a31bb563ed40a466c", + "71473513dc21c76b9a63f974aa0552737309aba702bc148548c6a614f5234434", + "0c7c1a392a1bc32d85693a21081843f9d6eadf10b81323603939d843f5957b9b", + "8b7a12f6dc0a0bc02e9a70a86bb4534a6d666b06cdab8cd7472b455ccfae3a11", + "e5a3d460dae72888e72d50e83c76b4d0ec6f9cbc16689bd5be63aa2da0d6d51d", + "5d86889f6c1e6e0c685b5dd67aaf7f5eabb258a326e863e0d31821ca87823732", + "a698b498c4ab6fee10022df9a1544f17bdc3f460741e8ff8fb17349122a65bbf", + "f83b3f874dad18c9d7c2641e7f29bf3987c692990a154079314ef704a6cead69", + "e85076a5a710a1c8198165dfd3279224fb90989f0cb26b100637d7c0e9224bf6", + "ea21ff308a483c9d84214e64a1f7e1f19963110652adf2f0b7a3c30e1dc763c7", + "d09ecbf24865e412cd9137280a783a4b6eb01bb82d279eb267f1b9e71d7f4d8e", + "2b07a483dc957f39c234f60eb8912e2ee514d559d11f696973956cedef5e9389", + "28e482e7afab5ab286eb15d1ac65fcadc4a77a5c17742aebfabce07d68a689ed", + "0eca6bfb635ef98c53ca559ef65be0b6477af1a15054ed164895dd6926544812", + "7249ea37b9913949e0e7a94916c860fe39142fecfdd35e131c3a8362c232875e", + "2c5c6b6135decbeb9c30c7df038dbb3d47899769ba7e7d3a0e6b6a35de378e8e", + "6042ee42b441385d8d4765140b6117f3a284e2821758ee6f5f92ed9b93ac85d2", + "9b6c13fc1f6bd36ad385d582abe22693e4c60c32bc3aace3c9a9743ee69855e0", + "9234eccd78e53f3b6938f4ed7b0cc21f94b446b93764aaa0e4ed493b202f3811", + "bc49c3f07c394184a5cbda02b9d73e04a18d5569db3592a891e0018c013a457a", + "b85642413d7cd2c32d744591359c2b3e4b0f8994db5da8dc22b4ae3ddb44bbbd", + "0ec7224ffabe3b78a5c24356b57d72dc811c695cb28bd8d07f185c5f3d7607b2", + "1b704b9acda0c1d6ee1e8e12bc76b0f7a9fdf08a105c77ba2a89f42d70b04ae7", + "35044af047628508f49a4fad7f22c93f830f0e1b5d370710d723af1e091e32f8", + "53bb63fe1b512264e26ff46d5c01f138b12d433283cacbcd60dacc2df4e5d6c6", + "c1a4558faefe3c3adf4badbe6d4f1cfcc97c7b4622b175a5a13928bf9fcc7a23", + "1516146b03974c48e83dea46a89d2ee83395ebe67eb46ac0b8765ef3f1a1983f", + "856094d76c5412ec8887e352087a43415483fbfab38f92227d82f7dc201e6bbd", + "8bab2b73a541da696edc4df6ecb68fa095aab41cdf9021e38535c0406679ffdf", + "d96b7049974c090b66ae3449d66022dc6d30b73465afa41ff2edc5c1f5945f41", + "7630cfc306a609322e183e53fb927675c38492031844dae2e5be962aae0b8790", + "67daf8b74359b8c9b5fd829365e69661e0892511add8255e0326ab25996a856e", + "06b76efd1147e7002604e6f54e601f8f5926c0d7b6cd953364edcb33154198ca", + "00fcda1b58a58bef95d6e6054212e8aa6e48f298f363a9305c79570d37930942", + "9c1ab85bfc37be469675179f9eb4ca292d781433d9c1de1b0a5ca55437fc9ecc", + "1ec921ccb828669d24d621336f73d7261d06e964aa160c340b141bed1fffd0ce", + "e5c7f0d7f8c95c7c7d03fe380d64e88a3f90ab16c99581ca6c8b1ad50c1b7d50", + "96fc7076f48efdf9f3c7b759ec3267c92de82cade719d60631296390644da0b4", + "cb3d98c07ce36ec8270996045b98fb02fd6c085ef8736082712bfab9d9488fd2", + "1fbd89b22867e3b9088823d3f17418a0cc3bef1d92fcc26a8586c09baa059993", + "1d1180d7417a005830c815c09049772cf467e06b75c2be15d453666b3c1dcaba", + "4f72c268a1fb93f3d00d7557e78f6ed808a72ff3c607c7959fc5a0e797da338a", + "b442d97c19f1ec9b59b12ec2cfceb7f81e6992732848d6f8f1327ca546eac17a", + "9234090bc1f88d6a6ab5d4cc7e48f0d881e9675dc1d124d08d0ec7ded15df3ba", + "1fdde92a852e62ac718262c29f96cec3bf0064cbf652322c93debf51a9d96e12", + "86b53ff4f5a60140acb628af2a03561d8dcc04c37438ab0232e5bb0576acd8ff", + "12d88cf7c78b1bd8d46be840d82fa88429e1ad482632e7a8d32844e755d3bcf5", + "663f91d696d2d677be0fc427596eeb3a2efeb8ec64aaee9de58f1de7932ed0e9", + "05d6118b796b01d5207680032313faec0ad7b6eb469d0fd34c3969b4408923d2", + "b24d19b0b280294418c608061edb9e34fc4feebc1772df58b75114d26e89be24", + "2f1ae4e802680c206ad7745022480560b1dfb9269a2efb261db8abe2db709d08", + "d3475b16326f351c7b0c89662314af1f216e942b30655e6b306962defa2c3808", + "bd872e811a371944493280e479de5a65b7dbac782af10a012d1619845c206df2", + "bbeb22a7e1f686144ad4e9ef27f2825b8eb705e078867d15f3dde29c181d28f3", + "513c93ae98c0dcb1e8101597e2ff5d514f044094bbc58654104c326d3159feec", + "0808f0a1f30a648c7cff83b1832f70135f7b8865a7238196023d25ac6338d335", + "26bff61efc6d24311a76df110be3511f765358047cc59c18915e7cd2a50ee707", + "5634513e4bc17a2741288cb7c3331a8f8275093fa7d9daa533798e537b523caa", + "a97a3936e9160ebf4353b7886666abaaf7d6217f7d05090cbc5734876b6188b8", + "980ba69443d9ac02f7627b2675050cccd7a2e4fdd5c54227c31f8091ae8c4ccb", + "376fa9599fcce60d3062c6e17c1ea27a830d988b9733018921d30d4c58898655", + "34756ca0b8dacacdc9cc5a2c220d68a4708abfa385bd9d0f2ef2e65835570d65", + "4a8bc0af6e114bdcbd0297d85badb1c2d0f84edabf30b16add9b8a73edc243fb", + "ecaee71f1027af54ced273e0c60ae96c02848d9d1ac1b13bed946df807b43933", + "d680a9be3bdce311601e3265f6ccbeacb161f247297c14f02e4f5721d656e776", + "dfe56bb494a981306c641256ced860f1484cc606108b4fe4ece4af484ca8c750", + "96429bfb6f77fe047743edde5a738c93f6468955ae48b07863c4282a8eaad83c", + "d024b227ae67afc8c565633f1597cfa6c0db4fd34fa0a456e0afbf2351fda40a", + "3fa7502e0394dc425087f8de6b66cc7b24a6bbea445a4f588d8ecf2791c6247d", + "b7dd43ac0332464f9d148aa0646f005a7b1bfd9dd291423e8d88797f972566dc", + "16527d3fc3111bec05d59d064bae03ef95b066b90993a73be5753f3fb02af2cb", + "6aa0cdc45c0155ec3e40f7d10612a54508e2201ae494ea23541309e1dbb51800", + "a3f4a433d7b699d3c825b9b796db6c7e3b05ae20943b753e644bb5972c654a1a", + "49e9434630bab3096c095387eaea2b079401b78ccd1b4c062c171ef6c5728539", + "39b82ea92cbdfa947df9edb826b47de57474fbf5df3328d0b01ce9d888c8a475", + "19be212efd6b6233a9f4ca64332ddd86796b6232ad488554ec9ecaa5e90ed2d5", + "b5473a45f4ea04ff47723387ff9483a1b92a9052d6df1ff7cfdab1c9dc9c0400", + "50428b1162a82b268dc44a91c26ded7103a003e7949ae43a777775732ff431f0", + "ee7b7118ecbe7fb3bbd563d86e7cea2fdaca012fff2aa58c1b66691f2c972f10", + "13b4ea13e5458c58afbe3b8096fcece438a95b3ff36512f2b522b2798ecd91c1", + "b90acb22538583c6ea67d6f6f88675208fe6a0a407dde3c0c9d2e83d11d6dd9a", + "9723e602bf0356d724964c5b8ada0b76bce6cc6cbe65ba58341b5d318c744cf8", + "2927929a85151cb12c8453cde70ca93fb1a4cc12d89b0b53ab1638b42a86ad3e", + "3d178a692010e23ca59fae48d7f8eb6f1c118bfcf994f775e0a2994af9754d81", + "eb211e6e24e9df075fa5ec02a895097f71a6d12d1a9195f696f01cda4d442711", + "470d382735e91f7d00c5a5f6b87001a994ce44b03cc2c6a8d6690ab43dbdd3d9", + "c5796f11c306ea58f55351632943dc6b0d5f37c3bdf6507d3fd58d3969532c74", + "23670a433d526602238896a1c649858b4111b4b611d2de51da385dfca70c0e7f", + "6a3a57887af0692bdbcb54c5eb8810cb4e75cbbec74287bef7ffae14b29e2315", + "026f510203afb367f89ac7b2b768981c9f24f243341a4b123fa91731a41e2cb4", + "79301b5e19292526557fcf29b2fd43a8d38a26821e04bdc45032b6fc2651aaa8", + "f959e5eedaf064a86f7c06c2a022dbc12877145c5b3dfe4fe7c9cbf36d8c72e6", + "7f377fb34d64e0e43963d75def1a4f6d6803a39ac4b44bb85e9ef6da1ba8698d", + "6e94e4c8a97057df83f0a0bb33f477203ea81fc5848d6c29fc6edf7836234e09", + "24a876ecbdd1320ededb2d789a8ff89f3abed12707dba7a32306fcf4f21293f4", + "e3ce735250d41096d96166ef35bfc3b00fc7661303e58e4c69748b987daa8b05", + "2a4e89064976aa4714732de8a80b8b2aae4cbbfa327604b28804bd9a38aae372", + "8cc5caa448e61538e8d0f356448fb196aa4b5e39747d4c6765fbb66f664bdc8c", + "979046570f707eaf56759b596b8a77746a6cfc052a6236376dc3d81332e7719f", + "70692e759fbed47e844692b5703ea53ba4621f4097597cbb57dab4705e2b5257", + "538c63d020dff951aaad1a0e0d1537199e5aa02e82abb7b76377ae1f0ad8e3c6", + "1fd265a951b44e539d50803f262f1471c4e3548d2d4aebaaa29136e6843bfe03", + "2e92a462b4d12d25832c44ccb200de3b5772bf2f2395ae49a5a4a87987ea1279", + "51a88021ac36bf733bb233332a558664139e2ef217738d5d6c7cc5ea4016a820", + "1f368e3689d28deda79979dfa9d67c62c676d64143018fd1d08e9f00287446db", + "c15c82af630405ad2034d500152464ed175a1c25a1a218a47e041ea5bb201762", + "8d9ff3aba5ff48eba28979c0f780793649e3d9e8811ee5de99d581ed94d02349", + "66ad89a593b225dd58b84faf1865501bca2fc3d26cb915a29033c311858d1ada", + "9db3ac2a2f81c697f56f4692dfd48a1081ef1181a0a8a67844223e065e111249", + "e52b84ffa5dd9e17e29c2a664fd424b5be8e8bb915b08278465ab41ba95c92db", + "556090f52e0286f1ee72a6ae83497dcacf6734653e685b87c29f3b797d2ea9da", + "07d29f10beaea55a935d0e05ebcf56f19c83382ede3452e1517b928fc2c53207", + "07e2c579c0b9c4b6806b7d4415dbe0428a74bbb53e326dfe4555a8e08720fd1d", + "f5f7fee61973bc8e652cc29efca0105cdbc9ae8fb93e486ad4b17c082b7b8b25", + "1b0a15da9484ce6a20e0cae3fdb0bd20cd771f6512cf53c23a23576933807e95", + "80bc919a09eb06085bb67447008db084d51e5b7e0bad8175bd5fc93545d3d220", + "c532d7b653886a9ce919615995855b57580a88136ae62ba387502f05bc1a5364", + "73945f057bbfb8ec29d38564e74e3f0fcc446157182a16179f132e84f3f72c28", + "350f84870fa808feebcc27bdabdbf79e2aa89ea20adb3c5ea57241243d73b3c7", + "9966dc8e1aeb303d3304bc3ccaa093a415f08e5eab8419db27d98945da8f0900", + "89a6a1f39f1aabf0a9db6cb3139fd6cba487b4f33abdcfcd9c9508f44047f6b1", + "2f30fbe0f00ecbb432ced49089dc9e8ad886cfb7e57a0f31ba7dc44cfda79cc0", + "2f53b1dded2948e574f6791b0219badb01aeceb4733c0fdc97feef4fb430071e", + "3e40c211ba7150dc28583266540d727fee90b85649db0187ef0126f1600a9d3a", + "9f399461a3ae5bf0afc4094b257b7e61f81a818b8e59d10cd957924a06dffe10", + "a3d85d113aab96770b0ccf7c6831177eb0d8fd0999e8fae936b28b4bca49cd96", + "71e38af49562636634633ef632875a7edaf0a54b34172c3d6426b15caee82b92", + "b1b09b45bb3be9f7bcce3e237b309aed3320b1e74df32ab7c4a304c30e606685", + "33682404bd89a9112120093fe1d242be9f3145800abdbaebe511d4cc37b9d56d", + "865a9fda430799a32c7403d7227736f4a6cfefd66fac69d98b18d82a2ff96e56", + "2eaaa0c88e7ebd0b355e8cdb88c217583ade1c88abdc740e5fbc8a392cafbda9", + "9c2a6950cce618d0889b79afbc0ae5fbc207de5b3b63c972ff3f705b34e18cb5", + "f0c607bfeb893b4817616344aef0d41367c49e4ebd97e9e96ccb4518705d32cf", + "93161443d2a91de31c77f11a1974e3eca75bf0d76f64a577733f0f4f7a583b8c", + "f1f367c7a65cebfe9ce1aa7ea14230f68e379fe0f7ef8f39c07dead599106b46", + "1aa8024e8ac3c3db778fc5cd3a3ffa0ae11fea60c13ee7e0b5e1ff3e1b2ebc1a", + "81779de0a45cbfd5e996ba205699e912c2f340f2ffce13c2be78d7ee2a549396", + "f03e3b2e58404a9dffb84a56ca57b2200097c5344a162519d6c2064db3888712", + "8e67196c99d9feecf89d7f1fa93d7a9daab329d76239e39503eb2caa0849f16b", + "d0f0502e9c353d3c5480dce4ef367a3a40d1acc980a18832b020f7d33b08054b", + "c7fe59aa811f4bf9adc8cc5e7f2a0ef83a06d4987ad0d01e83f668680e68f5b1", + "21cd2bfffd9eb56ea5b0f0f3e3d6fe52544e1128396607523a93c021501a7a0c", + "41477e5ae9c404d7409d8ecb6de2003ce0a98b7e8bc9003befbc7f9c76af01b8", + "5216f1932e76821329f9e65f09f492c66375b31293b3776b8bb802ea75847389", + "5e01b4dbe7d1d0f62aca065f806cca2ad44152eb1bfe20455ee94d4c00f040c8", + "265fac259d2c99dde1b5535900f02049cdeeba7532d1d10a2ce4bac6413cafde", + "5688b70bfefc02a09863ac620bdd356d8eee9387cfca968284e313d5bf6846ea", + "8d23bbd3cfa366fd41db3f67e612c927e9f8041237140f1f8a69d4c54afab7a7", + "c4757e43a20db4c5616d01cf6090d64eccbe278724efedaf6a05d1434d405c29", + "a183b52e98d9b81237c0ce4a82bb4be5d72e29ac7dbebcf7ace721697ca56277", + "4a85acf4ecb2f20549cc14a3d8f7de03055119f91e87a7a04321a1689de5bd1b", + "72e0d0589c1798bb879e0349f951e5f6e5f851a97e32434e827a219422cf1c4a", + "bff26f7ace1f4f6183dd7bcb2f17c3a755029d53ef927da938803baba4655395", + "6f041a2e97e01cd5fb2c64351cd13a2b6226f61674164620d97a567cc8751f57", + "0b9a5149e9c6b88f3f94381ddd06c104a7914888b22c5f950c51bd057e9c7517", + "ef6ea39f3fff99b82a172ee6e0b67d150ed598ce3638fba74ba1d6b4a59abccc", + "b121a6da1e04d245d836dca7e1ed84ef88263fd33e102579da5e443713a76c77", + "c4c517006245d2fe1cfd9115bae2cc88d9ea4c831aad499acfdb2b03a0f6d43d", + "d3459100c146be5532bcc39cdfa7a56de8356ace548c9d2185dfde31d73d9828", + "a6da7f6943e8d8c2e6709af64b37e6780fae1e12e6220ffffe0427ab89012687", + "7d98f3ed4fd3d54f44081aa5ccb75f7fa3e6bf5f0a81a7f8c70cc9531c155c76", + "700ac3b1dacf3b7859916fb2d8485c073189b404aa58a8ebe65a53b3366b52e2", + "a85a19975ccf26e88a785c4269aecf24426e1eb21a38496e64fa27cd9abf302c", + "1e0c34184d22d78bb1e3ce1a7a5d689527d9f2605bd3ba1862d77839750dd5e8", + "506abc7df4c17d1c08ff0481ef67495997054233c7b7969317e043c2d1b75c47", + "49ed81273501b8d828ec48927bac10f3f502a978a91364660dd7a353a6f9f8dc", + "1a235b19ae2cc5af96010cdd5c5f1f4d39e57c62d1770d371fbba0d61ef0ca38", + "860fc8989741a813402c56b5b80763abae04a1d1cfe1e1914774f04e76e8a4bd", + "4837aa73aadf70feea9c528c4ad9ad255ceadd3e68cf89b28d41f798d31b42b5", + "242ad8941a424ccfe4272d4b72434a752dbd476a536bda5b97c1269e2152fe3c", + "00bf429b3c9335c37925911f559dcd08b0fac8197f97501adba0274ed111cb4f", + "4110571c39f2791ccc900f9a6bad7015a3ae5ccb4acdb892bd7987a99e77e96f", + "76aa16c1c06496262be78469a72f45ad225c3e543568ab799fecaea29e4128ca", + "4b8031f56a53a49f04c7b7bdbf835cce3374c910172bc038beb554ab5a98792b", + "850c74514ceb171ad750888e1c1818e29ccea0c26367ba4bcb48402955bd1119", + "92f3a3131a80fb5f601524d3a1581c607306ba0b62b454a386085f34c6235075", + "5f4828afb9cdcb5fafc9e903d336442f1e72f6da855ffc95987abdc74c6f6a60", + "93e918d7b04dc93deec94e70df7f60da091e8a0e137e39c80a1f2b495ac393b4", + "5f2fae9dcf6a4d01a385e9c890e18f963ffe2239fa7af3e7ed4ac42f4565e7b3", + "4c5152a6c750dbd054724338a2fc95c2dfd76de7a843e0eaee3de41d98270653", + "7139402d5eae33bf27f7f59258a0e5b4125ca5a1f0b7b21ff377ce6bc8064a1a", + "7fa8d8f34644c45d127ed7cba73d03b0010bd949605be0932ad6195c2d7360a1", + "3f6b3666b2b7d56f0781ce4564ade126ca476b7abe75ef805a0335f634c43114", + "85e9199bd0002d451c2e7dd40e26365fa4abe3065f08521490a8721feddf5d8d", + "7c11e6c848ccfafbdb4ab2c250715b83f6263dc846a881cb4f64efcc929f44e9", + "6dac5dc3ea066d839eec91c0aad4364ebe21d1d9f4e9f1b5d338f12460c4c14b", + "c279a1737d782f92202fd61e65cb3b455894b7d7964566d7aa6cffb44e3b4655", + "e5247e3dbafa154dabfaec38efa90cb49487c09e4f3b1fae39eb34d57f93b630", + "8acba12c549593ed98164b8f361038290401da05c6da4eaa2485033128525472", + "b028e157cb10a1e39d215b312b5c05f61d017186253bf8d5ae4140954f3fced4", + "bbe9470ff655a093c0bbcf60d8ffd3332089eed859d25b317568a054d323e905", + "d5fb77639aff3fc31833a08cf12355cd41f413d39023f2aca216e3721ac2791b", + "e64aeeb2b9776ff4a7634251e307e74169ce590493e12d8972932d21fa027758", + "d0f75fab510a25ade85ebe9ef88565a531616066bbed105c05f37e71714e5dd9", + "04b8ae9b59d2b0502d71973de73b9ad2995b72d0e034288f1d9c4426de0bc9f1", + "01c265a397c7272bb8dfa4c7118be6c56077e4814ddab1c9effca79e230c1b57", + "b66a734c8f6e5187fb4f22867193e10e028b5815c57f8e234ff3e87131b057d1", + "397b0c95587811f93b4d59e6f6c9f41ca2f47523fd6b790e0251e9710f9542db", + "4377090cdb3caf3c0d6c98c03c0688cc8e4dcb614f93cd05ecb75b6653dba250", + "5a7bfe755339cd4caf23541a78a4f77089a28e0056b6b2054060cd1296d4efac", + "360be101e14aa72bb68f43c7e2354f39603cec887dc760eab563a7a1ad52b625", + "d4c2dc927c5ec1276fff529ccc4b3603b6538063c2478ed29b7945227cafd026", + "233a94cc8b5a99975bc37c87f8c4c969686554a1b2c07dc1d9e35d2c5cbaf2f2", + "d3be93c2b047eee5fd7b99e81a65ace8bc63f6e72f8a48a07a15c870b05ab1b5", + "8ea4ffc32f1ae4593a08b166104bc6fc52f9cbec46c48596418f4a40c32a3c94", + "4754036ef5b82fece6893c1720142306501cfc1a78dbbbb7ab9709aa6448b12f", + "c48119e1f69a1fb25906ad019ade9302c1b8b4236bb188360ddd2faf55e0cb55", + "1b6566624a80db12fc36b39ba7474902afee1c829d5ef7b8d7b4bdccd7082e7d", + "b22eb830efd1be3801a04a36a83a426af2ce47556086cb5f29cc61212dea754a", + "6f877ded0580d101276e9834b9a67d73e4cdc75bbcf82d85544c21b869eb70b6", + "7db06abb974a4fac17e1675ff3b052b8843c62ef037281afc128a72a8c9641a5", + "8bdc6bb5293685cadce2b1adc12aa2885729c2eea979bfede9a65458d3ba562e", + "509772ede9a9e8de48759d17f3e6eefcc4c2cbc4116d7ff0031c3eea299530f8", + "1939a5b666d342d25df097ac09fc761774306b07edf4820f1d6e0d5a4c51c98a", + "7964958b762f44769117ec56ea2b56ed6d7a28b09ad3ee418a7a0a487ca78c52", + "ef051ed648549c6c33a25ce06c5d9f75793225af791ffc6f4bd2547c8950fadb", + "1bc1707662ab5d13f6c23702ead302746bb8ca7fcee2b347b50d363c89d6e24f", + "43cebb99c9eefe0408855580bae106b5a96a2b451fa4ae088befad49d7be0e54", + "e4a359f91eeb141d1eb9e08962556aa2380641394d1ebf37847d994059f6d463", + "310402abcbb95ff7608d5e8c2f1cf54602ad5c88d640b3e492210899bca2d366", + "1d87cbdec61ccdb6ebb194659d67acf90b31696cda4bb2a603332cd9d03e9228", + "f03a16783ae7dfd6717f7fbaa220cd252f1bbd40a9d55ec358a0461ce8ddf9af", + "b599c2a2d2abbb05c4d6fe4f1c2c8063ab1cde73a8e0c1db0a651a09715b74d7", + "5e674f21ccdebee3908155e5982a804e6c0486cf4d677c633d4d9df1cf6673ae", + "7c59967de7d33d98ab5bc95e7a603f29782eac9bc6196031f8975030cca842db", + "9998c5b93b0206b678c48fbc765ac0c3d4fb78cff7d5900851e4400150a3911d", + "afc6497d3d83352503fc907f474fa36652f9267101ffa8562475a5efdac40019", + "5bd502c7eb4d52c2e67f32270bf75bba9571d32ed1f7dfabbf7452031ce0c871", + "3670362671c5622a267e435b2d7d100427fc2ed6a4171b486732c946ce1f9ffe", + "f7bd0bc57bdf8b92f6ef256a62c818c88cdbbf4e900d1b00a2327968ed5c1add", + "956ba0f143d05730b22e8998c7e1ea387facedf94205fc363bd2dcb18820cb5d", + "15bc9d0decb2202cbd6170e029535e0e6439c5935ff48e3bfdbd8bfe5ba589b5", + "e60178e9edffaee6ba5c40988b776b9645fb2c26f0e9f156e96031ff96183e60", + "e984ebcc87156118528bcd4b2fb4e2fbcd878ff821c48549c6d8b00917ca8fa2", + "d8980534c57370ce86b26b851a3db654aabcd354f32a7a3c4cc9f1443d272301", + "d9f1e12ad3af15065bbc8de881226d5fcb9dceeba0d31ef9f594113ded5e232e", + "b9159477fa7b66fefe61fa428057553f6cc0fff19c7708e769f9ffe826905e52", + "e380e51f9d48e9287ba16571aca06a6b2cbe6ff0cd2a6a1dfadc48f57fc928c5", + "0031613b88897c54f9bc9a964d168690f363405d5ad3ac54785967088f70d0f2", + "de20434b49dc7068d82f6d42dcac51025e9a75d95cbc81990402da342303f60f", + "233cdce058ed019d625d8a8166e5dbfda5bfcec43f17fea3792ca3fae2ca0058", + "30f8fdc3b151a06ea92b8fa6e63cce087325a840ad8015be5da2bf19de8c62f8", + "4698cb69ac5fc6eb234a89e481d77110933efc5328b025b4c15bd03fee582ea9", + "3368d05b629e42eaae1c6b10b57d99143782980d3048467f40bb1a858ad51d17", + "d17585bae8ce6c54827132fa7b7f5405c4ae46095910829f07ed35f857618122", + "cb3640fd0c3de7022f21a10267767b38c33be6ba1d99b69e6cae92956d6b6c0d", + "37f68d29dc6cfab38036bb1ed89b8c75ca7db4e2e9fed50904c7de0316ea8ca4", + "d275a97c915d828420ceade2c78ebe2d15630a35b1116db10f612b8b34728852", + "048a521b5c675e5fac1dae87eeb589ff45f4f4564fc2f4257029d7af22bb99e8", + "250895d167aaaad4a21a5911d45bca81ac78896f9dcc8e59a2080eabd756c874", + "19c6fc95d36f09b9a82e11b56472e6fd45a44ea91eef97bd508b67333344d5ce", + "da8f4aa466557257c33173e72c073aa23df4525b90150b0ff37ccb3c4ed7a52a", + "b5b08d0e81f8f79fb0405266fc23df850e65622c6f279dcac1dc97b944ab84e7", + "6e3a2100f0d99c805b046a0b51da08be291590b815085f35f806cad2f007b9aa", + "3299492ee4308003ca188c984bffc7692a575a217f3aefa613c4cabfa614cfa3", + "bf0dddadff431d9777194f5675959d61d2ace4af20ca2195238f2c83f3291f60", + "a618f5c86b6ff71bc6d305d884f2b1b1121c0b91ffe06659209167fecb9e08c8", + "a5dc72100176b51bd1dcd2393cff0fa5c480933c9e3d5594321868d544cf450e", + "35a46d94e3cb243165f90ea4ebecc9f689ed5a4b4bec83d857c22defb0ac2480", + "2b8f175741559a39cc9b85df4c236deda79857507b2b7416f7896a799b6babf6", + "5e8383ef0b4b9a83a058785154064ec856bb8a5256b36baf89946b95f4fd14c5", + "f9a3c58efa0cb16ead63733e730b359d5eec56592d7ef25577ef39e9a35bd18c", + "9eb0d5d4145e404103edd44ec65223b58d8070b9ff664cc0a8bb3d519fdf96f4", + "2d27a09e2d8198dfe2120de2315bda236a321387025d6ddcd09f503e05af05c9", + "2a7bf2d14201251765fe8c58cb761908209a7b417f221608b7ba83acf90584f4", + "06f4d3abb73bf13cfd6c3fbbda97c58d7f95b7409f54dc73058d0f86b4884264", + "5ae496002d201927bcea66f6afe71775d36163369fe3ae5a8b9fc94a1ed7f4f2", + "4a204e81c99bd78411b3b0605234f218af040dd0ebd1c4e381815eb37bbd2caa", + "3df18d99c1f2294a527be07383b9763a76692b67e60efb0f963ffbefdbea161b", + "56fbc29adbe1c7c63ac471ca96eacd22f6432a4acf73453693bdc4d1ef5829e5", + "8ce0cc0b6bdcdbc8d9c354f80721ede9b755caf3e9f48e5e999484eacc5e97ed", + "55706d1b03c3fac9de657c84b245b589283936e204ac490f96a8de7e5481bcba", + "0a09aed3e545582ebc63f9ffd54d5dcb1578f2639981abd50632f022e8d7cd83", + "d64b1cc5ffcb2ff0c6f32342bf701e9c05a06b1a811842b839e1dafd701d014f", + "d846616f1a6b6c58b596618e8cb3b63acf80934dbc6a305687fdd87a2f3b02e4", + "daf1114c8bc2ae1493ee6d0b319dae391d754e72e5f3b076b9aad17bad7796b2", + "cdfa3ace396a0b91df6ecccdaa2732f194093316893e7428aa18a1a7bb840e39", + "641935952626439538daeeb3021ec414e8bc58b60cfeaddcfc603721035fbece", + "c48732dcb01ce8d4cd6fa0f4786cc5025b0a5e0535decfa7a36b4e4048898feb", + "8469d2a167d857eeb3d6f7c9c901728c966d84d9564616a5f61fc92a3f1bc2e8", + "39129694341094e0850c6535c56477b4dbc2dd34ca0f55dc82fe06274523f3cb", + "2d0f6595d3b40b77b067d711f0508a8966613802f9dd3d838bf493b20eae2600", + "0c36b0831bf84bea127e4c2615675bfc119bf928edd0609c481538a95142ba73", + "b05d349621d006d4a361aab1095a4f4088d4c9532849f596a31bd68dbe8c3107", + "3b5cf37168c68a2a5dea53f228eaa28497f16c4447ceb15e3cb80f8cf52557d8", + "94139a85d5b369575f89c95ae2ede3f0d65903713ff7ccbacb5d9bcbf0e27852", + "7ad4aa557bbcc4bfdd5c860621e5c8ffc570714ce7e25d9885d870568821963c", + "7aa61d0fe4b3965c803748b37a534d45750ab651e5928075b1f634d703986bfa", + "571b72d4dbd0b3b31e6123106a1f206027485ab283ef44e1be705c24dff70cf2", + "9d427d864d06c9ed04f27b6242cc64c715a79d9c8d8b35f950814ac4de655b86", + "3e5969a4fa77f7117c3269813f30a211b2564172cb376e82db7c766501fa219f", + "81d416de821f068b2f281e9cb1c78648117cb7f7a8fcffbd3adafd4bf71f14e1", + "9f6b5f46e6bcd6712afbfd1c433e88285998dc3f8a123938f6e9e3c4789d9aee", + "8a23c6077018951447bceebdbecccce75062bef957cb3948659ec9502e15227f", + "6eabf703f200f2e0c9f4c34e2e78f3922378136b49c534ced3ef033c8d3a3c5a", + "1da7ea6282bd56fc2181cd2cf2e3368ae4e25d49209c2ec5acd8594bd813ae08", + "f8cd446c1aa5b456b986213b26213c3e8b558218296cf24ca202f3c51c97293a", + "4007bedfba78ce6be58e948b5ef43a84f28496678319cb11a60e213c59ada9ad", + "60df9f42d2d78e23d53a94c27df0b3f3eec9bf745a845e70091766db791e3783", + "41d8ca3916b0eb9feb067f2883d1e42cddcec92638dbd18c3e7670cf32bea153", + "c179d1fcbe342b70b9ce7068d61b021ec5904fc600edfe731999cd5aea101ad8", + "9265be61255c161c1c34e92e1aff30214999a65ab6d46159239a5a63c1fcb273", + "57195444f9b52f5ce63a69e32e9b94250d55af9312d90877deeb38a5781ad472", + "8809de4198648e4bc50c1f3324d0cf6857dc0fac99825499cc3a691ec4566788", + "c92b97e04b98f9509aec741098dc604c6b50a6f82f1cc683be26feb59fb3eb9c", + "b639541e99fbec7274937ee1b44faa4b91eea56315ac6f2b9e1b1effdea7e98d", + "c73efb06f1d7f59aa9f15894472b23ac05ec8a62b078f9004c6957cb9660941c", + "888b3cb0e652d7a45016e15edb81d22d09ea3a63e7203ec64e16a65422908f50", + "0c21c208cb39089db8d7d60599bb2936e5b887872057231ed1d887eda555adc6", + "c3c4807dcad7e6f35a4ddc7f7cf8485e3906df7143dd72cfe4b19f116105c465", + "20509d15adafeb7fbe95623791d081f5b8012e65d9b4b9d7ea238111333e7283", + "4c22461397b59da75e0386a76ca6b6701c7be32f6aa948e491f09f85a5622ef9", + "0767c7ffe50b3753ca20e55ed72ef2f9c55ea86cd2903ecddef1c7b923ac281c", + "d0ea5675d8d5cb2d7a734f804e792b04fb4d136582311419b73f499498c74c97", + "f8474002434d5428f900792644e3b92e0509100aaa570aef693c3c979ccf588b", + "7a16a9a6f97f5a23b3a6ba84ef1346b368222f6a10fadf16d10052622015bbdd", + "d01bf47941a4f8659504fa94cbc58123fe0eb1e04de0ca625775cbca5c892906", + "2957534cd740f628b3486986811c0021c6124b7f75967ec0da9f91f5798204ed", + "b117a333c3a63c5d1cf398e80403264c000c8f0651120dab184b43bd35fedce2", + "77a4279e9514a9c6d71d3d0bae4505ecfbc45521bcf1bca9fd5dcc19262d3931", + "57902ab2487431e60db0b88bea7a59f908db0f929e3bfe3c03f3d064a1521663", + "3e5ec8d232a89d42026c52b46569c8c41cf19d547b3fffb8a1062ec8982de2c3", + "2e1910d9292327f2b474adcdee66d19bab4b72ab45cd52ab9988d9c7d8022e60", + "7d7e18bb507e8699a3a2712ab0fd5c17768488a223316e8a434d4e4d09203d2a", + "a85dec3e12d631b2acf91cfedabec2abc14e7e77a5e4939b3855476e5a6c90f8", + "6bb2a14d11d5287f27d693a8e09659982986dd049eb0a1b41dffc47a50603bce", + "63fcab2ee2c141e7bd8f19d816422d19ec36315a8d125299dfe25ba1c84e6632", + "04b70a41bbc8932e9725cdbc9811d724bafc42edf3b91a562ba8b02372bd5989", + "7e83487075c74c86988a22b4a46e655dad16b8a350e5b667e83998aab95ec7c5", + "4baa458f26dddf3e434f39f8b4e828914d23d4963ad308a36a08414c56e5b31c", + "9ec6d647114321278b9aa62efb60327f593c09ed8dcb5d1f8c0c77df3ec8f907", + "75ea0c59d6f31721007a3d3fc4582581d0e506f63f3abf65274cc2e192db97b9", + "f5ecf1f43626cfa475d58bd3ece43dd539f278e74e29902626fb36c85383a18d", + "e9a6c10a253c2389217a70ae184c52764c2f8e3d98e916880fdc409336ce1d23", + "b52cab8dfa3d4e2b5b8ae5d3fe170024301c1e6d967e548935578d684412deae", + "ffdc0267cddbc7c28dffc3cae1b9470d8c9aa84b72317579ec49f65780fcb737", + "819869d52eba265551c537cfb7975bbe7f910e68468463a5ee9d77bf6be14704", + "f2aed7c7bbf53929432f0141c2590b324c8a2e8fc6dbfcdd85ee79ec86a8a800", + "0a0a3361efc500fc02aebc94c07fce56bb6fc4413880db4145356df5a2f9668c", + "714d9cc62dcd1f2f2ede0591c4bb040bf6541b91fb92c8b9103c5a75ebbdf1c2", + "2a3847da236a50d8aa1ec804b33af3713a30ba64c618cd01f0c67d945833a0f3", + "c2601f54276141cd3ab4eadf626b7a0a1e5bcf296853431353c3d42b81930bca", + "73b6e2aa672252ed8084c6df42b5fa59e3d23c66229b21ec984c25b638d3c49f", + "fafe0698474f6b3e535711f67af60a75103b7c7f2ec6d705cdccd750eb1eb3d2", + "e311005cf07fe4f670b28a78081329286462a5e83df9354c986ad1e6cf20eef5", + "78c11351e61e9d12a8b943338e33d0524f42955af5e503125ae07f91886b4b19", + "51d0e56c474b0502aaef7333beb34abb8380d6d9a4d7373f877c52028316a709", } -const ropstenPreverifiedHeight uint64 = 10953984 +const ropstenPreverifiedHeight uint64 = 11180352 diff --git a/turbo/stages/stageloop.go b/turbo/stages/stageloop.go index 7cac20c053b..99d892830e7 100644 --- a/turbo/stages/stageloop.go +++ b/turbo/stages/stageloop.go @@ -148,7 +148,7 @@ func StageLoopStep( var headTd *big.Int var head uint64 var headHash common.Hash - if head, err = stages.GetStageProgress(rotx, stages.Finish); err != nil { + if head, err = stages.GetStageProgress(rotx, stages.Headers); err != nil { return err } if headHash, err = rawdb.ReadCanonicalHash(rotx, head); err != nil { @@ -165,27 +165,25 @@ func StageLoopStep( } } rotx.Rollback() - headTd256 := new(uint256.Int) - overflow := headTd256.SetFromBig(headTd) + + headTd256, overflow := uint256.FromBig(headTd) if overflow { return fmt.Errorf("headTds higher than 2^256-1") } updateHead(ctx, head, headHash, headTd256) - if notifications.Accumulator != nil { + if notifications != nil && notifications.Accumulator != nil { if err := db.View(ctx, func(tx kv.Tx) error { header := rawdb.ReadCurrentHeader(tx) if header == nil { return nil } + pendingBaseFee := misc.CalcBaseFee(notifications.Accumulator.ChainConfig(), header) notifications.Accumulator.SendAndReset(ctx, notifications.StateChangesConsumer, pendingBaseFee.Uint64()) - err = stagedsync.NotifyNewHeaders(ctx, finishProgressBefore, sync.PrevUnwindPoint(), notifications.Events, tx) - if err != nil { - return err - } - return nil + return stagedsync.NotifyNewHeaders(ctx, finishProgressBefore, head, sync.PrevUnwindPoint(), notifications.Events, tx) + }); err != nil { return err } diff --git a/turbo/transactions/call.go b/turbo/transactions/call.go index fabbcf5ecf4..ea18b1f2b5c 100644 --- a/turbo/transactions/call.go +++ b/turbo/transactions/call.go @@ -172,7 +172,7 @@ func getHashGetter(requireCanonical bool, tx kv.Tx) func(uint64) common.Hash { return func(n uint64) common.Hash { hash, err := rawdb.ReadCanonicalHash(tx, n) if err != nil { - log.Debug("can't get block hash by number", "number", n, "only-canonical", requireCanonical) + log.Debug("Can't get block hash by number", "number", n, "only-canonical", requireCanonical) } return hash } diff --git a/turbo/transactions/tracing.go b/turbo/transactions/tracing.go index 150b251531e..66ea3420f6c 100644 --- a/turbo/transactions/tracing.go +++ b/turbo/transactions/tracing.go @@ -62,7 +62,7 @@ func ComputeTxEnv(ctx context.Context, block *types.Block, cfg *params.ChainConf vmenv.Reset(TxContext, statedb) // Not yet the searched for transaction, execute on top of the current state if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.GetGas()), true /* refunds */, false /* gasBailout */); err != nil { - return nil, vm.BlockContext{}, vm.TxContext{}, nil, nil, fmt.Errorf("transaction %x failed: %v", tx.Hash(), err) + return nil, vm.BlockContext{}, vm.TxContext{}, nil, nil, fmt.Errorf("transaction %x failed: %w", tx.Hash(), err) } // Ensure any modifications are committed to the state // Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect @@ -140,7 +140,7 @@ func TraceTx( stream.WriteArrayEnd() stream.WriteObjectEnd() } - return fmt.Errorf("tracing failed: %v", err) + return fmt.Errorf("tracing failed: %w", err) } // Depending on the tracer type, format and return the output if streaming { diff --git a/turbo/trie/trie.go b/turbo/trie/trie.go index d525ff994d4..c664870aee3 100644 --- a/turbo/trie/trie.go +++ b/turbo/trie/trie.go @@ -720,7 +720,7 @@ func (t *Trie) HookSubTries(subTries SubTries, hooks [][]byte) error { return fmt.Errorf("root==nil for hook %x", hookNibbles) } if err := t.hook(hookNibbles, root, hash[:]); err != nil { - return fmt.Errorf("hook %x: %v", hookNibbles, err) + return fmt.Errorf("hook %x: %w", hookNibbles, err) } } return nil diff --git a/turbo/txpool/p2p.go b/turbo/txpool/p2p.go index a8e380c828f..1243cc4084c 100644 --- a/turbo/txpool/p2p.go +++ b/turbo/txpool/p2p.go @@ -51,7 +51,7 @@ func NewP2PServer(ctx context.Context, sentries []direct.SentryClient, txPool *c func (tp *P2PServer) newPooledTransactionHashes66(ctx context.Context, inreq *proto_sentry.InboundMessage, sentry direct.SentryClient) error { var query eth.NewPooledTransactionHashesPacket if err := rlp.DecodeBytes(inreq.Data, &query); err != nil { - return fmt.Errorf("decoding newPooledTransactionHashes66: %v, data: %x", err, inreq.Data) + return fmt.Errorf("decoding newPooledTransactionHashes66: %w, data: %x", err, inreq.Data) } return tp.TxFetcher.Notify(string(gointerfaces.ConvertH512ToBytes(inreq.PeerId)), query) } @@ -59,7 +59,7 @@ func (tp *P2PServer) newPooledTransactionHashes66(ctx context.Context, inreq *pr func (tp *P2PServer) newPooledTransactionHashes65(ctx context.Context, inreq *proto_sentry.InboundMessage, sentry direct.SentryClient) error { var query eth.NewPooledTransactionHashesPacket if err := rlp.DecodeBytes(inreq.Data, &query); err != nil { - return fmt.Errorf("decoding newPooledTransactionHashes65: %v, data: %x", err, inreq.Data) + return fmt.Errorf("decoding newPooledTransactionHashes65: %w, data: %x", err, inreq.Data) } return tp.TxFetcher.Notify(string(gointerfaces.ConvertH512ToBytes(inreq.PeerId)), query) } @@ -67,7 +67,7 @@ func (tp *P2PServer) newPooledTransactionHashes65(ctx context.Context, inreq *pr func (tp *P2PServer) pooledTransactions66(ctx context.Context, inreq *proto_sentry.InboundMessage, sentry direct.SentryClient) error { txs := ð.PooledTransactionsPacket66{} if err := txs.DecodeRLP(rlp.NewStream(bytes.NewReader(inreq.Data), 0)); err != nil { - return fmt.Errorf("decoding pooledTransactions66: %v, data: %x", err, inreq.Data) + return fmt.Errorf("decoding pooledTransactions66: %w, data: %x", err, inreq.Data) } return tp.TxFetcher.Enqueue(string(gointerfaces.ConvertH512ToBytes(inreq.PeerId)), txs.PooledTransactionsPacket, true) @@ -76,7 +76,7 @@ func (tp *P2PServer) pooledTransactions66(ctx context.Context, inreq *proto_sent func (tp *P2PServer) pooledTransactions65(ctx context.Context, inreq *proto_sentry.InboundMessage, sentry direct.SentryClient) error { txs := ð.PooledTransactionsPacket{} if err := txs.DecodeRLP(rlp.NewStream(bytes.NewReader(inreq.Data), 0)); err != nil { - return fmt.Errorf("decoding pooledTransactions65: %v, data: %x", err, inreq.Data) + return fmt.Errorf("decoding pooledTransactions65: %w, data: %x", err, inreq.Data) } return tp.TxFetcher.Enqueue(string(gointerfaces.ConvertH512ToBytes(inreq.PeerId)), *txs, true) @@ -92,7 +92,7 @@ func (tp *P2PServer) transactions65(ctx context.Context, inreq *proto_sentry.Inb } var query eth.TransactionsPacket if err := rlp.DecodeBytes(inreq.Data, &query); err != nil { - return fmt.Errorf("decoding TransactionsPacket: %v, data: %x", err, inreq.Data) + return fmt.Errorf("decoding TransactionsPacket: %w, data: %x", err, inreq.Data) } return tp.TxFetcher.Enqueue(string(gointerfaces.ConvertH512ToBytes(inreq.PeerId)), query, false) } @@ -103,7 +103,7 @@ func (tp *P2PServer) getPooledTransactions66(ctx context.Context, inreq *proto_s } var query eth.GetPooledTransactionsPacket66 if err := rlp.DecodeBytes(inreq.Data, &query); err != nil { - return fmt.Errorf("decoding GetPooledTransactionsPacket66: %v, data: %x", err, inreq.Data) + return fmt.Errorf("decoding GetPooledTransactionsPacket66: %w, data: %x", err, inreq.Data) } _, txs := eth.AnswerGetPooledTransactions(tp.TxPool, query.GetPooledTransactionsPacket) b, err := rlp.EncodeToBytes(ð.PooledTransactionsRLPPacket66{ @@ -111,7 +111,7 @@ func (tp *P2PServer) getPooledTransactions66(ctx context.Context, inreq *proto_s PooledTransactionsRLPPacket: txs, }) if err != nil { - return fmt.Errorf("encode GetPooledTransactionsPacket66 response: %v", err) + return fmt.Errorf("encode GetPooledTransactionsPacket66 response: %w", err) } // TODO: implement logic from perr.ReplyPooledTransactionsRLP - to remember tx ids outreq := proto_sentry.SendMessageByIdRequest{ @@ -120,7 +120,7 @@ func (tp *P2PServer) getPooledTransactions66(ctx context.Context, inreq *proto_s } _, err = sentry.SendMessageById(ctx, &outreq, &grpc.EmptyCallOption{}) if err != nil { - return fmt.Errorf("send pooled transactions response: %v", err) + return fmt.Errorf("send pooled transactions response: %w", err) } return nil } @@ -131,12 +131,12 @@ func (tp *P2PServer) getPooledTransactions65(ctx context.Context, inreq *proto_s } var query eth.GetPooledTransactionsPacket if err := rlp.DecodeBytes(inreq.Data, &query); err != nil { - return fmt.Errorf("decoding getPooledTransactions65: %v, data: %x", err, inreq.Data) + return fmt.Errorf("decoding getPooledTransactions65: %w, data: %x", err, inreq.Data) } _, txs := eth.AnswerGetPooledTransactions(tp.TxPool, query) b, err := rlp.EncodeToBytes(eth.PooledTransactionsRLPPacket(txs)) if err != nil { - return fmt.Errorf("encode getPooledTransactions65 response: %v", err) + return fmt.Errorf("encode getPooledTransactions65 response: %w", err) } // TODO: implement logic from perr.ReplyPooledTransactionsRLP - to remember tx ids outreq := proto_sentry.SendMessageByIdRequest{ @@ -145,7 +145,7 @@ func (tp *P2PServer) getPooledTransactions65(ctx context.Context, inreq *proto_s } _, err = sentry.SendMessageById(ctx, &outreq, &grpc.EmptyCallOption{}) if err != nil { - return fmt.Errorf("send pooled transactions response: %v", err) + return fmt.Errorf("send pooled transactions response: %w", err) } return nil }