Compare commits
241
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4615b01723 | ||
|
|
bb56ca245a | ||
|
|
2c00b5db3c | ||
|
|
813d133c24 | ||
|
|
dd667d28be | ||
|
|
8fec6e31f2 | ||
|
|
a34cc5e4e9 | ||
|
|
afa95681af | ||
|
|
a3417e7488 | ||
|
|
6ae91467e6 | ||
|
|
717d2a0eeb | ||
|
|
3d5bebc2dd | ||
|
|
7214abfa3f | ||
|
|
5519b15d69 | ||
|
|
3283cb70a7 | ||
|
|
00535fe3ee | ||
|
|
ab81d4c1b1 | ||
|
|
73030c13dc | ||
|
|
003d32a1d5 | ||
|
|
231b2070d4 | ||
|
|
3407848e8c | ||
|
|
1ca071ef77 | ||
|
|
03344e168c | ||
|
|
867f9bb751 | ||
|
|
41f611a286 | ||
|
|
8f39834413 | ||
|
|
829311cd80 | ||
|
|
c620ff8c1f | ||
|
|
7e6b20cd97 | ||
|
|
82625e3fd9 | ||
|
|
f74cf00be6 | ||
|
|
bd59bba6f5 | ||
|
|
4a165b3551 | ||
|
|
7c093485ca | ||
|
|
81ce7a44ef | ||
|
|
f8831834d5 | ||
|
|
ce35422fb7 | ||
|
|
c61a740398 | ||
|
|
8a4290536d | ||
|
|
55117a779e | ||
|
|
814c16b60b | ||
|
|
8517e71ff8 | ||
|
|
7d8b9ed613 | ||
|
|
a14183e8e0 | ||
|
|
a3a2dba314 | ||
|
|
bef644cf6f | ||
|
|
d16456d4cd | ||
|
|
8690f93b1d | ||
|
|
7839b957f7 | ||
|
|
2c57c51753 | ||
|
|
aad537a4ac | ||
|
|
ba89467716 | ||
|
|
0b0d7c96df | ||
|
|
e73b16b804 | ||
|
|
c273cbd467 | ||
|
|
a1d260e838 | ||
|
|
b78f9ce342 | ||
|
|
e64a361097 | ||
|
|
0bb609324f | ||
|
|
b5a9607a59 | ||
|
|
af53e965d2 | ||
|
|
b11bd31144 | ||
|
|
73230b6021 | ||
|
|
320849653e | ||
|
|
d37697f5f1 | ||
|
|
94cbc8340e | ||
|
|
4bc41c887f | ||
|
|
aea0718ef8 | ||
|
|
1d832e4b14 | ||
|
|
84f9383061 | ||
|
|
cd79bcf52d | ||
|
|
6e026180a1 | ||
|
|
767f8ba85d | ||
|
|
44e0435f1a | ||
|
|
59873c7dcf | ||
|
|
92c3b0a42d | ||
|
|
d5fd4cdcc0 | ||
|
|
9b4df6a4d0 | ||
|
|
06d288e92b | ||
|
|
87105b5121 | ||
|
|
4645f25d8b | ||
|
|
1419bec03d | ||
|
|
5a710c3dd6 | ||
|
|
80039b1bac | ||
|
|
9879c8c976 | ||
|
|
369a4c4bfa | ||
|
|
ee5cad3796 | ||
|
|
943bf8be2c | ||
|
|
808a6e9226 | ||
|
|
22e0291fe8 | ||
|
|
3f5450fca8 | ||
|
|
a1562c672b | ||
|
|
4dd5886e3d | ||
|
|
fac122c358 | ||
|
|
dfd32620b1 | ||
|
|
b97b3361da | ||
|
|
9fd5721de9 | ||
|
|
7344dd5eb3 | ||
|
|
e6dc720224 | ||
|
|
5b5dd525f5 | ||
|
|
410bdc389e | ||
|
|
292e19893f | ||
|
|
ef070faca3 | ||
|
|
3b280ce269 | ||
|
|
fbb575975f | ||
|
|
ae75aa1d0d | ||
|
|
fb3c16207f | ||
|
|
dcd59ce587 | ||
|
|
66c1a0a0f8 | ||
|
|
a75f3b7acb | ||
|
|
fbafe1c507 | ||
|
|
24a714d123 | ||
|
|
b243c405b4 | ||
|
|
cff785fa37 | ||
|
|
c0c4e6bf35 | ||
|
|
02929dd166 | ||
|
|
12b30c0069 | ||
|
|
b1228b51ef | ||
|
|
9d58fff806 | ||
|
|
d121760172 | ||
|
|
e8455567fd | ||
|
|
ee0152fac4 | ||
|
|
aaf80542fc | ||
|
|
b67d1563ed | ||
|
|
7c0e9ea5c7 | ||
|
|
d8b63c738c | ||
|
|
ba79d56b30 | ||
|
|
71ba2e4ac4 | ||
|
|
3a74a2422a | ||
|
|
56b0348e87 | ||
|
|
389dc28860 | ||
|
|
29fbfaf13d | ||
|
|
5f593b3ae1 | ||
|
|
ad8cfe1da2 | ||
|
|
64a9453db8 | ||
|
|
72c5a9a574 | ||
|
|
6f9e02fd73 | ||
|
|
51266c3125 | ||
|
|
77b6b7ef10 | ||
|
|
78f54fa3db | ||
|
|
f22b314a8b | ||
|
|
d1b8af338e | ||
|
|
48a3076876 | ||
|
|
8bb6d423ff | ||
|
|
9387ffc593 | ||
|
|
3720e79806 | ||
|
|
7b473f60ae | ||
|
|
a6ae497c02 | ||
|
|
87801b5855 | ||
|
|
b6a77dfafc | ||
|
|
368278b19c | ||
|
|
21f8f642c9 | ||
|
|
3f00691f26 | ||
|
|
420f33017e | ||
|
|
6e22c08c1d | ||
|
|
84b07519c2 | ||
|
|
018c4e8a38 | ||
|
|
2d8dbf5bc1 | ||
|
|
14a7ae339f | ||
|
|
0374c50728 | ||
|
|
864eef3e4c | ||
|
|
6187f6b7ac | ||
|
|
d981baa362 | ||
|
|
40582335e9 | ||
|
|
5e76b05b17 | ||
|
|
9fc3c3351a | ||
|
|
2b367225e4 | ||
|
|
861134d923 | ||
|
|
00aad34194 | ||
|
|
7778fc2473 | ||
|
|
0787ff3bc3 | ||
|
|
46a3150784 | ||
|
|
1927b26abf | ||
|
|
444e75ef77 | ||
|
|
0e26a8d99b | ||
|
|
3fd57ff7d9 | ||
|
|
a791a795e9 | ||
|
|
5b394f0f98 | ||
|
|
e0f90274e4 | ||
|
|
1d893d6630 | ||
|
|
d64bc2c9be | ||
|
|
f1c70720df | ||
|
|
3f2d2eb659 | ||
|
|
121cd97f65 | ||
|
|
a8d693a2c0 | ||
|
|
e8570bd69c | ||
|
|
ac85a2e23b | ||
|
|
2acbdb43d7 | ||
|
|
444da43228 | ||
|
|
99990504b5 | ||
|
|
2fc2875106 | ||
|
|
c11a5bce59 | ||
|
|
49044b4c69 | ||
|
|
70cb445a12 | ||
|
|
30e4259eff | ||
|
|
5b9914790c | ||
|
|
bdffac300a | ||
|
|
10a9eb2155 | ||
|
|
768b2b3812 | ||
|
|
113b8b5002 | ||
|
|
f7c254b3de | ||
|
|
00335441ce | ||
|
|
26e9703548 | ||
|
|
8b77839d38 | ||
|
|
d23b96fc32 | ||
|
|
e5f32f288d | ||
|
|
7e40f8636b | ||
|
|
8aaa8de975 | ||
|
|
35ceb02c50 | ||
|
|
89a0b25377 | ||
|
|
2d7a9b0551 | ||
|
|
26b35b7f8e | ||
|
|
087d799547 | ||
|
|
6892c35aec | ||
|
|
861731ee7c | ||
|
|
131f87afb1 | ||
|
|
d9755dfb1c | ||
|
|
e06604d342 | ||
|
|
2a8ea957fa | ||
|
|
89dede32ac | ||
|
|
cfaeb2718f | ||
|
|
f06d67c5a2 | ||
|
|
7ef93448fb | ||
|
|
d70674c369 | ||
|
|
45eb890917 | ||
|
|
0dd7976ffb | ||
|
|
d771aa353e | ||
|
|
7c61e890c5 | ||
|
|
8ab6eaa6e3 | ||
|
|
d02b91e610 | ||
|
|
4ea712c011 | ||
|
|
5e5a81bf23 | ||
|
|
ef9a9175a1 | ||
|
|
20266857e6 | ||
|
|
14fba589bc | ||
|
|
82b13afed6 | ||
|
|
9567dee00c | ||
|
|
b92cff74f2 | ||
|
|
f3b3ff0dd2 | ||
|
|
41dd8954aa | ||
|
|
a750e63a7b |
@@ -996,23 +996,20 @@ workflows:
|
||||
- build
|
||||
suite: utest-unit-cli
|
||||
target: "./cli/... ./cmd/... ./api/..."
|
||||
get-params: true
|
||||
executor: golang-2xl
|
||||
get-params: true
|
||||
- test:
|
||||
name: test-unit-node
|
||||
requires:
|
||||
- build
|
||||
suite: utest-unit-node
|
||||
target: "./node/..."
|
||||
|
||||
|
||||
- test:
|
||||
name: test-unit-rest
|
||||
requires:
|
||||
- build
|
||||
suite: utest-unit-rest
|
||||
target: "./blockstore/... ./build/... ./chain/... ./conformance/... ./gateway/... ./journal/... ./lib/... ./markets/... ./paychmgr/... ./tools/..."
|
||||
|
||||
executor: golang-2xl
|
||||
- test:
|
||||
name: test-unit-storage
|
||||
@@ -1020,8 +1017,7 @@ workflows:
|
||||
- build
|
||||
suite: utest-unit-storage
|
||||
target: "./storage/... ./extern/..."
|
||||
|
||||
|
||||
get-params: true
|
||||
- test:
|
||||
go-test-flags: "-run=TestMulticoreSDR"
|
||||
requires:
|
||||
|
||||
+10
-3
@@ -557,9 +557,16 @@ workflows:
|
||||
- build
|
||||
suite: utest-[[ $suite ]]
|
||||
target: "[[ $pkgs ]]"
|
||||
[[if eq $suite "unit-cli"]]get-params: true[[end]]
|
||||
[[if eq $suite "unit-cli"]]executor: golang-2xl[[end]]
|
||||
[[- if eq $suite "unit-rest"]]executor: golang-2xl[[end]]
|
||||
[[- if eq $suite "unit-storage"]]
|
||||
get-params: true
|
||||
[[- end -]]
|
||||
[[- if eq $suite "unit-cli"]]
|
||||
executor: golang-2xl
|
||||
get-params: true
|
||||
[[- end -]]
|
||||
[[- if eq $suite "unit-rest"]]
|
||||
executor: golang-2xl
|
||||
[[- end -]]
|
||||
[[- end]]
|
||||
- test:
|
||||
go-test-flags: "-run=TestMulticoreSDR"
|
||||
|
||||
@@ -41,6 +41,7 @@ build/paramfetch.sh
|
||||
bin/ipget
|
||||
bin/tmp/*
|
||||
.idea
|
||||
.vscode
|
||||
scratchpad
|
||||
|
||||
build/builtin-actors/v*
|
||||
|
||||
@@ -14,6 +14,7 @@ linters:
|
||||
- varcheck
|
||||
- deadcode
|
||||
- scopelint
|
||||
- unused
|
||||
|
||||
# We don't want to skip builtin/
|
||||
skip-dirs-use-default: false
|
||||
|
||||
+88
-57
@@ -1,34 +1,34 @@
|
||||
# Lotus changelog
|
||||
|
||||
# v 1.25.0-rc5 / 2023-11-16
|
||||
# UNRELEASED
|
||||
- chore: Auto remove local chain data when importing chain file or snapshot ([filecoin-project/lotus#11277](https://github.com/filecoin-project/lotus/pull/11277))
|
||||
- feat: metric: export Mpool message count ([filecoin-project/lotus#11361](https://github.com/filecoin-project/lotus/pull/11361))
|
||||
- feat: sealing: load SectorsSummary from sealing SectorStats instead of calling API each time ([filecoin-project/lotus#11353](https://github.com/filecoin-project/lotus/pull/11353))
|
||||
- fix: miner info: Show correct sector state counts ([filecoin-project/lotus#11456](https://github.com/filecoin-project/lotus/pull/11456))
|
||||
- feat: add support for specifying block number when calling `eth_estimateGas` ([filecoin-project/lotus#11462](https://github.com/filecoin-project/lotus/pull/11462)).
|
||||
|
||||
This is the fifth release candidate of the upcoming OPTIONAL release Lotus v1.25.0. This optional release also supports the Filecoin network version 21 upgrade, codenamed Watermelon 🍉, in addition to the numerous improvements and enhancements for node operators, ETH RPC-providers and storage providers.
|
||||
## Improvements
|
||||
- fix: Add time slicing to splitstore purging step during compaction to reduce lock congestion [filecoin-project/lotus#11269](https://github.com/filecoin-project/lotus/pull/11269)
|
||||
- feat: Added instructions on how to setup Prometheus/Grafana for monitoring a local Lotus node [filecoin-project/lotus#11276](https://github.com/filecoin-project/lotus/pull/11276)
|
||||
- fix: Exclude reverted events in `eth_getLogs` results [filecoin-project/lotus#11318](https://github.com/filecoin-project/lotus/pull/11318)
|
||||
- fix: The Ethereum API will now use the correct state-tree when resolving "native" addresses into masked ID addresses. Additionally, pending messages from native account types won't be visible in the Ethereum API because there is no "correct" state-tree to pick in this case. However, pending _Ethereum_ transactions and native messages that have landed on-chain will still be visible through the Ethereum API.
|
||||
- feat: Unambiguously translate native messages to Ethereum transactions by:
|
||||
- Detecting native messages that "look" like Ethereum transactions (creating smart contracts, invoking a smart contract, etc.), and decoding them as such.
|
||||
- Otherwise, ABI-encoding the inputs as if they were calls to a `handle_filecoin_method` Solidity method.
|
||||
- fix: ensure that the Ethereum API never returns "empty" addresses for native messages. When a "to" address cannot be resolved to a 0x-style address, it will be re-written to `0xff0000000000000000000000ffffffffffffffff`. This can only happen when the native transaction _reverted_ (failing to create an account at the specified "to" address).
|
||||
|
||||
## :exclamation: Mainnet Upgrade Date Update
|
||||
# v 1.25.0 / 2023-11-22
|
||||
|
||||
Mainnet upgrade date has been adjusted due to the rescope of nv21 & retesting on test network, as well as giving the community enough time to upgrade their infrastructure.
|
||||
This is a highly recommended feature release of Lotus. This optional release supports the Filecoin network version 21 upgrade, codenamed Watermelon 🍉, in addition to the numerous improvements and enhancements for node operators, ETH RPC-providers and storage providers.
|
||||
|
||||
**The new date and epoch for the Mainnet nv21 upgrade has therefore been set to epoch 3469380 - 2023-12-12T13:30:00Z.**
|
||||
**The Filecoin network upgrade v21, codenamed Watermelon 🍉, is at epoch 3469380 - 2023-12-12T13:30:00Z**
|
||||
|
||||
|
||||
### FIP0070 descoped for nv21
|
||||
|
||||
[FIP0070: Allow SPs to move partitions between deadlines](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0070.md) was originally scoped for network version 21. However, during the testing on calibrationnet testing, this FIP has proven to be quite error prune to implement due to the complexity of the protocol and a couple bugs were discovered.
|
||||
|
||||
As the path to resolving this bug is not yet clear, core devs have decided to descope FIP-0070 from the upcoming nv21 upgrade ensure the security and stability of the network post upgrade.
|
||||
|
||||
|
||||
## Calibration WatermelonFix2
|
||||
|
||||
For the calibration network, the descoping of FIP0070 means that we will need to do another CodeCID migration to drop FIP0070 from nv21, and to get the test network into a state which will be similar to when the mainnet upgrades to nv21.
|
||||
|
||||
**This migration will happen at epoch 1108174 - 2023-11-21T13:00:00Z.**
|
||||
|
||||
Make sure to upgrade you calibration network nodes and storage providers to v1.24.0-rcx & ^ before this epoch.
|
||||
The full list of [protocol improvements delivered in the network upgrade can be found here](https://github.com/filecoin-project/core-devs/blob/master/Network%20Upgrades/v21.md).
|
||||
|
||||
## ☢️ Upgrade Warnings ☢️
|
||||
|
||||
- Please remove and clone a new Lotus repo (`git clone https://github.com/filecoin-project/lotus.git`) when upgrading to this version.
|
||||
- Read through the [changelog of the mandatory v1.24.0 release](https://github.com/filecoin-project/lotus/releases/tag/v1.24.0). Especially the `Migration` and `v12 Builtin Actor Bundle` sections.
|
||||
- Please remove and clone a new Lotus repo (`git clone https://github.com/filecoin-project/lotus.git`) when upgrading to this release.
|
||||
- This feature release requires a minimum Go version of v1.20.7 or higher to successfully build Lotus. Go version 1.21.x is not supported yet.
|
||||
- EthRPC providers, please check out the [new tracing API to Lotus RPC](https://github.com/filecoin-project/lotus/pull/11100)
|
||||
|
||||
@@ -109,6 +109,8 @@ Lotus-workers can now be built to leverage the SupraSeal C2 sealing optimization
|
||||
- fix: build: use tagged releases ([filecoin-project/lotus#11194](https://github.com/filecoin-project/lotus/pull/11194))
|
||||
- chore: test-vectors: update ([filecoin-project/lotus#11196](https://github.com/filecoin-project/lotus/pull/11196))
|
||||
- chore: backport #11365 to release/v1.25.0 ([filecoin-project/lotus#11369](https://github.com/filecoin-project/lotus/pull/11369))
|
||||
- chore: deps: update to go-state-types v0.12.8 ([filecoin-project/lotus#11339](https://github.com/filecoin-project/lotus/pull/11437))
|
||||
- chore: deps: update to final actors ([filecoin-project/lotus#11330](https://github.com/filecoin-project/lotus/pull/11440))
|
||||
- github.com/filecoin-project/go-amt-ipld/v4 (v4.0.0 -> v4.2.0)
|
||||
- github.com/filecoin-project/test-vectors/schema (v0.0.5 -> v0.0.7)
|
||||
|
||||
@@ -135,79 +137,104 @@ Lotus-workers can now be built to leverage the SupraSeal C2 sealing optimization
|
||||
- backport: tests: add SynthPorep layers to cachefiles ([filecoin-project/lotus#11344](https://github.com/filecoin-project/lotus/pull/11344))
|
||||
- chore: backport #11408 to release/v1.25.0 ([filecoin-project/lotus#11414](https://github.com/filecoin-project/lotus/pull/11414))
|
||||
- chore: backport calibnet lightweight patch ([filecoin-project/lotus#11422](https://github.com/filecoin-project/lotus/pull/11422))
|
||||
- chore: update bootstrap nodes ([filecoin-project/lotus#11288](https://github.com/filecoin-project/lotus/pull/11288))
|
||||
- chore: add bootstrap node on calibration ([filecoin-project/lotus#11175](https://github.com/filecoin-project/lotus/pull/11175))
|
||||
|
||||
# v1.24.0-rc2 / 2023-10-17
|
||||
# 1.24.0 / 2023-11-22
|
||||
|
||||
This is the second release candidate of the upcoming **MANDATORY Lotus v1.24.0** release, which will deliver the Filecoin network version 21, codenamed Watermelon 🍉.
|
||||
This is the stable release for the upcoming **MANDATORY** Filecoin network upgrade v21, codenamed Watermelon 🍉, at **epoch 3469380 - 2023-12-12T13:30:00Z**.
|
||||
|
||||
**This release candidate does NOT set an upgrade epoch for mainnet, but sets the calibration network to upgrade at epoch 1013134, which is 2023-10-19T13:00:00Z.** This second release candidate updates go-state-types to v0.12.5, adding a proofs mapping that was missing v0.12.5. Lotus v1.24.0-RC1 remains valid for the network upgrade in the Calibration network. However, storage providers intending to conduct Synthetic PoRep testing are advised to use RC2.
|
||||
|
||||
The Filecoin network version 21 delivers the following FIPs:
|
||||
|
||||
- [FIP0052: Increase Max Sector Commitment to 3.5 years](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0052.md)
|
||||
- [FIP0059: Synthetic PoRep](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0059.md)
|
||||
- [FIP0070: Allow SPs to move partitions between deadlines](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0070.md)
|
||||
- [FIP0071: Deterministic State Access (IPLD Reachability)](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0071.md)
|
||||
- [FIP0072: Improved event syscall API](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0072.md)
|
||||
- [FIP0073: Remove beneficiary from the self_destruct syscall](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0073.md)
|
||||
- [FIP0075: Improvements to FVM randomness syscalls](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0075.md)
|
||||
|
||||
|
||||
Full list of the other protocol improvements we are delivering can be found [here](https://github.com/filecoin-project/core-devs/blob/master/Network%20Upgrades/v21.md).
|
||||
|
||||
## ☢️ Upgrade Warnings ☢️
|
||||
|
||||
This feature release requires a minimum Go version of v1.20.7 or higher to successfully build Lotus. Go version 1.21.x is not supported yet.
|
||||
|
||||
## v12 Builtin Actor Bundles
|
||||
|
||||
The actor bundles for the calibration network can be checked as follows:
|
||||
[Builtin actor v12.0.0](https://github.com/filecoin-project/builtin-actors/releases/tag/v12.0.0) is used for supporting this upgrade.
|
||||
Make sure that your lotus actor bundle matches the v12 actors manifest by running the following cli after upgrading:
|
||||
|
||||
```
|
||||
lotus state actor-cids --network-version=21
|
||||
./lotus state actor-cids --network-version 21
|
||||
Network Version: 21
|
||||
Actor Version: 12
|
||||
Manifest CID: bafy2bzacedrunxfqta5skb7q7x32lnp4efz2oq7fn226ffm7fu5iqs62jkmvs
|
||||
Manifest CID: bafy2bzaceapkgfggvxyllnmuogtwasmsv5qi2qzhc2aybockd6kag2g5lzaio
|
||||
|
||||
Actor CID
|
||||
paymentchannel bafk2bzacebaxhk4itfiuvbftg7kz5zxugqnvdgerobitjq4vl6q4orcwk6wqg
|
||||
datacap bafk2bzacebpiwb2ml4qbnnaayxumtk43ryhc63exdgnhivy3hwgmzemawsmpq
|
||||
paymentchannel bafk2bzacectv4cm47bnhga5febf3lo3fq47g72kmmp2xd5s6tcxz7hiqdywa4
|
||||
storagemarket bafk2bzacedylkg5am446lcuih4voyzdn4yjeqfsxfzh5b6mcuhx4mok5ph5c4
|
||||
storagepower bafk2bzacecsij5tpfzjpfuckxvccv2p3bdqjklkrfyyoei6lx5dyj5j4fvjm6
|
||||
cron bafk2bzacechxjkfe2cehx4s7skj3wzfpzf7zolds64khrrrs66bhazsemktls
|
||||
eam bafk2bzaceb3elj4hfbbjp7g5bptc7su7mptszl4nlqfedilxvstjo5ungm6oe
|
||||
ethaccount bafk2bzaceb4gkau2vgsijcxpfuq33bd7w3efr2rrhxrwiacjmns2ntdiamswq
|
||||
reward bafk2bzacealqnxn5lwzwexd6reav4dppypquklx2ujlnvaxiqk2tzstyvkp5u
|
||||
verifiedregistry bafk2bzacedudgflxc75c77c6zkmfyq4u2xuk7k6xw6dfdccarjrvxx453b77q
|
||||
evm bafk2bzacecmnyfiwb52tkbwmm2dsd7ysi3nvuxl3lmspy7pl26wxj4zj7w4wi
|
||||
placeholder bafk2bzacedfvut2myeleyq67fljcrw4kkmn5pb5dpyozovj7jpoez5irnc3ro
|
||||
ethaccount bafk2bzaceajmc3y3sedsqymfla3dzzqzmbu5kmr2iskm26ga2u34ll5fpztfw
|
||||
evm bafk2bzaced4sozr7m6rzcgpobzeiupghthfw6afumysu3oz6bxxirv74uo3vw
|
||||
system bafk2bzacecioupndtcnyw6iq2hbrxag3aufvczlv5nobnfbkbywqzcyfaa376
|
||||
init bafk2bzaceaewh7b6zl2egclm7fqzx2lsqr57i75lb6cj43ndoa4mal3k5ld3m
|
||||
multisig bafk2bzacednkwcpw5yzxjceoaliajgupzj6iqxe7ks2ll3unspbprbo5f2now
|
||||
eam bafk2bzacecb6cnwftvavpph4p34zs4psuy5xvbrhf7vszkva4npw6mw3c42xe
|
||||
reward bafk2bzacedra77pcglf7vdca2itcaa4vd6xrxynxmgfgdjdxqxfwqyhtoxehy
|
||||
storagemarket bafk2bzacea7g46y7xxu2zjq2h75x6mmx3utz2uxnlvnwi6tzpsvulna3bmiva
|
||||
storageminer bafk2bzacecnh2ouohmonvebq7uughh4h3ppmg4cjsk74dzxlbbtlcij4xbzxq
|
||||
storagepower bafk2bzacedd3ka44k7d46ckbinjhv3diyuu2epgbyvhqqyjkc64qlrg3wlgzi
|
||||
verifiedregistry bafk2bzaceavldupmf7bimeeacs67z5xdfdlfca6p7sn6bev3mt5ggepfqvhqo
|
||||
account bafk2bzacechwwxdqvggkdylm37zldjsra2ivkdzwp7fee56bzxbzs544wv6u6
|
||||
cron bafk2bzacec4gdxxkqwxqqodsv6ug5dmdbqdfqwyqfek3yhxc2wweh5psxaeq6
|
||||
datacap bafk2bzacecq5ppfskxgv3iea3jarsix6jdduuhwsn4fbvngtbmzelzmlygorm
|
||||
storageminer bafk2bzacedo75pabe4i2l3hvhtsjmijrcytd2y76xwe573uku25fi7sugqld6
|
||||
system bafk2bzacebfqrja2hip7esf4eafxjmu6xcogoqu5xxtgdg7xa5szgvvdguchu
|
||||
account bafk2bzaceboftg75mdiba7xbo2i3uvgtca4brhnr3u5ptihonixgpnrvhpxoa
|
||||
init bafk2bzacebllyegx5r6lggf6ymyetbp7amacwpuxakhtjvjtvoy2bfkzk3vms
|
||||
```
|
||||
|
||||
## Migration
|
||||
|
||||
We are expecting a heavier than normal state migration for this upgrade due to the amount of state changes introduced for miner sector info. (This is a similar migration as the Shark upgrade, however, we have introduced a couple of migration performance optimizations since then for a smoother upgrade experience.)
|
||||
|
||||
All node operators, including storage providers, should be aware that ONE pre-migration is being scheduled 180 epochs before the upgrade, around 2023-12-12T12:00:00Z. It will take around 20-30 minutes for the pre-migration and less than 30 seconds for the final migration, depending on the amount of historical state in the node blockstore and the hardware specs the node is running on. During this time, expect slower block validation times, increased CPU and memory usage, and longer delays for API queries (during our testing, it topped out about 205 RAM(htop) on a 1TiB box).
|
||||
|
||||
We recommend node operators (who haven't enabled splitstore `discard` mode) that do not care about historical chain states, to prune the chain blockstore by syncing from a snapshot 1-2 days before the upgrade.
|
||||
|
||||
Note to full archival node operators: you may expect it takes some time for the node to complete the final migration, during this period your node will fall out of sync and your chain service may have some disruption. However, you can expect the node to catch up soon after the migration completes. You can test out the migration by running the following on your node in offline mode:
|
||||
|
||||
1. `lotus chain head | head -n1`
|
||||
2. Stop Lotus daemon
|
||||
3. `./lotus-shed migrate-state --repo=[path-to-your-lotus-repo] 21 [output-of-step-1]`
|
||||
|
||||
You can check out the [tutorial for benchmarking the network migration here.](https://lotus.filecoin.io/kb/test-migration/)
|
||||
|
||||
|
||||
## BREAKING CHANGE
|
||||
|
||||
There is a new protocol limit on how many partition could be submited in one PoSt - if you have any customized tooling for batching PoSts, please update accordingly.
|
||||
- feat: limit PoSted partitions to 3 ([filecoin-project/lotus#11327](https://github.com/filecoin-project/lotus/pull/11327))
|
||||
|
||||
## New features
|
||||
- Implement and support [FIP0052: Increase Max Sector Commitment to 3.5 years](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0052.md)
|
||||
- fix: docs: Update SectorLifetime to be in line with FIP-0052 ([filecoin-project/lotus#11314](https://github.com/filecoin-project/lotus/pull/11314))
|
||||
- Implement and support [FIP0059: Synthetic PoRep](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0059.md) - Check out the [Lotus documentation for Synthetic PoRep](https://lotus.filecoin.io/storage-providers/advanced-configurations/sealing/#synthetic-porep).
|
||||
- feat: implement Synthetic PoRep ([filecoin-project/lotus#11258](https://github.com/filecoin-project/lotus/pull/11258))
|
||||
- chore: config: Update todo in UseSyntheticPoRep ([filecoin-project/lotus#11297](https://github.com/filecoin-project/lotus/pull/11297))
|
||||
- Implement and support [FIP0070: Allow SPs to move partitions between deadlines](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0070.md) - Check out the [Lotus documentation for Moving Partitions](https://lotus.filecoin.io/storage-providers/operate/daily-chores/#move-partitions)
|
||||
- Feat: Lotus cli: actor: Support move partition command to move partitions' deadline ([filecoin-project/lotus#11301](https://github.com/filecoin-project/lotus/pull/11301))
|
||||
- feat: limit PoSted partitions to 3 ([filecoin-project/lotus#11327](https://github.com/filecoin-project/lotus/pull/11327))
|
||||
|
||||
## Improvements
|
||||
- Backport: feat: sealing: Switch to calling PreCommitSectorBatch2 ([filecoin-project/lotus#11215](https://github.com/filecoin-project/lotus/pull/11215))
|
||||
- updated the boostrap nodes
|
||||
|
||||
## Dependencies
|
||||
- github.com/filecoin-project/go-amt-ipld/v4 (v4.0.0 -> v4.2.0)
|
||||
- chore: deps: update bulitin-actors, FVM, and go-state-types ([filecoin-project/lotus#11291](https://github.com/filecoin-project/lotus/pull/11291))
|
||||
- chore: deps: update FFI, FVM, and actors ([filecoin-project/lotus#11310](https://github.com/filecoin-project/lotus/pull/11310))
|
||||
- chore: deps: update to latest actors and FFI ([filecoin-project/lotus#11330](https://github.com/filecoin-project/lotus/pull/11330))
|
||||
- chore: deps: update to go-state-types v0.12.5 ([filecoin-project/lotus#11339](https://github.com/filecoin-project/lotus/pull/11339))
|
||||
- chore: deps: update to final actors ([filecoin-project/lotus#11330](https://github.com/filecoin-project/lotus/pull/11440))
|
||||
- chore: deps: update to go-state-types v0.12.8 ([filecoin-project/lotus#11339](https://github.com/filecoin-project/lotus/pull/11437))
|
||||
- chore: deps: update libp2p to v0.30.0 #11434
|
||||
|
||||
|
||||
## Snapshots
|
||||
|
||||
The [Forest team](https://filecoinproject.slack.com/archives/C029LPZ5N73) at Chainsafe has launched a brand new lightweight snapshot service that is backed up by forest nodes! This is a great alternative service along with the fil-infra one, and it is compatible with lotus! We recommend lotus users to check it out [here](https://docs.filecoin.io/networks/mainnet#resources)!
|
||||
|
||||
## Others
|
||||
- chore: nv-skeleton for feat/nv21-branch ([filecoin-project/lotus#11176](https://github.com/filecoin-project/lotus/pull/11176))
|
||||
- chore: chain/actors: Use type proxies instead of versioned GST imports ([filecoin-project/lotus#11216](https://github.com/filecoin-project/lotus/pull/11216))
|
||||
- chore: butterfly: Add preliminary nv21 assets ([filecoin-project/lotus#11293](https://github.com/filecoin-project/lotus/pull/11293))
|
||||
- chore: butterfly: Update Butterfly Assets ([filecoin-project/lotus#11312](https://github.com/filecoin-project/lotus/pull/11312))
|
||||
- chore: release: Set calibration upgrade height ([filecoin-project/lotus#11331](https://github.com/filecoin-project/lotus/pull/11331))
|
||||
- chore: build: bump version to 1.24.0-rc1 ([filecoin-project/lotus#11332](https://github.com/filecoin-project/lotus/pull/11332))
|
||||
|
||||
|
||||
# v1.23.3 / 2023-08-01
|
||||
@@ -235,7 +262,7 @@ This feature release requires a **minimum Go version of v1.19.12 or higher to su
|
||||
- feat: sealing: flag to run data_cid untied from addpiece ([filecoin-project/lotus#10797](https://github.com/filecoin-project/lotus/pull/10797))
|
||||
- feat: Lotus Gateway: add MpoolPending, ChainGetBlock and MinerGetBaseInfo ([filecoin-project/lotus#10929](https://github.com/filecoin-project/lotus/pull/10929))
|
||||
|
||||
## Improvements
|
||||
## Improvements && Bug Fixes
|
||||
- chore: update ffi & fvm ([filecoin-project/lotus#11040](https://github.com/filecoin-project/lotus/pull/11040))
|
||||
- feat: Make sure we don't store duplidate actor events caused to reorgs in events.db ([filecoin-project/lotus#11015](https://github.com/filecoin-project/lotus/pull/11015))
|
||||
- sealing: Use only non-assigned deals when selecting snap sectors ([filecoin-project/lotus#11002](https://github.com/filecoin-project/lotus/pull/11002))
|
||||
@@ -313,6 +340,10 @@ This feature release requires a **minimum Go version of v1.19.12 or higher to su
|
||||
- fix: cli: Change arg wording in change-beneficiary cmd ([filecoin-project/lotus#10823](https://github.com/filecoin-project/lotus/pull/10823))
|
||||
- refactor: streamline error handling in CheckPendingMessages (#10818) ([filecoin-project/lotus#10818](https://github.com/filecoin-project/lotus/pull/10818))
|
||||
- feat: Add tmp indices to events table while performing migration to V2
|
||||
- fix: sync: iterate over returned messages directly #11373
|
||||
- fix: api: compute the effective gas cost with the correct base-fee #11357
|
||||
- fix: check invariants: v12 check #11371
|
||||
- fix: api: compute gasUsedRatio based on max gas in the tipset #11354
|
||||
|
||||
# v1.23.2 / 2023-06-28
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ All releases under an odd minor version number indicate **feature releases**. Th
|
||||
|
||||
Feature releases include new development and bug fixes. They are not mandatory, but still highly recommended, **as they may contain critical security fixes**. Note that some of these releases may be very small patch releases that include critical hotfixes. There is no way to distinguish between a bug fix release and a feature release on the "feature" version. Both cases will use the "patch" version number.
|
||||
|
||||
We aim to ship a new feature release of the Lotus software from our development (master) branch every 3 weeks, so users can expect a regular cadence of Lotus feature releases. Note that mandatory releases for network upgrades may disrupt this schedule. For more, see the Release Cycle section (TODO: Link).
|
||||
We aim to ship a new feature release of the Lotus software from our development (master) branch every 3 weeks, so users can expect a regular cadence of Lotus feature releases. Note that mandatory releases for network upgrades may disrupt this schedule. For more, see the [Release Cycle section](#release-cycle).
|
||||
|
||||
### Examples Scenarios
|
||||
|
||||
|
||||
@@ -71,10 +71,10 @@ For other distributions you can find the required dependencies [here.](https://l
|
||||
|
||||
#### Go
|
||||
|
||||
To build Lotus, you need a working installation of [Go 1.19.12 or higher](https://golang.org/dl/):
|
||||
To build Lotus, you need a working installation of [Go 1.20.10 or higher](https://golang.org/dl/):
|
||||
|
||||
```bash
|
||||
wget -c https://golang.org/dl/go1.19.12.linux-amd64.tar.gz -O - | sudo tar -xz -C /usr/local
|
||||
wget -c https://golang.org/dl/go1.20.10.linux-amd64.tar.gz -O - | sudo tar -xz -C /usr/local
|
||||
```
|
||||
|
||||
**TIP:**
|
||||
@@ -133,6 +133,8 @@ Note: The default branch `master` is the dev branch where the latest new feature
|
||||
|
||||
6. You should now have Lotus installed. You can now [start the Lotus daemon and sync the chain](https://lotus.filecoin.io/lotus/install/linux/#start-the-lotus-daemon-and-sync-the-chain).
|
||||
|
||||
7. (Optional) Follow the [Setting Up Prometheus and Grafana](https://github.com/filecoin-project/lotus/tree/master/metrics/README.md) guide for detailed instructions on setting up a working monitoring system running against a local running lotus node.
|
||||
|
||||
## License
|
||||
|
||||
Dual-licensed under [MIT](https://github.com/filecoin-project/lotus/blob/master/LICENSE-MIT) + [Apache 2.0](https://github.com/filecoin-project/lotus/blob/master/LICENSE-APACHE)
|
||||
|
||||
+1
-1
@@ -824,7 +824,7 @@ type FullNode interface {
|
||||
EthFeeHistory(ctx context.Context, p jsonrpc.RawParams) (ethtypes.EthFeeHistory, error) //perm:read
|
||||
|
||||
EthMaxPriorityFeePerGas(ctx context.Context) (ethtypes.EthBigInt, error) //perm:read
|
||||
EthEstimateGas(ctx context.Context, tx ethtypes.EthCall) (ethtypes.EthUint64, error) //perm:read
|
||||
EthEstimateGas(ctx context.Context, p jsonrpc.RawParams) (ethtypes.EthUint64, error) //perm:read
|
||||
EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthBytes, error) //perm:read
|
||||
|
||||
EthSendRawTransaction(ctx context.Context, rawTx ethtypes.EthBytes) (ethtypes.EthHash, error) //perm:read
|
||||
|
||||
+1
-1
@@ -114,7 +114,7 @@ type Gateway interface {
|
||||
EthGasPrice(ctx context.Context) (ethtypes.EthBigInt, error)
|
||||
EthFeeHistory(ctx context.Context, p jsonrpc.RawParams) (ethtypes.EthFeeHistory, error)
|
||||
EthMaxPriorityFeePerGas(ctx context.Context) (ethtypes.EthBigInt, error)
|
||||
EthEstimateGas(ctx context.Context, tx ethtypes.EthCall) (ethtypes.EthUint64, error)
|
||||
EthEstimateGas(ctx context.Context, p jsonrpc.RawParams) (ethtypes.EthUint64, error)
|
||||
EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthBytes, error)
|
||||
EthSendRawTransaction(ctx context.Context, rawTx ethtypes.EthBytes) (ethtypes.EthHash, error)
|
||||
EthGetLogs(ctx context.Context, filter *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error)
|
||||
|
||||
@@ -1042,7 +1042,7 @@ func (mr *MockFullNodeMockRecorder) EthChainId(arg0 interface{}) *gomock.Call {
|
||||
}
|
||||
|
||||
// EthEstimateGas mocks base method.
|
||||
func (m *MockFullNode) EthEstimateGas(arg0 context.Context, arg1 ethtypes.EthCall) (ethtypes.EthUint64, error) {
|
||||
func (m *MockFullNode) EthEstimateGas(arg0 context.Context, arg1 jsonrpc.RawParams) (ethtypes.EthUint64, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthEstimateGas", arg0, arg1)
|
||||
ret0, _ := ret[0].(ethtypes.EthUint64)
|
||||
|
||||
+6
-6
@@ -255,7 +255,7 @@ type FullNodeMethods struct {
|
||||
|
||||
EthChainId func(p0 context.Context) (ethtypes.EthUint64, error) `perm:"read"`
|
||||
|
||||
EthEstimateGas func(p0 context.Context, p1 ethtypes.EthCall) (ethtypes.EthUint64, error) `perm:"read"`
|
||||
EthEstimateGas func(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthUint64, error) `perm:"read"`
|
||||
|
||||
EthFeeHistory func(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthFeeHistory, error) `perm:"read"`
|
||||
|
||||
@@ -679,7 +679,7 @@ type GatewayMethods struct {
|
||||
|
||||
EthChainId func(p0 context.Context) (ethtypes.EthUint64, error) ``
|
||||
|
||||
EthEstimateGas func(p0 context.Context, p1 ethtypes.EthCall) (ethtypes.EthUint64, error) ``
|
||||
EthEstimateGas func(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthUint64, error) ``
|
||||
|
||||
EthFeeHistory func(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthFeeHistory, error) ``
|
||||
|
||||
@@ -2134,14 +2134,14 @@ func (s *FullNodeStub) EthChainId(p0 context.Context) (ethtypes.EthUint64, error
|
||||
return *new(ethtypes.EthUint64), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthEstimateGas(p0 context.Context, p1 ethtypes.EthCall) (ethtypes.EthUint64, error) {
|
||||
func (s *FullNodeStruct) EthEstimateGas(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthUint64, error) {
|
||||
if s.Internal.EthEstimateGas == nil {
|
||||
return *new(ethtypes.EthUint64), ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthEstimateGas(p0, p1)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthEstimateGas(p0 context.Context, p1 ethtypes.EthCall) (ethtypes.EthUint64, error) {
|
||||
func (s *FullNodeStub) EthEstimateGas(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthUint64, error) {
|
||||
return *new(ethtypes.EthUint64), ErrNotSupported
|
||||
}
|
||||
|
||||
@@ -4400,14 +4400,14 @@ func (s *GatewayStub) EthChainId(p0 context.Context) (ethtypes.EthUint64, error)
|
||||
return *new(ethtypes.EthUint64), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *GatewayStruct) EthEstimateGas(p0 context.Context, p1 ethtypes.EthCall) (ethtypes.EthUint64, error) {
|
||||
func (s *GatewayStruct) EthEstimateGas(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthUint64, error) {
|
||||
if s.Internal.EthEstimateGas == nil {
|
||||
return *new(ethtypes.EthUint64), ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthEstimateGas(p0, p1)
|
||||
}
|
||||
|
||||
func (s *GatewayStub) EthEstimateGas(p0 context.Context, p1 ethtypes.EthCall) (ethtypes.EthUint64, error) {
|
||||
func (s *GatewayStub) EthEstimateGas(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthUint64, error) {
|
||||
return *new(ethtypes.EthUint64), ErrNotSupported
|
||||
}
|
||||
|
||||
|
||||
+9
-1
@@ -56,9 +56,17 @@ type PubsubScore struct {
|
||||
Score *pubsub.PeerScoreSnapshot
|
||||
}
|
||||
|
||||
// MessageSendSpec contains optional fields which modify message sending behavior
|
||||
type MessageSendSpec struct {
|
||||
MaxFee abi.TokenAmount
|
||||
// MaxFee specifies a cap on network fees related to this message
|
||||
MaxFee abi.TokenAmount
|
||||
|
||||
// MsgUuid specifies a unique message identifier which can be used on node (or node cluster)
|
||||
// level to prevent double-sends of messages even when nonce generation is not handled by sender
|
||||
MsgUuid uuid.UUID
|
||||
|
||||
// MaximizeFeeCap makes message FeeCap be based entirely on MaxFee
|
||||
MaximizeFeeCap bool
|
||||
}
|
||||
|
||||
type MpoolMessageWhole struct {
|
||||
|
||||
@@ -183,3 +183,17 @@ func (b *idstore) Close() error {
|
||||
func (b *idstore) Flush(ctx context.Context) error {
|
||||
return b.bs.Flush(ctx)
|
||||
}
|
||||
|
||||
func (b *idstore) CollectGarbage(ctx context.Context, options ...BlockstoreGCOption) error {
|
||||
if bs, ok := b.bs.(BlockstoreGC); ok {
|
||||
return bs.CollectGarbage(ctx, options...)
|
||||
}
|
||||
return xerrors.Errorf("not supported")
|
||||
}
|
||||
|
||||
func (b *idstore) GCOnce(ctx context.Context, options ...BlockstoreGCOption) error {
|
||||
if bs, ok := b.bs.(BlockstoreGCOnce); ok {
|
||||
return bs.GCOnce(ctx, options...)
|
||||
}
|
||||
return xerrors.Errorf("not supported")
|
||||
}
|
||||
|
||||
@@ -182,7 +182,6 @@ type SplitStore struct {
|
||||
|
||||
compactionIndex int64
|
||||
pruneIndex int64
|
||||
onlineGCCnt int64
|
||||
|
||||
ctx context.Context
|
||||
cancel func()
|
||||
|
||||
@@ -66,8 +66,9 @@ var (
|
||||
)
|
||||
|
||||
const (
|
||||
batchSize = 16384
|
||||
cidKeySize = 128
|
||||
batchSize = 16384
|
||||
cidKeySize = 128
|
||||
purgeWorkSliceDuration = time.Second
|
||||
)
|
||||
|
||||
func (s *SplitStore) HeadChange(_, apply []*types.TipSet) error {
|
||||
@@ -1372,9 +1373,21 @@ func (s *SplitStore) purge(coldr *ColdSetReader, checkpoint *Checkpoint, markSet
|
||||
return err
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
|
||||
err := coldr.ForEach(func(c cid.Cid) error {
|
||||
batch = append(batch, c)
|
||||
if len(batch) == batchSize {
|
||||
// add some time slicing to the purge as this a very disk I/O heavy operation that
|
||||
// requires write access to txnLk that may starve other operations that require
|
||||
// access to the blockstore.
|
||||
elapsed := time.Since(now)
|
||||
if elapsed > purgeWorkSliceDuration {
|
||||
// work 1 slice, sleep 4 slices, or 20% utilization
|
||||
time.Sleep(4 * elapsed)
|
||||
now = time.Now()
|
||||
}
|
||||
|
||||
return deleteBatch()
|
||||
}
|
||||
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
/dns4/bootstrap-1.calibration.fildev.network/tcp/1347/p2p/12D3KooWDTayrBojBn9jWNNUih4nNQQBGJD7Zo3gQCKgBkUsS6dp
|
||||
/dns4/bootstrap-2.calibration.fildev.network/tcp/1347/p2p/12D3KooWNRxTHUn8bf7jz1KEUPMc2dMgGfa4f8ZJTsquVSn3vHCG
|
||||
/dns4/bootstrap-3.calibration.fildev.network/tcp/1347/p2p/12D3KooWFWUqE9jgXvcKHWieYs9nhyp6NF4ftwLGAHm4sCv73jjK
|
||||
/dns4/calibration.node.glif.io/tcp/1237/p2p/12D3KooWQPYouEAsUQKzvFUA9sQ8tz4rfpqtTzh2eL6USd9bwg7x
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
/dns4/bootstrap-0.mainnet.filops.net/tcp/1347/p2p/12D3KooWCVe8MmsEMes2FzgTpt9fXtmCY7wrq91GRiaC8PHSCCBj
|
||||
/dns4/bootstrap-1.mainnet.filops.net/tcp/1347/p2p/12D3KooWCwevHg1yLCvktf2nvLu7L9894mcrJR4MsBCcm4syShVc
|
||||
/dns4/bootstrap-2.mainnet.filops.net/tcp/1347/p2p/12D3KooWEWVwHGn2yR36gKLozmb4YjDJGerotAPGxmdWZx2nxMC4
|
||||
/dns4/bootstrap-3.mainnet.filops.net/tcp/1347/p2p/12D3KooWKhgq8c7NQ9iGjbyK7v7phXvG6492HQfiDaGHLHLQjk7R
|
||||
/dns4/bootstrap-4.mainnet.filops.net/tcp/1347/p2p/12D3KooWL6PsFNPhYftrJzGgF5U18hFoaVhfGk7xwzD8yVrHJ3Uc
|
||||
/dns4/bootstrap-5.mainnet.filops.net/tcp/1347/p2p/12D3KooWLFynvDQiUpXoHroV1YxKHhPJgysQGH2k3ZGwtWzR4dFH
|
||||
/dns4/bootstrap-6.mainnet.filops.net/tcp/1347/p2p/12D3KooWP5MwCiqdMETF9ub1P3MbCvQCcfconnYHbWg6sUJcDRQQ
|
||||
/dns4/bootstrap-7.mainnet.filops.net/tcp/1347/p2p/12D3KooWRs3aY1p3juFjPy8gPN95PEQChm2QKGUCAdcDCC4EBMKf
|
||||
/dns4/bootstrap-8.mainnet.filops.net/tcp/1347/p2p/12D3KooWScFR7385LTyR4zU1bYdzSiiAb5rnNABfVahPvVSzyTkR
|
||||
@@ -11,6 +8,5 @@
|
||||
/dns4/bootstrap-0.starpool.in/tcp/12757/p2p/12D3KooWGHpBMeZbestVEWkfdnC9u7p6uFHXL1n7m1ZBqsEmiUzz
|
||||
/dns4/bootstrap-1.starpool.in/tcp/12757/p2p/12D3KooWQZrGH1PxSNZPum99M1zNvjNFM33d1AAu5DcvdHptuU7u
|
||||
/dns4/node.glif.io/tcp/1235/p2p/12D3KooWBF8cpp65hp2u9LK5mh19x67ftAam84z9LsfaquTDSBpt
|
||||
/dns4/bootstrap-0.ipfsmain.cn/tcp/34721/p2p/12D3KooWQnwEGNqcM2nAcPtRR9rAX8Hrg4k9kJLCHoTR5chJfz6d
|
||||
/dns4/bootstrap-1.ipfsmain.cn/tcp/34723/p2p/12D3KooWMKxMkD5DMpSWsW7dBddKxKT7L2GgbNuckz9otxvkvByP
|
||||
/dns4/bootstarp-0.1475.io/tcp/61256/p2p/12D3KooWRzCVDwHUkgdK7eRgnoXbjDAELhxPErjHzbRLguSV1aRt
|
||||
/dns4/bootstarp-0.1475.io/tcp/61256/p2p/12D3KooWRzCVDwHUkgdK7eRgnoXbjDAELhxPErjHzbRLguSV1aRt
|
||||
/dns4/bootstrap-venus.mainnet.filincubator.com/tcp/8888/p2p/QmQu8C6deXwKvJP2D8B6QGyhngc3ZiDnFzEHBDx8yeBXST
|
||||
|
||||
@@ -97,7 +97,7 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
|
||||
}, {
|
||||
Network: "butterflynet",
|
||||
Version: 12,
|
||||
BundleGitTag: "v12.0.0-rc.3",
|
||||
BundleGitTag: "v12.0.0",
|
||||
ManifestCid: MustParseCid("bafy2bzacectxvbk77ntedhztd6sszp2btrtvsmy7lp2ypnrk6yl74zb34t2cq"),
|
||||
Actors: map[string]cid.Cid{
|
||||
"account": MustParseCid("bafk2bzacebp7anjdtg2sohyt6lromx4xs7nujtwdfcsffnptphaayabx7ysxs"),
|
||||
@@ -203,7 +203,7 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
|
||||
}, {
|
||||
Network: "calibrationnet",
|
||||
Version: 12,
|
||||
BundleGitTag: "v12.0.0-rc.3",
|
||||
BundleGitTag: "v12.0.0",
|
||||
ManifestCid: MustParseCid("bafy2bzacednzb3pkrfnbfhmoqtb3bc6dgvxszpqklf3qcc7qzcage4ewzxsca"),
|
||||
Actors: map[string]cid.Cid{
|
||||
"account": MustParseCid("bafk2bzacechwwxdqvggkdylm37zldjsra2ivkdzwp7fee56bzxbzs544wv6u6"),
|
||||
@@ -318,7 +318,7 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
|
||||
}, {
|
||||
Network: "caterpillarnet",
|
||||
Version: 12,
|
||||
BundleGitTag: "v12.0.0-rc.3",
|
||||
BundleGitTag: "v12.0.0",
|
||||
ManifestCid: MustParseCid("bafy2bzacebxiub6qsy67asvl5cx33x5vjbuqinalmf3xtnbmokxmmklzdkvei"),
|
||||
Actors: map[string]cid.Cid{
|
||||
"account": MustParseCid("bafk2bzacecereuhejfvodut5357cai4lmhsyr7uenhcxvmw6jpmhe6auuly32"),
|
||||
@@ -424,7 +424,7 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
|
||||
}, {
|
||||
Network: "devnet",
|
||||
Version: 12,
|
||||
BundleGitTag: "v12.0.0-rc.3",
|
||||
BundleGitTag: "v12.0.0",
|
||||
ManifestCid: MustParseCid("bafy2bzaceasjdukhhyjbegpli247vbf5h64f7uvxhhebdihuqsj2mwisdwa6o"),
|
||||
Actors: map[string]cid.Cid{
|
||||
"account": MustParseCid("bafk2bzacedki4apynvdxxuoigmqkgaktgy2erjftoxqxqaklnelgveyaqknfu"),
|
||||
@@ -553,7 +553,7 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
|
||||
}, {
|
||||
Network: "mainnet",
|
||||
Version: 12,
|
||||
BundleGitTag: "v12.0.0-rc.3",
|
||||
BundleGitTag: "v12.0.0",
|
||||
ManifestCid: MustParseCid("bafy2bzaceapkgfggvxyllnmuogtwasmsv5qi2qzhc2aybockd6kag2g5lzaio"),
|
||||
Actors: map[string]cid.Cid{
|
||||
"account": MustParseCid("bafk2bzaceboftg75mdiba7xbo2i3uvgtca4brhnr3u5ptihonixgpnrvhpxoa"),
|
||||
@@ -659,7 +659,7 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
|
||||
}, {
|
||||
Network: "testing",
|
||||
Version: 12,
|
||||
BundleGitTag: "v12.0.0-rc.3",
|
||||
BundleGitTag: "v12.0.0",
|
||||
ManifestCid: MustParseCid("bafy2bzaceaaxd6ytavsek5bi5soqo7qamezuqfyfjy42es2clpbzu3pwzcmye"),
|
||||
Actors: map[string]cid.Cid{
|
||||
"account": MustParseCid("bafk2bzacea74qqkfvacykmq5emzqblh4f4nmxdkiyixxpzs7kkcfnbfa7cb6m"),
|
||||
@@ -765,7 +765,7 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
|
||||
}, {
|
||||
Network: "testing-fake-proofs",
|
||||
Version: 12,
|
||||
BundleGitTag: "v12.0.0-rc.3",
|
||||
BundleGitTag: "v12.0.0",
|
||||
ManifestCid: MustParseCid("bafy2bzacecver4l5d6jiuzubhrtcxjjfdx6jnxbmyp4bselol2atgkhz3e3um"),
|
||||
Actors: map[string]cid.Cid{
|
||||
"account": MustParseCid("bafk2bzacea74qqkfvacykmq5emzqblh4f4nmxdkiyixxpzs7kkcfnbfa7cb6m"),
|
||||
|
||||
@@ -5,5 +5,8 @@ import (
|
||||
)
|
||||
|
||||
func IsNearUpgrade(epoch, upgradeEpoch abi.ChainEpoch) bool {
|
||||
if upgradeEpoch < 0 {
|
||||
return false
|
||||
}
|
||||
return epoch > upgradeEpoch-Finality && epoch < upgradeEpoch+Finality
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1
-1
@@ -37,7 +37,7 @@ func BuildTypeString() string {
|
||||
}
|
||||
|
||||
// BuildVersion is the local build version
|
||||
const BuildVersion = "1.25.0-rc5"
|
||||
const BuildVersion = "1.25.1-dev"
|
||||
|
||||
func UserVersion() string {
|
||||
if os.Getenv("LOTUS_VERSION_IGNORE_COMMIT") == "1" {
|
||||
|
||||
@@ -72,7 +72,7 @@ func (s *state{{.v}}) AvailableBalance(bal abi.TokenAmount) (available abi.Token
|
||||
available = abi.NewTokenAmount(0)
|
||||
}
|
||||
}()
|
||||
// this panics if the miner doesnt have enough funds to cover their locked pledge
|
||||
// this panics if the miner doesn't have enough funds to cover their locked pledge
|
||||
available{{if (ge .v 2)}}, err{{end}} = s.GetAvailableBalance(bal)
|
||||
return available, err
|
||||
}
|
||||
|
||||
Generated
+1
-1
@@ -62,7 +62,7 @@ func (s *state0) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmoun
|
||||
available = abi.NewTokenAmount(0)
|
||||
}
|
||||
}()
|
||||
// this panics if the miner doesnt have enough funds to cover their locked pledge
|
||||
// this panics if the miner doesn't have enough funds to cover their locked pledge
|
||||
available = s.GetAvailableBalance(bal)
|
||||
return available, err
|
||||
}
|
||||
|
||||
Generated
+1
-1
@@ -62,7 +62,7 @@ func (s *state10) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmou
|
||||
available = abi.NewTokenAmount(0)
|
||||
}
|
||||
}()
|
||||
// this panics if the miner doesnt have enough funds to cover their locked pledge
|
||||
// this panics if the miner doesn't have enough funds to cover their locked pledge
|
||||
available, err = s.GetAvailableBalance(bal)
|
||||
return available, err
|
||||
}
|
||||
|
||||
Generated
+1
-1
@@ -62,7 +62,7 @@ func (s *state11) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmou
|
||||
available = abi.NewTokenAmount(0)
|
||||
}
|
||||
}()
|
||||
// this panics if the miner doesnt have enough funds to cover their locked pledge
|
||||
// this panics if the miner doesn't have enough funds to cover their locked pledge
|
||||
available, err = s.GetAvailableBalance(bal)
|
||||
return available, err
|
||||
}
|
||||
|
||||
Generated
+1
-1
@@ -62,7 +62,7 @@ func (s *state12) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmou
|
||||
available = abi.NewTokenAmount(0)
|
||||
}
|
||||
}()
|
||||
// this panics if the miner doesnt have enough funds to cover their locked pledge
|
||||
// this panics if the miner doesn't have enough funds to cover their locked pledge
|
||||
available, err = s.GetAvailableBalance(bal)
|
||||
return available, err
|
||||
}
|
||||
|
||||
Generated
+1
-1
@@ -61,7 +61,7 @@ func (s *state2) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmoun
|
||||
available = abi.NewTokenAmount(0)
|
||||
}
|
||||
}()
|
||||
// this panics if the miner doesnt have enough funds to cover their locked pledge
|
||||
// this panics if the miner doesn't have enough funds to cover their locked pledge
|
||||
available, err = s.GetAvailableBalance(bal)
|
||||
return available, err
|
||||
}
|
||||
|
||||
Generated
+1
-1
@@ -62,7 +62,7 @@ func (s *state3) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmoun
|
||||
available = abi.NewTokenAmount(0)
|
||||
}
|
||||
}()
|
||||
// this panics if the miner doesnt have enough funds to cover their locked pledge
|
||||
// this panics if the miner doesn't have enough funds to cover their locked pledge
|
||||
available, err = s.GetAvailableBalance(bal)
|
||||
return available, err
|
||||
}
|
||||
|
||||
Generated
+1
-1
@@ -62,7 +62,7 @@ func (s *state4) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmoun
|
||||
available = abi.NewTokenAmount(0)
|
||||
}
|
||||
}()
|
||||
// this panics if the miner doesnt have enough funds to cover their locked pledge
|
||||
// this panics if the miner doesn't have enough funds to cover their locked pledge
|
||||
available, err = s.GetAvailableBalance(bal)
|
||||
return available, err
|
||||
}
|
||||
|
||||
Generated
+1
-1
@@ -62,7 +62,7 @@ func (s *state5) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmoun
|
||||
available = abi.NewTokenAmount(0)
|
||||
}
|
||||
}()
|
||||
// this panics if the miner doesnt have enough funds to cover their locked pledge
|
||||
// this panics if the miner doesn't have enough funds to cover their locked pledge
|
||||
available, err = s.GetAvailableBalance(bal)
|
||||
return available, err
|
||||
}
|
||||
|
||||
Generated
+1
-1
@@ -62,7 +62,7 @@ func (s *state6) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmoun
|
||||
available = abi.NewTokenAmount(0)
|
||||
}
|
||||
}()
|
||||
// this panics if the miner doesnt have enough funds to cover their locked pledge
|
||||
// this panics if the miner doesn't have enough funds to cover their locked pledge
|
||||
available, err = s.GetAvailableBalance(bal)
|
||||
return available, err
|
||||
}
|
||||
|
||||
Generated
+1
-1
@@ -62,7 +62,7 @@ func (s *state7) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmoun
|
||||
available = abi.NewTokenAmount(0)
|
||||
}
|
||||
}()
|
||||
// this panics if the miner doesnt have enough funds to cover their locked pledge
|
||||
// this panics if the miner doesn't have enough funds to cover their locked pledge
|
||||
available, err = s.GetAvailableBalance(bal)
|
||||
return available, err
|
||||
}
|
||||
|
||||
Generated
+1
-1
@@ -62,7 +62,7 @@ func (s *state8) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmoun
|
||||
available = abi.NewTokenAmount(0)
|
||||
}
|
||||
}()
|
||||
// this panics if the miner doesnt have enough funds to cover their locked pledge
|
||||
// this panics if the miner doesn't have enough funds to cover their locked pledge
|
||||
available, err = s.GetAvailableBalance(bal)
|
||||
return available, err
|
||||
}
|
||||
|
||||
Generated
+1
-1
@@ -62,7 +62,7 @@ func (s *state9) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmoun
|
||||
available = abi.NewTokenAmount(0)
|
||||
}
|
||||
}()
|
||||
// this panics if the miner doesnt have enough funds to cover their locked pledge
|
||||
// this panics if the miner doesn't have enough funds to cover their locked pledge
|
||||
available, err = s.GetAvailableBalance(bal)
|
||||
return available, err
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
// Load returns an abstract copy of payment channel state, irregardless of actor version
|
||||
// Load returns an abstract copy of payment channel state, regardless of actor version
|
||||
func Load(store adt.Store, act *types.Actor) (State, error) {
|
||||
if name, av, ok := actors.GetActorMetaByCode(act.Code); ok {
|
||||
if name != manifest.PaychKey {
|
||||
|
||||
@@ -29,7 +29,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
// Load returns an abstract copy of payment channel state, irregardless of actor version
|
||||
// Load returns an abstract copy of payment channel state, regardless of actor version
|
||||
func Load(store adt.Store, act *types.Actor) (State, error) {
|
||||
if name, av, ok := actors.GetActorMetaByCode(act.Code); ok {
|
||||
if name != manifest.PaychKey {
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
func SerializeParams(i cbg.CBORMarshaler) ([]byte, aerrors.ActorError) {
|
||||
buf := new(bytes.Buffer)
|
||||
if err := i.MarshalCBOR(buf); err != nil {
|
||||
// TODO: shouldnt this be a fatal error?
|
||||
// TODO: shouldn't this be a fatal error?
|
||||
return nil, aerrors.Absorb(err, exitcode.ErrSerialization, "failed to encode parameter")
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
|
||||
@@ -29,19 +29,6 @@ import (
|
||||
|
||||
var log = logging.Logger("drand")
|
||||
|
||||
type drandPeer struct {
|
||||
addr string
|
||||
tls bool
|
||||
}
|
||||
|
||||
func (dp *drandPeer) Address() string {
|
||||
return dp.addr
|
||||
}
|
||||
|
||||
func (dp *drandPeer) IsTLS() bool {
|
||||
return dp.tls
|
||||
}
|
||||
|
||||
// DrandBeacon connects Lotus with a drand network in order to provide
|
||||
// randomness to the system in a way that's aligned with Filecoin rounds/epochs.
|
||||
//
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
)
|
||||
|
||||
func TestPrintGroupInfo(t *testing.T) {
|
||||
server := build.DrandConfigs[build.DrandDevnet].Servers[0]
|
||||
server := build.DrandConfigs[build.DrandTestnet].Servers[0]
|
||||
c, err := hclient.New(server, nil, nil)
|
||||
assert.NoError(t, err)
|
||||
cg := c.(interface {
|
||||
@@ -31,7 +31,7 @@ func TestPrintGroupInfo(t *testing.T) {
|
||||
|
||||
func TestMaxBeaconRoundForEpoch(t *testing.T) {
|
||||
todayTs := uint64(1652222222)
|
||||
db, err := NewDrandBeacon(todayTs, build.BlockDelaySecs, nil, build.DrandConfigs[build.DrandDevnet])
|
||||
db, err := NewDrandBeacon(todayTs, build.BlockDelaySecs, nil, build.DrandConfigs[build.DrandTestnet])
|
||||
assert.NoError(t, err)
|
||||
mbr15 := db.MaxBeaconRoundForEpoch(network.Version15, 100)
|
||||
mbr16 := db.MaxBeaconRoundForEpoch(network.Version16, 100)
|
||||
|
||||
@@ -147,9 +147,6 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context,
|
||||
return xerrors.Errorf("callback failed on cron message: %w", err)
|
||||
}
|
||||
}
|
||||
if ret.ExitCode != 0 {
|
||||
return xerrors.Errorf("cron exit was non-zero: %d", ret.ExitCode)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -91,9 +91,6 @@ var RewardFunc = func(ctx context.Context, vmi vm.Interface, em stmgr.ExecMonito
|
||||
}
|
||||
}
|
||||
|
||||
if ret.ExitCode != 0 {
|
||||
return xerrors.Errorf("reward application message failed (exit %d): %s", ret.ExitCode, ret.ActorErr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -180,7 +180,7 @@ func (e *heightEventsObserver) Revert(ctx context.Context, from, to *types.TipSe
|
||||
// Update the head first so we don't accidental skip reverting a concurrent call to ChainAt.
|
||||
e.updateHead(to)
|
||||
|
||||
// Call revert on all hights between the two tipsets, handling empty tipsets.
|
||||
// Call revert on all heights between the two tipsets, handling empty tipsets.
|
||||
for h := from.Height(); h > to.Height(); h-- {
|
||||
e.lk.Lock()
|
||||
triggers := e.tsHeights[h]
|
||||
|
||||
@@ -673,7 +673,7 @@ func TestCalled(t *testing.T) {
|
||||
}, 3, 20, matchAddrMethod(t0123, 5))
|
||||
require.NoError(t, err)
|
||||
|
||||
// create few blocks to make sure nothing get's randomly called
|
||||
// create few blocks to make sure nothing gets randomly called
|
||||
|
||||
fcs.advance(0, 4, 0, nil) // H=5
|
||||
require.Equal(t, false, applied)
|
||||
@@ -991,7 +991,7 @@ func TestCalledNull(t *testing.T) {
|
||||
}, 3, 20, matchAddrMethod(t0123, 5))
|
||||
require.NoError(t, err)
|
||||
|
||||
// create few blocks to make sure nothing get's randomly called
|
||||
// create few blocks to make sure nothing gets randomly called
|
||||
|
||||
fcs.advance(0, 4, 0, nil) // H=5
|
||||
require.Equal(t, false, applied)
|
||||
@@ -1050,7 +1050,7 @@ func TestRemoveTriggersOnMessage(t *testing.T) {
|
||||
}, 3, 20, matchAddrMethod(t0123, 5))
|
||||
require.NoError(t, err)
|
||||
|
||||
// create few blocks to make sure nothing get's randomly called
|
||||
// create few blocks to make sure nothing gets randomly called
|
||||
|
||||
fcs.advance(0, 4, 0, nil) // H=5
|
||||
require.Equal(t, false, applied)
|
||||
@@ -1155,7 +1155,7 @@ func TestStateChanged(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// create few blocks to make sure nothing get's randomly called
|
||||
// create few blocks to make sure nothing gets randomly called
|
||||
|
||||
fcs.advance(0, 4, 0, nil) // H=5
|
||||
require.Equal(t, false, applied)
|
||||
|
||||
@@ -388,7 +388,7 @@ func (m *EventFilterManager) Install(ctx context.Context, minHeight, maxHeight a
|
||||
|
||||
if m.EventIndex != nil && minHeight != -1 && minHeight < currentHeight {
|
||||
// Filter needs historic events
|
||||
if err := m.EventIndex.PrefillFilter(ctx, f); err != nil {
|
||||
if err := m.EventIndex.PrefillFilter(ctx, f, true); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ var ddls = []string{
|
||||
)`,
|
||||
|
||||
`CREATE INDEX IF NOT EXISTS height_tipset_key ON event (height,tipset_key)`,
|
||||
`CREATE INDEX IF NOT EXISTS event_emitter_addr ON event (emitter_addr)`,
|
||||
|
||||
`CREATE TABLE IF NOT EXISTS event_entry (
|
||||
event_id INTEGER,
|
||||
@@ -56,6 +57,8 @@ var ddls = []string{
|
||||
value BLOB NOT NULL
|
||||
)`,
|
||||
|
||||
`CREATE INDEX IF NOT EXISTS event_entry_key_index ON event_entry (key)`,
|
||||
|
||||
// metadata containing version of schema
|
||||
`CREATE TABLE IF NOT EXISTS _meta (
|
||||
version UINT64 NOT NULL UNIQUE
|
||||
@@ -63,6 +66,7 @@ var ddls = []string{
|
||||
|
||||
`INSERT OR IGNORE INTO _meta (version) VALUES (1)`,
|
||||
`INSERT OR IGNORE INTO _meta (version) VALUES (2)`,
|
||||
`INSERT OR IGNORE INTO _meta (version) VALUES (3)`,
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -70,7 +74,7 @@ var (
|
||||
)
|
||||
|
||||
const (
|
||||
schemaVersion = 2
|
||||
schemaVersion = 3
|
||||
|
||||
eventExists = `SELECT MAX(id) FROM event WHERE height=? AND tipset_key=? AND tipset_key_cid=? AND emitter_addr=? AND event_index=? AND message_cid=? AND message_index=?`
|
||||
insertEvent = `INSERT OR IGNORE INTO event(height, tipset_key, tipset_key_cid, emitter_addr, event_index, message_cid, message_index, reverted) VALUES(?, ?, ?, ?, ?, ?, ?, ?)`
|
||||
@@ -321,6 +325,22 @@ func NewEventIndex(ctx context.Context, path string, chainStore *store.ChainStor
|
||||
version = 2
|
||||
}
|
||||
|
||||
if version == 2 {
|
||||
log.Infof("upgrading event index from version 2 to version 3")
|
||||
|
||||
// to upgrade to version 3 we only need to create an index on the event_entry.key column
|
||||
// and on the event.emitter_addr column
|
||||
// which means we can just reapply the schema (it will not have any effect on existing data)
|
||||
for _, ddl := range ddls {
|
||||
if _, err := db.Exec(ddl); err != nil {
|
||||
_ = db.Close()
|
||||
return nil, xerrors.Errorf("could not upgrade index to version 3, exec ddl %q: %w", ddl, err)
|
||||
}
|
||||
}
|
||||
|
||||
version = 3
|
||||
}
|
||||
|
||||
if version != schemaVersion {
|
||||
_ = db.Close()
|
||||
return nil, xerrors.Errorf("invalid database version: got %d, expected %d", version, schemaVersion)
|
||||
@@ -481,7 +501,7 @@ func (ei *EventIndex) CollectEvents(ctx context.Context, te *TipSetEvents, rever
|
||||
}
|
||||
|
||||
// PrefillFilter fills a filter's collection of events from the historic index
|
||||
func (ei *EventIndex) PrefillFilter(ctx context.Context, f *EventFilter) error {
|
||||
func (ei *EventIndex) PrefillFilter(ctx context.Context, f *EventFilter, excludeReverted bool) error {
|
||||
clauses := []string{}
|
||||
values := []any{}
|
||||
joins := []string{}
|
||||
@@ -500,6 +520,11 @@ func (ei *EventIndex) PrefillFilter(ctx context.Context, f *EventFilter) error {
|
||||
}
|
||||
}
|
||||
|
||||
if excludeReverted {
|
||||
clauses = append(clauses, "event.reverted=?")
|
||||
values = append(values, false)
|
||||
}
|
||||
|
||||
if len(f.addresses) > 0 {
|
||||
subclauses := []string{}
|
||||
for _, addr := range f.addresses {
|
||||
|
||||
@@ -272,7 +272,7 @@ func TestEventIndexPrefillFilter(t *testing.T) {
|
||||
for _, tc := range testCases {
|
||||
tc := tc // appease lint
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
if err := ei.PrefillFilter(context.Background(), tc.filter); err != nil {
|
||||
if err := ei.PrefillFilter(context.Background(), tc.filter, false); err != nil {
|
||||
require.NoError(t, err, "prefill filter events")
|
||||
}
|
||||
|
||||
@@ -281,3 +281,619 @@ func TestEventIndexPrefillFilter(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEventIndexPrefillFilterExcludeReverted(t *testing.T) {
|
||||
rng := pseudo.New(pseudo.NewSource(299792458))
|
||||
a1 := randomF4Addr(t, rng)
|
||||
a2 := randomF4Addr(t, rng)
|
||||
a3 := randomF4Addr(t, rng)
|
||||
|
||||
a1ID := abi.ActorID(1)
|
||||
a2ID := abi.ActorID(2)
|
||||
|
||||
addrMap := addressMap{}
|
||||
addrMap.add(a1ID, a1)
|
||||
addrMap.add(a2ID, a2)
|
||||
|
||||
ev1 := fakeEvent(
|
||||
a1ID,
|
||||
[]kv{
|
||||
{k: "type", v: []byte("approval")},
|
||||
{k: "signer", v: []byte("addr1")},
|
||||
},
|
||||
[]kv{
|
||||
{k: "amount", v: []byte("2988181")},
|
||||
},
|
||||
)
|
||||
ev2 := fakeEvent(
|
||||
a2ID,
|
||||
[]kv{
|
||||
{k: "type", v: []byte("approval")},
|
||||
{k: "signer", v: []byte("addr2")},
|
||||
},
|
||||
[]kv{
|
||||
{k: "amount", v: []byte("2988182")},
|
||||
},
|
||||
)
|
||||
|
||||
st := newStore()
|
||||
events := []*types.Event{ev1}
|
||||
revertedEvents := []*types.Event{ev2}
|
||||
em := executedMessage{
|
||||
msg: fakeMessage(randomF4Addr(t, rng), randomF4Addr(t, rng)),
|
||||
rct: fakeReceipt(t, rng, st, events),
|
||||
evs: events,
|
||||
}
|
||||
revertedEm := executedMessage{
|
||||
msg: fakeMessage(randomF4Addr(t, rng), randomF4Addr(t, rng)),
|
||||
rct: fakeReceipt(t, rng, st, revertedEvents),
|
||||
evs: revertedEvents,
|
||||
}
|
||||
|
||||
events14000 := buildTipSetEvents(t, rng, 14000, em)
|
||||
revertedEvents14000 := buildTipSetEvents(t, rng, 14000, revertedEm)
|
||||
cid14000, err := events14000.msgTs.Key().Cid()
|
||||
require.NoError(t, err, "tipset cid")
|
||||
reveredCID14000, err := revertedEvents14000.msgTs.Key().Cid()
|
||||
require.NoError(t, err, "tipset cid")
|
||||
|
||||
noCollectedEvents := []*CollectedEvent{}
|
||||
oneCollectedEvent := []*CollectedEvent{
|
||||
{
|
||||
Entries: ev1.Entries,
|
||||
EmitterAddr: a1,
|
||||
EventIdx: 0,
|
||||
Reverted: false,
|
||||
Height: 14000,
|
||||
TipSetKey: events14000.msgTs.Key(),
|
||||
MsgIdx: 0,
|
||||
MsgCid: em.msg.Cid(),
|
||||
},
|
||||
}
|
||||
twoCollectedEvent := []*CollectedEvent{
|
||||
{
|
||||
Entries: ev1.Entries,
|
||||
EmitterAddr: a1,
|
||||
EventIdx: 0,
|
||||
Reverted: false,
|
||||
Height: 14000,
|
||||
TipSetKey: events14000.msgTs.Key(),
|
||||
MsgIdx: 0,
|
||||
MsgCid: em.msg.Cid(),
|
||||
},
|
||||
{
|
||||
Entries: ev2.Entries,
|
||||
EmitterAddr: a2,
|
||||
EventIdx: 0,
|
||||
Reverted: true,
|
||||
Height: 14000,
|
||||
TipSetKey: revertedEvents14000.msgTs.Key(),
|
||||
MsgIdx: 0,
|
||||
MsgCid: revertedEm.msg.Cid(),
|
||||
},
|
||||
}
|
||||
oneCollectedRevertedEvent := []*CollectedEvent{
|
||||
{
|
||||
Entries: ev2.Entries,
|
||||
EmitterAddr: a2,
|
||||
EventIdx: 0,
|
||||
Reverted: true,
|
||||
Height: 14000,
|
||||
TipSetKey: revertedEvents14000.msgTs.Key(),
|
||||
MsgIdx: 0,
|
||||
MsgCid: revertedEm.msg.Cid(),
|
||||
},
|
||||
}
|
||||
|
||||
workDir, err := os.MkdirTemp("", "lotusevents")
|
||||
require.NoError(t, err, "create temporary work directory")
|
||||
|
||||
defer func() {
|
||||
_ = os.RemoveAll(workDir)
|
||||
}()
|
||||
t.Logf("using work dir %q", workDir)
|
||||
|
||||
dbPath := filepath.Join(workDir, "actorevents.db")
|
||||
|
||||
ei, err := NewEventIndex(context.Background(), dbPath, nil)
|
||||
require.NoError(t, err, "create event index")
|
||||
if err := ei.CollectEvents(context.Background(), revertedEvents14000, false, addrMap.ResolveAddress); err != nil {
|
||||
require.NoError(t, err, "collect reverted events")
|
||||
}
|
||||
if err := ei.CollectEvents(context.Background(), revertedEvents14000, true, addrMap.ResolveAddress); err != nil {
|
||||
require.NoError(t, err, "revert reverted events")
|
||||
}
|
||||
if err := ei.CollectEvents(context.Background(), events14000, false, addrMap.ResolveAddress); err != nil {
|
||||
require.NoError(t, err, "collect events")
|
||||
}
|
||||
|
||||
inclusiveTestCases := []struct {
|
||||
name string
|
||||
filter *EventFilter
|
||||
te *TipSetEvents
|
||||
want []*CollectedEvent
|
||||
}{
|
||||
{
|
||||
name: "nomatch tipset min height",
|
||||
filter: &EventFilter{
|
||||
minHeight: 14001,
|
||||
maxHeight: -1,
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "nomatch tipset max height",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: 13999,
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "match tipset min height",
|
||||
filter: &EventFilter{
|
||||
minHeight: 14000,
|
||||
maxHeight: -1,
|
||||
},
|
||||
te: events14000,
|
||||
want: twoCollectedEvent,
|
||||
},
|
||||
{
|
||||
name: "match tipset cid",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
tipsetCid: cid14000,
|
||||
},
|
||||
te: events14000,
|
||||
want: oneCollectedEvent,
|
||||
},
|
||||
{
|
||||
name: "match tipset cid",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
tipsetCid: reveredCID14000,
|
||||
},
|
||||
te: revertedEvents14000,
|
||||
want: oneCollectedRevertedEvent,
|
||||
},
|
||||
{
|
||||
name: "nomatch address",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
addresses: []address.Address{a3},
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "match address 2",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
addresses: []address.Address{a2},
|
||||
},
|
||||
te: revertedEvents14000,
|
||||
want: oneCollectedRevertedEvent,
|
||||
},
|
||||
{
|
||||
name: "match address 1",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
addresses: []address.Address{a1},
|
||||
},
|
||||
te: events14000,
|
||||
want: oneCollectedEvent,
|
||||
},
|
||||
{
|
||||
name: "match one entry",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"type": {
|
||||
[]byte("approval"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: twoCollectedEvent,
|
||||
},
|
||||
{
|
||||
name: "match one entry with alternate values",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"type": {
|
||||
[]byte("cancel"),
|
||||
[]byte("propose"),
|
||||
[]byte("approval"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: twoCollectedEvent,
|
||||
},
|
||||
{
|
||||
name: "nomatch one entry by missing value",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"type": {
|
||||
[]byte("cancel"),
|
||||
[]byte("propose"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "nomatch one entry by missing key",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"method": {
|
||||
[]byte("approval"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "match one entry with multiple keys",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"type": {
|
||||
[]byte("approval"),
|
||||
},
|
||||
"signer": {
|
||||
[]byte("addr1"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: oneCollectedEvent,
|
||||
},
|
||||
{
|
||||
name: "match one entry with multiple keys",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"type": {
|
||||
[]byte("approval"),
|
||||
},
|
||||
"signer": {
|
||||
[]byte("addr2"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: revertedEvents14000,
|
||||
want: oneCollectedRevertedEvent,
|
||||
},
|
||||
{
|
||||
name: "nomatch one entry with one mismatching key",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"type": {
|
||||
[]byte("approval"),
|
||||
},
|
||||
"approver": {
|
||||
[]byte("addr1"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "nomatch one entry with one mismatching value",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"type": {
|
||||
[]byte("approval"),
|
||||
},
|
||||
"signer": {
|
||||
[]byte("addr3"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "nomatch one entry with one unindexed key",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"amount": {
|
||||
[]byte("2988181"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "nomatch one entry with one unindexed key",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"amount": {
|
||||
[]byte("2988182"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
}
|
||||
|
||||
exclusiveTestCases := []struct {
|
||||
name string
|
||||
filter *EventFilter
|
||||
te *TipSetEvents
|
||||
want []*CollectedEvent
|
||||
}{
|
||||
{
|
||||
name: "nomatch tipset min height",
|
||||
filter: &EventFilter{
|
||||
minHeight: 14001,
|
||||
maxHeight: -1,
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "nomatch tipset max height",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: 13999,
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "match tipset min height",
|
||||
filter: &EventFilter{
|
||||
minHeight: 14000,
|
||||
maxHeight: -1,
|
||||
},
|
||||
te: events14000,
|
||||
want: oneCollectedEvent,
|
||||
},
|
||||
{
|
||||
name: "match tipset cid",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
tipsetCid: cid14000,
|
||||
},
|
||||
te: events14000,
|
||||
want: oneCollectedEvent,
|
||||
},
|
||||
{
|
||||
name: "match tipset cid but reverted",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
tipsetCid: reveredCID14000,
|
||||
},
|
||||
te: revertedEvents14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "nomatch address",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
addresses: []address.Address{a3},
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "nomatch address 2 but reverted",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
addresses: []address.Address{a2},
|
||||
},
|
||||
te: revertedEvents14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "match address",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
addresses: []address.Address{a1},
|
||||
},
|
||||
te: events14000,
|
||||
want: oneCollectedEvent,
|
||||
},
|
||||
{
|
||||
name: "match one entry",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"type": {
|
||||
[]byte("approval"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: oneCollectedEvent,
|
||||
},
|
||||
{
|
||||
name: "match one entry with alternate values",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"type": {
|
||||
[]byte("cancel"),
|
||||
[]byte("propose"),
|
||||
[]byte("approval"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: oneCollectedEvent,
|
||||
},
|
||||
{
|
||||
name: "nomatch one entry by missing value",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"type": {
|
||||
[]byte("cancel"),
|
||||
[]byte("propose"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "nomatch one entry by missing key",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"method": {
|
||||
[]byte("approval"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "match one entry with multiple keys",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"type": {
|
||||
[]byte("approval"),
|
||||
},
|
||||
"signer": {
|
||||
[]byte("addr1"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: oneCollectedEvent,
|
||||
},
|
||||
{
|
||||
name: "nomatch one entry with one mismatching key",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"type": {
|
||||
[]byte("approval"),
|
||||
},
|
||||
"approver": {
|
||||
[]byte("addr1"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "nomatch one entry with matching reverted value",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"type": {
|
||||
[]byte("approval"),
|
||||
},
|
||||
"signer": {
|
||||
[]byte("addr2"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "nomatch one entry with one mismatching value",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"type": {
|
||||
[]byte("approval"),
|
||||
},
|
||||
"signer": {
|
||||
[]byte("addr3"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "nomatch one entry with one unindexed key",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"amount": {
|
||||
[]byte("2988181"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range inclusiveTestCases {
|
||||
tc := tc // appease lint
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
if err := ei.PrefillFilter(context.Background(), tc.filter, false); err != nil {
|
||||
require.NoError(t, err, "prefill filter events")
|
||||
}
|
||||
|
||||
coll := tc.filter.TakeCollectedEvents(context.Background())
|
||||
require.ElementsMatch(t, coll, tc.want, tc.name)
|
||||
})
|
||||
}
|
||||
|
||||
for _, tc := range exclusiveTestCases {
|
||||
tc := tc // appease lint
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
if err := ei.PrefillFilter(context.Background(), tc.filter, true); err != nil {
|
||||
require.NoError(t, err, "prefill filter events")
|
||||
}
|
||||
|
||||
coll := tc.filter.TakeCollectedEvents(context.Background())
|
||||
require.ElementsMatch(t, coll, tc.want, tc.name)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
package state
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
)
|
||||
|
||||
type contextStore struct {
|
||||
ctx context.Context
|
||||
cst *cbor.BasicIpldStore
|
||||
}
|
||||
|
||||
func (cs *contextStore) Context() context.Context {
|
||||
return cs.ctx
|
||||
}
|
||||
|
||||
func (cs *contextStore) Get(ctx context.Context, c cid.Cid, out interface{}) error {
|
||||
return cs.cst.Get(ctx, c, out)
|
||||
}
|
||||
|
||||
func (cs *contextStore) Put(ctx context.Context, v interface{}) (cid.Cid, error) {
|
||||
return cs.cst.Put(ctx, v)
|
||||
}
|
||||
@@ -242,7 +242,7 @@ func (c *client) processResponse(req *Request, res *Response, tipsets []*types.T
|
||||
// If we didn't request the headers they should have been provided
|
||||
// by the caller.
|
||||
if len(tipsets) < len(res.Chain) {
|
||||
return nil, xerrors.Errorf("not enought tipsets provided for message response validation, needed %d, have %d", len(res.Chain), len(tipsets))
|
||||
return nil, xerrors.Errorf("not enough tipsets provided for message response validation, needed %d, have %d", len(res.Chain), len(tipsets))
|
||||
}
|
||||
chain := make([]*BSTipSet, 0, resLength)
|
||||
for i, resChain := range res.Chain {
|
||||
@@ -381,7 +381,7 @@ func (c *client) sendRequestToPeer(ctx context.Context, peer peer.ID, req *Reque
|
||||
defer span.End()
|
||||
if span.IsRecordingEvents() {
|
||||
span.AddAttributes(
|
||||
trace.StringAttribute("peer", peer.Pretty()),
|
||||
trace.StringAttribute("peer", peer.String()),
|
||||
)
|
||||
}
|
||||
defer func() {
|
||||
|
||||
@@ -131,7 +131,7 @@ func NewMsgIndex(lctx context.Context, basePath string, cs ChainStore) (MsgIndex
|
||||
|
||||
db, err := sql.Open("sqlite3", dbPath)
|
||||
if err != nil {
|
||||
// TODO [nice to have]: automaticaly delete corrupt databases
|
||||
// TODO [nice to have]: automatically delete corrupt databases
|
||||
// but for now we can just error and let the operator delete.
|
||||
return nil, xerrors.Errorf("error opening msgindex database: %w", err)
|
||||
}
|
||||
|
||||
@@ -39,23 +39,6 @@ func (ps *Store) save(ctx context.Context, state *FundedAddressState) error {
|
||||
return ps.ds.Put(ctx, k, b)
|
||||
}
|
||||
|
||||
// get the state for the given address
|
||||
func (ps *Store) get(ctx context.Context, addr address.Address) (*FundedAddressState, error) {
|
||||
k := dskeyForAddr(addr)
|
||||
|
||||
data, err := ps.ds.Get(ctx, k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var state FundedAddressState
|
||||
err = cborrpc.ReadCborRPC(bytes.NewReader(data), &state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &state, nil
|
||||
}
|
||||
|
||||
// forEach calls iter with each address in the datastore
|
||||
func (ps *Store) forEach(ctx context.Context, iter func(*FundedAddressState)) error {
|
||||
res, err := ps.ds.Query(ctx, dsq.Query{Prefix: dsKeyAddr})
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
||||
"github.com/minio/blake2b-simd"
|
||||
"github.com/raulk/clock"
|
||||
"go.opencensus.io/stats"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
ffi "github.com/filecoin-project/filecoin-ffi"
|
||||
@@ -210,8 +211,10 @@ func ComputeRBF(curPrem abi.TokenAmount, replaceByFeeRatio types.Percent) abi.To
|
||||
|
||||
func CapGasFee(mff dtypes.DefaultMaxFeeFunc, msg *types.Message, sendSpec *api.MessageSendSpec) {
|
||||
var maxFee abi.TokenAmount
|
||||
var maximizeFeeCap bool
|
||||
if sendSpec != nil {
|
||||
maxFee = sendSpec.MaxFee
|
||||
maximizeFeeCap = sendSpec.MaximizeFeeCap
|
||||
}
|
||||
if maxFee.Int == nil || maxFee.Equals(big.Zero()) {
|
||||
mf, err := mff()
|
||||
@@ -222,15 +225,12 @@ func CapGasFee(mff dtypes.DefaultMaxFeeFunc, msg *types.Message, sendSpec *api.M
|
||||
maxFee = mf
|
||||
}
|
||||
|
||||
gl := types.NewInt(uint64(msg.GasLimit))
|
||||
totalFee := types.BigMul(msg.GasFeeCap, gl)
|
||||
|
||||
if totalFee.LessThanEqual(maxFee) {
|
||||
msg.GasPremium = big.Min(msg.GasFeeCap, msg.GasPremium) // cap premium at FeeCap
|
||||
return
|
||||
gaslimit := types.NewInt(uint64(msg.GasLimit))
|
||||
totalFee := types.BigMul(msg.GasFeeCap, gaslimit)
|
||||
if maximizeFeeCap || totalFee.GreaterThan(maxFee) {
|
||||
msg.GasFeeCap = big.Div(maxFee, gaslimit)
|
||||
}
|
||||
|
||||
msg.GasFeeCap = big.Div(maxFee, gl)
|
||||
msg.GasPremium = big.Min(msg.GasFeeCap, msg.GasPremium) // cap premium at FeeCap
|
||||
}
|
||||
|
||||
@@ -1022,6 +1022,9 @@ func (mp *MessagePool) addLocked(ctx context.Context, m *types.SignedMessage, st
|
||||
}
|
||||
})
|
||||
|
||||
// Record the current size of the Mpool
|
||||
stats.Record(ctx, metrics.MpoolMessageCount.M(int64(mp.currentSize)))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1214,6 +1217,9 @@ func (mp *MessagePool) remove(ctx context.Context, from address.Address, nonce u
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Record the current size of the Mpool
|
||||
stats.Record(ctx, metrics.MpoolMessageCount.M(int64(mp.currentSize)))
|
||||
}
|
||||
|
||||
func (mp *MessagePool) Pending(ctx context.Context) ([]*types.SignedMessage, *types.TipSet) {
|
||||
|
||||
@@ -570,7 +570,7 @@ func (st *StateTree) ForEach(f func(address.Address, *types.Actor) error) error
|
||||
}
|
||||
|
||||
// no need to record anything here, there are no duplicates in the actors HAMT
|
||||
// iself.
|
||||
// itself.
|
||||
if _, ok := seen[addr]; ok {
|
||||
return nil
|
||||
}
|
||||
@@ -588,7 +588,7 @@ func (st *StateTree) ForEach(f func(address.Address, *types.Actor) error) error
|
||||
}
|
||||
|
||||
// no need to record anything here, there are no duplicates in the actors HAMT
|
||||
// iself.
|
||||
// itself.
|
||||
if _, ok := seen[addr]; ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -235,11 +235,6 @@ func (sm *StateManager) hasExpensiveForkBetween(parent, height abi.ChainEpoch) b
|
||||
return false
|
||||
}
|
||||
|
||||
func (sm *StateManager) hasExpensiveFork(height abi.ChainEpoch) bool {
|
||||
_, ok := sm.expensiveUpgrades[height]
|
||||
return ok
|
||||
}
|
||||
|
||||
func runPreMigration(ctx context.Context, sm *StateManager, fn PreMigrationFunc, cache *nv16.MemMigrationCache, ts *types.TipSet) {
|
||||
height := ts.Height()
|
||||
parent := ts.ParentState()
|
||||
|
||||
@@ -42,7 +42,7 @@ func TestIndexSeeks(t *testing.T) {
|
||||
cs := store.NewChainStore(nbs, nbs, syncds.MutexWrap(datastore.NewMapDatastore()), filcns.Weight, nil)
|
||||
defer cs.Close() //nolint:errcheck
|
||||
|
||||
_, err = cs.Import(ctx, bytes.NewReader(gencar))
|
||||
_, _, err = cs.Import(ctx, bytes.NewReader(gencar))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -212,13 +212,8 @@ func (cs *ChainStore) MessagesForTipset(ctx context.Context, ts *types.TipSet) (
|
||||
|
||||
var out []types.ChainMsg
|
||||
for _, bm := range bmsgs {
|
||||
for _, blsm := range bm.BlsMessages {
|
||||
out = append(out, blsm)
|
||||
}
|
||||
|
||||
for _, secm := range bm.SecpkMessages {
|
||||
out = append(out, secm)
|
||||
}
|
||||
out = append(out, bm.BlsMessages...)
|
||||
out = append(out, bm.SecpkMessages...)
|
||||
}
|
||||
|
||||
return out, nil
|
||||
|
||||
+39
-13
@@ -60,7 +60,7 @@ func (cs *ChainStore) Export(ctx context.Context, ts *types.TipSet, inclRecentRo
|
||||
})
|
||||
}
|
||||
|
||||
func (cs *ChainStore) Import(ctx context.Context, r io.Reader) (*types.TipSet, error) {
|
||||
func (cs *ChainStore) Import(ctx context.Context, r io.Reader) (head *types.TipSet, genesis *types.BlockHeader, err error) {
|
||||
// TODO: writing only to the state blockstore is incorrect.
|
||||
// At this time, both the state and chain blockstores are backed by the
|
||||
// universal store. When we physically segregate the stores, we will need
|
||||
@@ -69,7 +69,7 @@ func (cs *ChainStore) Import(ctx context.Context, r io.Reader) (*types.TipSet, e
|
||||
|
||||
br, err := carv2.NewBlockReader(r)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("loadcar failed: %w", err)
|
||||
return nil, nil, xerrors.Errorf("loadcar failed: %w", err)
|
||||
}
|
||||
|
||||
s := cs.StateBlockstore()
|
||||
@@ -80,27 +80,51 @@ func (cs *ChainStore) Import(ctx context.Context, r io.Reader) (*types.TipSet, e
|
||||
putThrottle <- nil
|
||||
}
|
||||
|
||||
if len(br.Roots) == 0 {
|
||||
return nil, nil, xerrors.Errorf("no roots in snapshot car file")
|
||||
}
|
||||
nextTailCid := br.Roots[0]
|
||||
|
||||
var tailBlock types.BlockHeader
|
||||
tailBlock.Height = abi.ChainEpoch(-1)
|
||||
|
||||
var buf []blocks.Block
|
||||
for {
|
||||
blk, err := br.Next()
|
||||
if err != nil {
|
||||
|
||||
// we're at the end
|
||||
if err == io.EOF {
|
||||
if len(buf) > 0 {
|
||||
if err := s.PutMany(ctx, buf); err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// check for header block, looking for genesis
|
||||
if blk.Cid() == nextTailCid && tailBlock.Height != 0 {
|
||||
if err := tailBlock.UnmarshalCBOR(bytes.NewReader(blk.RawData())); err != nil {
|
||||
return nil, nil, xerrors.Errorf("failed to unmarshal genesis block: %w", err)
|
||||
}
|
||||
if len(tailBlock.Parents) > 0 {
|
||||
nextTailCid = tailBlock.Parents[0]
|
||||
} else {
|
||||
// note: even the 0th block has a parent linking to the cbor genesis block
|
||||
return nil, nil, xerrors.Errorf("current block (epoch %d cid %s) has no parents", tailBlock.Height, tailBlock.Cid())
|
||||
}
|
||||
}
|
||||
|
||||
// append to batch
|
||||
buf = append(buf, blk)
|
||||
|
||||
if len(buf) > 1000 {
|
||||
if lastErr := <-putThrottle; lastErr != nil { // consume one error to have the right to add one
|
||||
return nil, lastErr
|
||||
return nil, nil, lastErr
|
||||
}
|
||||
|
||||
go func(buf []blocks.Block) {
|
||||
@@ -113,13 +137,17 @@ func (cs *ChainStore) Import(ctx context.Context, r io.Reader) (*types.TipSet, e
|
||||
// check errors
|
||||
for i := 0; i < parallelPuts; i++ {
|
||||
if lastErr := <-putThrottle; lastErr != nil {
|
||||
return nil, lastErr
|
||||
return nil, nil, lastErr
|
||||
}
|
||||
}
|
||||
|
||||
if tailBlock.Height != 0 {
|
||||
return nil, nil, xerrors.Errorf("expected genesis block to have height 0 (genesis), got %d: %s", tailBlock.Height, tailBlock.Cid())
|
||||
}
|
||||
|
||||
root, err := cs.LoadTipSet(ctx, types.NewTipSetKey(br.Roots...))
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to load root tipset from chainfile: %w", err)
|
||||
return nil, nil, xerrors.Errorf("failed to load root tipset from chainfile: %w", err)
|
||||
}
|
||||
|
||||
ts := root
|
||||
@@ -135,10 +163,10 @@ func (cs *ChainStore) Import(ctx context.Context, r io.Reader) (*types.TipSet, e
|
||||
}
|
||||
|
||||
if err := cs.PersistTipsets(ctx, tssToPersist); err != nil {
|
||||
return nil, xerrors.Errorf("failed to persist tipsets: %w", err)
|
||||
return nil, nil, xerrors.Errorf("failed to persist tipsets: %w", err)
|
||||
}
|
||||
|
||||
return root, nil
|
||||
return root, &tailBlock, nil
|
||||
}
|
||||
|
||||
type walkSchedTaskType int
|
||||
@@ -167,7 +195,7 @@ func (t walkSchedTaskType) String() string {
|
||||
case dagTask:
|
||||
return "dag"
|
||||
}
|
||||
panic(fmt.Sprintf("unknow task %d", t))
|
||||
panic(fmt.Sprintf("unknown task %d", t))
|
||||
}
|
||||
|
||||
type walkTask struct {
|
||||
@@ -656,9 +684,7 @@ func (cs *ChainStore) WalkSnapshot(ctx context.Context, ts *types.TipSet, inclRe
|
||||
}
|
||||
|
||||
if b.Height > 0 {
|
||||
for _, p := range b.Parents {
|
||||
blocksToWalk = append(blocksToWalk, p)
|
||||
}
|
||||
blocksToWalk = append(blocksToWalk, b.Parents...)
|
||||
} else {
|
||||
// include the genesis block
|
||||
cids = append(cids, b.Parents...)
|
||||
|
||||
@@ -118,7 +118,7 @@ func TestChainExportImport(t *testing.T) {
|
||||
cs := store.NewChainStore(nbs, nbs, datastore.NewMapDatastore(), filcns.Weight, nil)
|
||||
defer cs.Close() //nolint:errcheck
|
||||
|
||||
root, err := cs.Import(context.TODO(), buf)
|
||||
root, _, err := cs.Import(context.TODO(), buf)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -153,7 +153,7 @@ func TestChainImportTipsetKeyCid(t *testing.T) {
|
||||
cs := store.NewChainStore(nbs, nbs, datastore.NewMapDatastore(), filcns.Weight, nil)
|
||||
defer cs.Close() //nolint:errcheck
|
||||
|
||||
root, err := cs.Import(ctx, buf)
|
||||
root, _, err := cs.Import(ctx, buf)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Truef(t, root.Equals(last), "imported chain differed from exported chain")
|
||||
@@ -202,7 +202,7 @@ func TestChainExportImportFull(t *testing.T) {
|
||||
cs := store.NewChainStore(nbs, nbs, ds, filcns.Weight, nil)
|
||||
defer cs.Close() //nolint:errcheck
|
||||
|
||||
root, err := cs.Import(context.TODO(), buf)
|
||||
root, _, err := cs.Import(context.TODO(), buf)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -516,7 +516,7 @@ func (v *IndexerMessageValidator) Validate(ctx context.Context, pid peer.ID, msg
|
||||
return pubsub.ValidationReject
|
||||
}
|
||||
if len(idxrMsg.ExtraData) == 0 {
|
||||
log.Debugw("ignoring messsage missing miner id", "peer", originPeer)
|
||||
log.Debugw("ignoring message missing miner id", "peer", originPeer)
|
||||
return pubsub.ValidationIgnore
|
||||
}
|
||||
|
||||
@@ -552,7 +552,7 @@ func (v *IndexerMessageValidator) Validate(ctx context.Context, pid peer.ID, msg
|
||||
// Check that the miner ID maps to the peer that sent the message.
|
||||
err = v.authenticateMessage(ctx, minerAddr, originPeer)
|
||||
if err != nil {
|
||||
log.Warnw("cannot authenticate messsage", "err", err, "peer", originPeer, "minerID", minerAddr)
|
||||
log.Warnw("cannot authenticate message", "err", err, "peer", originPeer, "minerID", minerAddr)
|
||||
stats.Record(ctx, metrics.IndexerMessageValidationFailure.M(1))
|
||||
return pubsub.ValidationReject
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package ratelimit
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestQueue(t *testing.T) {
|
||||
const size = 3
|
||||
q := &queue{buf: make([]int64, size)}
|
||||
|
||||
if q.len() != 0 {
|
||||
t.Fatalf("q.len() = %d, expect 0", q.len())
|
||||
}
|
||||
|
||||
if q.cap() != size {
|
||||
t.Fatalf("q.cap() = %d, expect %d", q.cap(), size)
|
||||
}
|
||||
|
||||
for i := int64(0); i < int64(size); i++ {
|
||||
err := q.push(i)
|
||||
if err != nil {
|
||||
t.Fatalf("cannot push element %d", i)
|
||||
}
|
||||
}
|
||||
|
||||
if q.len() != size {
|
||||
t.Fatalf("q.len() = %d, expect %d", q.len(), size)
|
||||
}
|
||||
|
||||
err := q.push(int64(size))
|
||||
if err != ErrRateLimitExceeded {
|
||||
t.Fatalf("pushing element beyond capacity should have failed with err: %s, got %s", ErrRateLimitExceeded, err)
|
||||
}
|
||||
|
||||
if q.front() != 0 {
|
||||
t.Fatalf("q.front() = %d, expect 0", q.front())
|
||||
}
|
||||
|
||||
if q.back() != int64(size-1) {
|
||||
t.Fatalf("q.back() = %d, expect %d", q.back(), size-1)
|
||||
}
|
||||
|
||||
popVal := q.pop()
|
||||
if popVal != 0 {
|
||||
t.Fatalf("q.pop() = %d, expect 0", popVal)
|
||||
}
|
||||
|
||||
if q.len() != size-1 {
|
||||
t.Fatalf("q.len() = %d, expect %d", q.len(), size-1)
|
||||
}
|
||||
|
||||
// Testing truncation.
|
||||
threshold := int64(1)
|
||||
q.truncate(threshold)
|
||||
if q.len() != 1 {
|
||||
t.Fatalf("q.len() after truncate = %d, expect 1", q.len())
|
||||
}
|
||||
if q.front() != 2 {
|
||||
t.Fatalf("q.front() after truncate = %d, expect 2", q.front())
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -844,7 +844,7 @@ loop:
|
||||
return nil, xerrors.Errorf("failed to load next local tipset: %w", err)
|
||||
}
|
||||
if base.IsChildOf(knownParent) {
|
||||
// common case: receiving a block thats potentially part of the same tipset as our best block
|
||||
// common case: receiving a block that's potentially part of the same tipset as our best block
|
||||
return blockSet, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/ipfs/go-cid"
|
||||
ds "github.com/ipfs/go-datastore"
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
"github.com/libp2p/go-libp2p/core/peer"
|
||||
mocknet "github.com/libp2p/go-libp2p/p2p/net/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
@@ -344,13 +343,6 @@ func (tu *syncTestUtil) addClientNode() int {
|
||||
return len(tu.nds) - 1
|
||||
}
|
||||
|
||||
func (tu *syncTestUtil) pid(n int) peer.ID {
|
||||
nal, err := tu.nds[n].NetAddrsListen(tu.ctx)
|
||||
require.NoError(tu.t, err)
|
||||
|
||||
return nal.ID
|
||||
}
|
||||
|
||||
func (tu *syncTestUtil) connect(from, to int) {
|
||||
toPI, err := tu.nds[to].NetAddrsListen(tu.ctx)
|
||||
require.NoError(tu.t, err)
|
||||
|
||||
@@ -7,9 +7,6 @@ import (
|
||||
)
|
||||
|
||||
func TestDecodeBlockMsg(t *testing.T) {
|
||||
type args struct {
|
||||
b []byte
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
data []byte
|
||||
|
||||
@@ -62,9 +62,14 @@ type EthTxArgs struct {
|
||||
// - BlockHash
|
||||
// - BlockNumber
|
||||
// - TransactionIndex
|
||||
// - From
|
||||
// - Hash
|
||||
func EthTxFromSignedEthMessage(smsg *types.SignedMessage) (EthTx, error) {
|
||||
// The from address is always an f410f address, never an ID or other address.
|
||||
if !IsEthAddress(smsg.Message.From) {
|
||||
return EthTx{}, xerrors.Errorf("sender must be an eth account, was %s", smsg.Message.From)
|
||||
}
|
||||
|
||||
// Probably redundant, but we might as well check.
|
||||
if smsg.Signature.Type != typescrypto.SigTypeDelegated {
|
||||
return EthTx{}, xerrors.Errorf("signature is not delegated type, is type: %d", smsg.Signature.Type)
|
||||
}
|
||||
@@ -79,10 +84,18 @@ func EthTxFromSignedEthMessage(smsg *types.SignedMessage) (EthTx, error) {
|
||||
return EthTx{}, xerrors.Errorf("failed to recover signature: %w", err)
|
||||
}
|
||||
|
||||
from, err := EthAddressFromFilecoinAddress(smsg.Message.From)
|
||||
if err != nil {
|
||||
// This should be impossible as we've already asserted that we have an EthAddress
|
||||
// sender...
|
||||
return EthTx{}, xerrors.Errorf("sender was not an eth account")
|
||||
}
|
||||
|
||||
return EthTx{
|
||||
Nonce: EthUint64(txArgs.Nonce),
|
||||
ChainID: EthUint64(txArgs.ChainID),
|
||||
To: txArgs.To,
|
||||
From: from,
|
||||
Value: EthBigInt(txArgs.Value),
|
||||
Type: Eip1559TxType,
|
||||
Gas: EthUint64(txArgs.GasLimit),
|
||||
|
||||
@@ -799,6 +799,45 @@ func GetContractEthAddressFromCode(sender EthAddress, salt [32]byte, initcode []
|
||||
return ethAddr, nil
|
||||
}
|
||||
|
||||
// EthEstimateGasParams handles raw jsonrpc params for eth_estimateGas
|
||||
type EthEstimateGasParams struct {
|
||||
Tx EthCall
|
||||
BlkParam *EthBlockNumberOrHash
|
||||
}
|
||||
|
||||
func (e *EthEstimateGasParams) UnmarshalJSON(b []byte) error {
|
||||
var params []json.RawMessage
|
||||
err := json.Unmarshal(b, ¶ms)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch len(params) {
|
||||
case 2:
|
||||
err = json.Unmarshal(params[1], &e.BlkParam)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fallthrough
|
||||
case 1:
|
||||
err = json.Unmarshal(params[0], &e.Tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
return xerrors.Errorf("expected 1 or 2 params, got %d", len(params))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e EthEstimateGasParams) MarshalJSON() ([]byte, error) {
|
||||
if e.BlkParam != nil {
|
||||
return json.Marshal([]interface{}{e.Tx, e.BlkParam})
|
||||
}
|
||||
return json.Marshal([]interface{}{e.Tx})
|
||||
}
|
||||
|
||||
// EthFeeHistoryParams handles raw jsonrpc params for eth_feeHistory
|
||||
type EthFeeHistoryParams struct {
|
||||
BlkCount EthUint64
|
||||
|
||||
@@ -140,7 +140,7 @@ func (t *messageReceiptV0) UnmarshalCBOR(r io.Reader) (err error) {
|
||||
case cbg.MajNegativeInt:
|
||||
extraI = int64(extra)
|
||||
if extraI < 0 {
|
||||
return fmt.Errorf("int64 negative oveflow")
|
||||
return fmt.Errorf("int64 negative overflow")
|
||||
}
|
||||
extraI = -1 - extraI
|
||||
default:
|
||||
@@ -186,7 +186,7 @@ func (t *messageReceiptV0) UnmarshalCBOR(r io.Reader) (err error) {
|
||||
case cbg.MajNegativeInt:
|
||||
extraI = int64(extra)
|
||||
if extraI < 0 {
|
||||
return fmt.Errorf("int64 negative oveflow")
|
||||
return fmt.Errorf("int64 negative overflow")
|
||||
}
|
||||
extraI = -1 - extraI
|
||||
default:
|
||||
@@ -278,7 +278,7 @@ func (t *messageReceiptV1) UnmarshalCBOR(r io.Reader) (err error) {
|
||||
case cbg.MajNegativeInt:
|
||||
extraI = int64(extra)
|
||||
if extraI < 0 {
|
||||
return fmt.Errorf("int64 negative oveflow")
|
||||
return fmt.Errorf("int64 negative overflow")
|
||||
}
|
||||
extraI = -1 - extraI
|
||||
default:
|
||||
@@ -324,7 +324,7 @@ func (t *messageReceiptV1) UnmarshalCBOR(r io.Reader) (err error) {
|
||||
case cbg.MajNegativeInt:
|
||||
extraI = int64(extra)
|
||||
if extraI < 0 {
|
||||
return fmt.Errorf("int64 negative oveflow")
|
||||
return fmt.Errorf("int64 negative overflow")
|
||||
}
|
||||
extraI = -1 - extraI
|
||||
default:
|
||||
|
||||
@@ -27,24 +27,3 @@ type StateTree interface {
|
||||
|
||||
Version() StateTreeVersion
|
||||
}
|
||||
|
||||
type storageWrapper struct {
|
||||
s Storage
|
||||
}
|
||||
|
||||
func (sw *storageWrapper) Put(i cbg.CBORMarshaler) (cid.Cid, error) {
|
||||
c, err := sw.s.Put(i)
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (sw *storageWrapper) Get(c cid.Cid, out cbg.CBORUnmarshaler) error {
|
||||
if err := sw.s.Get(c, out); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
+2
-2
@@ -282,7 +282,7 @@ var NetDisconnect = &cli.Command{
|
||||
fmt.Println("failure")
|
||||
return err
|
||||
}
|
||||
fmt.Printf("disconnect %s: ", pid.Pretty())
|
||||
fmt.Printf("disconnect %s: ", pid)
|
||||
err = api.NetDisconnect(ctx, pid)
|
||||
if err != nil {
|
||||
fmt.Println("failure")
|
||||
@@ -312,7 +312,7 @@ var NetConnect = &cli.Command{
|
||||
}
|
||||
|
||||
for _, pi := range pis {
|
||||
fmt.Printf("connect %s: ", pi.ID.Pretty())
|
||||
fmt.Printf("connect %s: ", pi.ID)
|
||||
err := api.NetConnect(ctx, pi)
|
||||
if err != nil {
|
||||
fmt.Println("failure")
|
||||
|
||||
+23
-2
@@ -1920,8 +1920,29 @@ var StateSysActorCIDsCmd = &cli.Command{
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for name, cid := range actorsCids {
|
||||
_, _ = fmt.Fprintf(tw, "%v\t%v\n", name, cid)
|
||||
|
||||
var actorsCidTuples []struct {
|
||||
actorName string
|
||||
actorCid cid.Cid
|
||||
}
|
||||
|
||||
for name, actorCid := range actorsCids {
|
||||
keyVal := struct {
|
||||
actorName string
|
||||
actorCid cid.Cid
|
||||
}{
|
||||
actorName: name,
|
||||
actorCid: actorCid,
|
||||
}
|
||||
actorsCidTuples = append(actorsCidTuples, keyVal)
|
||||
}
|
||||
|
||||
sort.Slice(actorsCidTuples, func(i, j int) bool {
|
||||
return actorsCidTuples[i].actorName < actorsCidTuples[j].actorName
|
||||
})
|
||||
|
||||
for _, keyVal := range actorsCidTuples {
|
||||
_, _ = fmt.Fprintf(tw, "%v\t%v\n", keyVal.actorName, keyVal.actorCid)
|
||||
}
|
||||
return tw.Flush()
|
||||
},
|
||||
|
||||
+7
-1
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/api/v0api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
cliutil "github.com/filecoin-project/lotus/cli/util"
|
||||
)
|
||||
|
||||
var SyncCmd = &cli.Command{
|
||||
@@ -262,6 +263,9 @@ func SyncWait(ctx context.Context, napi v0api.FullNode, watch bool) error {
|
||||
}
|
||||
firstApp = state.VMApplied
|
||||
|
||||
// eta computes the ETA for the sync to complete (with a lookback of 10 processed items)
|
||||
eta := cliutil.NewETA(10)
|
||||
|
||||
for {
|
||||
state, err := napi.SyncState(ctx)
|
||||
if err != nil {
|
||||
@@ -312,8 +316,10 @@ func SyncWait(ctx context.Context, napi v0api.FullNode, watch bool) error {
|
||||
fmt.Print("\r\x1b[2K\x1b[A")
|
||||
}
|
||||
|
||||
todo := theight - ss.Height
|
||||
|
||||
fmt.Printf("Worker: %d; Base: %d; Target: %d (diff: %d)\n", workerID, baseHeight, theight, heightDiff)
|
||||
fmt.Printf("State: %s; Current Epoch: %d; Todo: %d\n", ss.Stage, ss.Height, theight-ss.Height)
|
||||
fmt.Printf("State: %s; Current Epoch: %d; Todo: %d, ETA: %s\n", ss.Stage, ss.Height, todo, eta.Update(int64(todo)))
|
||||
lastLines = 2
|
||||
|
||||
if i%samples == 0 {
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
package cliutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ETA implements a very simple eta calculator based on the number of remaining items. It does not
|
||||
// require knowing the work size in advance and is therefore suitable for streaming workloads and
|
||||
// also does not require that consecutive updates have a monotonically decreasing remaining value.
|
||||
type ETA struct {
|
||||
// max number of items to keep in memory
|
||||
maxItems int
|
||||
// a queue of most recently updated items
|
||||
items []item
|
||||
// we store the last calculated ETA which we reuse if there was not change in remaining items
|
||||
lastETA string
|
||||
}
|
||||
|
||||
type item struct {
|
||||
timestamp time.Time
|
||||
remaining int64
|
||||
}
|
||||
|
||||
// NewETA creates a new ETA calculator of the given size
|
||||
func NewETA(maxItems int) *ETA {
|
||||
return &ETA{
|
||||
maxItems: maxItems,
|
||||
items: make([]item, 0),
|
||||
}
|
||||
}
|
||||
|
||||
// Update updates the ETA calculator with the remaining number of items and returns the ETA
|
||||
func (e *ETA) Update(remaining int64) string {
|
||||
item := item{
|
||||
timestamp: time.Now(),
|
||||
remaining: remaining,
|
||||
}
|
||||
|
||||
if len(e.items) == 0 {
|
||||
e.items = append(e.items, item)
|
||||
return ""
|
||||
}
|
||||
|
||||
if e.items[len(e.items)-1].remaining == remaining {
|
||||
// we ignore updates with the same remaining value and just return the previous ETA
|
||||
return e.lastETA
|
||||
} else if e.items[len(e.items)-1].remaining < remaining {
|
||||
// remaining went up from previous update, lets estimate how many items were processed using the
|
||||
// average number processed items in the queue.
|
||||
var avgProcessedPerItem int64 = 1
|
||||
if len(e.items) > 1 {
|
||||
diffRemaining := e.items[0].remaining - e.items[len(e.items)-1].remaining
|
||||
avgProcessedPerItem = int64(math.Round(float64(diffRemaining) / float64(len(e.items))))
|
||||
}
|
||||
|
||||
// diff is the difference in increase in remaining since last update plus the average number of processed
|
||||
// items we estimate that were processed this round
|
||||
diff := remaining - e.items[len(e.items)-1].remaining + avgProcessedPerItem
|
||||
|
||||
// we update all items in the queue by shifting their remaining value accordingly. This means that we
|
||||
// always have strictly decreasing remaining values in the queue
|
||||
for i := range e.items {
|
||||
e.items[i].remaining += diff
|
||||
}
|
||||
}
|
||||
|
||||
// append the item to the queue and remove the oldest item if needed
|
||||
if len(e.items) >= e.maxItems {
|
||||
e.items = e.items[1:]
|
||||
}
|
||||
e.items = append(e.items, item)
|
||||
|
||||
// calculate the average processing time per item in the queue
|
||||
diffMs := e.items[len(e.items)-1].timestamp.Sub(e.items[0].timestamp).Milliseconds()
|
||||
nrItemsProcessed := e.items[0].remaining - e.items[len(e.items)-1].remaining
|
||||
avg := diffMs / nrItemsProcessed
|
||||
|
||||
// use that average processing time to estimate how long the remaining items will take
|
||||
// and cache that ETA so we don't have to recalculate it on every update unless the
|
||||
// remaining value changes
|
||||
e.lastETA = msToETA(avg * remaining)
|
||||
|
||||
return e.lastETA
|
||||
}
|
||||
|
||||
func msToETA(ms int64) string {
|
||||
seconds := ms / 1000
|
||||
minutes := seconds / 60
|
||||
hours := minutes / 60
|
||||
|
||||
return fmt.Sprintf("%02dh:%02dm:%02ds", hours, minutes%60, seconds%60)
|
||||
}
|
||||
+7
-1
@@ -22,6 +22,7 @@ import (
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/lib/tablewriter"
|
||||
)
|
||||
@@ -459,7 +460,12 @@ var walletSign = &cli.Command{
|
||||
sig, err := api.WalletSign(ctx, addr, msg)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
// Check if the address is a multisig address
|
||||
act, actErr := api.StateGetActor(ctx, addr, types.EmptyTSK)
|
||||
if actErr == nil && builtin.IsMultisigActor(act.Code) {
|
||||
return xerrors.Errorf("specified signer address is a multisig actor, it doesn’t have keys to sign transactions. To send a message with a multisig, signers of the multisig need to propose and approve transactions.")
|
||||
}
|
||||
return xerrors.Errorf("failed to sign message: %w", err)
|
||||
}
|
||||
|
||||
sigBytes := append([]byte{byte(sig.Type)}, sig.Data...)
|
||||
|
||||
@@ -0,0 +1,312 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var cliCmd = &cli.Command{
|
||||
Name: "cli",
|
||||
Usage: "Runs a concurrent stress test on one or more binaries commands and prints the performance metrics including latency distribution and histogram",
|
||||
Description: `This benchmark has the following features:
|
||||
* Can query each command both sequentially and concurrently
|
||||
* Supports rate limiting
|
||||
* Can query multiple different commands at once (supporting different concurrency level and rate limiting for each command)
|
||||
* Gives a nice reporting summary of the stress testing of each command (including latency distribution, histogram and more)
|
||||
* Easy to use
|
||||
|
||||
To use this benchmark you must specify the commands you want to test using the --cmd options, the format of it is:
|
||||
|
||||
--cmd=CMD[:CONCURRENCY][:QPS] where only NAME is required.
|
||||
|
||||
Here are some real examples:
|
||||
lotus-bench cli --cmd='lotus-shed mpool miner-select-messages' // runs the command with default concurrency and qps
|
||||
lotus-bench cli --cmd='lotus-shed mpool miner-select-messages:3' // override concurrency to 3
|
||||
lotus-bench cli --cmd='lotus-shed mpool miner-select-messages::100' // override to 100 qps while using default concurrency
|
||||
lotus-bench cli --cmd='lotus-shed mpool miner-select-messages:3:100' // run using 3 workers but limit to 100 qps
|
||||
lotus-bench cli --cmd='lotus-shed mpool miner-select-messages' --cmd='lotus sync wait' // run two commands at once
|
||||
`,
|
||||
Flags: []cli.Flag{
|
||||
&cli.DurationFlag{
|
||||
Name: "duration",
|
||||
Value: 60 * time.Second,
|
||||
Usage: "Duration of benchmark in seconds",
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "concurrency",
|
||||
Value: 10,
|
||||
Usage: "How many workers should be used per command (can be overridden per command)",
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "qps",
|
||||
Value: 0,
|
||||
Usage: "How many requests per second should be sent per command (can be overridden per command), a value of 0 means no limit",
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "cmd",
|
||||
Usage: `Command to benchmark, you can specify multiple commands by repeating this flag. You can also specify command specific options to set the concurrency and qps for each command (see usage).`,
|
||||
},
|
||||
&cli.DurationFlag{
|
||||
Name: "watch",
|
||||
Value: 0 * time.Second,
|
||||
Usage: "If >0 then generates reports every N seconds (only supports linux/unix)",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "print-response",
|
||||
Value: false,
|
||||
Usage: "print the response of each request",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
if len(cctx.StringSlice("cmd")) == 0 {
|
||||
return errors.New("you must specify and least one cmd to benchmark")
|
||||
}
|
||||
|
||||
var cmds []*CMD
|
||||
for _, str := range cctx.StringSlice("cmd") {
|
||||
entries := strings.SplitN(str, ":", 3)
|
||||
if len(entries) == 0 {
|
||||
return errors.New("invalid cmd format")
|
||||
}
|
||||
|
||||
// check if concurrency was specified
|
||||
concurrency := cctx.Int("concurrency")
|
||||
if len(entries) > 1 {
|
||||
if len(entries[1]) > 0 {
|
||||
var err error
|
||||
concurrency, err = strconv.Atoi(entries[1])
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse concurrency value from command %s: %v", entries[0], err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check if qps was specified
|
||||
qps := cctx.Int("qps")
|
||||
if len(entries) > 2 {
|
||||
if len(entries[2]) > 0 {
|
||||
var err error
|
||||
qps, err = strconv.Atoi(entries[2])
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse qps value from command %s: %v", entries[0], err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cmds = append(cmds, &CMD{
|
||||
w: os.Stdout,
|
||||
cmd: entries[0],
|
||||
concurrency: concurrency,
|
||||
qps: qps,
|
||||
printResp: cctx.Bool("print-response"),
|
||||
})
|
||||
}
|
||||
|
||||
// terminate early on ctrl+c
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, os.Interrupt)
|
||||
go func() {
|
||||
<-c
|
||||
fmt.Println("Received interrupt, stopping...")
|
||||
for _, cmd := range cmds {
|
||||
cmd.Stop()
|
||||
}
|
||||
}()
|
||||
|
||||
// stop all threads after duration
|
||||
go func() {
|
||||
time.Sleep(cctx.Duration("duration"))
|
||||
for _, cmd := range cmds {
|
||||
cmd.Stop()
|
||||
}
|
||||
}()
|
||||
|
||||
// start all threads
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(len(cmds))
|
||||
|
||||
for _, cmd := range cmds {
|
||||
go func(cmd *CMD) {
|
||||
defer wg.Done()
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
fmt.Printf("error running cmd: %v\n", err)
|
||||
}
|
||||
}(cmd)
|
||||
}
|
||||
|
||||
// if watch is set then print a report every N seconds
|
||||
var progressCh chan struct{}
|
||||
if cctx.Duration("watch") > 0 {
|
||||
progressCh = make(chan struct{}, 1)
|
||||
go func(progressCh chan struct{}) {
|
||||
ticker := time.NewTicker(cctx.Duration("watch"))
|
||||
for {
|
||||
clearAndPrintReport := func() {
|
||||
// clear the screen move the cursor to the top left
|
||||
fmt.Print("\033[2J")
|
||||
fmt.Printf("\033[%d;%dH", 1, 1)
|
||||
for i, cmd := range cmds {
|
||||
cmd.Report()
|
||||
if i < len(cmds)-1 {
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
}
|
||||
select {
|
||||
case <-ticker.C:
|
||||
clearAndPrintReport()
|
||||
case <-progressCh:
|
||||
clearAndPrintReport()
|
||||
return
|
||||
}
|
||||
}
|
||||
}(progressCh)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
if progressCh != nil {
|
||||
// wait for the watch go routine to return
|
||||
progressCh <- struct{}{}
|
||||
|
||||
// no need to print the report again
|
||||
return nil
|
||||
}
|
||||
|
||||
// print the report for each command
|
||||
for i, cmd := range cmds {
|
||||
cmd.Report()
|
||||
if i < len(cmds)-1 {
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// CMD handles the benchmarking of a single command.
|
||||
type CMD struct {
|
||||
w io.Writer
|
||||
// the cmd we want to benchmark
|
||||
cmd string
|
||||
// the number of concurrent requests to make to this command
|
||||
concurrency int
|
||||
// if >0 then limit to qps is the max number of requests per second to make to this command (0 = no limit)
|
||||
qps int
|
||||
// whether or not to print the response of each request (useful for debugging)
|
||||
printResp bool
|
||||
// instruct the worker go routines to stop
|
||||
stopCh chan struct{}
|
||||
// when the command bencharking started
|
||||
start time.Time
|
||||
// results channel is used by the workers to send results to the reporter
|
||||
results chan *result
|
||||
// reporter handles reading the results from workers and printing the report statistics
|
||||
reporter *Reporter
|
||||
}
|
||||
|
||||
func (c *CMD) Run() error {
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(c.concurrency)
|
||||
|
||||
c.results = make(chan *result, c.concurrency*1_000)
|
||||
c.stopCh = make(chan struct{}, c.concurrency)
|
||||
|
||||
go func() {
|
||||
c.reporter = NewReporter(c.results, c.w)
|
||||
c.reporter.Run()
|
||||
}()
|
||||
|
||||
c.start = time.Now()
|
||||
|
||||
// throttle the number of requests per second
|
||||
var qpsTicker *time.Ticker
|
||||
if c.qps > 0 {
|
||||
qpsTicker = time.NewTicker(time.Second / time.Duration(c.qps))
|
||||
}
|
||||
|
||||
for i := 0; i < c.concurrency; i++ {
|
||||
go func() {
|
||||
c.startWorker(qpsTicker)
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
// close the results channel so reporter will stop
|
||||
close(c.results)
|
||||
|
||||
// wait until the reporter is done
|
||||
<-c.reporter.doneCh
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CMD) startWorker(qpsTicker *time.Ticker) {
|
||||
for {
|
||||
// check if we should stop
|
||||
select {
|
||||
case <-c.stopCh:
|
||||
return
|
||||
default:
|
||||
}
|
||||
|
||||
// wait for the next tick if we are rate limiting this command
|
||||
if qpsTicker != nil {
|
||||
<-qpsTicker.C
|
||||
}
|
||||
|
||||
start := time.Now()
|
||||
|
||||
var statusCode int = 0
|
||||
|
||||
arr := strings.Fields(c.cmd)
|
||||
|
||||
data, err := exec.Command(arr[0], arr[1:]...).Output()
|
||||
if err != nil {
|
||||
fmt.Println("1")
|
||||
if exitError, ok := err.(*exec.ExitError); ok {
|
||||
statusCode = exitError.ExitCode()
|
||||
} else {
|
||||
statusCode = 1
|
||||
}
|
||||
} else {
|
||||
if c.printResp {
|
||||
fmt.Printf("[%s] %s", c.cmd, string(data))
|
||||
}
|
||||
}
|
||||
|
||||
c.results <- &result{
|
||||
statusCode: &statusCode,
|
||||
err: err,
|
||||
duration: time.Since(start),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CMD) Stop() {
|
||||
for i := 0; i < c.concurrency; i++ {
|
||||
c.stopCh <- struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CMD) Report() {
|
||||
total := time.Since(c.start)
|
||||
fmt.Fprintf(c.w, "[%s]:\n", c.cmd)
|
||||
fmt.Fprintf(c.w, "- Options:\n")
|
||||
fmt.Fprintf(c.w, " - concurrency: %d\n", c.concurrency)
|
||||
fmt.Fprintf(c.w, " - qps: %d\n", c.qps)
|
||||
c.reporter.Print(total, c.w)
|
||||
}
|
||||
@@ -304,7 +304,7 @@ var importBenchCmd = &cli.Command{
|
||||
return fmt.Errorf("no CAR file provided for import")
|
||||
}
|
||||
|
||||
head, err = cs.Import(cctx.Context, carFile)
|
||||
head, _, err = cs.Import(cctx.Context, carFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -497,21 +497,6 @@ type Invocation struct {
|
||||
|
||||
const GasPerNs = 10
|
||||
|
||||
func countGasCosts(et *types.ExecutionTrace) int64 {
|
||||
var cgas int64
|
||||
|
||||
for _, gc := range et.GasCharges {
|
||||
cgas += gc.ComputeGas
|
||||
}
|
||||
|
||||
for _, sub := range et.Subcalls {
|
||||
c := countGasCosts(&sub) //nolint
|
||||
cgas += c
|
||||
}
|
||||
|
||||
return cgas
|
||||
}
|
||||
|
||||
type stats struct {
|
||||
timeTaken meanVar
|
||||
gasRatio meanVar
|
||||
|
||||
@@ -120,6 +120,7 @@ func main() {
|
||||
sealBenchCmd,
|
||||
simpleCmd,
|
||||
importBenchCmd,
|
||||
cliCmd,
|
||||
rpcCmd,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
)
|
||||
|
||||
// result is the result of a single rpc method request.
|
||||
type result struct {
|
||||
err error
|
||||
statusCode *int
|
||||
duration time.Duration
|
||||
}
|
||||
|
||||
// Reporter reads the results from the workers through the results channel and aggregates the results.
|
||||
type Reporter struct {
|
||||
// write the report to this writer
|
||||
w io.Writer
|
||||
// the reporter read the results from this channel
|
||||
results chan *result
|
||||
// doneCh is used to signal that the reporter has finished reading the results (channel has closed)
|
||||
doneCh chan bool
|
||||
|
||||
// lock protect the following fields during critical sections (if --watch was specified)
|
||||
lock sync.Mutex
|
||||
// the latencies of all requests
|
||||
latencies []int64
|
||||
// the number of requests that returned each status code
|
||||
statusCodes map[int]int
|
||||
// the number of errors that occurred
|
||||
errors map[string]int
|
||||
}
|
||||
|
||||
func NewReporter(results chan *result, w io.Writer) *Reporter {
|
||||
return &Reporter{
|
||||
w: w,
|
||||
results: results,
|
||||
doneCh: make(chan bool, 1),
|
||||
statusCodes: make(map[int]int),
|
||||
errors: make(map[string]int),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Reporter) Run() {
|
||||
for res := range r.results {
|
||||
r.lock.Lock()
|
||||
|
||||
r.latencies = append(r.latencies, res.duration.Milliseconds())
|
||||
|
||||
if res.statusCode != nil {
|
||||
r.statusCodes[*res.statusCode]++
|
||||
}
|
||||
|
||||
if res.err != nil {
|
||||
if len(r.errors) < 1_000_000 {
|
||||
r.errors[res.err.Error()]++
|
||||
} else {
|
||||
// we don't want to store too many errors in memory
|
||||
r.errors["hidden"]++
|
||||
}
|
||||
} else {
|
||||
r.errors["nil"]++
|
||||
}
|
||||
|
||||
r.lock.Unlock()
|
||||
}
|
||||
|
||||
r.doneCh <- true
|
||||
}
|
||||
|
||||
func (r *Reporter) Print(elapsed time.Duration, w io.Writer) {
|
||||
r.lock.Lock()
|
||||
defer r.lock.Unlock()
|
||||
|
||||
nrReq := int64(len(r.latencies))
|
||||
if nrReq == 0 {
|
||||
fmt.Println("No requests were made")
|
||||
return
|
||||
}
|
||||
|
||||
// we need to sort the latencies slice to calculate the percentiles
|
||||
sort.Slice(r.latencies, func(i, j int) bool {
|
||||
return r.latencies[i] < r.latencies[j]
|
||||
})
|
||||
|
||||
var totalLatency int64 = 0
|
||||
for _, latency := range r.latencies {
|
||||
totalLatency += latency
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "- Total Requests: %d\n", nrReq)
|
||||
fmt.Fprintf(w, "- Total Duration: %dms\n", elapsed.Milliseconds())
|
||||
fmt.Fprintf(w, "- Requests/sec: %f\n", float64(nrReq)/elapsed.Seconds())
|
||||
fmt.Fprintf(w, "- Avg latency: %dms\n", totalLatency/nrReq)
|
||||
fmt.Fprintf(w, "- Median latency: %dms\n", r.latencies[nrReq/2])
|
||||
fmt.Fprintf(w, "- Latency distribution:\n")
|
||||
percentiles := []float64{0.1, 0.5, 0.9, 0.95, 0.99, 0.999}
|
||||
for _, p := range percentiles {
|
||||
idx := int64(p * float64(nrReq))
|
||||
fmt.Fprintf(w, " %s%% in %dms\n", fmt.Sprintf("%.2f", p*100.0), r.latencies[idx])
|
||||
}
|
||||
|
||||
// create a simple histogram with 10 buckets spanning the range of latency
|
||||
// into equal ranges
|
||||
//
|
||||
nrBucket := 10
|
||||
buckets := make([]Bucket, nrBucket)
|
||||
latencyRange := r.latencies[len(r.latencies)-1]
|
||||
bucketRange := latencyRange / int64(nrBucket)
|
||||
|
||||
// mark the end of each bucket
|
||||
for i := 0; i < nrBucket; i++ {
|
||||
buckets[i].start = int64(i) * bucketRange
|
||||
buckets[i].end = buckets[i].start + bucketRange
|
||||
// extend the last bucked by any remaning range caused by the integer division
|
||||
if i == nrBucket-1 {
|
||||
buckets[i].end = latencyRange
|
||||
}
|
||||
}
|
||||
|
||||
// count the number of requests in each bucket
|
||||
currBucket := 0
|
||||
for i := 0; i < len(r.latencies); {
|
||||
if r.latencies[i] <= buckets[currBucket].end {
|
||||
buckets[currBucket].cnt++
|
||||
i++
|
||||
} else {
|
||||
currBucket++
|
||||
}
|
||||
}
|
||||
|
||||
// print the histogram using a tabwriter which will align the columns nicely
|
||||
fmt.Fprintf(w, "- Histogram:\n")
|
||||
const padding = 2
|
||||
tabWriter := tabwriter.NewWriter(w, 0, 0, padding, ' ', tabwriter.AlignRight|tabwriter.Debug)
|
||||
for i := 0; i < nrBucket; i++ {
|
||||
ratio := float64(buckets[i].cnt) / float64(nrReq)
|
||||
bars := strings.Repeat("#", int(ratio*100))
|
||||
fmt.Fprintf(tabWriter, " %d-%dms\t%d\t%s (%s%%)\n", buckets[i].start, buckets[i].end, buckets[i].cnt, bars, fmt.Sprintf("%.2f", ratio*100))
|
||||
}
|
||||
tabWriter.Flush() //nolint:errcheck
|
||||
|
||||
fmt.Fprintf(w, "- Status codes:\n")
|
||||
for code, cnt := range r.statusCodes {
|
||||
fmt.Fprintf(w, " [%d]: %d\n", code, cnt)
|
||||
}
|
||||
|
||||
// print the 10 most occurring errors (in case error values are not unique)
|
||||
//
|
||||
type kv struct {
|
||||
err string
|
||||
cnt int
|
||||
}
|
||||
var sortedErrors []kv
|
||||
for err, cnt := range r.errors {
|
||||
sortedErrors = append(sortedErrors, kv{err, cnt})
|
||||
}
|
||||
sort.Slice(sortedErrors, func(i, j int) bool {
|
||||
return sortedErrors[i].cnt > sortedErrors[j].cnt
|
||||
})
|
||||
fmt.Fprintf(w, "- Errors (top 10):\n")
|
||||
for i, se := range sortedErrors {
|
||||
if i > 10 {
|
||||
break
|
||||
}
|
||||
fmt.Fprintf(w, " [%s]: %d\n", se.err, se.cnt)
|
||||
}
|
||||
}
|
||||
|
||||
type Bucket struct {
|
||||
start int64
|
||||
// the end value of the bucket
|
||||
end int64
|
||||
// how many entries are in the bucket
|
||||
cnt int
|
||||
}
|
||||
@@ -9,11 +9,9 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
@@ -243,13 +241,6 @@ type RPCMethod struct {
|
||||
reporter *Reporter
|
||||
}
|
||||
|
||||
// result is the result of a single rpc method request.
|
||||
type result struct {
|
||||
err error
|
||||
statusCode *int
|
||||
duration time.Duration
|
||||
}
|
||||
|
||||
func (rpc *RPCMethod) Run() error {
|
||||
client := &http.Client{
|
||||
Timeout: 0,
|
||||
@@ -411,166 +402,3 @@ func (rpc *RPCMethod) Report() {
|
||||
fmt.Fprintf(rpc.w, " - qps: %d\n", rpc.qps)
|
||||
rpc.reporter.Print(total, rpc.w)
|
||||
}
|
||||
|
||||
// Reporter reads the results from the workers through the results channel and aggregates the results.
|
||||
type Reporter struct {
|
||||
// write the report to this writer
|
||||
w io.Writer
|
||||
// the reporter read the results from this channel
|
||||
results chan *result
|
||||
// doneCh is used to signal that the reporter has finished reading the results (channel has closed)
|
||||
doneCh chan bool
|
||||
|
||||
// lock protect the following fields during critical sections (if --watch was specified)
|
||||
lock sync.Mutex
|
||||
// the latencies of all requests
|
||||
latencies []int64
|
||||
// the number of requests that returned each status code
|
||||
statusCodes map[int]int
|
||||
// the number of errors that occurred
|
||||
errors map[string]int
|
||||
}
|
||||
|
||||
func NewReporter(results chan *result, w io.Writer) *Reporter {
|
||||
return &Reporter{
|
||||
w: w,
|
||||
results: results,
|
||||
doneCh: make(chan bool, 1),
|
||||
statusCodes: make(map[int]int),
|
||||
errors: make(map[string]int),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Reporter) Run() {
|
||||
for res := range r.results {
|
||||
r.lock.Lock()
|
||||
|
||||
r.latencies = append(r.latencies, res.duration.Milliseconds())
|
||||
|
||||
if res.statusCode != nil {
|
||||
r.statusCodes[*res.statusCode]++
|
||||
}
|
||||
|
||||
if res.err != nil {
|
||||
if len(r.errors) < 1_000_000 {
|
||||
r.errors[res.err.Error()]++
|
||||
} else {
|
||||
// we don't want to store too many errors in memory
|
||||
r.errors["hidden"]++
|
||||
}
|
||||
} else {
|
||||
r.errors["nil"]++
|
||||
}
|
||||
|
||||
r.lock.Unlock()
|
||||
}
|
||||
|
||||
r.doneCh <- true
|
||||
}
|
||||
|
||||
func (r *Reporter) Print(elapsed time.Duration, w io.Writer) {
|
||||
r.lock.Lock()
|
||||
defer r.lock.Unlock()
|
||||
|
||||
nrReq := int64(len(r.latencies))
|
||||
if nrReq == 0 {
|
||||
fmt.Println("No requests were made")
|
||||
return
|
||||
}
|
||||
|
||||
// we need to sort the latencies slice to calculate the percentiles
|
||||
sort.Slice(r.latencies, func(i, j int) bool {
|
||||
return r.latencies[i] < r.latencies[j]
|
||||
})
|
||||
|
||||
var totalLatency int64 = 0
|
||||
for _, latency := range r.latencies {
|
||||
totalLatency += latency
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "- Total Requests: %d\n", nrReq)
|
||||
fmt.Fprintf(w, "- Total Duration: %dms\n", elapsed.Milliseconds())
|
||||
fmt.Fprintf(w, "- Requests/sec: %f\n", float64(nrReq)/elapsed.Seconds())
|
||||
fmt.Fprintf(w, "- Avg latency: %dms\n", totalLatency/nrReq)
|
||||
fmt.Fprintf(w, "- Median latency: %dms\n", r.latencies[nrReq/2])
|
||||
fmt.Fprintf(w, "- Latency distribution:\n")
|
||||
percentiles := []float64{0.1, 0.5, 0.9, 0.95, 0.99, 0.999}
|
||||
for _, p := range percentiles {
|
||||
idx := int64(p * float64(nrReq))
|
||||
fmt.Fprintf(w, " %s%% in %dms\n", fmt.Sprintf("%.2f", p*100.0), r.latencies[idx])
|
||||
}
|
||||
|
||||
// create a simple histogram with 10 buckets spanning the range of latency
|
||||
// into equal ranges
|
||||
//
|
||||
nrBucket := 10
|
||||
buckets := make([]Bucket, nrBucket)
|
||||
latencyRange := r.latencies[len(r.latencies)-1]
|
||||
bucketRange := latencyRange / int64(nrBucket)
|
||||
|
||||
// mark the end of each bucket
|
||||
for i := 0; i < nrBucket; i++ {
|
||||
buckets[i].start = int64(i) * bucketRange
|
||||
buckets[i].end = buckets[i].start + bucketRange
|
||||
// extend the last bucked by any remaning range caused by the integer division
|
||||
if i == nrBucket-1 {
|
||||
buckets[i].end = latencyRange
|
||||
}
|
||||
}
|
||||
|
||||
// count the number of requests in each bucket
|
||||
currBucket := 0
|
||||
for i := 0; i < len(r.latencies); {
|
||||
if r.latencies[i] <= buckets[currBucket].end {
|
||||
buckets[currBucket].cnt++
|
||||
i++
|
||||
} else {
|
||||
currBucket++
|
||||
}
|
||||
}
|
||||
|
||||
// print the histogram using a tabwriter which will align the columns nicely
|
||||
fmt.Fprintf(w, "- Histogram:\n")
|
||||
const padding = 2
|
||||
tabWriter := tabwriter.NewWriter(w, 0, 0, padding, ' ', tabwriter.AlignRight|tabwriter.Debug)
|
||||
for i := 0; i < nrBucket; i++ {
|
||||
ratio := float64(buckets[i].cnt) / float64(nrReq)
|
||||
bars := strings.Repeat("#", int(ratio*100))
|
||||
fmt.Fprintf(tabWriter, " %d-%dms\t%d\t%s (%s%%)\n", buckets[i].start, buckets[i].end, buckets[i].cnt, bars, fmt.Sprintf("%.2f", ratio*100))
|
||||
}
|
||||
tabWriter.Flush() //nolint:errcheck
|
||||
|
||||
fmt.Fprintf(w, "- Status codes:\n")
|
||||
for code, cnt := range r.statusCodes {
|
||||
fmt.Fprintf(w, " [%d]: %d\n", code, cnt)
|
||||
}
|
||||
|
||||
// print the 10 most occurring errors (in case error values are not unique)
|
||||
//
|
||||
type kv struct {
|
||||
err string
|
||||
cnt int
|
||||
}
|
||||
var sortedErrors []kv
|
||||
for err, cnt := range r.errors {
|
||||
sortedErrors = append(sortedErrors, kv{err, cnt})
|
||||
}
|
||||
sort.Slice(sortedErrors, func(i, j int) bool {
|
||||
return sortedErrors[i].cnt > sortedErrors[j].cnt
|
||||
})
|
||||
fmt.Fprintf(w, "- Errors (top 10):\n")
|
||||
for i, se := range sortedErrors {
|
||||
if i > 10 {
|
||||
break
|
||||
}
|
||||
fmt.Fprintf(w, " [%s]: %d\n", se.err, se.cnt)
|
||||
}
|
||||
}
|
||||
|
||||
type Bucket struct {
|
||||
start int64
|
||||
// the end value of the bucket
|
||||
end int64
|
||||
// how many entries are in the bucket
|
||||
cnt int
|
||||
}
|
||||
|
||||
@@ -266,7 +266,10 @@ var simplePreCommit1 = &cli.Command{
|
||||
ProofType: spt(sectorSize, cctx.Bool("synthetic")),
|
||||
}
|
||||
|
||||
var ticket [32]byte // all zero
|
||||
ticket := [32]byte{}
|
||||
for i := range ticket {
|
||||
ticket[i] = 1
|
||||
}
|
||||
|
||||
pieces, err := ParsePieceInfos(cctx, 3)
|
||||
if err != nil {
|
||||
@@ -305,7 +308,36 @@ var simplePreCommit2 = &cli.Command{
|
||||
Name: "synthetic",
|
||||
Usage: "generate synthetic PoRep proofs",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "external-pc2",
|
||||
Usage: "command for computing PC2 externally",
|
||||
},
|
||||
},
|
||||
Description: `Compute PreCommit2 inputs and seal a sector.
|
||||
|
||||
--external-pc2 can be used to compute the PreCommit2 inputs externally.
|
||||
The flag behaves similarly to the related lotus-worker flag, using it in
|
||||
lotus-bench may be useful for testing if the external PreCommit2 command is
|
||||
invoked correctly.
|
||||
|
||||
The command will be called with a number of environment variables set:
|
||||
* EXTSEAL_PC2_SECTOR_NUM: the sector number
|
||||
* EXTSEAL_PC2_SECTOR_MINER: the miner id
|
||||
* EXTSEAL_PC2_PROOF_TYPE: the proof type
|
||||
* EXTSEAL_PC2_SECTOR_SIZE: the sector size in bytes
|
||||
* EXTSEAL_PC2_CACHE: the path to the cache directory
|
||||
* EXTSEAL_PC2_SEALED: the path to the sealed sector file (initialized with unsealed data by the caller)
|
||||
* EXTSEAL_PC2_PC1OUT: output from rust-fil-proofs precommit1 phase (base64 encoded json)
|
||||
|
||||
The command is expected to:
|
||||
* Create cache sc-02-data-tree-r* files
|
||||
* Create cache sc-02-data-tree-c* files
|
||||
* Create cache p_aux / t_aux files
|
||||
* Transform the sealed file in place
|
||||
|
||||
Example invocation of lotus-bench as external executor:
|
||||
'./lotus-bench simple precommit2 --sector-size $EXTSEAL_PC2_SECTOR_SIZE $EXTSEAL_PC2_SEALED $EXTSEAL_PC2_CACHE $EXTSEAL_PC2_PC1OUT'
|
||||
`,
|
||||
ArgsUsage: "[sealed] [cache] [pc1 out]",
|
||||
Action: func(cctx *cli.Context) error {
|
||||
ctx := cctx.Context
|
||||
@@ -330,7 +362,18 @@ var simplePreCommit2 = &cli.Command{
|
||||
storiface.FTSealed: cctx.Args().Get(0),
|
||||
storiface.FTCache: cctx.Args().Get(1),
|
||||
}
|
||||
sealer, err := ffiwrapper.New(pp)
|
||||
|
||||
var opts []ffiwrapper.FFIWrapperOpt
|
||||
|
||||
if cctx.IsSet("external-pc2") {
|
||||
extSeal := ffiwrapper.ExternalSealer{
|
||||
PreCommit2: ffiwrapper.MakeExternPrecommit2(cctx.String("external-pc2")),
|
||||
}
|
||||
|
||||
opts = append(opts, ffiwrapper.WithExternalSealCalls(extSeal))
|
||||
}
|
||||
|
||||
sealer, err := ffiwrapper.New(pp, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -420,7 +463,12 @@ var simpleCommit1 = &cli.Command{
|
||||
|
||||
start := time.Now()
|
||||
|
||||
var ticket, seed [32]byte // all zero
|
||||
ticket := [32]byte{}
|
||||
seed := [32]byte{}
|
||||
for i := range ticket {
|
||||
ticket[i] = 1
|
||||
seed[i] = 1
|
||||
}
|
||||
|
||||
commd, err := cid.Parse(cctx.Args().Get(2))
|
||||
if err != nil {
|
||||
@@ -650,6 +698,10 @@ var simpleWinningPost = &cli.Command{
|
||||
Usage: "pass miner address (only necessary if using existing sectorbuilder)",
|
||||
Value: "t01000",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "show-inputs",
|
||||
Usage: "output inputs for winning post generation",
|
||||
},
|
||||
},
|
||||
ArgsUsage: "[sealed] [cache] [comm R] [sector num]",
|
||||
Action: func(cctx *cli.Context) error {
|
||||
@@ -720,6 +772,17 @@ var simpleWinningPost = &cli.Command{
|
||||
fmt.Printf("Vanilla %s (%s)\n", challenge.Sub(start), bps(sectorSize, 1, challenge.Sub(start)))
|
||||
fmt.Printf("Proof %s (%s)\n", end.Sub(challenge), bps(sectorSize, 1, end.Sub(challenge)))
|
||||
fmt.Println(base64.StdEncoding.EncodeToString(proof[0].ProofBytes))
|
||||
|
||||
if cctx.Bool("show-inputs") {
|
||||
fmt.Println("GenerateWinningPoStWithVanilla info:")
|
||||
|
||||
fmt.Printf(" wpt: %d\n", wpt)
|
||||
fmt.Printf(" mid: %d\n", mid)
|
||||
fmt.Printf(" rand: %x\n", rand)
|
||||
fmt.Printf(" vp: %x\n", vp)
|
||||
fmt.Printf(" proof: %x\n", proof)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ var runCmd = &cli.Command{
|
||||
},
|
||||
&cli.DurationFlag{
|
||||
Name: "rate-limit-timeout",
|
||||
Usage: "the maximum time to wait for the rate limter before returning an error to clients",
|
||||
Usage: "the maximum time to wait for the rate limiter before returning an error to clients",
|
||||
Value: gateway.DefaultRateLimitTimeout,
|
||||
},
|
||||
&cli.Int64Flag{
|
||||
|
||||
@@ -2566,6 +2566,8 @@ var sectorsUnsealCmd = &cli.Command{
|
||||
return xerrors.Errorf("could not parse sector number: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Unsealing sector %d\n", sectorNum)
|
||||
|
||||
return minerAPI.SectorUnseal(ctx, abi.SectorNumber(sectorNum))
|
||||
},
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ var genesisVerifyCmd = &cli.Command{
|
||||
return xerrors.Errorf("opening the car file: %w", err)
|
||||
}
|
||||
|
||||
ts, err := cs.Import(cctx.Context, f)
|
||||
ts, _, err := cs.Import(cctx.Context, f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
@@ -43,10 +44,20 @@ var minerSelectMsgsCmd = &cli.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
// Get the size of the mempool
|
||||
pendingMsgs, err := api.MpoolPending(ctx, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mpoolSize := len(pendingMsgs)
|
||||
|
||||
// Measure the time taken by MpoolSelect
|
||||
startTime := time.Now()
|
||||
msgs, err := api.MpoolSelect(ctx, head.Key(), cctx.Float64("ticket-quality"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
duration := time.Since(startTime)
|
||||
|
||||
var totalGas int64
|
||||
for i, f := range msgs {
|
||||
@@ -64,6 +75,9 @@ var minerSelectMsgsCmd = &cli.Command{
|
||||
totalGas += f.Message.GasLimit
|
||||
}
|
||||
|
||||
// Log the duration, size of the mempool, selected messages and total gas limit of selected messages
|
||||
fmt.Printf("Message selection took %s\n", duration)
|
||||
fmt.Printf("Size of the mempool: %d\n", mpoolSize)
|
||||
fmt.Println("selected messages: ", len(msgs))
|
||||
fmt.Printf("total gas limit of selected messages: %d / %d (%0.2f%%)\n", totalGas, build.BlockGasLimit, 100*float64(totalGas)/float64(build.BlockGasLimit))
|
||||
return nil
|
||||
|
||||
+14
-22
@@ -12,7 +12,7 @@ import (
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
|
||||
badgerbs "github.com/filecoin-project/lotus/blockstore/badger"
|
||||
"github.com/filecoin-project/lotus/blockstore"
|
||||
"github.com/filecoin-project/lotus/chain/consensus/filcns"
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
"github.com/filecoin-project/lotus/node/repo"
|
||||
@@ -144,13 +144,6 @@ var stateTreePruneCmd = &cli.Command{
|
||||
}
|
||||
}()
|
||||
|
||||
// After migrating to native blockstores, this has been made
|
||||
// database-specific.
|
||||
badgbs, ok := bs.(*badgerbs.Blockstore)
|
||||
if !ok {
|
||||
return fmt.Errorf("only badger blockstores are supported")
|
||||
}
|
||||
|
||||
mds, err := lkrepo.Datastore(context.Background(), "/metadata")
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -160,8 +153,12 @@ var stateTreePruneCmd = &cli.Command{
|
||||
const DiscardRatio = 0.2
|
||||
if cctx.Bool("only-ds-gc") {
|
||||
fmt.Println("running datastore gc....")
|
||||
gbs, ok := bs.(blockstore.BlockstoreGCOnce)
|
||||
if !ok {
|
||||
return xerrors.Errorf("blockstore %T does not support GC", bs)
|
||||
}
|
||||
for i := 0; i < cctx.Int("gc-count"); i++ {
|
||||
if err := badgbs.DB().RunValueLogGC(DiscardRatio); err != nil {
|
||||
if err := gbs.GCOnce(ctx, blockstore.WithThreshold(DiscardRatio)); err != nil {
|
||||
return xerrors.Errorf("datastore GC failed: %w", err)
|
||||
}
|
||||
}
|
||||
@@ -208,13 +205,6 @@ var stateTreePruneCmd = &cli.Command{
|
||||
return nil
|
||||
}
|
||||
|
||||
b := badgbs.DB().NewWriteBatch()
|
||||
defer b.Cancel()
|
||||
|
||||
markForRemoval := func(c cid.Cid) error {
|
||||
return b.Delete(badgbs.StorageKey(nil, c))
|
||||
}
|
||||
|
||||
keys, err := bs.AllKeysChan(context.Background())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to query blockstore: %w", err)
|
||||
@@ -225,12 +215,12 @@ var stateTreePruneCmd = &cli.Command{
|
||||
var deleteCount int
|
||||
var goodHits int
|
||||
for k := range keys {
|
||||
if goodSet.HasRaw(k.Bytes()) {
|
||||
if goodSet.Has(k) {
|
||||
goodHits++
|
||||
continue
|
||||
}
|
||||
|
||||
if err := markForRemoval(k); err != nil {
|
||||
if err := bs.DeleteBlock(ctx, k); err != nil {
|
||||
return fmt.Errorf("failed to remove cid %s: %w", k, err)
|
||||
}
|
||||
|
||||
@@ -243,13 +233,15 @@ var stateTreePruneCmd = &cli.Command{
|
||||
}
|
||||
}
|
||||
|
||||
if err := b.Flush(); err != nil {
|
||||
return xerrors.Errorf("failed to flush final batch delete: %w", err)
|
||||
fmt.Println("running datastore gc....")
|
||||
gbs, ok := bs.(blockstore.BlockstoreGCOnce)
|
||||
if !ok {
|
||||
fmt.Println("gc not supported...")
|
||||
return nil
|
||||
}
|
||||
|
||||
fmt.Println("running datastore gc....")
|
||||
for i := 0; i < cctx.Int("gc-count"); i++ {
|
||||
if err := badgbs.DB().RunValueLogGC(DiscardRatio); err != nil {
|
||||
if err := gbs.GCOnce(ctx, blockstore.WithThreshold(DiscardRatio)); err != nil {
|
||||
return xerrors.Errorf("datastore GC failed: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
+69
-13
@@ -7,6 +7,7 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
@@ -38,6 +39,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/node/repo"
|
||||
"github.com/filecoin-project/lotus/storage/paths"
|
||||
"github.com/filecoin-project/lotus/storage/sealer"
|
||||
"github.com/filecoin-project/lotus/storage/sealer/ffiwrapper"
|
||||
"github.com/filecoin-project/lotus/storage/sealer/sealtasks"
|
||||
"github.com/filecoin-project/lotus/storage/sealer/storiface"
|
||||
)
|
||||
@@ -283,7 +285,36 @@ var runCmd = &cli.Command{
|
||||
Value: true,
|
||||
DefaultText: "inherits --addpiece",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "external-pc2",
|
||||
Usage: "command for computing PC2 externally",
|
||||
},
|
||||
},
|
||||
Description: `Run lotus-worker.
|
||||
|
||||
--external-pc2 can be used to compute the PreCommit2 inputs externally.
|
||||
The flag behaves similarly to the related lotus-worker flag, using it in
|
||||
lotus-bench may be useful for testing if the external PreCommit2 command is
|
||||
invoked correctly.
|
||||
|
||||
The command will be called with a number of environment variables set:
|
||||
* EXTSEAL_PC2_SECTOR_NUM: the sector number
|
||||
* EXTSEAL_PC2_SECTOR_MINER: the miner id
|
||||
* EXTSEAL_PC2_PROOF_TYPE: the proof type
|
||||
* EXTSEAL_PC2_SECTOR_SIZE: the sector size in bytes
|
||||
* EXTSEAL_PC2_CACHE: the path to the cache directory
|
||||
* EXTSEAL_PC2_SEALED: the path to the sealed sector file (initialized with unsealed data by the caller)
|
||||
* EXTSEAL_PC2_PC1OUT: output from rust-fil-proofs precommit1 phase (base64 encoded json)
|
||||
|
||||
The command is expected to:
|
||||
* Create cache sc-02-data-tree-r* files
|
||||
* Create cache sc-02-data-tree-c* files
|
||||
* Create cache p_aux / t_aux files
|
||||
* Transform the sealed file in place
|
||||
|
||||
Example invocation of lotus-bench as external executor:
|
||||
'./lotus-bench simple precommit2 --sector-size $EXTSEAL_PC2_SECTOR_SIZE $EXTSEAL_PC2_SEALED $EXTSEAL_PC2_CACHE $EXTSEAL_PC2_PC1OUT'
|
||||
`,
|
||||
Before: func(cctx *cli.Context) error {
|
||||
if cctx.IsSet("address") {
|
||||
log.Warnf("The '--address' flag is deprecated, it has been replaced by '--listen'")
|
||||
@@ -348,6 +379,18 @@ var runCmd = &cli.Command{
|
||||
// Connect to storage-miner
|
||||
ctx := lcli.ReqContext(cctx)
|
||||
|
||||
// Create a new context with cancel function
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
|
||||
// Listen for interrupt signals
|
||||
go func() {
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, os.Interrupt)
|
||||
<-c
|
||||
cancel()
|
||||
}()
|
||||
|
||||
var nodeApi api.StorageMiner
|
||||
var closer func()
|
||||
for {
|
||||
@@ -359,14 +402,13 @@ var runCmd = &cli.Command{
|
||||
}
|
||||
}
|
||||
fmt.Printf("\r\x1b[0KConnecting to miner API... (%s)", err)
|
||||
time.Sleep(time.Second)
|
||||
continue
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return xerrors.New("Interrupted by user")
|
||||
case <-time.After(time.Second):
|
||||
}
|
||||
}
|
||||
|
||||
defer closer()
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
|
||||
// Register all metric views
|
||||
if err := view.Register(
|
||||
metrics.DefaultViews...,
|
||||
@@ -611,18 +653,32 @@ var runCmd = &cli.Command{
|
||||
fh.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
// Parse ffi executor flags
|
||||
|
||||
var ffiOpts []ffiwrapper.FFIWrapperOpt
|
||||
|
||||
if cctx.IsSet("external-pc2") {
|
||||
extSeal := ffiwrapper.ExternalSealer{
|
||||
PreCommit2: ffiwrapper.MakeExternPrecommit2(cctx.String("external-pc2")),
|
||||
}
|
||||
|
||||
ffiOpts = append(ffiOpts, ffiwrapper.WithExternalSealCalls(extSeal))
|
||||
}
|
||||
|
||||
// Create / expose the worker
|
||||
|
||||
wsts := statestore.New(namespace.Wrap(ds, modules.WorkerCallsPrefix))
|
||||
|
||||
workerApi := &sealworker.Worker{
|
||||
LocalWorker: sealer.NewLocalWorker(sealer.WorkerConfig{
|
||||
TaskTypes: taskTypes,
|
||||
NoSwap: cctx.Bool("no-swap"),
|
||||
MaxParallelChallengeReads: cctx.Int("post-parallel-reads"),
|
||||
ChallengeReadTimeout: cctx.Duration("post-read-timeout"),
|
||||
Name: cctx.String("name"),
|
||||
}, remote, localStore, nodeApi, nodeApi, wsts),
|
||||
LocalWorker: sealer.NewLocalWorkerWithExecutor(
|
||||
sealer.FFIExec(ffiOpts...),
|
||||
sealer.WorkerConfig{
|
||||
TaskTypes: taskTypes,
|
||||
NoSwap: cctx.Bool("no-swap"),
|
||||
MaxParallelChallengeReads: cctx.Int("post-parallel-reads"),
|
||||
ChallengeReadTimeout: cctx.Duration("post-read-timeout"),
|
||||
Name: cctx.String("name"),
|
||||
}, os.LookupEnv, remote, localStore, nodeApi, nodeApi, wsts),
|
||||
LocalStore: localStore,
|
||||
Storage: lr,
|
||||
}
|
||||
|
||||
+36
-15
@@ -269,7 +269,37 @@ var DaemonCmd = &cli.Command{
|
||||
}
|
||||
}
|
||||
|
||||
if cctx.Bool("remove-existing-chain") {
|
||||
chainfile := cctx.String("import-chain")
|
||||
snapshot := cctx.String("import-snapshot")
|
||||
willImportChain := false
|
||||
if chainfile != "" || snapshot != "" {
|
||||
if chainfile != "" && snapshot != "" {
|
||||
return fmt.Errorf("cannot specify both 'import-snapshot' and 'import-chain'")
|
||||
}
|
||||
willImportChain = true
|
||||
}
|
||||
|
||||
willRemoveChain := cctx.Bool("remove-existing-chain")
|
||||
if willImportChain && !willRemoveChain {
|
||||
// Confirm with the user about the intention to remove chain data.
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
fmt.Print("Importing chain or snapshot will by default delete existing local chain data. Do you want to proceed and delete? (yes/no): ")
|
||||
userInput, err := reader.ReadString('\n')
|
||||
if err != nil {
|
||||
return xerrors.Errorf("reading user input: %w", err)
|
||||
}
|
||||
userInput = strings.ToLower(strings.TrimSpace(userInput))
|
||||
|
||||
if userInput == "yes" {
|
||||
willRemoveChain = true
|
||||
} else if userInput == "no" {
|
||||
willRemoveChain = false
|
||||
} else {
|
||||
return fmt.Errorf("invalid input. please answer with 'yes' or 'no'")
|
||||
}
|
||||
}
|
||||
|
||||
if willRemoveChain {
|
||||
lr, err := repo.NewFS(cctx.String("repo"))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("error opening fs repo: %w", err)
|
||||
@@ -289,12 +319,7 @@ var DaemonCmd = &cli.Command{
|
||||
}
|
||||
}
|
||||
|
||||
chainfile := cctx.String("import-chain")
|
||||
snapshot := cctx.String("import-snapshot")
|
||||
if chainfile != "" || snapshot != "" {
|
||||
if chainfile != "" && snapshot != "" {
|
||||
return fmt.Errorf("cannot specify both 'import-snapshot' and 'import-chain'")
|
||||
}
|
||||
if willImportChain {
|
||||
var issnapshot bool
|
||||
if chainfile == "" {
|
||||
chainfile = snapshot
|
||||
@@ -540,7 +565,7 @@ func ImportChain(ctx context.Context, r repo.Repo, fname string, snapshot bool)
|
||||
}
|
||||
|
||||
bar.Start()
|
||||
ts, err := cst.Import(ctx, ir)
|
||||
ts, gen, err := cst.Import(ctx, ir)
|
||||
bar.Finish()
|
||||
|
||||
if err != nil {
|
||||
@@ -551,18 +576,14 @@ func ImportChain(ctx context.Context, r repo.Repo, fname string, snapshot bool)
|
||||
return xerrors.Errorf("flushing validation cache failed: %w", err)
|
||||
}
|
||||
|
||||
gb, err := cst.GetTipsetByHeight(ctx, 0, ts, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = cst.SetGenesis(ctx, gb.Blocks()[0])
|
||||
log.Infof("setting genesis")
|
||||
err = cst.SetGenesis(ctx, gen)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !snapshot {
|
||||
shd, err := drand.BeaconScheduleFromDrandSchedule(build.DrandConfigSchedule(), gb.MinTimestamp(), nil)
|
||||
shd, err := drand.BeaconScheduleFromDrandSchedule(build.DrandConfigSchedule(), gen.Timestamp, nil)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to construct beacon schedule: %w", err)
|
||||
}
|
||||
|
||||
@@ -2289,7 +2289,8 @@ Inputs:
|
||||
},
|
||||
{
|
||||
"MaxFee": "0",
|
||||
"MsgUuid": "07070707-0707-0707-0707-070707070707"
|
||||
"MsgUuid": "07070707-0707-0707-0707-070707070707",
|
||||
"MaximizeFeeCap": true
|
||||
},
|
||||
[
|
||||
{
|
||||
@@ -2766,7 +2767,8 @@ Inputs:
|
||||
],
|
||||
{
|
||||
"MaxFee": "0",
|
||||
"MsgUuid": "07070707-0707-0707-0707-070707070707"
|
||||
"MsgUuid": "07070707-0707-0707-0707-070707070707",
|
||||
"MaximizeFeeCap": true
|
||||
}
|
||||
]
|
||||
```
|
||||
@@ -3025,7 +3027,8 @@ Inputs:
|
||||
},
|
||||
{
|
||||
"MaxFee": "0",
|
||||
"MsgUuid": "07070707-0707-0707-0707-070707070707"
|
||||
"MsgUuid": "07070707-0707-0707-0707-070707070707",
|
||||
"MaximizeFeeCap": true
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
@@ -2402,14 +2402,7 @@ Perms: read
|
||||
Inputs:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"from": "0x5cbeecf99d3fdb3f25e309cc264f240bb0664031",
|
||||
"to": "0x5cbeecf99d3fdb3f25e309cc264f240bb0664031",
|
||||
"gas": "0x5",
|
||||
"gasPrice": "0x0",
|
||||
"value": "0x0",
|
||||
"data": "0x07"
|
||||
}
|
||||
"Bw=="
|
||||
]
|
||||
```
|
||||
|
||||
@@ -3357,7 +3350,8 @@ Inputs:
|
||||
},
|
||||
{
|
||||
"MaxFee": "0",
|
||||
"MsgUuid": "07070707-0707-0707-0707-070707070707"
|
||||
"MsgUuid": "07070707-0707-0707-0707-070707070707",
|
||||
"MaximizeFeeCap": true
|
||||
},
|
||||
[
|
||||
{
|
||||
@@ -3834,7 +3828,8 @@ Inputs:
|
||||
],
|
||||
{
|
||||
"MaxFee": "0",
|
||||
"MsgUuid": "07070707-0707-0707-0707-070707070707"
|
||||
"MsgUuid": "07070707-0707-0707-0707-070707070707",
|
||||
"MaximizeFeeCap": true
|
||||
}
|
||||
]
|
||||
```
|
||||
@@ -4226,7 +4221,8 @@ Inputs:
|
||||
},
|
||||
{
|
||||
"MaxFee": "0",
|
||||
"MsgUuid": "07070707-0707-0707-0707-070707070707"
|
||||
"MsgUuid": "07070707-0707-0707-0707-070707070707",
|
||||
"MaximizeFeeCap": true
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
@@ -104,9 +104,9 @@ domain separation tag.
|
||||
### Winning PoSt proof
|
||||
|
||||
Draw randomness for current epoch with `WinningPoSt` domain separation tag.
|
||||
Get list of sectors challanged in this epoch for this miner, based on the randomness drawn.
|
||||
Get list of sectors challenged in this epoch for this miner, based on the randomness drawn.
|
||||
|
||||
`V`: Use filecoin proofs system to verify that miner prooved access to sealed versions of these sectors.
|
||||
`V`: Use filecoin proofs system to verify that miner proved access to sealed versions of these sectors.
|
||||
|
||||
## `(*StateManager).TipSetState()`
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ USAGE:
|
||||
lotus-miner [global options] command [command options] [arguments...]
|
||||
|
||||
VERSION:
|
||||
1.25.0-rc5
|
||||
1.25.1-dev
|
||||
|
||||
COMMANDS:
|
||||
init Initialize a lotus miner repo
|
||||
|
||||
@@ -7,7 +7,7 @@ USAGE:
|
||||
lotus-worker [global options] command [command options] [arguments...]
|
||||
|
||||
VERSION:
|
||||
1.25.0-rc5
|
||||
1.25.1-dev
|
||||
|
||||
COMMANDS:
|
||||
run Start lotus worker
|
||||
@@ -34,6 +34,33 @@ NAME:
|
||||
USAGE:
|
||||
lotus-worker run [command options] [arguments...]
|
||||
|
||||
DESCRIPTION:
|
||||
Run lotus-worker.
|
||||
|
||||
--external-pc2 can be used to compute the PreCommit2 inputs externally.
|
||||
The flag behaves similarly to the related lotus-worker flag, using it in
|
||||
lotus-bench may be useful for testing if the external PreCommit2 command is
|
||||
invoked correctly.
|
||||
|
||||
The command will be called with a number of environment variables set:
|
||||
* EXTSEAL_PC2_SECTOR_NUM: the sector number
|
||||
* EXTSEAL_PC2_SECTOR_MINER: the miner id
|
||||
* EXTSEAL_PC2_PROOF_TYPE: the proof type
|
||||
* EXTSEAL_PC2_SECTOR_SIZE: the sector size in bytes
|
||||
* EXTSEAL_PC2_CACHE: the path to the cache directory
|
||||
* EXTSEAL_PC2_SEALED: the path to the sealed sector file (initialized with unsealed data by the caller)
|
||||
* EXTSEAL_PC2_PC1OUT: output from rust-fil-proofs precommit1 phase (base64 encoded json)
|
||||
|
||||
The command is expected to:
|
||||
* Create cache sc-02-data-tree-r* files
|
||||
* Create cache sc-02-data-tree-c* files
|
||||
* Create cache p_aux / t_aux files
|
||||
* Transform the sealed file in place
|
||||
|
||||
Example invocation of lotus-bench as external executor:
|
||||
'./lotus-bench simple precommit2 --sector-size $EXTSEAL_PC2_SECTOR_SIZE $EXTSEAL_PC2_SEALED $EXTSEAL_PC2_CACHE $EXTSEAL_PC2_PC1OUT'
|
||||
|
||||
|
||||
OPTIONS:
|
||||
--listen value host address and port the worker api will listen on (default: "0.0.0.0:3456") [$LOTUS_WORKER_LISTEN]
|
||||
--no-local-storage don't use storageminer repo for sector storage (default: false) [$LOTUS_WORKER_NO_LOCAL_STORAGE]
|
||||
@@ -57,6 +84,7 @@ OPTIONS:
|
||||
--timeout value used when 'listen' is unspecified. must be a valid duration recognized by golang's time.ParseDuration function (default: "30m") [$LOTUS_WORKER_TIMEOUT]
|
||||
--http-server-timeout value (default: "30s")
|
||||
--data-cid Run the data-cid task. true|false (default: inherits --addpiece)
|
||||
--external-pc2 value command for computing PC2 externally
|
||||
--help, -h show help
|
||||
```
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ USAGE:
|
||||
lotus [global options] command [command options] [arguments...]
|
||||
|
||||
VERSION:
|
||||
1.25.0-rc5
|
||||
1.25.1-dev
|
||||
|
||||
COMMANDS:
|
||||
daemon Start a lotus daemon process
|
||||
|
||||
@@ -195,7 +195,7 @@
|
||||
|
||||
[Chainstore.Splitstore]
|
||||
# ColdStoreType specifies the type of the coldstore.
|
||||
# It can be "messages" (default) to store only messages, "universal" to store all chain state or "discard" for discarding cold blocks.
|
||||
# It can be "discard" (default) for discarding cold blocks, "messages" to store only messages or "universal" to store all chain state..
|
||||
#
|
||||
# type: string
|
||||
# env var: LOTUS_CHAINSTORE_SPLITSTORE_COLDSTORETYPE
|
||||
|
||||
@@ -778,6 +778,10 @@
|
||||
# env var: LOTUS_FEES_MAXMARKETBALANCEADDFEE
|
||||
#MaxMarketBalanceAddFee = "0.007 FIL"
|
||||
|
||||
# type: bool
|
||||
# env var: LOTUS_FEES_MAXIMIZEWINDOWPOSTFEECAP
|
||||
#MaximizeWindowPoStFeeCap = true
|
||||
|
||||
[Fees.MaxPreCommitBatchGasFee]
|
||||
# type: types.FIL
|
||||
# env var: LOTUS_FEES_MAXPRECOMMITBATCHGASFEE_BASE
|
||||
|
||||
@@ -14,11 +14,13 @@
|
||||
**Note for whoever is owning the release:** please capture notes as comments in this issue for anything you noticed that could be improved for future releases. There is a *Post Release* step below for incorporating changes back into the [RELEASE_ISSUE_TEMPLATE](https://github.com/filecoin-project/lotus/blob/master/documentation/misc/RELEASE_ISSUE_TEMPLATE.md), and this is easier done by collecting notes from along the way rather than just thinking about it at the end.
|
||||
|
||||
First steps:
|
||||
- [ ] FFI: Fork a new branch (`release/lotus-vX.Y.Z`) from the filecoin-ffi `master` branch
|
||||
- [ ] FFI: Tag the head of `release/lotus-vX.Y.Z` as `vX.Y.Z-pre1`
|
||||
- [ ] Set shell variables vX.Y.Z `export X=1 && export Y=24 && export Z=3`
|
||||
- [ ] FFI: Fork a new branch (`release/lotus-vX.Y.Z`) from the filecoin-ffi `master` branch: `git checkout master && git checkout -b release/lotus-v$X.$Y.$Z`
|
||||
- [ ] FFI: Tag the head of `release/lotus-vX.Y.Z` as `vX.Y.Z-pre1`: `git tag -a v$X.$Y.$Z-pre1 -m"release"`
|
||||
- [ ] Open and land a PR in lotus `master` that updates the FFI dependency to `vX.Y.Z-pre1` as cut in the previous step
|
||||
- [ ] Fork a new branch (`release/vX.Y.Z`) from `master` and make any further release related changes to this branch. If any "non-trivial" changes get added to the release, uncheck all the checkboxes and return to this stage.
|
||||
- [ ] Bump the version in `build/version.go` in the `master` branch to `vX.Y.(Z+1)-dev` (bump from feature release) or `vX.(Y+1).0-dev` (bump from mandatory release). Run make gen and make docsgen-cli before committing changes
|
||||
- [ ] Bump the version in `build/version.go` in the `master` branch to `vX.Y.(Z+1)-dev` (bump from feature release) or `vX.(Y+1).0-dev` (bump from mandatory release).
|
||||
- [ ] Run `make gen && make docsgen-cli` before committing changes
|
||||
|
||||
**Prepping an RC**:
|
||||
|
||||
@@ -26,6 +28,7 @@ First steps:
|
||||
- [ ] run `make gen && make docsgen-cli`
|
||||
- [ ] Generate changelog using the script at scripts/mkreleaselog
|
||||
- [ ] Add contents of generated text to lotus/CHANGELOG.md in addition to other details
|
||||
- [ ] Commit using PR
|
||||
- [ ] tag commit with `vX.Y.Z-rcN`
|
||||
- [ ] cut a pre-release [here](https://github.com/filecoin-project/lotus/releases/new?prerelease=true)
|
||||
|
||||
|
||||
Vendored
+1
-1
Submodule extern/filecoin-ffi updated: 441fa8e611...4176a1e662
+1
-1
@@ -131,7 +131,7 @@ type TargetAPI interface {
|
||||
EthGasPrice(ctx context.Context) (ethtypes.EthBigInt, error)
|
||||
EthFeeHistory(ctx context.Context, p jsonrpc.RawParams) (ethtypes.EthFeeHistory, error)
|
||||
EthMaxPriorityFeePerGas(ctx context.Context) (ethtypes.EthBigInt, error)
|
||||
EthEstimateGas(ctx context.Context, tx ethtypes.EthCall) (ethtypes.EthUint64, error)
|
||||
EthEstimateGas(ctx context.Context, p jsonrpc.RawParams) (ethtypes.EthUint64, error)
|
||||
EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthBytes, error)
|
||||
EthSendRawTransaction(ctx context.Context, rawTx ethtypes.EthBytes) (ethtypes.EthHash, error)
|
||||
EthGetLogs(ctx context.Context, filter *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error)
|
||||
|
||||
@@ -353,13 +353,19 @@ func (gw *Node) EthMaxPriorityFeePerGas(ctx context.Context) (ethtypes.EthBigInt
|
||||
return gw.target.EthMaxPriorityFeePerGas(ctx)
|
||||
}
|
||||
|
||||
func (gw *Node) EthEstimateGas(ctx context.Context, tx ethtypes.EthCall) (ethtypes.EthUint64, error) {
|
||||
func (gw *Node) EthEstimateGas(ctx context.Context, p jsonrpc.RawParams) (ethtypes.EthUint64, error) {
|
||||
// validate params
|
||||
_, err := jsonrpc.DecodeParams[ethtypes.EthEstimateGasParams](p)
|
||||
if err != nil {
|
||||
return ethtypes.EthUint64(0), xerrors.Errorf("decoding params: %w", err)
|
||||
}
|
||||
|
||||
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// todo limit gas? to what?
|
||||
return gw.target.EthEstimateGas(ctx, tx)
|
||||
return gw.target.EthEstimateGas(ctx, p)
|
||||
}
|
||||
|
||||
func (gw *Node) EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthBytes, error) {
|
||||
|
||||
@@ -45,7 +45,7 @@ require (
|
||||
github.com/filecoin-project/go-jsonrpc v0.3.1
|
||||
github.com/filecoin-project/go-padreader v0.0.1
|
||||
github.com/filecoin-project/go-paramfetch v0.0.4
|
||||
github.com/filecoin-project/go-state-types v0.12.5
|
||||
github.com/filecoin-project/go-state-types v0.12.8
|
||||
github.com/filecoin-project/go-statemachine v1.0.3
|
||||
github.com/filecoin-project/go-statestore v0.2.0
|
||||
github.com/filecoin-project/go-storedcounter v0.1.0
|
||||
@@ -107,7 +107,7 @@ require (
|
||||
github.com/kelseyhightower/envconfig v1.4.0
|
||||
github.com/koalacxr/quantile v0.0.1
|
||||
github.com/libp2p/go-buffer-pool v0.1.0
|
||||
github.com/libp2p/go-libp2p v0.30.0
|
||||
github.com/libp2p/go-libp2p v0.31.0
|
||||
github.com/libp2p/go-libp2p-consensus v0.0.1
|
||||
github.com/libp2p/go-libp2p-gorpc v0.5.0
|
||||
github.com/libp2p/go-libp2p-kad-dht v0.24.0
|
||||
@@ -136,6 +136,7 @@ require (
|
||||
github.com/raulk/go-watchdog v1.3.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
|
||||
github.com/triplewz/poseidon v0.0.0-20220525065023-a7cdb0e183e7
|
||||
github.com/urfave/cli/v2 v2.25.5
|
||||
github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba
|
||||
github.com/whyrusleeping/cbor-gen v0.0.0-20230923211252-36a87e1ba72f
|
||||
@@ -297,7 +298,7 @@ require (
|
||||
github.com/prometheus/statsd_exporter v0.22.7 // indirect
|
||||
github.com/quic-go/qpack v0.4.0 // indirect
|
||||
github.com/quic-go/qtls-go1-20 v0.3.3 // indirect
|
||||
github.com/quic-go/quic-go v0.37.6 // indirect
|
||||
github.com/quic-go/quic-go v0.38.1 // indirect
|
||||
github.com/quic-go/webtransport-go v0.5.3 // indirect
|
||||
github.com/rivo/uniseg v0.1.0 // indirect
|
||||
github.com/rs/cors v1.7.0 // indirect
|
||||
@@ -338,3 +339,5 @@ require (
|
||||
replace github.com/filecoin-project/filecoin-ffi => ./extern/filecoin-ffi
|
||||
|
||||
replace github.com/filecoin-project/test-vectors => ./extern/test-vectors
|
||||
|
||||
replace github.com/triplewz/poseidon => github.com/magik6k/poseidon v0.0.0-neptune
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user