Compare commits
861
Commits
v1.11.0-rc2
...
origin
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88efbfa6ff | ||
|
|
fcd630e529 | ||
|
|
073150a306 | ||
|
|
7d70ef79af | ||
|
|
bb040abb2c | ||
|
|
00c3432e5a | ||
|
|
4b6fa79ea2 | ||
|
|
b3c951c924 | ||
|
|
299b106f38 | ||
|
|
1b5a2dd79a | ||
|
|
107777fdac | ||
|
|
d37ae957e0 | ||
|
|
92056423c3 | ||
|
|
8442bac5b2 | ||
|
|
029ba39fd9 | ||
|
|
0daee83735 | ||
|
|
786d3e79eb | ||
|
|
fd33b96e08 | ||
|
|
4417be81ad | ||
|
|
ec78d3d7b1 | ||
|
|
0caabf1328 | ||
|
|
a24b2436b0 | ||
|
|
7a3193a75b | ||
|
|
d039764a34 | ||
|
|
d8c90b91be | ||
|
|
c119ab6ed9 | ||
|
|
0c036b1157 | ||
|
|
cea26348c4 | ||
|
|
0dd83c6755 | ||
|
|
9b7a7713a7 | ||
|
|
5073c7e6cf | ||
|
|
c8b0f11841 | ||
|
|
94318da0e6 | ||
|
|
9ba6a41ef4 | ||
|
|
5d047c59b1 | ||
|
|
80fcad5ad5 | ||
|
|
b6112c6fc9 | ||
|
|
650d6efb1a | ||
|
|
c8900aac42 | ||
|
|
193cb91340 | ||
|
|
2e98f8b5d2 | ||
|
|
8a54273f8b | ||
|
|
db86630fb3 | ||
|
|
7a9a4bac1e | ||
|
|
f4fa4c8cce | ||
|
|
db6b94cf1e | ||
|
|
56d8003000 | ||
|
|
7c2341b43c | ||
|
|
90fa7ff057 | ||
|
|
35c90349ce | ||
|
|
505bc58530 | ||
|
|
38c91a28aa | ||
|
|
2ba48a7581 | ||
|
|
4918a7c16f | ||
|
|
19182999dd | ||
|
|
83f7dc8c96 | ||
|
|
6751185d6f | ||
|
|
2a2b442aae | ||
|
|
d0353d1ef1 | ||
|
|
1250f8009f | ||
|
|
4b70d13a4b | ||
|
|
987fc0b77d | ||
|
|
e4b225f4ba | ||
|
|
b04fb75a92 | ||
|
|
cef65cd989 | ||
|
|
7c28ff3826 | ||
|
|
6e9f480063 | ||
|
|
1d87ffcee4 | ||
|
|
0e99500b93 | ||
|
|
db12fd4a03 | ||
|
|
2790c9439f | ||
|
|
80b334d04f | ||
|
|
944aeed13e | ||
|
|
109a8242ae | ||
|
|
2f03b456de | ||
|
|
3451acbc03 | ||
|
|
18f5997d02 | ||
|
|
bc82a48693 | ||
|
|
e46f02f59d | ||
|
|
48cddd3644 | ||
|
|
e4ebbf106a | ||
|
|
69f0b22f6a | ||
|
|
c2575327c0 | ||
|
|
e0522a6b1f | ||
|
|
06d01d7dc0 | ||
|
|
7c195245a1 | ||
|
|
da3e36acdc | ||
|
|
8809707158 | ||
|
|
c21c413695 | ||
|
|
bb2d99908c | ||
|
|
b82f953fd5 | ||
|
|
59aebba0d9 | ||
|
|
d24b2acc63 | ||
|
|
0baeec0686 | ||
|
|
649fc62863 | ||
|
|
d6ace68540 | ||
|
|
cbaffab9dd | ||
|
|
c03859c1b5 | ||
|
|
9d25464703 | ||
|
|
96c1123c33 | ||
|
|
0dd325866d | ||
|
|
160fab08aa | ||
|
|
9bdbbf33cb | ||
|
|
790f27d6a2 | ||
|
|
2ca174482b | ||
|
|
20c5dd5bdc | ||
|
|
7ffe63a358 | ||
|
|
39325e5463 | ||
|
|
acc38817ec | ||
|
|
2772b54eda | ||
|
|
98c8a2abe5 | ||
|
|
ef24593544 | ||
|
|
c7e94beddc | ||
|
|
ed387b43cc | ||
|
|
26e961380a | ||
|
|
c52c2738ab | ||
|
|
18caefc4a1 | ||
|
|
0fd8fc24e1 | ||
|
|
104626acb7 | ||
|
|
9d61f91cdf | ||
|
|
7de866d881 | ||
|
|
50e1dc6b6e | ||
|
|
11d3f19a5b | ||
|
|
938330e6c3 | ||
|
|
aa0bd51b2c | ||
|
|
20f93a520f | ||
|
|
4cdb34e448 | ||
|
|
21e7c188da | ||
|
|
b1f60e85e9 | ||
|
|
5acae50e07 | ||
|
|
fb3986226f | ||
|
|
c747f2f1e2 | ||
|
|
a843665132 | ||
|
|
94509968a0 | ||
|
|
5cf6fdf81d | ||
|
|
524564e2cf | ||
|
|
f2c7b08be5 | ||
|
|
608a9f84d2 | ||
|
|
4b0b37a4ef | ||
|
|
4715b1f436 | ||
|
|
aec126879e | ||
|
|
001c04f2dd | ||
|
|
b741d61b20 | ||
|
|
76a9f4241b | ||
|
|
5048c3f717 | ||
|
|
1f6935f8c4 | ||
|
|
3c409d5023 | ||
|
|
2cfd73c879 | ||
|
|
74009bd67f | ||
|
|
221dc7024f | ||
|
|
ce528a1293 | ||
|
|
30e4b405b7 | ||
|
|
baaa9a7738 | ||
|
|
77604db716 | ||
|
|
a0d6fdba33 | ||
|
|
c00b86e8a8 | ||
|
|
2dc72d5849 | ||
|
|
5285a14d27 | ||
|
|
5718da237f | ||
|
|
21bb2bda09 | ||
|
|
5b2e4d8ad4 | ||
|
|
c99dc3e811 | ||
|
|
3d2ae433ee | ||
|
|
1918ffda4e | ||
|
|
e317c831a8 | ||
|
|
ce6f410f2a | ||
|
|
254c489164 | ||
|
|
33cdc90f13 | ||
|
|
da66e7a878 | ||
|
|
e696a2c0cc | ||
|
|
36b209ca5c | ||
|
|
92b9d8c895 | ||
|
|
0c68bccbda | ||
|
|
78f94c4c6b | ||
|
|
8d873e3edc | ||
|
|
8693df4656 | ||
|
|
2edf7fd25b | ||
|
|
5cb7411c2a | ||
|
|
7832545b7a | ||
|
|
e615eecbea | ||
|
|
39cc536115 | ||
|
|
f09c4733ad | ||
|
|
d14b84cd11 | ||
|
|
816ee0b004 | ||
|
|
02a37a1e22 | ||
|
|
5b4d5c2eb4 | ||
|
|
964df1a2ec | ||
|
|
91c6aca7e7 | ||
|
|
80af6de316 | ||
|
|
ac2a1bfeab | ||
|
|
4b8a5068bd | ||
|
|
a26712ebc4 | ||
|
|
d6ebead756 | ||
|
|
1480c22447 | ||
|
|
ed7f70e68e | ||
|
|
3f4973cb41 | ||
|
|
4757b014bc | ||
|
|
8b1f19e94c | ||
|
|
97f5bb66c7 | ||
|
|
cf65804883 | ||
|
|
9faa3d5fd7 | ||
|
|
9d5cf4177b | ||
|
|
dec5e13c85 | ||
|
|
a8c0fd1654 | ||
|
|
4df6073382 | ||
|
|
f492f8d450 | ||
|
|
f75d982c76 | ||
|
|
2891a31c99 | ||
|
|
f2b7c3e6f2 | ||
|
|
12c3432b8d | ||
|
|
be9530b66e | ||
|
|
2c26abc551 | ||
|
|
54a6968327 | ||
|
|
db39323390 | ||
|
|
d3564cc2a3 | ||
|
|
52498f78a1 | ||
|
|
7ef167b04f | ||
|
|
b79690cef4 | ||
|
|
e41bc229e3 | ||
|
|
bda25dd6f2 | ||
|
|
d6783736dc | ||
|
|
19048e6a91 | ||
|
|
21f9dc8096 | ||
|
|
4ffbb03a82 | ||
|
|
c08e547efa | ||
|
|
f68b43a526 | ||
|
|
ab02ca7e38 | ||
|
|
0f21fcc87e | ||
|
|
5266b240b8 | ||
|
|
2a68ae8dad | ||
|
|
2d40089b7e | ||
|
|
f9752d8a0a | ||
|
|
adba595350 | ||
|
|
15a6995cda | ||
|
|
e6eb51b2d5 | ||
|
|
0656b62176 | ||
|
|
e647d9913e | ||
|
|
604e972e6e | ||
|
|
c130d2cb87 | ||
|
|
3155609304 | ||
|
|
09adc4d5e2 | ||
|
|
fe5e1b23d5 | ||
|
|
d6a8a7aeb8 | ||
|
|
4cd05fa39c | ||
|
|
ed844c5283 | ||
|
|
9fc4a25bd1 | ||
|
|
56d71a190f | ||
|
|
cbc07cb939 | ||
|
|
545cc723e0 | ||
|
|
aff7200b3e | ||
|
|
47b5afa84b | ||
|
|
f49a8248f0 | ||
|
|
90ad0d85a5 | ||
|
|
660829703a | ||
|
|
e64626cdf3 | ||
|
|
48e8f54c6a | ||
|
|
776c216072 | ||
|
|
3006dda786 | ||
|
|
1ebfc74657 | ||
|
|
4fc1dfacb4 | ||
|
|
0c02207fc9 | ||
|
|
da5aeda197 | ||
|
|
91107df701 | ||
|
|
c8776d74ec | ||
|
|
9a12247840 | ||
|
|
bf066403e8 | ||
|
|
c9bc247732 | ||
|
|
a3687a6cfa | ||
|
|
283793f943 | ||
|
|
e7f39a3179 | ||
|
|
395451b3e9 | ||
|
|
c9999f7ca2 | ||
|
|
c60959ea9f | ||
|
|
e52c639f02 | ||
|
|
62044c34b1 | ||
|
|
ab4093fea0 | ||
|
|
dfa57ffbc1 | ||
|
|
4b6258f2a2 | ||
|
|
f972021b23 | ||
|
|
8bf06bacfa | ||
|
|
067b45d9ab | ||
|
|
7531e543f3 | ||
|
|
c8d328d386 | ||
|
|
d89e2f065c | ||
|
|
4830a3406b | ||
|
|
fd879e0426 | ||
|
|
27f3170022 | ||
|
|
5b1241d213 | ||
|
|
eaee1578dd | ||
|
|
9e5c5b624b | ||
|
|
640d69f5cb | ||
|
|
36876c2601 | ||
|
|
39c1594505 | ||
|
|
86e1c854fa | ||
|
|
9ad408a0ba | ||
|
|
1af89236da | ||
|
|
90c8891f95 | ||
|
|
0236f2ec5d | ||
|
|
c29f375a7a | ||
|
|
9741867426 | ||
|
|
b7b98f94a6 | ||
|
|
fb50d68c32 | ||
|
|
692961e019 | ||
|
|
312cc94e6d | ||
|
|
ea71e4de60 | ||
|
|
4ed9cd152c | ||
|
|
0dbb1940f0 | ||
|
|
9d0596e6e8 | ||
|
|
29195470d6 | ||
|
|
2c5a867eab | ||
|
|
1452a361a9 | ||
|
|
503c08f999 | ||
|
|
6bee14d6fa | ||
|
|
839abdf910 | ||
|
|
6057f2e6d9 | ||
|
|
fe31956713 | ||
|
|
213dbc6bc8 | ||
|
|
fc77705229 | ||
|
|
12d7db4efb | ||
|
|
d7827da5bb | ||
|
|
c49dbf0999 | ||
|
|
8029a9ffe3 | ||
|
|
aea338ecf0 | ||
|
|
38919f59ad | ||
|
|
c1f0ebbefa | ||
|
|
8413c080e3 | ||
|
|
cd4571f0b0 | ||
|
|
6c6df04112 | ||
|
|
8ddd12d144 | ||
|
|
865e7ca80a | ||
|
|
f9c759fcb2 | ||
|
|
ad1dd36193 | ||
|
|
e0208e3595 | ||
|
|
591320dd44 | ||
|
|
bd7aa99175 | ||
|
|
5e66960ab6 | ||
|
|
353ccf0c55 | ||
|
|
b2ff2edd0c | ||
|
|
13e845ae51 | ||
|
|
0c90868929 | ||
|
|
44496afc66 | ||
|
|
c1b304b633 | ||
|
|
546d192439 | ||
|
|
8becd922cf | ||
|
|
16be5b5478 | ||
|
|
1e7095995b | ||
|
|
ffb995035f | ||
|
|
ffe7185443 | ||
|
|
44036d9a4a | ||
|
|
c9930cb7db | ||
|
|
839b00ab40 | ||
|
|
c47fce8d2d | ||
|
|
ebbaf23af8 | ||
|
|
4a93e3b8a8 | ||
|
|
b6a7a8c987 | ||
|
|
905592a3dc | ||
|
|
eef3fd5d7a | ||
|
|
1c30d07d68 | ||
|
|
006050ed27 | ||
|
|
d8431da9b9 | ||
|
|
1b77361301 | ||
|
|
3b4df5e10d | ||
|
|
089bcceb33 | ||
|
|
9042429abd | ||
|
|
aeb8e57eef | ||
|
|
b2feb7e960 | ||
|
|
d5c9cccf21 | ||
|
|
b20581bac2 | ||
|
|
9724248a49 | ||
|
|
fd9f5dc83c | ||
|
|
ed058ae193 | ||
|
|
ca5a2eaa74 | ||
|
|
35b39063ac | ||
|
|
1d9dcef878 | ||
|
|
25cd577d06 | ||
|
|
e003203bea | ||
|
|
812dc266cf | ||
|
|
49e26cce7d | ||
|
|
33c347956c | ||
|
|
f07a370711 | ||
|
|
a03c5ac3d2 | ||
|
|
a259ee307f | ||
|
|
46b78406b1 | ||
|
|
ab2f159d54 | ||
|
|
d023026cb0 | ||
|
|
b2f8b4011a | ||
|
|
3e9ec01d04 | ||
|
|
a48a6a168a | ||
|
|
ac03c01e4a | ||
|
|
bdaa73a413 | ||
|
|
cf81c897df | ||
|
|
81d614a607 | ||
|
|
5e5b4b7191 | ||
|
|
dd0f4dea81 | ||
|
|
c738d1f7ef | ||
|
|
5a23f64b3b | ||
|
|
44d01712c8 | ||
|
|
3f3a12b75c | ||
|
|
023146803d | ||
|
|
3d77ae1f4d | ||
|
|
6f126c80bf | ||
|
|
ff093fae00 | ||
|
|
669b47cfc9 | ||
|
|
818b8de182 | ||
|
|
c93328b036 | ||
|
|
35180b4761 | ||
|
|
dc81c0e6a2 | ||
|
|
f0c9e4e8f2 | ||
|
|
71ddbdaf10 | ||
|
|
856cbb2ca0 | ||
|
|
a37ababc20 | ||
|
|
677c193e6c | ||
|
|
dd09666399 | ||
|
|
583a8a13d9 | ||
|
|
837322ea59 | ||
|
|
0678b3fa05 | ||
|
|
7526a074d9 | ||
|
|
2af02af1c1 | ||
|
|
c37401a1a3 | ||
|
|
6efd2e7335 | ||
|
|
af399529ec | ||
|
|
257423e917 | ||
|
|
04abd190ab | ||
|
|
60212c86cb | ||
|
|
759594d01c | ||
|
|
5c3e79e8d0 | ||
|
|
92ec239202 | ||
|
|
4433c3cd7c | ||
|
|
7728d6bfc3 | ||
|
|
83f2368507 | ||
|
|
4bc9fa04ba | ||
|
|
056136ef5a | ||
|
|
a423c46f2a | ||
|
|
d89ddb9315 | ||
|
|
16784aa2cc | ||
|
|
88ac2ebc0c | ||
|
|
13dcfec8fe | ||
|
|
20582037c5 | ||
|
|
e983d90a28 | ||
|
|
ea9ad8c5a8 | ||
|
|
93d929a10a | ||
|
|
df9670c58d | ||
|
|
0c5e336ff1 | ||
|
|
cbf281d1ca | ||
|
|
71ddf73f44 | ||
|
|
f7f5fd4809 | ||
|
|
dff097a992 | ||
|
|
870a47f55d | ||
|
|
f5ae10e3d1 | ||
|
|
41290383e2 | ||
|
|
b9a5ea8f7b | ||
|
|
c0a1cfffa1 | ||
|
|
18161fee38 | ||
|
|
095d7427ba | ||
|
|
da0feb3fa4 | ||
|
|
acc4c374ef | ||
|
|
872843e491 | ||
|
|
565faff754 | ||
|
|
4f89d260b0 | ||
|
|
de5e21bf1a | ||
|
|
909f7039d4 | ||
|
|
abdf4a161a | ||
|
|
77a1a8a23f | ||
|
|
dbc721af3a | ||
|
|
b6611125b6 | ||
|
|
60dd97c7fc | ||
|
|
44e81424f2 | ||
|
|
ed0cc0b56d | ||
|
|
10825e3a95 | ||
|
|
8f7bf1df86 | ||
|
|
79b0bfb272 | ||
|
|
c0537848b3 | ||
|
|
fa30ac8c5d | ||
|
|
616fcb974c | ||
|
|
00d7772f57 | ||
|
|
e258e7c353 | ||
|
|
5cf1e09e81 | ||
|
|
9aa4f3b3b2 | ||
|
|
4dd59b566c | ||
|
|
140a2e0200 | ||
|
|
e6eacbdd56 | ||
|
|
48f13a43b7 | ||
|
|
f5c45bd517 | ||
|
|
9bdea91a70 | ||
|
|
4f808367f8 | ||
|
|
fee50b13a2 | ||
|
|
c6421f8a75 | ||
|
|
d0e87a7487 | ||
|
|
2dc27d6ab4 | ||
|
|
ee97aa0a8a | ||
|
|
c7bb326c78 | ||
|
|
8f5c0c60f5 | ||
|
|
82efe01c70 | ||
|
|
bb466ede66 | ||
|
|
aec2ba2c82 | ||
|
|
ec586a852a | ||
|
|
451ddf50ab | ||
|
|
9dbb2e0abd | ||
|
|
49896afe9f | ||
|
|
1fe08f5973 | ||
|
|
6b014f57e5 | ||
|
|
caa366bc6a | ||
|
|
42ae876711 | ||
|
|
a5ba556fff | ||
|
|
44d088be1e | ||
|
|
dcfbb1998f | ||
|
|
b40985a57c | ||
|
|
f8d32f5328 | ||
|
|
83c30dc4c0 | ||
|
|
6cc2112749 | ||
|
|
05dbbe9681 | ||
|
|
ba236fe258 | ||
|
|
2b5164c956 | ||
|
|
ca2d441b6d | ||
|
|
90da6227b3 | ||
|
|
0e2af11f6a | ||
|
|
88c578bc54 | ||
|
|
f268068457 | ||
|
|
251214dfd9 | ||
|
|
a8ca7baa93 | ||
|
|
9977a6d1d7 | ||
|
|
9d6d1f5715 | ||
|
|
566a9d5541 | ||
|
|
9f83da836d | ||
|
|
2a7af38538 | ||
|
|
7a78527fde | ||
|
|
b572c2b7bc | ||
|
|
10dc90f7fe | ||
|
|
898687ea2e | ||
|
|
8cf3accc53 | ||
|
|
604be5fc82 | ||
|
|
51696bb35d | ||
|
|
f2f4af669d | ||
|
|
ff2772a58c | ||
|
|
9839d5701b | ||
|
|
c1c25868cc | ||
|
|
fdff1bebc9 | ||
|
|
5c514504f7 | ||
|
|
dc8139a1d2 | ||
|
|
8697edc8b7 | ||
|
|
bed4c03a50 | ||
|
|
e041fe130b | ||
|
|
c4ae3e0c3d | ||
|
|
169ab262f5 | ||
|
|
55a9e0ccd1 | ||
|
|
bf7aeb3167 | ||
|
|
0659235e21 | ||
|
|
a07a0935fe | ||
|
|
525a2c71dd | ||
|
|
c6ad8fdaed | ||
|
|
2cbd3faf5a | ||
|
|
51ab891d5c | ||
|
|
bd436ab9de | ||
|
|
e859942fa4 | ||
|
|
3477d265c6 | ||
|
|
97207df705 | ||
|
|
73d07999bf | ||
|
|
af8cf712be | ||
|
|
17c0b9be44 | ||
|
|
d76cbf805a | ||
|
|
5e5de9b41b | ||
|
|
a56b6fea99 | ||
|
|
5a099b7d05 | ||
|
|
59639a0788 | ||
|
|
5a87f04e71 | ||
|
|
fa195bede2 | ||
|
|
4be0a7a215 | ||
|
|
a544fa0f97 | ||
|
|
add113f585 | ||
|
|
59936ef468 | ||
|
|
44985722d2 | ||
|
|
0b7153be86 | ||
|
|
d8b8d75e0f | ||
|
|
d7709deb2b | ||
|
|
3ec834b2e3 | ||
|
|
918a7ec749 | ||
|
|
2ea2abc07d | ||
|
|
839f7bd2b5 | ||
|
|
c81ae5fc20 | ||
|
|
4c41f52828 | ||
|
|
3597192d58 | ||
|
|
1726eb993c | ||
|
|
8ecdc929b4 | ||
|
|
db53859e7a | ||
|
|
b08e0b7102 | ||
|
|
94efae419e | ||
|
|
f33d4e79aa | ||
|
|
40c271cda1 | ||
|
|
13d612f72f | ||
|
|
f124389b66 | ||
|
|
4d286da593 | ||
|
|
680af8eb09 | ||
|
|
1f02428225 | ||
|
|
2c7a89a1db | ||
|
|
028a5c4942 | ||
|
|
8e56fffb33 | ||
|
|
95c3aaec9a | ||
|
|
190cb18ab0 | ||
|
|
19d1b1f532 | ||
|
|
0a1d7b3732 | ||
|
|
08cad30be2 | ||
|
|
eafffc1634 | ||
|
|
36f93649ef | ||
|
|
6fa2cd232d | ||
|
|
5f7ae1f489 | ||
|
|
1f2b604c07 | ||
|
|
d476a3db2c | ||
|
|
68a83500bc | ||
|
|
00fcf6dd72 | ||
|
|
642f0e4740 | ||
|
|
c5cf8e226b | ||
|
|
d79e4da7aa | ||
|
|
6f58fdcb22 | ||
|
|
2b03316cd9 | ||
|
|
184d3802b6 | ||
|
|
228a435ba7 | ||
|
|
9d6cabd18a | ||
|
|
8157f889ce | ||
|
|
736d6a3c19 | ||
|
|
39723bbe60 | ||
|
|
5834231e58 | ||
|
|
e4bb4be855 | ||
|
|
68bc5d2291 | ||
|
|
b87295db93 | ||
|
|
637fbf6c5b | ||
|
|
9d6bcd7705 | ||
|
|
484dfaebce | ||
|
|
1d41e1544a | ||
|
|
da00fc66ee | ||
|
|
4071488ef2 | ||
|
|
bd92c230da | ||
|
|
a98a062347 | ||
|
|
13a674330f | ||
|
|
982867317e | ||
|
|
4de0cd9fcb | ||
|
|
b3ddaa5f02 | ||
|
|
2faa4aa993 | ||
|
|
aeaa59d4b5 | ||
|
|
3e8e9273ca | ||
|
|
d0bfe421b5 | ||
|
|
7f473f56eb | ||
|
|
a29947d47c | ||
|
|
be6cc2c3e6 | ||
|
|
e472cacb3e | ||
|
|
6a3cbea790 | ||
|
|
f97535d87e | ||
|
|
90dc274113 | ||
|
|
40f42db7fa | ||
|
|
09efed50fd | ||
|
|
7de0771883 | ||
|
|
e29b64c5de | ||
|
|
4bed3161f0 | ||
|
|
7307eb54dc | ||
|
|
57e25ae1cd | ||
|
|
b2b13bbe89 | ||
|
|
0b315e97c8 | ||
|
|
dec61fa333 | ||
|
|
7ebef6d838 | ||
|
|
40ff5bf164 | ||
|
|
9fda61abec | ||
|
|
4a71c68e06 | ||
|
|
31497f4bd3 | ||
|
|
6af3a23dd4 | ||
|
|
65ccc99e79 | ||
|
|
cb665d07e0 | ||
|
|
649b7dd162 | ||
|
|
50ebaf25aa | ||
|
|
375a1790e7 | ||
|
|
b187b5c301 | ||
|
|
a53c4e1597 | ||
|
|
fce7b8dc9b | ||
|
|
fc247e4223 | ||
|
|
0390285c4e | ||
|
|
30dbe4978b | ||
|
|
a21f55919b | ||
|
|
79d21489df | ||
|
|
a25ac80777 | ||
|
|
a178c1fb93 | ||
|
|
c4d95de987 | ||
|
|
b7897595eb | ||
|
|
933c786421 | ||
|
|
66f1630f14 | ||
|
|
bb17608ae0 | ||
|
|
421f05eab9 | ||
|
|
9b6448518c | ||
|
|
3fe4261f12 | ||
|
|
7b02673620 | ||
|
|
997f2c098b | ||
|
|
7c814cd2e3 | ||
|
|
41573f1fb2 | ||
|
|
fa6481401d | ||
|
|
fda291b876 | ||
|
|
d33a44e67f | ||
|
|
bdb97d6186 | ||
|
|
7cf75e667d | ||
|
|
e9f531b4aa | ||
|
|
b2b7eb2ded | ||
|
|
3a9b7c592d | ||
|
|
d7ceef104e | ||
|
|
e3cbeec6ee | ||
|
|
04f2e102a1 | ||
|
|
5cca29d1db | ||
|
|
4d3c73f4ca | ||
|
|
a577bf340e | ||
|
|
5c643d6141 | ||
|
|
069fd0a244 | ||
|
|
de13b6edc5 | ||
|
|
303d5d6ff6 | ||
|
|
40b30d1fb1 | ||
|
|
dae6c757b5 | ||
|
|
31ecce3a72 | ||
|
|
5a7743214a | ||
|
|
13d4563c25 | ||
|
|
0b5d1551fe | ||
|
|
a06ecde580 | ||
|
|
94574447e6 | ||
|
|
29763df433 | ||
|
|
0511770d53 | ||
|
|
e2f48b21ab | ||
|
|
8a94ab676e | ||
|
|
ebbfe03831 | ||
|
|
bcb839a7d3 | ||
|
|
30efcf21f0 | ||
|
|
c5ea17f838 | ||
|
|
4fe3ecb8fc | ||
|
|
db30d891c8 | ||
|
|
4c3bcd121b | ||
|
|
5aeacd2989 | ||
|
|
504882e162 | ||
|
|
ca40234031 | ||
|
|
592b8c4f4a | ||
|
|
3370450711 | ||
|
|
6d555c9183 | ||
|
|
c21e275ebd | ||
|
|
ab2503f446 | ||
|
|
76fff49266 | ||
|
|
042166996b | ||
|
|
1a869632f6 | ||
|
|
bb2b13430a | ||
|
|
38b476c507 | ||
|
|
35c0e3cf8c | ||
|
|
60ecbdee8f | ||
|
|
adba1a792a | ||
|
|
e9d0a25436 | ||
|
|
ab6e01e379 | ||
|
|
724f728f60 | ||
|
|
8dbae00847 | ||
|
|
287e06995a | ||
|
|
9e85492b85 | ||
|
|
96245c3cfa | ||
|
|
4194c7fa24 | ||
|
|
71e1577a62 | ||
|
|
df53b97fe4 | ||
|
|
fe3ad4fd60 | ||
|
|
20c8250872 | ||
|
|
1869de7662 | ||
|
|
7c2c8b2a95 | ||
|
|
c094aa82ec | ||
|
|
98a4be475c | ||
|
|
88bb9f422e | ||
|
|
73e58f7af1 | ||
|
|
d02a2a2cfa | ||
|
|
d3ff5a2a4f | ||
|
|
3091e2a771 | ||
|
|
3aa6d03cc1 | ||
|
|
6a5b94ca3b | ||
|
|
229d5e5c80 | ||
|
|
2dad06d59f | ||
|
|
f45340461d | ||
|
|
19a536d869 | ||
|
|
4f0a96c9c7 | ||
|
|
9ec7cd7239 | ||
|
|
ed2d7964ad | ||
|
|
b0b070ffe7 | ||
|
|
3dd3476bfd | ||
|
|
a4342f3997 | ||
|
|
022d4b548a | ||
|
|
49de60d33b | ||
|
|
7b1b082381 | ||
|
|
7d4887b1f1 | ||
|
|
df86efbd43 | ||
|
|
73704c92ba | ||
|
|
5c3d67a811 | ||
|
|
07487b6d20 | ||
|
|
b8866f1d16 | ||
|
|
a8d5ae5213 | ||
|
|
4217ec5308 | ||
|
|
21b51328f9 | ||
|
|
99646d209e | ||
|
|
7fb93d4585 | ||
|
|
51a4657ef7 | ||
|
|
d98eca7260 | ||
|
|
accb03719a | ||
|
|
fc7feffaad | ||
|
|
aa584475cc | ||
|
|
218c9199f3 | ||
|
|
4f2d8b0a85 | ||
|
|
a828b15fbe | ||
|
|
9567807144 | ||
|
|
e656aad298 | ||
|
|
b0d1668ab9 | ||
|
|
00618672f5 | ||
|
|
5e10d53ca8 | ||
|
|
6720463799 | ||
|
|
02f4182749 | ||
|
|
577b730415 | ||
|
|
89df3cc207 | ||
|
|
338bd042b9 | ||
|
|
d45bb14015 | ||
|
|
323c78ef44 | ||
|
|
090a16316c | ||
|
|
c0feb36e70 | ||
|
|
31e6fb154e | ||
|
|
beb5bffaf6 | ||
|
|
9ab84bdc0a | ||
|
|
30ba9a2751 | ||
|
|
3f5f96dcbd | ||
|
|
4dd093b160 | ||
|
|
c0607a0e2a | ||
|
|
9f3ec82cc1 | ||
|
|
de646a5b93 | ||
|
|
b0cb0c1a4a | ||
|
|
042ac8240f | ||
|
|
ded5341da0 | ||
|
|
ed634bc3a4 | ||
|
|
c4d10bc44e | ||
|
|
6f125cc129 | ||
|
|
d9a7348ae1 | ||
|
|
8bd09e39ca | ||
|
|
c877166b4a | ||
|
|
7f234809fc | ||
|
|
88756f3ebf | ||
|
|
0a79f49dc5 | ||
|
|
e4136b0d42 | ||
|
|
d195a12565 | ||
|
|
46a368d2b9 | ||
|
|
c311520968 | ||
|
|
9979de24db | ||
|
|
8d3d3c88d4 | ||
|
|
9a7b0b657e | ||
|
|
19bd5beb96 | ||
|
|
1a9b5760a7 | ||
|
|
90928991b3 | ||
|
|
4693c61305 | ||
|
|
76bb424de0 | ||
|
|
cb603c62d9 | ||
|
|
c12d802811 | ||
|
|
2562f2e9a6 | ||
|
|
2aad7b6979 | ||
|
|
1295c924e1 | ||
|
|
83e55dc09e | ||
|
|
55401116bb | ||
|
|
e275b54f55 | ||
|
|
87ed228fd3 | ||
|
|
a989f60e27 | ||
|
|
2cb3c89570 | ||
|
|
640d6fa474 | ||
|
|
ef08bd48b5 | ||
|
|
3be84787d4 | ||
|
|
87f2719195 | ||
|
|
77ec7caaad |
@@ -735,6 +735,45 @@ jobs:
|
|||||||
- packer/build:
|
- packer/build:
|
||||||
template: tools/packer/lotus.pkr.hcl
|
template: tools/packer/lotus.pkr.hcl
|
||||||
args: "-var ci_workspace_bins=./linux-nerpanet -var lotus_network=nerpanet -var git_tag=$CIRCLE_TAG"
|
args: "-var ci_workspace_bins=./linux-nerpanet -var lotus_network=nerpanet -var git_tag=$CIRCLE_TAG"
|
||||||
|
publish-dockerhub:
|
||||||
|
description: publish to dockerhub
|
||||||
|
machine:
|
||||||
|
image: ubuntu-2004:202010-01
|
||||||
|
parameters:
|
||||||
|
tag:
|
||||||
|
type: string
|
||||||
|
default: latest
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run:
|
||||||
|
name: dockerhub login
|
||||||
|
command: echo $DOCKERHUB_PASSWORD | docker login --username $DOCKERHUB_USERNAME --password-stdin
|
||||||
|
- run:
|
||||||
|
name: docker build
|
||||||
|
command: |
|
||||||
|
docker build --target lotus -t filecoin/lotus:<< parameters.tag >> -f Dockerfile.lotus .
|
||||||
|
docker build --target lotus-all-in-one -t filecoin/lotus-all-in-one:<< parameters.tag >> -f Dockerfile.lotus .
|
||||||
|
if [[ ! -z $CIRCLE_SHA1 ]]; then
|
||||||
|
docker build --target lotus -t filecoin/lotus:$CIRCLE_SHA1 -f Dockerfile.lotus .
|
||||||
|
docker build --target lotus-all-in-one -t filecoin/lotus-all-in-one:$CIRCLE_SHA1 -f Dockerfile.lotus .
|
||||||
|
fi
|
||||||
|
if [[ ! -z $CIRCLE_TAG ]]; then
|
||||||
|
docker build --target lotus -t filecoin/lotus:$CIRCLE_TAG -f Dockerfile.lotus .
|
||||||
|
docker build --target lotus-all-in-one -t filecoin/lotus-all-in-one:$CIRCLE_TAG -f Dockerfile.lotus .
|
||||||
|
fi
|
||||||
|
- run:
|
||||||
|
name: docker push
|
||||||
|
command: |
|
||||||
|
docker push filecoin/lotus:<< parameters.tag >>
|
||||||
|
docker push filecoin/lotus-all-in-one:<< parameters.tag >>
|
||||||
|
if [[ ! -z $CIRCLE_SHA1 ]]; then
|
||||||
|
docker push filecoin/lotus:$CIRCLE_SHA1
|
||||||
|
docker push filecoin/lotus-all-in-one:$CIRCLE_SHA1
|
||||||
|
fi
|
||||||
|
if [[ ! -z $CIRCLE_TAG ]]; then
|
||||||
|
docker push filecoin/lotus:$CIRCLE_TAG
|
||||||
|
docker push filecoin/lotus-all-in-one:$CIRCLE_TAG
|
||||||
|
fi
|
||||||
|
|
||||||
workflows:
|
workflows:
|
||||||
version: 2.1
|
version: 2.1
|
||||||
@@ -781,6 +820,11 @@ workflows:
|
|||||||
suite: itest-deals_offline
|
suite: itest-deals_offline
|
||||||
target: "./itests/deals_offline_test.go"
|
target: "./itests/deals_offline_test.go"
|
||||||
|
|
||||||
|
- test:
|
||||||
|
name: test-itest-deals_padding
|
||||||
|
suite: itest-deals_padding
|
||||||
|
target: "./itests/deals_padding_test.go"
|
||||||
|
|
||||||
- test:
|
- test:
|
||||||
name: test-itest-deals_power
|
name: test-itest-deals_power
|
||||||
suite: itest-deals_power
|
suite: itest-deals_power
|
||||||
@@ -806,11 +850,21 @@ workflows:
|
|||||||
suite: itest-gateway
|
suite: itest-gateway
|
||||||
target: "./itests/gateway_test.go"
|
target: "./itests/gateway_test.go"
|
||||||
|
|
||||||
|
- test:
|
||||||
|
name: test-itest-get_messages_in_ts
|
||||||
|
suite: itest-get_messages_in_ts
|
||||||
|
target: "./itests/get_messages_in_ts_test.go"
|
||||||
|
|
||||||
- test:
|
- test:
|
||||||
name: test-itest-multisig
|
name: test-itest-multisig
|
||||||
suite: itest-multisig
|
suite: itest-multisig
|
||||||
target: "./itests/multisig_test.go"
|
target: "./itests/multisig_test.go"
|
||||||
|
|
||||||
|
- test:
|
||||||
|
name: test-itest-nonce
|
||||||
|
suite: itest-nonce
|
||||||
|
target: "./itests/nonce_test.go"
|
||||||
|
|
||||||
- test:
|
- test:
|
||||||
name: test-itest-paych_api
|
name: test-itest-paych_api
|
||||||
suite: itest-paych_api
|
suite: itest-paych_api
|
||||||
@@ -831,6 +885,11 @@ workflows:
|
|||||||
suite: itest-sector_finalize_early
|
suite: itest-sector_finalize_early
|
||||||
target: "./itests/sector_finalize_early_test.go"
|
target: "./itests/sector_finalize_early_test.go"
|
||||||
|
|
||||||
|
- test:
|
||||||
|
name: test-itest-sector_miner_collateral
|
||||||
|
suite: itest-sector_miner_collateral
|
||||||
|
target: "./itests/sector_miner_collateral_test.go"
|
||||||
|
|
||||||
- test:
|
- test:
|
||||||
name: test-itest-sector_pledge
|
name: test-itest-sector_pledge
|
||||||
suite: itest-sector_pledge
|
suite: itest-sector_pledge
|
||||||
@@ -1002,6 +1061,16 @@ workflows:
|
|||||||
tags:
|
tags:
|
||||||
only:
|
only:
|
||||||
- /^v\d+\.\d+\.\d+(-rc\d+)?$/
|
- /^v\d+\.\d+\.\d+(-rc\d+)?$/
|
||||||
|
- publish-dockerhub:
|
||||||
|
name: publish-dockerhub
|
||||||
|
tag: stable
|
||||||
|
filters:
|
||||||
|
branches:
|
||||||
|
ignore:
|
||||||
|
- /.*/
|
||||||
|
tags:
|
||||||
|
only:
|
||||||
|
- /^v\d+\.\d+\.\d+(-rc\d+)?$/
|
||||||
|
|
||||||
nightly:
|
nightly:
|
||||||
triggers:
|
triggers:
|
||||||
@@ -1015,3 +1084,6 @@ workflows:
|
|||||||
- publish-snapcraft:
|
- publish-snapcraft:
|
||||||
name: publish-snapcraft-nightly
|
name: publish-snapcraft-nightly
|
||||||
channel: edge
|
channel: edge
|
||||||
|
- publish-dockerhub:
|
||||||
|
name: publish-dockerhub-nightly
|
||||||
|
tag: nightly
|
||||||
|
|||||||
@@ -735,6 +735,45 @@ jobs:
|
|||||||
- packer/build:
|
- packer/build:
|
||||||
template: tools/packer/lotus.pkr.hcl
|
template: tools/packer/lotus.pkr.hcl
|
||||||
args: "-var ci_workspace_bins=./linux-nerpanet -var lotus_network=nerpanet -var git_tag=$CIRCLE_TAG"
|
args: "-var ci_workspace_bins=./linux-nerpanet -var lotus_network=nerpanet -var git_tag=$CIRCLE_TAG"
|
||||||
|
publish-dockerhub:
|
||||||
|
description: publish to dockerhub
|
||||||
|
machine:
|
||||||
|
image: ubuntu-2004:202010-01
|
||||||
|
parameters:
|
||||||
|
tag:
|
||||||
|
type: string
|
||||||
|
default: latest
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run:
|
||||||
|
name: dockerhub login
|
||||||
|
command: echo $DOCKERHUB_PASSWORD | docker login --username $DOCKERHUB_USERNAME --password-stdin
|
||||||
|
- run:
|
||||||
|
name: docker build
|
||||||
|
command: |
|
||||||
|
docker build --target lotus -t filecoin/lotus:<< parameters.tag >> -f Dockerfile.lotus .
|
||||||
|
docker build --target lotus-all-in-one -t filecoin/lotus-all-in-one:<< parameters.tag >> -f Dockerfile.lotus .
|
||||||
|
if [["[[ ! -z $CIRCLE_SHA1 ]]"]]; then
|
||||||
|
docker build --target lotus -t filecoin/lotus:$CIRCLE_SHA1 -f Dockerfile.lotus .
|
||||||
|
docker build --target lotus-all-in-one -t filecoin/lotus-all-in-one:$CIRCLE_SHA1 -f Dockerfile.lotus .
|
||||||
|
fi
|
||||||
|
if [["[[ ! -z $CIRCLE_TAG ]]"]]; then
|
||||||
|
docker build --target lotus -t filecoin/lotus:$CIRCLE_TAG -f Dockerfile.lotus .
|
||||||
|
docker build --target lotus-all-in-one -t filecoin/lotus-all-in-one:$CIRCLE_TAG -f Dockerfile.lotus .
|
||||||
|
fi
|
||||||
|
- run:
|
||||||
|
name: docker push
|
||||||
|
command: |
|
||||||
|
docker push filecoin/lotus:<< parameters.tag >>
|
||||||
|
docker push filecoin/lotus-all-in-one:<< parameters.tag >>
|
||||||
|
if [["[[ ! -z $CIRCLE_SHA1 ]]"]]; then
|
||||||
|
docker push filecoin/lotus:$CIRCLE_SHA1
|
||||||
|
docker push filecoin/lotus-all-in-one:$CIRCLE_SHA1
|
||||||
|
fi
|
||||||
|
if [["[[ ! -z $CIRCLE_TAG ]]"]]; then
|
||||||
|
docker push filecoin/lotus:$CIRCLE_TAG
|
||||||
|
docker push filecoin/lotus-all-in-one:$CIRCLE_TAG
|
||||||
|
fi
|
||||||
|
|
||||||
workflows:
|
workflows:
|
||||||
version: 2.1
|
version: 2.1
|
||||||
@@ -887,6 +926,16 @@ workflows:
|
|||||||
tags:
|
tags:
|
||||||
only:
|
only:
|
||||||
- /^v\d+\.\d+\.\d+(-rc\d+)?$/
|
- /^v\d+\.\d+\.\d+(-rc\d+)?$/
|
||||||
|
- publish-dockerhub:
|
||||||
|
name: publish-dockerhub
|
||||||
|
tag: stable
|
||||||
|
filters:
|
||||||
|
branches:
|
||||||
|
ignore:
|
||||||
|
- /.*/
|
||||||
|
tags:
|
||||||
|
only:
|
||||||
|
- /^v\d+\.\d+\.\d+(-rc\d+)?$/
|
||||||
|
|
||||||
nightly:
|
nightly:
|
||||||
triggers:
|
triggers:
|
||||||
@@ -900,3 +949,6 @@ workflows:
|
|||||||
- publish-snapcraft:
|
- publish-snapcraft:
|
||||||
name: publish-snapcraft-nightly
|
name: publish-snapcraft-nightly
|
||||||
channel: edge
|
channel: edge
|
||||||
|
- publish-dockerhub:
|
||||||
|
name: publish-dockerhub-nightly
|
||||||
|
tag: nightly
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# Reference
|
||||||
|
# https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-repository-on-github/about-code-owners
|
||||||
|
|
||||||
|
# Global owners
|
||||||
|
# Ensure maintainers team is a requested reviewer for non-draft PRs
|
||||||
|
* @filecoin-project/lotus-maintainers
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
---
|
|
||||||
name: Bug Report
|
|
||||||
about: Create a report to help us improve
|
|
||||||
title: "[BUG] "
|
|
||||||
labels: hint/needs-triaging, kind/bug
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
> Note: For security-related bugs/issues, please follow the [security policy](https://github.com/filecoin-project/lotus/security/policy).
|
|
||||||
|
|
||||||
**Describe the bug**
|
|
||||||
A clear and concise description of what the bug is.
|
|
||||||
(If you are not sure what the bug is, try to figure it out via a [discussion](https://github.com/filecoin-project/lotus/discussions/new) first!
|
|
||||||
|
|
||||||
**Version (run `lotus version`):**
|
|
||||||
|
|
||||||
**To Reproduce**
|
|
||||||
Steps to reproduce the behavior:
|
|
||||||
1. Run '...'
|
|
||||||
2. See error
|
|
||||||
|
|
||||||
**Expected behavior**
|
|
||||||
A clear and concise description of what you expected to happen.
|
|
||||||
|
|
||||||
**Logs**
|
|
||||||
Provide daemon/miner/worker logs, and goroutines(if available) for troubleshooting.
|
|
||||||
|
|
||||||
**Screenshots**
|
|
||||||
If applicable, add screenshots to help explain your problem.
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context about the problem here.
|
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
name: "Bug Report"
|
||||||
|
description: "File a bug report to help us improve"
|
||||||
|
labels: [need/triage, kind/bug]
|
||||||
|
body:
|
||||||
|
- type: checkboxes
|
||||||
|
attributes:
|
||||||
|
label: Checklist
|
||||||
|
description: Please check off the following boxes before continuing to file a bug report!
|
||||||
|
options:
|
||||||
|
- label: This is **not** a security-related bug/issue. If it is, please follow please follow the [security policy](https://github.com/filecoin-project/lotus/security/policy).
|
||||||
|
required: true
|
||||||
|
- label: This is **not** a question or a support request. If you have any lotus related questions, please ask in the [lotus forum](https://github.com/filecoin-project/lotus/discussions).
|
||||||
|
required: true
|
||||||
|
- label: This is **not** a new feature request. If it is, please file a [feature request](https://github.com/filecoin-project/lotus/issues/new?assignees=&labels=need%2Ftriage%2Ckind%2Ffeature&template=feature_request.yml) instead.
|
||||||
|
required: true
|
||||||
|
- label: This is **not** an enhancement request. If it is, please file a [improvement suggestion](https://github.com/filecoin-project/lotus/issues/new?assignees=&labels=need%2Ftriage%2Ckind%2Fenhancement&template=enhancement.yml) instead.
|
||||||
|
required: true
|
||||||
|
- label: I **have** searched on the [issue tracker](https://github.com/filecoin-project/lotus/issues) and the [lotus forum](https://github.com/filecoin-project/lotus/discussions), and there is no existing related issue or discussion.
|
||||||
|
required: true
|
||||||
|
- label: I am running the [`Latest release`](https://github.com/filecoin-project/lotus/releases), or the most recent RC(release canadiate) for the upcoming release or the dev branch(master), or have an issue updating to any of these.
|
||||||
|
required: true
|
||||||
|
- label: I did not make any code changes to lotus.
|
||||||
|
required: false
|
||||||
|
- type: dropdown
|
||||||
|
id: component-and-area
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
attributes:
|
||||||
|
label: Lotus component
|
||||||
|
description: Please select the lotus component you are filing a bug for
|
||||||
|
options:
|
||||||
|
- lotus daemon - chain sync
|
||||||
|
- lotus miner - mining and block production
|
||||||
|
- lotus miner/worker - sealing
|
||||||
|
- lotus miner - proving(WindowPoSt)
|
||||||
|
- lotus miner/market - storage deal
|
||||||
|
- lotus miner/market - retrieval deal
|
||||||
|
- lotus client
|
||||||
|
- lotus JSON-RPC API
|
||||||
|
- lotus message management (mpool)
|
||||||
|
- Other
|
||||||
|
- type: textarea
|
||||||
|
id: version
|
||||||
|
attributes:
|
||||||
|
label: Lotus Version
|
||||||
|
description: Enter the output of `lotus version` and `lotus-miner version` if applicable.
|
||||||
|
placeholder: |
|
||||||
|
e.g.
|
||||||
|
Daemon:1.11.0-rc2+debug+git.0519cd371.dirty+api1.3.0
|
||||||
|
Local: lotus version 1.11.0-rc2+debug+git.0519cd371.dirty
|
||||||
|
validations:
|
||||||
|
reuiqred: true
|
||||||
|
- type: textarea
|
||||||
|
id: Description
|
||||||
|
attributes:
|
||||||
|
label: Describe the Bug
|
||||||
|
description: |
|
||||||
|
This is where you get to tell us what went wrong, when doing so, please try to provide a clear and concise description of the bug with all related information:
|
||||||
|
* What you were doding when you experienced the bug?
|
||||||
|
* Any *error* messages you saw, *where* you saw them, and what you believe may have caused them (if you have any ideas).
|
||||||
|
* What is the expected behaviour?
|
||||||
|
* For sealing issues, include the output of `lotus-miner sectors status --log <sectorId>` for the failed sector(s).
|
||||||
|
* For proving issues, include the output of `lotus-miner proving` info.
|
||||||
|
* For deal making issues, include the output of `lotus client list-deals -v` and/or `lotus-miner storage-deals|retrieval-deals|data-transfers list [-v]` commands for the deal(s) in question.
|
||||||
|
render: bash
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: extraInfo
|
||||||
|
attributes:
|
||||||
|
label: Logging Information
|
||||||
|
description: |
|
||||||
|
Please provide debug logs of the problem, remember you can get set log level control for:
|
||||||
|
* lotus: use `lotus log list` to get all log systems available and set level by `lotus log set-level`. An example can be found [here](https://docs.filecoin.io/get-started/lotus/configuration-and-advanced-usage/#log-level-control).
|
||||||
|
* lotus-miner:`lotus-miner log list` to get all log systems available and set level by `lotus-miner log set-level
|
||||||
|
If you don't provide detailed logs when you raise the issue it will almost certainly be the first request I make before furthur diagnosing the problem.
|
||||||
|
render: bash
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: RepoSteps
|
||||||
|
attributes:
|
||||||
|
label: Repo Steps
|
||||||
|
description: "Steps to reproduce the behavior"
|
||||||
|
value: |
|
||||||
|
1. Run '...'
|
||||||
|
2. Do '...'
|
||||||
|
3. See error '...'
|
||||||
|
...
|
||||||
|
render: bash
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
---
|
|
||||||
name: Deal Making Issues
|
|
||||||
about: Create a report for help with deal making failures.
|
|
||||||
title: "[Deal Making Issue]"
|
|
||||||
labels: hint/needs-triaging, area/markets
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
> Note: For security-related bugs/issues, please follow the [security policy](https://github.com/filecoin-project/lotus/security/policy).
|
|
||||||
|
|
||||||
Please provide all the information requested here to help us troubleshoot "deal making failed" issues.
|
|
||||||
If the information requested is missing, we will probably have to just ask you to provide it anyway,
|
|
||||||
before we can help debug.
|
|
||||||
|
|
||||||
**Basic Information**
|
|
||||||
Including information like, Are you the client or the miner? Is this a storage deal or a retrieval deal? Is it an offline deal?
|
|
||||||
|
|
||||||
**Describe the problem**
|
|
||||||
|
|
||||||
A brief description of the problem you encountered while trying to make a deal.
|
|
||||||
|
|
||||||
**Version**
|
|
||||||
|
|
||||||
The output of `lotus --version`.
|
|
||||||
|
|
||||||
**Setup**
|
|
||||||
|
|
||||||
You miner(if applicable) and daemon setup, i.e: What hardware do you use, how much ram and etc.
|
|
||||||
|
|
||||||
**To Reproduce**
|
|
||||||
Steps to reproduce the behavior:
|
|
||||||
1. Run '...'
|
|
||||||
2. See error
|
|
||||||
|
|
||||||
**Deal status**
|
|
||||||
|
|
||||||
The output of `lotus client list-deals -v` and/or `lotus-miner storage-deals|retrieval-deals|data-transfers list [-v]` commands for the deal(s) in question.
|
|
||||||
|
|
||||||
**Lotus daemon and miner logs**
|
|
||||||
|
|
||||||
Please go through the logs of your daemon and miner(if applicable), and include screenshots of any error/warning-like messages you find.
|
|
||||||
|
|
||||||
Alternatively please upload full log files and share a link here
|
|
||||||
|
|
||||||
** Code modifications **
|
|
||||||
|
|
||||||
If you have modified parts of lotus, please describe which areas were modified,
|
|
||||||
and the scope of those modifications
|
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
name: Enhancement
|
||||||
|
description: Suggest an improvement to an existing lotus feature.
|
||||||
|
labels: [need/triage, kind/enhancement]
|
||||||
|
body:
|
||||||
|
- type: checkboxes
|
||||||
|
attributes:
|
||||||
|
label: Checklist
|
||||||
|
description: Please check off the following boxes before continuing to create an improvement suggestion!
|
||||||
|
options:
|
||||||
|
- label: This is **not** a new feature or an enhancement to the Filecoin protocol. If it is, please open an [FIP issue](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0001.md).
|
||||||
|
required: true
|
||||||
|
- label: This is **not** a new feature request. If it is, please file a [feature request](https://github.com/filecoin-project/lotus/issues/new?assignees=&labels=need%2Ftriage%2Ckind%2Ffeature&template=feature_request.yml) instead.
|
||||||
|
required: true
|
||||||
|
- label: This is **not** brainstorming ideas. If you have an idea you'd like to discuss, please open a new discussion on [the lotus forum](https://github.com/filecoin-project/lotus/discussions/categories/ideas) and select the category as `Ideas`.
|
||||||
|
required: true
|
||||||
|
- label: I **have** a specific, actionable, and well motivated improvement to propose.
|
||||||
|
required: true
|
||||||
|
- type: dropdown
|
||||||
|
id: component
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
attributes:
|
||||||
|
label: Lotus component
|
||||||
|
description: Please select the lotus component you are propoing improvement for
|
||||||
|
options:
|
||||||
|
- lotus daemon - chain sync
|
||||||
|
- lotus miner - mining and block production
|
||||||
|
- lotus miner/worker - sealing
|
||||||
|
- lotus miner - proving(WindowPoSt)
|
||||||
|
- lotus miner/market - storage deal
|
||||||
|
- lotus miner/market - retrieval deal
|
||||||
|
- lotus client
|
||||||
|
- lotus JSON-RPC API
|
||||||
|
- lotus message management (mpool)
|
||||||
|
- Other
|
||||||
|
- type: textarea
|
||||||
|
id: request
|
||||||
|
attributes:
|
||||||
|
label: Improvement Suggestion
|
||||||
|
description: A clear and concise description of what the motivation or the current problem is and what is the suggested improvement?
|
||||||
|
placeholder: Ex. Currently lotus... However, as a storage provider, I'd like...
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
---
|
|
||||||
name: Feature request
|
|
||||||
about: Suggest an idea for this project
|
|
||||||
title: "[Feature Request]"
|
|
||||||
labels: hint/needs-triaging
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Is your feature request related to a problem? Please describe.**
|
|
||||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
|
||||||
|
|
||||||
**Describe the solution you'd like**
|
|
||||||
A clear and concise description of what you want to happen.
|
|
||||||
|
|
||||||
**Describe alternatives you've considered**
|
|
||||||
A clear and concise description of any alternative solutions or features you've considered.
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context or screenshots about the feature request here.
|
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
name: Feature request
|
||||||
|
description: Suggest an idea for lotus
|
||||||
|
labels: [need/triage, kind/feature]
|
||||||
|
body:
|
||||||
|
- type: checkboxes
|
||||||
|
attributes:
|
||||||
|
label: Checklist
|
||||||
|
description: Please check off the following boxes before continuing to create a new feature request!
|
||||||
|
options:
|
||||||
|
- label: This is **not** a new feature or an enhancement to the Filecoin protocol. If it is, please open an [FIP issue](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0001.md).
|
||||||
|
required: true
|
||||||
|
- label: This is **not** brainstorming ideas. If you have an idea you'd like to discuss, please open a new discussion on [the lotus forum](https://github.com/filecoin-project/lotus/discussions/categories/ideas) and select the category as `Ideas`.
|
||||||
|
required: true
|
||||||
|
- label: I **have** a specific, actionable, and well motivated feature request to propose.
|
||||||
|
required: true
|
||||||
|
- type: dropdown
|
||||||
|
id: component
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
attributes:
|
||||||
|
label: Lotus component
|
||||||
|
description: Please select the lotus component you are requesting a new feature for
|
||||||
|
options:
|
||||||
|
- lotus daemon - chain sync
|
||||||
|
- lotus miner - mining and block production
|
||||||
|
- lotus miner/worker - sealing
|
||||||
|
- lotus miner - proving(WindowPoSt)
|
||||||
|
- lotus miner/market - storage deal
|
||||||
|
- lotus miner/market - retrieval deal
|
||||||
|
- lotus client
|
||||||
|
- lotus JSON-RPC API
|
||||||
|
- lotus message management (mpool)
|
||||||
|
- Other
|
||||||
|
- type: textarea
|
||||||
|
id: request
|
||||||
|
attributes:
|
||||||
|
label: What is the motivation behind this feature request? Is your feature request related to a problem? Please describe.
|
||||||
|
description: A clear and concise description of what the motivation or the problem is.
|
||||||
|
placeholder: Ex. I'm always frustrated when [...]
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: solution
|
||||||
|
attributes:
|
||||||
|
label: Describe the solution you'd like
|
||||||
|
description: A clear and concise description of what you want to happen.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: alternates
|
||||||
|
attributes:
|
||||||
|
label: Describe alternatives you've considered
|
||||||
|
description: A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
id: extra
|
||||||
|
attributes:
|
||||||
|
label: Additional context
|
||||||
|
description: Add any other context, design docs or screenshots about the feature request here.
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
name: "M1 Bug Report For Deal Making"
|
||||||
|
description: "File a bug report around deal making for the M1 releases"
|
||||||
|
labels: [need/triage, kind/bug, M1-release]
|
||||||
|
body:
|
||||||
|
- type: checkboxes
|
||||||
|
id: checklist
|
||||||
|
attributes:
|
||||||
|
label: Checklist
|
||||||
|
description: Please check off the following boxes before continuing to file a bug report!
|
||||||
|
options:
|
||||||
|
- label: This is **not** a question or a support request. If you have any lotus related questions, please ask in the [lotus forum](https://github.com/filecoin-project/lotus/discussions).
|
||||||
|
required: true
|
||||||
|
- label: I **am** reporting a bug w.r.t one of the [M1 tags](https://github.com/filecoin-project/lotus/discussions/6852#discussioncomment-1043951). If not, choose another issue option [here](https://github.com/filecoin-project/lotus/issues/new/choose).
|
||||||
|
required: true
|
||||||
|
- label: I **am** reporting a bug around deal making. If not, create a [M1 Bug Report For Non Deal Making Issue](https://github.com/filecoin-project/lotus/issues/new?assignees=&labels=need%2Ftriage%2Ckind%2Fbug%2CM1-release&template=m1_bug_report_non_deal.yml).
|
||||||
|
required: true
|
||||||
|
- label: I have my log level set as instructed [here](https://github.com/filecoin-project/lotus/discussions/6852#discussioncomment-1043678) and have logs available for troubleshooting.
|
||||||
|
required: true
|
||||||
|
- label: The deal is coming from one of the M1 clients(communitcated in the coordination slack channel).
|
||||||
|
required: true
|
||||||
|
- label: I **have** searched on the [issue tracker](https://github.com/filecoin-project/lotus/issues) and the [lotus forum](https://github.com/filecoin-project/lotus/discussions), and there is no existing related issue or discussion.
|
||||||
|
required: true
|
||||||
|
- type: dropdown
|
||||||
|
id: lotus-componets
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
attributes:
|
||||||
|
label: Lotus Component
|
||||||
|
description: Please select the lotus component you are filing a bug for
|
||||||
|
options:
|
||||||
|
- lotus miner market subsystem - storage deal
|
||||||
|
- lotus miner market subsystem - retrieval deal
|
||||||
|
- lotus miner - storage deal
|
||||||
|
- lotus miner - retrieval deal
|
||||||
|
- type: textarea
|
||||||
|
id: version
|
||||||
|
attributes:
|
||||||
|
label: Lotus Tag and Version
|
||||||
|
description: Enter the lotus tag, output of `lotus version` and `lotus-miner version`.
|
||||||
|
validations:
|
||||||
|
reuiqred: true
|
||||||
|
- type: textarea
|
||||||
|
id: Description
|
||||||
|
attributes:
|
||||||
|
label: Describe the Bug
|
||||||
|
description: |
|
||||||
|
This is where you get to tell us what went wrong, when doing so, please try to provide a clear and concise description of the bug with all related information:
|
||||||
|
* What you were doding when you experienced the bug?
|
||||||
|
* Any *error* messages you saw, *where* you saw them, and what you believe may have caused them (if you have any ideas).
|
||||||
|
* What is the expected behaviour?
|
||||||
|
render: bash
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: deal-status
|
||||||
|
attributes:
|
||||||
|
label: Deal Status
|
||||||
|
description: What's the status of the deal?
|
||||||
|
placeholder: |
|
||||||
|
Please share the output of `lotus-miner storage-deals|retrieval-deals list [-v]` commands for the deal(s) in question.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: data-transfer-status
|
||||||
|
attributes:
|
||||||
|
label: Data Transfer Status
|
||||||
|
description: What's the status of the data transfer?
|
||||||
|
placeholder: |
|
||||||
|
Please share the output of `lotus-miner data-transfers list -v` commands for the deal(s) in question.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: logging
|
||||||
|
attributes:
|
||||||
|
label: Logging Information
|
||||||
|
description: Please link to the whole of the miner logs on your side of the transaction. You can upload the logs to a [gist](https://gist.github.com).
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: RepoSteps
|
||||||
|
attributes:
|
||||||
|
label: Repo Steps (optional)
|
||||||
|
description: "Steps to reproduce the behavior"
|
||||||
|
value: |
|
||||||
|
1. Run '...'
|
||||||
|
2. Do '...'
|
||||||
|
3. See error '...'
|
||||||
|
...
|
||||||
|
render: bash
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
name: "M1 Bug Report For Non Deal Making Issue"
|
||||||
|
description: "File a bug report around non deal making issue for the M1 releases"
|
||||||
|
labels: [need/triage, kind/bug, M1-release]
|
||||||
|
body:
|
||||||
|
- type: checkboxes
|
||||||
|
id: checklist
|
||||||
|
attributes:
|
||||||
|
label: Checklist
|
||||||
|
description: Please check off the following boxes before continuing to file a bug report!
|
||||||
|
options:
|
||||||
|
- label: This is **not** a question or a support request. If you have any lotus related questions, please ask in the [lotus forum](https://github.com/filecoin-project/lotus/discussions).
|
||||||
|
required: true
|
||||||
|
- label: I **am** reporting a bug w.r.t one of the [M1 tags](https://github.com/filecoin-project/lotus/discussions/6852#discussioncomment-1043951). If not, choose another issue option [here](https://github.com/filecoin-project/lotus/issues/new/choose).
|
||||||
|
required: true
|
||||||
|
- label: I am **not** reporting a bug around deal making. If yes, create a [M1 Bug Report For Deal Making](https://github.com/filecoin-project/lotus/issues/new?assignees=&labels=need%2Ftriage%2Ckind%2Fbug%2CM1-release&template=m1_bug_report_deal.yml).
|
||||||
|
required: true
|
||||||
|
- label: I **have** searched on the [issue tracker](https://github.com/filecoin-project/lotus/issues) and the [lotus forum](https://github.com/filecoin-project/lotus/discussions), and there is no existing related issue or discussion.
|
||||||
|
required: true
|
||||||
|
- type: dropdown
|
||||||
|
id: component-and-area
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
attributes:
|
||||||
|
label: Lotus component
|
||||||
|
description: Please select the lotus component you are filing a bug for
|
||||||
|
options:
|
||||||
|
- lotus daemon - chain sync **with** splitstore enabled
|
||||||
|
- lotus daemon - chain sync **without** splitstore enabled
|
||||||
|
- lotus miner - mining and block production
|
||||||
|
- lotus miner/worker - sealing
|
||||||
|
- lotus miner - proving(WindowPoSt)
|
||||||
|
- lotus client
|
||||||
|
- lotus JSON-RPC API
|
||||||
|
- lotus message management (mpool)
|
||||||
|
- Other
|
||||||
|
- type: textarea
|
||||||
|
id: version
|
||||||
|
attributes:
|
||||||
|
label: Lotus Tag and Version
|
||||||
|
description: Enter the lotus tag, output of `lotus version` and `lotus-miner version`.
|
||||||
|
validations:
|
||||||
|
reuiqred: true
|
||||||
|
- type: textarea
|
||||||
|
id: Description
|
||||||
|
attributes:
|
||||||
|
label: Describe the Bug
|
||||||
|
description: |
|
||||||
|
This is where you get to tell us what went wrong, when doing so, please try to provide a clear and concise description of the bug with all related information:
|
||||||
|
* What you were doding when you experienced the bug?
|
||||||
|
* Any *error* messages you saw, *where* you saw them, and what you believe may have caused them (if you have any ideas).
|
||||||
|
* What is the expected behaviour?
|
||||||
|
* For sealing issues, include the output of `lotus-miner sectors status --log <sectorId>` for the failed sector(s).
|
||||||
|
* For proving issues, include the output of `lotus-miner proving` info.
|
||||||
|
render: bash
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: extraInfo
|
||||||
|
attributes:
|
||||||
|
label: Logging Information
|
||||||
|
description: |
|
||||||
|
Please provide debug logs of the problem, remember you can get set log level control for:
|
||||||
|
* lotus: use `lotus log list` to get all log systems available and set level by `lotus log set-level`. An example can be found [here](https://docs.filecoin.io/get-started/lotus/configuration-and-advanced-usage/#log-level-control).
|
||||||
|
* lotus-miner:`lotus-miner log list` to get all log systems available and set level by `lotus-miner log set-level
|
||||||
|
If you don't provide detailed logs when you raise the issue it will almost certainly be the first request I make before furthur diagnosing the problem.
|
||||||
|
render: bash
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: RepoSteps
|
||||||
|
attributes:
|
||||||
|
label: Repo Steps
|
||||||
|
description: "Steps to reproduce the behavior"
|
||||||
|
value: |
|
||||||
|
1. Run '...'
|
||||||
|
2. Do '...'
|
||||||
|
3. See error '...'
|
||||||
|
...
|
||||||
|
render: bash
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
---
|
|
||||||
name: Mining Issues
|
|
||||||
about: Create a report for help with mining failures.
|
|
||||||
title: "[Mining Issue]"
|
|
||||||
labels: hint/needs-triaging, area/mining
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
> Note: For security-related bugs/issues, please follow the [security policy](https://github.com/filecoin-project/lotus/security/policy).
|
|
||||||
|
|
||||||
Please provide all the information requested here to help us troubleshoot "mining/WinningPoSt failed" issues.
|
|
||||||
If the information requested is missing, you may be asked you to provide it.
|
|
||||||
|
|
||||||
**Describe the problem**
|
|
||||||
A brief description of the problem you encountered while mining new blocks.
|
|
||||||
|
|
||||||
**Version**
|
|
||||||
|
|
||||||
The output of `lotus --version`.
|
|
||||||
|
|
||||||
**Setup**
|
|
||||||
|
|
||||||
You miner and daemon setup, including what hardware do you use, your environment variable settings, how do you run your miner and worker, do you use GPU and etc.
|
|
||||||
|
|
||||||
**Lotus daemon and miner logs**
|
|
||||||
|
|
||||||
Please go through the logs of your daemon and miner, and include screenshots of any error/warning-like messages you find, highlighting the one has "winning post" in it.
|
|
||||||
|
|
||||||
Alternatively please upload full log files and share a link here
|
|
||||||
|
|
||||||
** Code modifications **
|
|
||||||
|
|
||||||
If you have modified parts of lotus, please describe which areas were modified,
|
|
||||||
and the scope of those modifications
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
---
|
|
||||||
name: Proving Issues
|
|
||||||
about: Create a report for help with proving failures.
|
|
||||||
title: "[Proving Issue]"
|
|
||||||
labels: area/proving, hint/needs-triaging
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
> Note: For security-related bugs/issues, please follow the [security policy](https://github.com/filecoin-project/lotus/security/policy).
|
|
||||||
|
|
||||||
Please provide all the information requested here to help us troubleshoot "proving/window PoSt failed" issues.
|
|
||||||
If the information requested is missing, we will probably have to just ask you to provide it anyway,
|
|
||||||
before we can help debug.
|
|
||||||
|
|
||||||
**Describe the problem**
|
|
||||||
A brief description of the problem you encountered while proving the storage.
|
|
||||||
|
|
||||||
**Version**
|
|
||||||
|
|
||||||
The output of `lotus --version`.
|
|
||||||
|
|
||||||
**Setup**
|
|
||||||
|
|
||||||
You miner and daemon setup, including what hardware do you use, your environment variable settings, how do you run your miner and worker, do you use GPU and etc.
|
|
||||||
|
|
||||||
**Proving status**
|
|
||||||
|
|
||||||
The output of `lotus-miner proving` info.
|
|
||||||
|
|
||||||
**Lotus miner logs**
|
|
||||||
|
|
||||||
Please go through the logs of your miner, and include screenshots of any error-like messages you find, highlighting the one has "window post" in it.
|
|
||||||
|
|
||||||
Alternatively please upload full log files and share a link here
|
|
||||||
|
|
||||||
**Lotus miner diagnostic info**
|
|
||||||
|
|
||||||
Please collect the following diagnostic information, and share a link here
|
|
||||||
|
|
||||||
* lotus-miner diagnostic info `lotus-miner info all > allinfo.txt`
|
|
||||||
|
|
||||||
** Code modifications **
|
|
||||||
|
|
||||||
If you have modified parts of lotus, please describe which areas were modified,
|
|
||||||
and the scope of those modifications
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
---
|
|
||||||
name: Sealing Issues
|
|
||||||
about: Create a report for help with sealing (commit) failures.
|
|
||||||
title: "[Sealing Issue]"
|
|
||||||
labels: hint/needs-triaging, area/sealing
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
> Note: For security-related bugs/issues, please follow the [security policy](https://github.com/filecoin-project/lotus/security/policy).
|
|
||||||
|
|
||||||
Please provide all the information requested here to help us troubleshoot "commit failed" issues.
|
|
||||||
If the information requested is missing, we will probably have to just ask you to provide it anyway,
|
|
||||||
before we can help debug.
|
|
||||||
|
|
||||||
**Describe the problem**
|
|
||||||
A brief description of the problem you encountered while sealing a sector.
|
|
||||||
|
|
||||||
**Version**
|
|
||||||
|
|
||||||
The output of `lotus --version`.
|
|
||||||
|
|
||||||
**Setup**
|
|
||||||
|
|
||||||
You miner and daemon setup, including what hardware do you use, your environment variable settings, how do you run your miner and worker, do you use GPU and etc.
|
|
||||||
|
|
||||||
**Commands**
|
|
||||||
|
|
||||||
Commands you ran.
|
|
||||||
|
|
||||||
**Sectors status**
|
|
||||||
|
|
||||||
The output of `lotus-miner sectors status --log <sectorId>` for the failed sector(s).
|
|
||||||
|
|
||||||
**Lotus miner logs**
|
|
||||||
|
|
||||||
Please go through the logs of your miner, and include screenshots of any error-like messages you find.
|
|
||||||
|
|
||||||
Alternatively please upload full log files and share a link here
|
|
||||||
|
|
||||||
**Lotus miner diagnostic info**
|
|
||||||
|
|
||||||
Please collect the following diagnostic information, and share a link here
|
|
||||||
|
|
||||||
* lotus-miner diagnostic info `lotus-miner info all > allinfo`
|
|
||||||
|
|
||||||
** Code modifications **
|
|
||||||
|
|
||||||
If you have modified parts of lotus, please describe which areas were modified,
|
|
||||||
and the scope of those modifications
|
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
name: Close and mark stale issue
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 12 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
stale:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/stale@v3
|
||||||
|
with:
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
stale-issue-message: 'Oops, seems like we needed more information for this issue, please comment with more details or this issue will be closed in 24 hours.'
|
||||||
|
close-issue-message: 'This issue was closed because it is missing author input.'
|
||||||
|
stale-pr-message: 'Thank you for submitting the PR and contributing to lotus! Lotus maintainers need more of your input before merging it, please address the suggested changes or reply to the comments or this PR will be closed in 48 hours. You are always more than welcome to reopen the PR later as well!'
|
||||||
|
close-pr-message: 'This PR was closed because it is missing author input. Please feel free to reopen the PR when you get to it! Thank you for your interest in contributing to lotus!'
|
||||||
|
stale-issue-label: 'kind/stale'
|
||||||
|
stale-pr-label: 'kind/stale'
|
||||||
|
any-of-labels: 'need/author-input '
|
||||||
|
days-before-issue-stale: 3
|
||||||
|
days-before-issue-close: 1
|
||||||
|
days-before-pr-stale: 5
|
||||||
|
days-before-pr-close: 2
|
||||||
|
remove-stale-when-updated: true
|
||||||
|
enable-statistics: true
|
||||||
|
|
||||||
|
|
||||||
+404
-220
@@ -1,235 +1,380 @@
|
|||||||
# Lotus changelog
|
# Lotus changelog
|
||||||
|
|
||||||
# 1.11.0-rc2 / 2021-07-02
|
# 1.11.1-rc1 / 2021-07-27
|
||||||
|
|
||||||
This is the second release candidate for the optional Lotus v1.11.0 release that introduces several months of bugfixes
|
This is the first release candidate for the **highly-recommended** but optional Lotus v1.11.1 release that introduces many deal making and datastore improvements and new features along with other bug fixes. A more organized and detailed release note will be shared in the next few days with future RCs, highlights are:
|
||||||
and feature development. A more detailed changelog will follow upon final release.
|
- [lotus-miner market subsystem](https://docs.filecoin.io/mine/lotus/split-markets-miners/#frontmatter-title)
|
||||||
|
- [splistore](https://github.com/filecoin-project/lotus/blob/master/blockstore/splitstore/README.md)
|
||||||
|
|
||||||
- github.com/filecoin-project/lotus:
|
- github.com/filecoin-project/lotus:
|
||||||
- update changelog and bump version to v1.11.0-rc2
|
- Merge branch 'releases' into release/v1.11.1
|
||||||
|
- Update to proof v8.0.3 ([filecoin-project/lotus#6890](https://github.com/filecoin-project/lotus/pull/6890))
|
||||||
- Lotus version 1.11.0
|
- lotus-shed: initial export cmd for markets related metadata ([filecoin-project/lotus#6840](https://github.com/filecoin-project/lotus/pull/6840))
|
||||||
- gateway: Add support for Version method ([filecoin-project/lotus#6618](https://github.com/filecoin-project/lotus/pull/6618))
|
- add a very verbose -vv flag to lotus and lotus-miner. ([filecoin-project/lotus#6888](https://github.com/filecoin-project/lotus/pull/6888))
|
||||||
- Miner SimultaneousTransfers config ([filecoin-project/lotus#6612](https://github.com/filecoin-project/lotus/pull/6612))
|
- Update RELEASE_ISSUE_TEMPLATE.md ([filecoin-project/lotus#6880](https://github.com/filecoin-project/lotus/pull/6880))
|
||||||
- revamped integration test kit (aka. Operation Sparks Joy) ([filecoin-project/lotus#6329](https://github.com/filecoin-project/lotus/pull/6329))
|
- Moving GC for badger ([filecoin-project/lotus#6854](https://github.com/filecoin-project/lotus/pull/6854))
|
||||||
- downgrade libp2p/go-libp2p-yamux to v0.5.1. ([filecoin-project/lotus#6605](https://github.com/filecoin-project/lotus/pull/6605))
|
- Add github actions for staled pr ([filecoin-project/lotus#6879](https://github.com/filecoin-project/lotus/pull/6879))
|
||||||
- Fix wallet error messages ([filecoin-project/lotus#6594](https://github.com/filecoin-project/lotus/pull/6594))
|
- Add allocated sectorid vis ([filecoin-project/lotus#4638](https://github.com/filecoin-project/lotus/pull/4638))
|
||||||
- Fix CircleCI gen ([filecoin-project/lotus#6589](https://github.com/filecoin-project/lotus/pull/6589))
|
- rename `cmd/lotus{-storage=>}-miner` to match binary. ([filecoin-project/lotus#6886](https://github.com/filecoin-project/lotus/pull/6886))
|
||||||
- Make query-ask CLI more graceful ([filecoin-project/lotus#6590](https://github.com/filecoin-project/lotus/pull/6590))
|
- update to go-fil-market v1.6.0 ([filecoin-project/lotus#6885](https://github.com/filecoin-project/lotus/pull/6885))
|
||||||
- ([filecoin-project/lotus#6406](https://github.com/filecoin-project/lotus/pull/6406))
|
- Bump go-multihash, adjust test for supported version ([filecoin-project/lotus#6674](https://github.com/filecoin-project/lotus/pull/6674))
|
||||||
- move with changed name ([filecoin-project/lotus#6587](https://github.com/filecoin-project/lotus/pull/6587))
|
- Fix padding of deals, which only partially shipped in #5988 ([filecoin-project/lotus#6683](https://github.com/filecoin-project/lotus/pull/6683))
|
||||||
- scale up sector expiration to avoid sector expire in batch-pre-commit waitting ([filecoin-project/lotus#6566](https://github.com/filecoin-project/lotus/pull/6566))
|
- fix racy TestSimultanenousTransferLimit. ([filecoin-project/lotus#6862](https://github.com/filecoin-project/lotus/pull/6862))
|
||||||
- Merge release branch into master ([filecoin-project/lotus#6583](https://github.com/filecoin-project/lotus/pull/6583))
|
- Improve splitstore warmup ([filecoin-project/lotus#6867](https://github.com/filecoin-project/lotus/pull/6867))
|
||||||
- ([filecoin-project/lotus#6582](https://github.com/filecoin-project/lotus/pull/6582))
|
- ValidateBlock: Assert that block header height's are greater than parents ([filecoin-project/lotus#6872](https://github.com/filecoin-project/lotus/pull/6872))
|
||||||
- fix circleci being out of sync. ([filecoin-project/lotus#6573](https://github.com/filecoin-project/lotus/pull/6573))
|
- feat: Don't panic when api impl is nil ([filecoin-project/lotus#6857](https://github.com/filecoin-project/lotus/pull/6857))
|
||||||
- dynamic circleci config for streamlining test execution ([filecoin-project/lotus#6561](https://github.com/filecoin-project/lotus/pull/6561))
|
- splitstore shed utils ([filecoin-project/lotus#6811](https://github.com/filecoin-project/lotus/pull/6811))
|
||||||
- Merge 1.10 branch into master ([filecoin-project/lotus#6571](https://github.com/filecoin-project/lotus/pull/6571))
|
- Fix links in issue templates
|
||||||
- Fix helptext ([filecoin-project/lotus#6560](https://github.com/filecoin-project/lotus/pull/6560))
|
- Update issue templates and add templates for M1 ([filecoin-project/lotus#6856](https://github.com/filecoin-project/lotus/pull/6856))
|
||||||
- extern/storage: add ability to ignore worker resources when scheduling. ([filecoin-project/lotus#6542](https://github.com/filecoin-project/lotus/pull/6542))
|
- Splitstore: support on-disk marksets using badger ([filecoin-project/lotus#6833](https://github.com/filecoin-project/lotus/pull/6833))
|
||||||
- Merge 1.10 branch into master ([filecoin-project/lotus#6540](https://github.com/filecoin-project/lotus/pull/6540))
|
- Config UX improvements ([filecoin-project/lotus#6848](https://github.com/filecoin-project/lotus/pull/6848))
|
||||||
- Initial draft: basic build instructions on Readme ([filecoin-project/lotus#6498](https://github.com/filecoin-project/lotus/pull/6498))
|
- fix deal concurrency test failures by upgrading graphsync and others ([filecoin-project/lotus#6724](https://github.com/filecoin-project/lotus/pull/6724))
|
||||||
- fix commit finalize failed ([filecoin-project/lotus#6521](https://github.com/filecoin-project/lotus/pull/6521))
|
- Update issue templates to forms ([filecoin-project/lotus#6798](https://github.com/filecoin-project/lotus/pull/6798))
|
||||||
- Dynamic Retrieval pricing ([filecoin-project/lotus#6175](https://github.com/filecoin-project/lotus/pull/6175))
|
- Nerpa v13 upgrade ([filecoin-project/lotus#6837](https://github.com/filecoin-project/lotus/pull/6837))
|
||||||
- Fix soup ([filecoin-project/lotus#6501](https://github.com/filecoin-project/lotus/pull/6501))
|
- add docker-compose file ([filecoin-project/lotus#6544](https://github.com/filecoin-project/lotus/pull/6544))
|
||||||
- fix: pick the correct partitions-per-post limit ([filecoin-project/lotus#6502](https://github.com/filecoin-project/lotus/pull/6502))
|
- fix warmup by decoupling state from message receipt walk ([filecoin-project/lotus#6841](https://github.com/filecoin-project/lotus/pull/6841))
|
||||||
- Fix the build
|
- add a command for compacting sector numbers bitfield ([filecoin-project/lotus#4640](https://github.com/filecoin-project/lotus/pull/4640))
|
||||||
- Adjust various CLI display ratios to arbitrary precision ([filecoin-project/lotus#6309](https://github.com/filecoin-project/lotus/pull/6309))
|
- PriceListByVersion ([filecoin-project/lotus#6766](https://github.com/filecoin-project/lotus/pull/6766))
|
||||||
- Add utils to use multisigs as miner owners ([filecoin-project/lotus#6490](https://github.com/filecoin-project/lotus/pull/6490))
|
- easy way to make install app ([filecoin-project/lotus#5183](https://github.com/filecoin-project/lotus/pull/5183))
|
||||||
- Test multicore SDR support ([filecoin-project/lotus#6479](https://github.com/filecoin-project/lotus/pull/6479))
|
- api: Separate the Net interface from Common ([filecoin-project/lotus#6627](https://github.com/filecoin-project/lotus/pull/6627))
|
||||||
- sealing: Fix restartSectors race ([filecoin-project/lotus#6495](https://github.com/filecoin-project/lotus/pull/6495))
|
- cache loaded block messages ([filecoin-project/lotus#6760](https://github.com/filecoin-project/lotus/pull/6760))
|
||||||
- Merge 1.10 into master ([filecoin-project/lotus#6487](https://github.com/filecoin-project/lotus/pull/6487))
|
- fix: on randomness change, use new rand ([filecoin-project/lotus#6805](https://github.com/filecoin-project/lotus/pull/6805))
|
||||||
- Unit tests for sector batchers ([filecoin-project/lotus#6432](https://github.com/filecoin-project/lotus/pull/6432))
|
- Splitstore: add retention policy option for keeping messages in the hotstore ([filecoin-project/lotus#6775](https://github.com/filecoin-project/lotus/pull/6775))
|
||||||
- Merge 1.10 changes into master ([filecoin-project/lotus#6466](https://github.com/filecoin-project/lotus/pull/6466))
|
- Introduce the LOTUS_CHAIN_BADGERSTORE_DISABLE_FSYNC envvar ([filecoin-project/lotus#6817](https://github.com/filecoin-project/lotus/pull/6817))
|
||||||
- Update chain list with correct help instructions ([filecoin-project/lotus#6465](https://github.com/filecoin-project/lotus/pull/6465))
|
- add StateReadState to gateway api ([filecoin-project/lotus#6818](https://github.com/filecoin-project/lotus/pull/6818))
|
||||||
- clean failed sectors in batch commit ([filecoin-project/lotus#6451](https://github.com/filecoin-project/lotus/pull/6451))
|
- add SealProof in SectorBuilder ([filecoin-project/lotus#6815](https://github.com/filecoin-project/lotus/pull/6815))
|
||||||
- itests/kit: add guard to ensure imports from tests only. ([filecoin-project/lotus#6445](https://github.com/filecoin-project/lotus/pull/6445))
|
- release -> master ([filecoin-project/lotus#6828](https://github.com/filecoin-project/lotus/pull/6828))
|
||||||
- consolidate integration tests into `itests` package; create test kit; cleanup ([filecoin-project/lotus#6311](https://github.com/filecoin-project/lotus/pull/6311))
|
- sealing: Handle preCommitParams errors more correctly ([filecoin-project/lotus#6763](https://github.com/filecoin-project/lotus/pull/6763))
|
||||||
- Remove rc changelog, compile the new changelog for final release only ([filecoin-project/lotus#6444](https://github.com/filecoin-project/lotus/pull/6444))
|
- fix: always check if StateSearchMessage returns nil ([filecoin-project/lotus#6802](https://github.com/filecoin-project/lotus/pull/6802))
|
||||||
- updated configuration comments for docs ([filecoin-project/lotus#6440](https://github.com/filecoin-project/lotus/pull/6440))
|
- ClientFindData: always fetch peer id from chain ([filecoin-project/lotus#6807](https://github.com/filecoin-project/lotus/pull/6807))
|
||||||
- Set ntwk v13 HyperDrive Calibration upgrade epoch ([filecoin-project/lotus#6441](https://github.com/filecoin-project/lotus/pull/6441))
|
- test: fix flaky window post tests ([filecoin-project/lotus#6804](https://github.com/filecoin-project/lotus/pull/6804))
|
||||||
- Merge release/v1.10.10 into master ([filecoin-project/lotus#6439](https://github.com/filecoin-project/lotus/pull/6439))
|
- ([filecoin-project/lotus#6800](https://github.com/filecoin-project/lotus/pull/6800))
|
||||||
- implement a command to export a car ([filecoin-project/lotus#6405](https://github.com/filecoin-project/lotus/pull/6405))
|
- fixes #6786 segfault ([filecoin-project/lotus#6787](https://github.com/filecoin-project/lotus/pull/6787))
|
||||||
- Merge v1.10 release branch into master ([filecoin-project/lotus#6435](https://github.com/filecoin-project/lotus/pull/6435))
|
- Splitstore: add support for protecting out of chain references in the blockstore ([filecoin-project/lotus#6777](https://github.com/filecoin-project/lotus/pull/6777))
|
||||||
- Fee config for sector batching ([filecoin-project/lotus#6420](https://github.com/filecoin-project/lotus/pull/6420))
|
- Resurrect CODEOWNERS, but for maintainers group ([filecoin-project/lotus#6773](https://github.com/filecoin-project/lotus/pull/6773))
|
||||||
- Fix: correct the change of message size limit ([filecoin-project/lotus#6430](https://github.com/filecoin-project/lotus/pull/6430))
|
- update go-libp2p-pubsub to v0.5.0 ([filecoin-project/lotus#6764](https://github.com/filecoin-project/lotus/pull/6764))
|
||||||
- UX: lotus state power CLI should fail if called with a not-miner ([filecoin-project/lotus#6425](https://github.com/filecoin-project/lotus/pull/6425))
|
- Implement exposed splitstore ([filecoin-project/lotus#6762](https://github.com/filecoin-project/lotus/pull/6762))
|
||||||
- network reset friday
|
- Add ChainGetMessagesInTipset API ([filecoin-project/lotus#6642](https://github.com/filecoin-project/lotus/pull/6642))
|
||||||
- Increase message size limit ([filecoin-project/lotus#6419](https://github.com/filecoin-project/lotus/pull/6419))
|
- test: handle null blocks in TestForkRefuseCall ([filecoin-project/lotus#6758](https://github.com/filecoin-project/lotus/pull/6758))
|
||||||
- polish(stmgr): define ExecMonitor for message application callback ([filecoin-project/lotus#6389](https://github.com/filecoin-project/lotus/pull/6389))
|
- Master disclaimer ([filecoin-project/lotus#6757](https://github.com/filecoin-project/lotus/pull/6757))
|
||||||
- upgrade testground action version ([filecoin-project/lotus#6403](https://github.com/filecoin-project/lotus/pull/6403))
|
- Splitstore code reorg ([filecoin-project/lotus#6756](https://github.com/filecoin-project/lotus/pull/6756))
|
||||||
- Fix logging of stringified CIDs double-encoded in hex ([filecoin-project/lotus#6413](https://github.com/filecoin-project/lotus/pull/6413))
|
- Create stale.yml ([filecoin-project/lotus#6747](https://github.com/filecoin-project/lotus/pull/6747))
|
||||||
- Update libp2p to 0.14.2 ([filecoin-project/lotus#6404](https://github.com/filecoin-project/lotus/pull/6404))
|
- Splitstore: Some small fixes ([filecoin-project/lotus#6754](https://github.com/filecoin-project/lotus/pull/6754))
|
||||||
- Bypass task scheduler for reading unsealed pieces ([filecoin-project/lotus#6280](https://github.com/filecoin-project/lotus/pull/6280))
|
- ([filecoin-project/lotus#6746](https://github.com/filecoin-project/lotus/pull/6746))
|
||||||
- testplans: lotus-soup: use default WPoStChallengeWindow ([filecoin-project/lotus#6400](https://github.com/filecoin-project/lotus/pull/6400))
|
- Handle the --color flag via proper global state ([filecoin-project/lotus#6743](https://github.com/filecoin-project/lotus/pull/6743))
|
||||||
- build snapcraft ([filecoin-project/lotus#6388](https://github.com/filecoin-project/lotus/pull/6388))
|
- Config for collateral from miner available balance ([filecoin-project/lotus#6629](https://github.com/filecoin-project/lotus/pull/6629))
|
||||||
- Fix the doc errors of the sealing config funcs ([filecoin-project/lotus#6399](https://github.com/filecoin-project/lotus/pull/6399))
|
- Support standalone miner-market process ([filecoin-project/lotus#6356](https://github.com/filecoin-project/lotus/pull/6356))
|
||||||
- Integration tests for offline deals ([filecoin-project/lotus#6081](https://github.com/filecoin-project/lotus/pull/6081))
|
- Splitstore Enhanchements ([filecoin-project/lotus#6474](https://github.com/filecoin-project/lotus/pull/6474))
|
||||||
- Fix success handling in Retreival ([filecoin-project/lotus#5921](https://github.com/filecoin-project/lotus/pull/5921))
|
- ([filecoin-project/lotus#6739](https://github.com/filecoin-project/lotus/pull/6739))
|
||||||
- Fix some flaky tests ([filecoin-project/lotus#6397](https://github.com/filecoin-project/lotus/pull/6397))
|
- Add more deal details to lotus-miner info ([filecoin-project/lotus#6708](https://github.com/filecoin-project/lotus/pull/6708))
|
||||||
- build appimage in CI ([filecoin-project/lotus#6384](https://github.com/filecoin-project/lotus/pull/6384))
|
- Release template: Update all testnet infra at once ([filecoin-project/lotus#6710](https://github.com/filecoin-project/lotus/pull/6710))
|
||||||
- Add doc on gas balancing ([filecoin-project/lotus#6392](https://github.com/filecoin-project/lotus/pull/6392))
|
- Fix Lotus shed
|
||||||
- Add a command to list retrievals ([filecoin-project/lotus#6337](https://github.com/filecoin-project/lotus/pull/6337))
|
- Fix bugs in sectors extend --v1-sectors ([filecoin-project/lotus#6066](https://github.com/filecoin-project/lotus/pull/6066))
|
||||||
- Add interop network ([filecoin-project/lotus#6387](https://github.com/filecoin-project/lotus/pull/6387))
|
- add election backtest ([filecoin-project/lotus#5950](https://github.com/filecoin-project/lotus/pull/5950))
|
||||||
- Network version 13 (v1.11) ([filecoin-project/lotus#6342](https://github.com/filecoin-project/lotus/pull/6342))
|
- Envvar to disable slash filter ([filecoin-project/lotus#6620](https://github.com/filecoin-project/lotus/pull/6620))
|
||||||
- Generate AppImage ([filecoin-project/lotus#6208](https://github.com/filecoin-project/lotus/pull/6208))
|
- Release Template: remove binary validation step ([filecoin-project/lotus#6709](https://github.com/filecoin-project/lotus/pull/6709))
|
||||||
- lotus-gateway: add check command ([filecoin-project/lotus#6373](https://github.com/filecoin-project/lotus/pull/6373))
|
- Config for deal publishing control addresses ([filecoin-project/lotus#6697](https://github.com/filecoin-project/lotus/pull/6697))
|
||||||
- Add a warning to the release issue template ([filecoin-project/lotus#6374](https://github.com/filecoin-project/lotus/pull/6374))
|
- Reset of the interop network ([filecoin-project/lotus#6689](https://github.com/filecoin-project/lotus/pull/6689))
|
||||||
- update to markets-v1.4.0 ([filecoin-project/lotus#6369](https://github.com/filecoin-project/lotus/pull/6369))
|
- Enable color by default only if os.Stdout is a TTY ([filecoin-project/lotus#6696](https://github.com/filecoin-project/lotus/pull/6696))
|
||||||
- Add test for AddVerifiedClient ([filecoin-project/lotus#6317](https://github.com/filecoin-project/lotus/pull/6317))
|
- Stop outputing ANSI color on non-TTY ([filecoin-project/lotus#6694](https://github.com/filecoin-project/lotus/pull/6694))
|
||||||
- Typo fix in error message: "pubusb" -> "pubsub" ([filecoin-project/lotus#6365](https://github.com/filecoin-project/lotus/pull/6365))
|
- add dollar sign ([filecoin-project/lotus#6690](https://github.com/filecoin-project/lotus/pull/6690))
|
||||||
- Improve the cli state call command ([filecoin-project/lotus#6226](https://github.com/filecoin-project/lotus/pull/6226))
|
- get-actor cli spelling fix ([filecoin-project/lotus#6681](https://github.com/filecoin-project/lotus/pull/6681))
|
||||||
- Upscale mineOne message to a WARN on unexpected ineligibility ([filecoin-project/lotus#6358](https://github.com/filecoin-project/lotus/pull/6358))
|
- fix "lotus-seed genesis car" error "merkledag: not found" ([filecoin-project/lotus#6688](https://github.com/filecoin-project/lotus/pull/6688))
|
||||||
- storagefsm: Fix batch deal packing behavior ([filecoin-project/lotus#6041](https://github.com/filecoin-project/lotus/pull/6041))
|
- polish(statetree): accept a context in statetree diff for timeouts ([filecoin-project/lotus#6639](https://github.com/filecoin-project/lotus/pull/6639))
|
||||||
- Remove few useless variable assignments ([filecoin-project/lotus#6359](https://github.com/filecoin-project/lotus/pull/6359))
|
- Add helptext to lotus chain export ([filecoin-project/lotus#6672](https://github.com/filecoin-project/lotus/pull/6672))
|
||||||
- lotus-wallet: JWT Support ([filecoin-project/lotus#6360](https://github.com/filecoin-project/lotus/pull/6360))
|
- Get retrieval pricing input should not error out on a deal state fetch ([filecoin-project/lotus#6679](https://github.com/filecoin-project/lotus/pull/6679))
|
||||||
- Reduce noise from 'peer has different genesis' messages ([filecoin-project/lotus#6357](https://github.com/filecoin-project/lotus/pull/6357))
|
- Fix more CID double-encoding as hex ([filecoin-project/lotus#6680](https://github.com/filecoin-project/lotus/pull/6680))
|
||||||
- events: Fix handling of multiple matched events per epoch ([filecoin-project/lotus#6355](https://github.com/filecoin-project/lotus/pull/6355))
|
- add an incremental nonce itest. ([filecoin-project/lotus#6663](https://github.com/filecoin-project/lotus/pull/6663))
|
||||||
- Update RELEASE_ISSUE_TEMPLATE.md ([filecoin-project/lotus#6236](https://github.com/filecoin-project/lotus/pull/6236))
|
- storage: Fix FinalizeSector with sectors in stoage paths ([filecoin-project/lotus#6653](https://github.com/filecoin-project/lotus/pull/6653))
|
||||||
- Get current seal proof when necessary ([filecoin-project/lotus#6339](https://github.com/filecoin-project/lotus/pull/6339))
|
- Fix tiny error in check-client-datacap ([filecoin-project/lotus#6664](https://github.com/filecoin-project/lotus/pull/6664))
|
||||||
- Allow starting networks from arbitrary actor versions ([filecoin-project/lotus#6333](https://github.com/filecoin-project/lotus/pull/6333))
|
- Fix: precommit_batch method used the wrong cfg.CommitBatchWait ([filecoin-project/lotus#6658](https://github.com/filecoin-project/lotus/pull/6658))
|
||||||
- Remove log line when tracing is not configured ([filecoin-project/lotus#6334](https://github.com/filecoin-project/lotus/pull/6334))
|
- fix ticket expiration check ([filecoin-project/lotus#6635](https://github.com/filecoin-project/lotus/pull/6635))
|
||||||
- Revert "Allow starting networks from arbitrary actor versions" ([filecoin-project/lotus#6330](https://github.com/filecoin-project/lotus/pull/6330))
|
- commit batch: AggregateAboveBaseFee config ([filecoin-project/lotus#6650](https://github.com/filecoin-project/lotus/pull/6650))
|
||||||
- separate tracing environment variables ([filecoin-project/lotus#6323](https://github.com/filecoin-project/lotus/pull/6323))
|
- commit batch: Initialize the FailedSectors map ([filecoin-project/lotus#6647](https://github.com/filecoin-project/lotus/pull/6647))
|
||||||
- Allow starting networks from arbitrary actor versions ([filecoin-project/lotus#6305](https://github.com/filecoin-project/lotus/pull/6305))
|
- Fast-path retry submitting commit aggregate if commit is still valid ([filecoin-project/lotus#6638](https://github.com/filecoin-project/lotus/pull/6638))
|
||||||
- feat: log dispute rate ([filecoin-project/lotus#6322](https://github.com/filecoin-project/lotus/pull/6322))
|
- remove precommit check in handleCommitFailed ([filecoin-project/lotus#6634](https://github.com/filecoin-project/lotus/pull/6634))
|
||||||
- Use new actor tags ([filecoin-project/lotus#6291](https://github.com/filecoin-project/lotus/pull/6291))
|
- Reuse timers in sealing batch logic ([filecoin-project/lotus#6636](https://github.com/filecoin-project/lotus/pull/6636))
|
||||||
- Fix logging around mineOne ([filecoin-project/lotus#6310](https://github.com/filecoin-project/lotus/pull/6310))
|
- shed tool to estimate aggregate network fees ([filecoin-project/lotus#6631](https://github.com/filecoin-project/lotus/pull/6631))
|
||||||
- Fix shell completions ([filecoin-project/lotus#6316](https://github.com/filecoin-project/lotus/pull/6316))
|
- fix prove commit aggregate send token amount ([filecoin-project/lotus#6625](https://github.com/filecoin-project/lotus/pull/6625))
|
||||||
- Allow 8MB sectors in devnet ([filecoin-project/lotus#6312](https://github.com/filecoin-project/lotus/pull/6312))
|
- Update version.go to 1.11.1 ([filecoin-project/lotus#6621](https://github.com/filecoin-project/lotus/pull/6621))
|
||||||
- fix ticket expired ([filecoin-project/lotus#6304](https://github.com/filecoin-project/lotus/pull/6304))
|
- github.com/filecoin-project/go-data-transfer (v1.6.0 -> v1.7.0):
|
||||||
- oh, snap! ([filecoin-project/lotus#6202](https://github.com/filecoin-project/lotus/pull/6202))
|
- release: v1.7.0
|
||||||
- Move verifreg shed utils to CLI ([filecoin-project/lotus#6135](https://github.com/filecoin-project/lotus/pull/6135))
|
- Fire a transfer queued event when a transfer is queued in Graphsync (#221) ([filecoin-project/go-data-transfer#221](https://github.com/filecoin-project/go-data-transfer/pull/221))
|
||||||
- consider storiface.PathStorage when calculating storage requirements ([filecoin-project/lotus#6233](https://github.com/filecoin-project/lotus/pull/6233))
|
- feat: pass ChannelID to ValidatePush & ValidatePull (#220) ([filecoin-project/go-data-transfer#220](https://github.com/filecoin-project/go-data-transfer/pull/220))
|
||||||
- `storage` module: add go docs and minor code quality refactors ([filecoin-project/lotus#6259](https://github.com/filecoin-project/lotus/pull/6259))
|
- release: v1.6.1 ([filecoin-project/go-data-transfer#218](https://github.com/filecoin-project/go-data-transfer/pull/218))
|
||||||
- Revert "chore: update go-libp2p" ([filecoin-project/lotus#6306](https://github.com/filecoin-project/lotus/pull/6306))
|
- Remove CID lists (#217) ([filecoin-project/go-data-transfer#217](https://github.com/filecoin-project/go-data-transfer/pull/217))
|
||||||
- Increase data transfer timeouts ([filecoin-project/lotus#6300](https://github.com/filecoin-project/lotus/pull/6300))
|
- Merge v1.6.0 ([filecoin-project/go-data-transfer#214](https://github.com/filecoin-project/go-data-transfer/pull/214))
|
||||||
- gateway: spin off from cmd to package ([filecoin-project/lotus#6294](https://github.com/filecoin-project/lotus/pull/6294))
|
- Remove restart ack timeout (#211) ([filecoin-project/go-data-transfer#211](https://github.com/filecoin-project/go-data-transfer/pull/211))
|
||||||
- Update to markets 1.3 ([filecoin-project/lotus#6149](https://github.com/filecoin-project/lotus/pull/6149))
|
- feat: use different extension names to fit multiple hooks data in same graphsync message (#204) ([filecoin-project/go-data-transfer#204](https://github.com/filecoin-project/go-data-transfer/pull/204))
|
||||||
- Add a shed util to count 64 GiB miner stats ([filecoin-project/lotus#6290](https://github.com/filecoin-project/lotus/pull/6290))
|
- fix: map race in GS transport (#208) ([filecoin-project/go-data-transfer#208](https://github.com/filecoin-project/go-data-transfer/pull/208))
|
||||||
- Delete CODEOWNERS ([filecoin-project/lotus#6289](https://github.com/filecoin-project/lotus/pull/6289))
|
- refactor: simplify graphsync transport (#203) ([filecoin-project/go-data-transfer#203](https://github.com/filecoin-project/go-data-transfer/pull/203))
|
||||||
- Merge v1.9.0 to master ([filecoin-project/lotus#6275](https://github.com/filecoin-project/lotus/pull/6275))
|
- release: v1.5.0 (#200) ([filecoin-project/go-data-transfer#200](https://github.com/filecoin-project/go-data-transfer/pull/200))
|
||||||
- Backport 6200 to master ([filecoin-project/lotus#6272](https://github.com/filecoin-project/lotus/pull/6272))
|
- github.com/filecoin-project/go-fil-markets (v1.5.0 -> v1.6.0):
|
||||||
- Introduce stateless offline dealflow, bypassing the FSM/deallists ([filecoin-project/lotus#5961](https://github.com/filecoin-project/lotus/pull/5961))
|
|
||||||
- chore: update go-libp2p ([filecoin-project/lotus#6231](https://github.com/filecoin-project/lotus/pull/6231))
|
|
||||||
- fix: wait-api should use GetAPI to acquire binary specific API ([filecoin-project/lotus#6246](https://github.com/filecoin-project/lotus/pull/6246))
|
|
||||||
- Update RELEASE_ISSUE_TEMPLATE.md
|
|
||||||
- fix(ci): Updates to lotus CI build process ([filecoin-project/lotus#6256](https://github.com/filecoin-project/lotus/pull/6256))
|
|
||||||
- add flags to control gateway lookback parameters ([filecoin-project/lotus#6247](https://github.com/filecoin-project/lotus/pull/6247))
|
|
||||||
- Feat/nerpa v4 ([filecoin-project/lotus#6248](https://github.com/filecoin-project/lotus/pull/6248))
|
|
||||||
- chore(ci): Enable build on RC tags ([filecoin-project/lotus#6238](https://github.com/filecoin-project/lotus/pull/6238))
|
|
||||||
- Transplant some useful commands to lotus-shed actor ([filecoin-project/lotus#5913](https://github.com/filecoin-project/lotus/pull/5913))
|
|
||||||
- wip actor wrapper codegen ([filecoin-project/lotus#6108](https://github.com/filecoin-project/lotus/pull/6108))
|
|
||||||
- Robust message management ([filecoin-project/lotus#5822](https://github.com/filecoin-project/lotus/pull/5822))
|
|
||||||
- Add a shed util to count miners by post type ([filecoin-project/lotus#6169](https://github.com/filecoin-project/lotus/pull/6169))
|
|
||||||
- Introduce a release issue template ([filecoin-project/lotus#5826](https://github.com/filecoin-project/lotus/pull/5826))
|
|
||||||
- cron-wc ([filecoin-project/lotus#6178](https://github.com/filecoin-project/lotus/pull/6178))
|
|
||||||
- This is a 1:1 forward-port of PR#6183 from 1.9.x to master ([filecoin-project/lotus#6196](https://github.com/filecoin-project/lotus/pull/6196))
|
|
||||||
- Allow creation of state tree v3s ([filecoin-project/lotus#6167](https://github.com/filecoin-project/lotus/pull/6167))
|
|
||||||
- drand: fix beacon cache ([filecoin-project/lotus#6164](https://github.com/filecoin-project/lotus/pull/6164))
|
|
||||||
- Update cli gen ([filecoin-project/lotus#6155](https://github.com/filecoin-project/lotus/pull/6155))
|
|
||||||
- mpool: Cleanup pre-nv12 selection logic ([filecoin-project/lotus#6148](https://github.com/filecoin-project/lotus/pull/6148))
|
|
||||||
- Update ffi to proofs v7 ([filecoin-project/lotus#6150](https://github.com/filecoin-project/lotus/pull/6150))
|
|
||||||
- Generate CLI docs ([filecoin-project/lotus#6145](https://github.com/filecoin-project/lotus/pull/6145))
|
|
||||||
- feat: allow checkpointing to forks ([filecoin-project/lotus#6107](https://github.com/filecoin-project/lotus/pull/6107))
|
|
||||||
- attempt to do better padding on pieces being written into sectors ([filecoin-project/lotus#5988](https://github.com/filecoin-project/lotus/pull/5988))
|
|
||||||
- remove duplicate ask and calculate ping before lock ([filecoin-project/lotus#5968](https://github.com/filecoin-project/lotus/pull/5968))
|
|
||||||
- Add a command to get the fees of a deal ([filecoin-project/lotus#5307](https://github.com/filecoin-project/lotus/pull/5307))
|
|
||||||
- flaky tests improvement: separate TestBatchDealInput from TestAPIDealFlow ([filecoin-project/lotus#6141](https://github.com/filecoin-project/lotus/pull/6141))
|
|
||||||
- Testground checks on push ([filecoin-project/lotus#5887](https://github.com/filecoin-project/lotus/pull/5887))
|
|
||||||
- Add a CLI tool for miner proving deadline ([filecoin-project/lotus#6132](https://github.com/filecoin-project/lotus/pull/6132))
|
|
||||||
- Use EmptyTSK where appropriate ([filecoin-project/lotus#6134](https://github.com/filecoin-project/lotus/pull/6134))
|
|
||||||
- fix: use a consistent tipset in commands ([filecoin-project/lotus#6142](https://github.com/filecoin-project/lotus/pull/6142))
|
|
||||||
- go mod tidy for lotus-soup testplans ([filecoin-project/lotus#6124](https://github.com/filecoin-project/lotus/pull/6124))
|
|
||||||
- fix testground payment channel tests: use 1 miner ([filecoin-project/lotus#6126](https://github.com/filecoin-project/lotus/pull/6126))
|
|
||||||
- fix: use the parent state when listing actors ([filecoin-project/lotus#6143](https://github.com/filecoin-project/lotus/pull/6143))
|
|
||||||
- Speed up StateListMessages in some cases ([filecoin-project/lotus#6007](https://github.com/filecoin-project/lotus/pull/6007))
|
|
||||||
- Return total power when GetPowerRaw doesn't find miner claim ([filecoin-project/lotus#4938](https://github.com/filecoin-project/lotus/pull/4938))
|
|
||||||
- fix(splitstore): fix a panic on revert-only head changes ([filecoin-project/lotus#6133](https://github.com/filecoin-project/lotus/pull/6133))
|
|
||||||
- shed: command to list duplicate messages in tipsets (steb) ([filecoin-project/lotus#5847](https://github.com/filecoin-project/lotus/pull/5847))
|
|
||||||
- upgrade `lotus-soup` testplans and reduce deals concurrency to a single miner ([filecoin-project/lotus#6122](https://github.com/filecoin-project/lotus/pull/6122))
|
|
||||||
- Merge releases (1.8.0) into master ([filecoin-project/lotus#6118](https://github.com/filecoin-project/lotus/pull/6118))
|
|
||||||
- github.com/filecoin-project/go-commp-utils (v0.1.0 -> v0.1.1-0.20210427191551-70bf140d31c7):
|
|
||||||
- add a padding helper function ([filecoin-project/go-commp-utils#3](https://github.com/filecoin-project/go-commp-utils/pull/3))
|
|
||||||
- github.com/filecoin-project/go-data-transfer (v1.4.3 -> v1.6.0):
|
|
||||||
- release: v1.6.0
|
- release: v1.6.0
|
||||||
- fix: option to disable accept and complete timeouts
|
- support padding out smaller files (#536) ([filecoin-project/go-fil-markets#536](https://github.com/filecoin-project/go-fil-markets/pull/536))
|
||||||
- fix: disable restart ack timeout
|
- On overloaded CI 10 seconds just isn't enough (#587) ([filecoin-project/go-fil-markets#587](https://github.com/filecoin-project/go-fil-markets/pull/587))
|
||||||
- release: v1.5.0
|
- Do not hex-encode CIDs in logs (#561) ([filecoin-project/go-fil-markets#561](https://github.com/filecoin-project/go-fil-markets/pull/561))
|
||||||
- Add isRestart param to validators (#197) ([filecoin-project/go-data-transfer#197](https://github.com/filecoin-project/go-data-transfer/pull/197))
|
- remove wrong peer check in push deal validation (#585) ([filecoin-project/go-fil-markets#585](https://github.com/filecoin-project/go-fil-markets/pull/585))
|
||||||
- fix: flaky TestChannelMonitorAutoRestart (#198) ([filecoin-project/go-data-transfer#198](https://github.com/filecoin-project/go-data-transfer/pull/198))
|
- fix: circleci docs-gen task (#574) ([filecoin-project/go-fil-markets#574](https://github.com/filecoin-project/go-fil-markets/pull/574))
|
||||||
- Channel monitor watches for errors instead of measuring data rate (#190) ([filecoin-project/go-data-transfer#190](https://github.com/filecoin-project/go-data-transfer/pull/190))
|
- Storage market request queued event and validation interface changes (#555) ([filecoin-project/go-fil-markets#555](https://github.com/filecoin-project/go-fil-markets/pull/555))
|
||||||
- fix: prevent concurrent restarts for same channel (#195) ([filecoin-project/go-data-transfer#195](https://github.com/filecoin-project/go-data-transfer/pull/195))
|
- build(deps): bump ws from 6.2.1 to 6.2.2 (#554) ([filecoin-project/go-fil-markets#554](https://github.com/filecoin-project/go-fil-markets/pull/554))
|
||||||
- fix: channel state machine event handling (#194) ([filecoin-project/go-data-transfer#194](https://github.com/filecoin-project/go-data-transfer/pull/194))
|
- release: v1.5.0 ([filecoin-project/go-fil-markets#553](https://github.com/filecoin-project/go-fil-markets/pull/553))
|
||||||
- Dont double count data sent (#185) ([filecoin-project/go-data-transfer#185](https://github.com/filecoin-project/go-data-transfer/pull/185))
|
- github.com/filecoin-project/go-padreader (v0.0.0-20200903213702-ed5fae088b20 -> v0.0.0-20210723183308-812a16dc01b1):
|
||||||
- release: v1.4.3 (#189) ([filecoin-project/go-data-transfer#189](https://github.com/filecoin-project/go-data-transfer/pull/189))
|
- New method to pad harder (#6) ([filecoin-project/go-padreader#6](https://github.com/filecoin-project/go-padreader/pull/6))
|
||||||
- github.com/filecoin-project/go-fil-markets (v1.2.5 -> v1.5.0):
|
- Create SECURITY.md (#5) ([filecoin-project/go-padreader#5](https://github.com/filecoin-project/go-padreader/pull/5))
|
||||||
- release: v1.5.0
|
- github.com/filecoin-project/go-state-types (v0.1.1-0.20210506134452-99b279731c48 -> v0.1.1-0.20210722133031-ad9bfe54c124):
|
||||||
- Dynamic Retrieval Pricing (#542) ([filecoin-project/go-fil-markets#542](https://github.com/filecoin-project/go-fil-markets/pull/542))
|
- Add version 6.5 (#30) ([filecoin-project/go-state-types#30](https://github.com/filecoin-project/go-state-types/pull/30))
|
||||||
- release: v1.4.0 (#551) ([filecoin-project/go-fil-markets#551](https://github.com/filecoin-project/go-fil-markets/pull/551))
|
- rename file
|
||||||
- Update to go data transfer v1.6.0 (#550) ([filecoin-project/go-fil-markets#550](https://github.com/filecoin-project/go-fil-markets/pull/550))
|
- github.com/filecoin-project/specs-actors/v5 (v5.0.1 -> v5.0.3):
|
||||||
- fix first make error (#548) ([filecoin-project/go-fil-markets#548](https://github.com/filecoin-project/go-fil-markets/pull/548))
|
- Adjust code for subtle change in go-multihash 0.0.15 (#1463) ([filecoin-project/specs-actors#1463](https://github.com/filecoin-project/specs-actors/pull/1463))
|
||||||
- release: v1.3.0 (#544) ([filecoin-project/go-fil-markets#544](https://github.com/filecoin-project/go-fil-markets/pull/544))
|
- Bump go state types (#1464) ([filecoin-project/specs-actors#1464](https://github.com/filecoin-project/specs-actors/pull/1464))
|
||||||
- fix restarts during data transfer for a retrieval deal (#540) ([filecoin-project/go-fil-markets#540](https://github.com/filecoin-project/go-fil-markets/pull/540))
|
- Create CODEOWNERS (#1465) ([filecoin-project/specs-actors#1465](https://github.com/filecoin-project/specs-actors/pull/1465))
|
||||||
- Test Retrieval for offline deals (#541) ([filecoin-project/go-fil-markets#541](https://github.com/filecoin-project/go-fil-markets/pull/541))
|
- Test deterministic offset (#1462) ([filecoin-project/specs-actors#1462](https://github.com/filecoin-project/specs-actors/pull/1462))
|
||||||
- Allow anonymous submodule checkout (#535) ([filecoin-project/go-fil-markets#535](https://github.com/filecoin-project/go-fil-markets/pull/535))
|
|
||||||
- github.com/filecoin-project/specs-actors (v0.9.13 -> v0.9.14):
|
|
||||||
- Set ConsensusMinerMinPower to 10 TiB (#1427) ([filecoin-project/specs-actors#1427](https://github.com/filecoin-project/specs-actors/pull/1427))
|
|
||||||
- github.com/filecoin-project/specs-actors/v2 (v2.3.5-0.20210114162132-5b58b773f4fb -> v2.3.5):
|
|
||||||
- Set ConsensusMinerMinPower to 10 TiB (#1428) ([filecoin-project/specs-actors#1428](https://github.com/filecoin-project/specs-actors/pull/1428))
|
|
||||||
- v2 VM satisfies SimVM interface (#1355) ([filecoin-project/specs-actors#1355](https://github.com/filecoin-project/specs-actors/pull/1355))
|
|
||||||
- github.com/filecoin-project/specs-actors/v3 (v3.1.0 -> v3.1.1):
|
|
||||||
- Set ConsensusMinerMinPower to 10 TiB for all PoStProofPolicies (#1429) ([filecoin-project/specs-actors#1429](https://github.com/filecoin-project/specs-actors/pull/1429))
|
|
||||||
- github.com/filecoin-project/specs-actors/v4 (v4.0.0 -> v4.0.1):
|
|
||||||
- Set ConsensusMinerMinPower to 10 TiB for all PoStProofPolicies (#1430) ([filecoin-project/specs-actors#1430](https://github.com/filecoin-project/specs-actors/pull/1430))
|
|
||||||
|
|
||||||
Contributors
|
Contributors
|
||||||
|
|
||||||
| Contributor | Commits | Lines ± | Files Changed |
|
| Contributor | Commits | Lines ± | Files Changed |
|
||||||
|-------------|---------|---------|---------------|
|
|-------------|---------|---------|---------------|
|
||||||
| Raúl Kripalani | 118 | +11972/-10860 | 472 |
|
| vyzo | 295 | +8700/-5936 | 397 |
|
||||||
| Łukasz Magiera | 65 | +10824/-4158 | 353 |
|
| Anton Evangelatov | 94 | +4680/-2965 | 277 |
|
||||||
| aarshkshah1992 | 59 | +8057/-3355 | 224 |
|
| Łukasz Magiera | 37 | +3851/-1611 | 146 |
|
||||||
| Aayush Rajasekaran | 41 | +8786/-1691 | 331 |
|
| Mike Greenberg | 1 | +2310/-578 | 8 |
|
||||||
| Steven Allen | 106 | +7653/-2718 | 273 |
|
| dirkmc | 7 | +1154/-726 | 29 |
|
||||||
|
| Jennifer Wang | 9 | +485/-341 | 26 |
|
||||||
|
| Peter Rabbitson | 18 | +469/-273 | 64 |
|
||||||
|
| Cory Schwartz | 5 | +576/-135 | 14 |
|
||||||
|
| hunjixin | 7 | +404/-82 | 19 |
|
||||||
|
| ZenGround0 | 17 | +284/-135 | 44 |
|
||||||
|
| Dirk McCormick | 17 | +348/-47 | 17 |
|
||||||
|
| Raúl Kripalani | 18 | +254/-97 | 62 |
|
||||||
|
| tchardin | 1 | +261/-33 | 4 |
|
||||||
|
| Jakub Sztandera | 4 | +254/-16 | 4 |
|
||||||
|
| Aarsh Shah | 2 | +196/-40 | 28 |
|
||||||
|
| whyrusleeping | 3 | +150/-9 | 8 |
|
||||||
|
| Whyrusleeping | 2 | +87/-66 | 10 |
|
||||||
|
| Aayush Rajasekaran | 10 | +81/-53 | 13 |
|
||||||
|
| zgfzgf | 2 | +104/-4 | 2 |
|
||||||
|
| aarshkshah1992 | 4 | +73/-7 | 6 |
|
||||||
|
| llifezou | 4 | +59/-20 | 4 |
|
||||||
|
| Steven Allen | 7 | +47/-17 | 9 |
|
||||||
|
| johnli-helloworld | 3 | +46/-15 | 5 |
|
||||||
|
| frrist | 1 | +28/-23 | 2 |
|
||||||
|
| Jennifer | 4 | +31/-2 | 4 |
|
||||||
|
| wangchao | 1 | +1/-27 | 1 |
|
||||||
|
| Jiaying Wang | 2 | +7/-21 | 2 |
|
||||||
|
| hannahhoward | 3 | +21/-2 | 3 |
|
||||||
|
| chadwick2143 | 1 | +15/-1 | 1 |
|
||||||
|
| Jerry | 2 | +9/-4 | 2 |
|
||||||
|
| Steve Loeppky | 2 | +12/-0 | 2 |
|
||||||
|
| David Dias | 1 | +9/-0 | 1 |
|
||||||
|
| dependabot[bot] | 1 | +3/-3 | 1 |
|
||||||
|
| zhoutian527 | 1 | +2/-2 | 1 |
|
||||||
|
| xloem | 1 | +4/-0 | 1 |
|
||||||
|
| Travis Person | 2 | +2/-2 | 3 |
|
||||||
|
| Liviu Damian | 2 | +2/-2 | 2 |
|
||||||
|
| Jim Pick | 2 | +2/-2 | 2 |
|
||||||
|
| Frank | 1 | +3/-0 | 1 |
|
||||||
|
| turuslan | 1 | +1/-1 | 1 |
|
||||||
|
| Kirk Baird | 1 | +0/-0 | 1 |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# 1.11.0 / 2021-07-22
|
||||||
|
|
||||||
|
This is a **highly recommended** release of Lotus that have many bug fixes, improvements and new features.
|
||||||
|
|
||||||
|
## Highlights
|
||||||
|
- Miner SimultaneousTransfers config ([filecoin-project/lotus#6612](https://github.com/filecoin-project/lotus/pull/6612))
|
||||||
|
- Set `SimultaneousTransfers` in lotus miner config to configure the maximum number of parallel online data transfers, including both storage and retrieval deals.
|
||||||
|
- Dynamic Retrieval pricing ([filecoin-project/lotus#6175](https://github.com/filecoin-project/lotus/pull/6175))
|
||||||
|
- Customize your retrieval ask price, see a quick tutorial [here](https://github.com/filecoin-project/lotus/discussions/6780).
|
||||||
|
- Robust message management ([filecoin-project/lotus#5822](https://github.com/filecoin-project/lotus/pull/5822))
|
||||||
|
- run `lotus mpool manage and follow the instructions!
|
||||||
|
- Demo available at https://www.youtube.com/watch?v=QDocpLQjZgQ.
|
||||||
|
- Add utils to use multisigs as miner owners ([filecoin-project/lotus#6490](https://github.com/filecoin-project/lotus/pull/6490))
|
||||||
|
|
||||||
|
## More New Features
|
||||||
|
- feat: implement lotus-sim ([filecoin-project/lotus#6406](https://github.com/filecoin-project/lotus/pull/6406))
|
||||||
|
- implement a command to export a car ([filecoin-project/lotus#6405](https://github.com/filecoin-project/lotus/pull/6405))
|
||||||
|
- Add a command to get the fees of a deal ([filecoin-project/lotus#5307](https://github.com/filecoin-project/lotus/pull/5307))
|
||||||
|
- run `lotus-shed market get-deal-fees`
|
||||||
|
- Add a command to list retrievals ([filecoin-project/lotus#6337](https://github.com/filecoin-project/lotus/pull/6337))
|
||||||
|
- run `lotus client list-retrievals`
|
||||||
|
- lotus-gateway: add check command ([filecoin-project/lotus#6373](https://github.com/filecoin-project/lotus/pull/6373))
|
||||||
|
- lotus-wallet: JWT Support ([filecoin-project/lotus#6360](https://github.com/filecoin-project/lotus/pull/6360))
|
||||||
|
- Allow starting networks from arbitrary actor versions ([filecoin-project/lotus#6305](https://github.com/filecoin-project/lotus/pull/6305))
|
||||||
|
- oh, snap! ([filecoin-project/lotus#6202](https://github.com/filecoin-project/lotus/pull/6202))
|
||||||
|
- Add a shed util to count 64 GiB miner stats ([filecoin-project/lotus#6290](https://github.com/filecoin-project/lotus/pull/6290))
|
||||||
|
- Introduce stateless offline dealflow, bypassing the FSM/deallists ([filecoin-project/lotus#5961](https://github.com/filecoin-project/lotus/pull/5961))
|
||||||
|
- Transplant some useful commands to lotus-shed actor ([filecoin-project/lotus#5913](https://github.com/filecoin-project/lotus/pull/5913))
|
||||||
|
- run `lotus-shed actor`
|
||||||
|
- actor wrapper codegen ([filecoin-project/lotus#6108](https://github.com/filecoin-project/lotus/pull/6108))
|
||||||
|
- Add a shed util to count miners by post type ([filecoin-project/lotus#6169](https://github.com/filecoin-project/lotus/pull/6169))
|
||||||
|
- shed: command to list duplicate messages in tipsets (steb) ([filecoin-project/lotus#5847](https://github.com/filecoin-project/lotus/pull/5847))
|
||||||
|
- feat: allow checkpointing to forks ([filecoin-project/lotus#6107](https://github.com/filecoin-project/lotus/pull/6107))
|
||||||
|
- Add a CLI tool for miner proving deadline ([filecoin-project/lotus#6132](https://github.com/filecoin-project/lotus/pull/6132))
|
||||||
|
- run `lotus state miner-proving-deadline`
|
||||||
|
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
- Fix wallet error messages ([filecoin-project/lotus#6594](https://github.com/filecoin-project/lotus/pull/6594))
|
||||||
|
- Fix CircleCI gen ([filecoin-project/lotus#6589](https://github.com/filecoin-project/lotus/pull/6589))
|
||||||
|
- Make query-ask CLI more graceful ([filecoin-project/lotus#6590](https://github.com/filecoin-project/lotus/pull/6590))
|
||||||
|
- scale up sector expiration to avoid sector expire in batch-pre-commit waitting ([filecoin-project/lotus#6566](https://github.com/filecoin-project/lotus/pull/6566))
|
||||||
|
- Fix an error in msigLockCancel ([filecoin-project/lotus#6582](https://github.com/filecoin-project/lotus/pull/6582)
|
||||||
|
- fix circleci being out of sync. ([filecoin-project/lotus#6573](https://github.com/filecoin-project/lotus/pull/6573))
|
||||||
|
- Fix helptext for ask price([filecoin-project/lotus#6560](https://github.com/filecoin-project/lotus/pull/6560))
|
||||||
|
- fix commit finalize failed ([filecoin-project/lotus#6521](https://github.com/filecoin-project/lotus/pull/6521))
|
||||||
|
- Fix soup ([filecoin-project/lotus#6501](https://github.com/filecoin-project/lotus/pull/6501))
|
||||||
|
- fix: pick the correct partitions-per-post limit ([filecoin-project/lotus#6502](https://github.com/filecoin-project/lotus/pull/6502))
|
||||||
|
- sealing: Fix restartSectors race ([filecoin-project/lotus#6495](https://github.com/filecoin-project/lotus/pull/6495))
|
||||||
|
- Fix: correct the change of message size limit ([filecoin-project/lotus#6430](https://github.com/filecoin-project/lotus/pull/6430))
|
||||||
|
- Fix logging of stringified CIDs double-encoded in hex ([filecoin-project/lotus#6413](https://github.com/filecoin-project/lotus/pull/6413))
|
||||||
|
- Fix success handling in Retreival ([filecoin-project/lotus#5921](https://github.com/filecoin-project/lotus/pull/5921))
|
||||||
|
- storagefsm: Fix batch deal packing behavior ([filecoin-project/lotus#6041](https://github.com/filecoin-project/lotus/pull/6041))
|
||||||
|
- events: Fix handling of multiple matched events per epoch ([filecoin-project/lotus#6355](https://github.com/filecoin-project/lotus/pull/6355))
|
||||||
|
- Fix logging around mineOne ([filecoin-project/lotus#6310](https://github.com/filecoin-project/lotus/pull/6310))
|
||||||
|
- Fix shell completions ([filecoin-project/lotus#6316](https://github.com/filecoin-project/lotus/pull/6316))
|
||||||
|
- Allow 8MB sectors in devnet ([filecoin-project/lotus#6312](https://github.com/filecoin-project/lotus/pull/6312))
|
||||||
|
- fix ticket expired ([filecoin-project/lotus#6304](https://github.com/filecoin-project/lotus/pull/6304))
|
||||||
|
- Revert "chore: update go-libp2p" ([filecoin-project/lotus#6306](https://github.com/filecoin-project/lotus/pull/6306))
|
||||||
|
- fix: wait-api should use GetAPI to acquire binary specific API ([filecoin-project/lotus#6246](https://github.com/filecoin-project/lotus/pull/6246))
|
||||||
|
- fix(ci): Updates to lotus CI build process ([filecoin-project/lotus#6256](https://github.com/filecoin-project/lotus/pull/6256))
|
||||||
|
- fix: use a consistent tipset in commands ([filecoin-project/lotus#6142](https://github.com/filecoin-project/lotus/pull/6142))
|
||||||
|
- go mod tidy for lotus-soup testplans ([filecoin-project/lotus#6124](https://github.com/filecoin-project/lotus/pull/6124))
|
||||||
|
- fix testground payment channel tests: use 1 miner ([filecoin-project/lotus#6126](https://github.com/filecoin-project/lotus/pull/6126))
|
||||||
|
- fix: use the parent state when listing actors ([filecoin-project/lotus#6143](https://github.com/filecoin-project/lotus/pull/6143))
|
||||||
|
- Speed up StateListMessages in some cases ([filecoin-project/lotus#6007](https://github.com/filecoin-project/lotus/pull/6007))
|
||||||
|
- fix(splitstore): fix a panic on revert-only head changes ([filecoin-project/lotus#6133](https://github.com/filecoin-project/lotus/pull/6133))
|
||||||
|
- drand: fix beacon cache ([filecoin-project/lotus#6164](https://github.com/filecoin-project/lotus/pull/6164))
|
||||||
|
|
||||||
|
## Improvements
|
||||||
|
- gateway: Add support for Version method ([filecoin-project/lotus#6618](https://github.com/filecoin-project/lotus/pull/6618))
|
||||||
|
- revamped integration test kit (aka. Operation Sparks Joy) ([filecoin-project/lotus#6329](https://github.com/filecoin-project/lotus/pull/6329))
|
||||||
|
- move with changed name ([filecoin-project/lotus#6587](https://github.com/filecoin-project/lotus/pull/6587))
|
||||||
|
- dynamic circleci config for streamlining test execution ([filecoin-project/lotus#6561](https://github.com/filecoin-project/lotus/pull/6561))
|
||||||
|
- extern/storage: add ability to ignore worker resources when scheduling. ([filecoin-project/lotus#6542](https://github.com/filecoin-project/lotus/pull/6542))
|
||||||
|
- Adjust various CLI display ratios to arbitrary precision ([filecoin-project/lotus#6309](https://github.com/filecoin-project/lotus/pull/6309))
|
||||||
|
- Test multicore SDR support ([filecoin-project/lotus#6479](https://github.com/filecoin-project/lotus/pull/6479))
|
||||||
|
- Unit tests for sector batchers ([filecoin-project/lotus#6432](https://github.com/filecoin-project/lotus/pull/6432))
|
||||||
|
- Update chain list with correct help instructions ([filecoin-project/lotus#6465](https://github.com/filecoin-project/lotus/pull/6465))
|
||||||
|
- clean failed sectors in batch commit ([filecoin-project/lotus#6451](https://github.com/filecoin-project/lotus/pull/6451))
|
||||||
|
- itests/kit: add guard to ensure imports from tests only. ([filecoin-project/lotus#6445](https://github.com/filecoin-project/lotus/pull/6445))
|
||||||
|
- consolidate integration tests into `itests` package; create test kit; cleanup ([filecoin-project/lotus#6311](https://github.com/filecoin-project/lotus/pull/6311))
|
||||||
|
- Fee config for sector batching ([filecoin-project/lotus#6420](https://github.com/filecoin-project/lotus/pull/6420))
|
||||||
|
- UX: lotus state power CLI should fail if called with a not-miner ([filecoin-project/lotus#6425](https://github.com/filecoin-project/lotus/pull/6425))
|
||||||
|
- Increase message size limit ([filecoin-project/lotus#6419](https://github.com/filecoin-project/lotus/pull/6419))
|
||||||
|
- polish(stmgr): define ExecMonitor for message application callback ([filecoin-project/lotus#6389](https://github.com/filecoin-project/lotus/pull/6389))
|
||||||
|
- upgrade testground action version ([filecoin-project/lotus#6403](https://github.com/filecoin-project/lotus/pull/6403))
|
||||||
|
- Bypass task scheduler for reading unsealed pieces ([filecoin-project/lotus#6280](https://github.com/filecoin-project/lotus/pull/6280))
|
||||||
|
- testplans: lotus-soup: use default WPoStChallengeWindow ([filecoin-project/lotus#6400](https://github.com/filecoin-project/lotus/pull/6400))
|
||||||
|
- Integration tests for offline deals ([filecoin-project/lotus#6081](https://github.com/filecoin-project/lotus/pull/6081))
|
||||||
|
- Fix some flaky tests ([filecoin-project/lotus#6397](https://github.com/filecoin-project/lotus/pull/6397))
|
||||||
|
- build appimage in CI ([filecoin-project/lotus#6384](https://github.com/filecoin-project/lotus/pull/6384))
|
||||||
|
- Generate AppImage ([filecoin-project/lotus#6208](https://github.com/filecoin-project/lotus/pull/6208))
|
||||||
|
- Add test for AddVerifiedClient ([filecoin-project/lotus#6317](https://github.com/filecoin-project/lotus/pull/6317))
|
||||||
|
- Typo fix in error message: "pubusb" -> "pubsub" ([filecoin-project/lotus#6365](https://github.com/filecoin-project/lotus/pull/6365))
|
||||||
|
- Improve the cli state call command ([filecoin-project/lotus#6226](https://github.com/filecoin-project/lotus/pull/6226))
|
||||||
|
- Upscale mineOne message to a WARN on unexpected ineligibility ([filecoin-project/lotus#6358](https://github.com/filecoin-project/lotus/pull/6358))
|
||||||
|
- Remove few useless variable assignments ([filecoin-project/lotus#6359](https://github.com/filecoin-project/lotus/pull/6359))
|
||||||
|
- Reduce noise from 'peer has different genesis' messages ([filecoin-project/lotus#6357](https://github.com/filecoin-project/lotus/pull/6357))
|
||||||
|
- Get current seal proof when necessary ([filecoin-project/lotus#6339](https://github.com/filecoin-project/lotus/pull/6339))
|
||||||
|
- Remove log line when tracing is not configured ([filecoin-project/lotus#6334](https://github.com/filecoin-project/lotus/pull/6334))
|
||||||
|
- separate tracing environment variables ([filecoin-project/lotus#6323](https://github.com/filecoin-project/lotus/pull/6323))
|
||||||
|
- feat: log dispute rate ([filecoin-project/lotus#6322](https://github.com/filecoin-project/lotus/pull/6322))
|
||||||
|
- Move verifreg shed utils to CLI ([filecoin-project/lotus#6135](https://github.com/filecoin-project/lotus/pull/6135))
|
||||||
|
- consider storiface.PathStorage when calculating storage requirements ([filecoin-project/lotus#6233](https://github.com/filecoin-project/lotus/pull/6233))
|
||||||
|
- `storage` module: add go docs and minor code quality refactors ([filecoin-project/lotus#6259](https://github.com/filecoin-project/lotus/pull/6259))
|
||||||
|
- Increase data transfer timeouts ([filecoin-project/lotus#6300](https://github.com/filecoin-project/lotus/pull/6300))
|
||||||
|
- gateway: spin off from cmd to package ([filecoin-project/lotus#6294](https://github.com/filecoin-project/lotus/pull/6294))
|
||||||
|
- Return total power when GetPowerRaw doesn't find miner claim ([filecoin-project/lotus#4938](https://github.com/filecoin-project/lotus/pull/4938))
|
||||||
|
- add flags to control gateway lookback parameters ([filecoin-project/lotus#6247](https://github.com/filecoin-project/lotus/pull/6247))
|
||||||
|
- chore(ci): Enable build on RC tags ([filecoin-project/lotus#6238](https://github.com/filecoin-project/lotus/pull/6238))
|
||||||
|
- cron-wc ([filecoin-project/lotus#6178](https://github.com/filecoin-project/lotus/pull/6178))
|
||||||
|
- Allow creation of state tree v3s ([filecoin-project/lotus#6167](https://github.com/filecoin-project/lotus/pull/6167))
|
||||||
|
- mpool: Cleanup pre-nv12 selection logic ([filecoin-project/lotus#6148](https://github.com/filecoin-project/lotus/pull/6148))
|
||||||
|
- attempt to do better padding on pieces being written into sectors ([filecoin-project/lotus#5988](https://github.com/filecoin-project/lotus/pull/5988))
|
||||||
|
- remove duplicate ask and calculate ping before lock ([filecoin-project/lotus#5968](https://github.com/filecoin-project/lotus/pull/5968))
|
||||||
|
- flaky tests improvement: separate TestBatchDealInput from TestAPIDealFlow ([filecoin-project/lotus#6141](https://github.com/filecoin-project/lotus/pull/6141))
|
||||||
|
- Testground checks on push ([filecoin-project/lotus#5887](https://github.com/filecoin-project/lotus/pull/5887))
|
||||||
|
- Use EmptyTSK where appropriate ([filecoin-project/lotus#6134](https://github.com/filecoin-project/lotus/pull/6134))
|
||||||
|
- upgrade `lotus-soup` testplans and reduce deals concurrency to a single miner ([filecoin-project/lotus#6122](https://github.com/filecoin-project/lotus/pull/6122)
|
||||||
|
|
||||||
|
## Dependency Updates
|
||||||
|
- downgrade libp2p/go-libp2p-yamux to v0.5.1. ([filecoin-project/lotus#6605](https://github.com/filecoin-project/lotus/pull/6605))
|
||||||
|
- Update libp2p to 0.14.2 ([filecoin-project/lotus#6404](https://github.com/filecoin-project/lotus/pull/6404))
|
||||||
|
- update to markets-v1.4.0 ([filecoin-project/lotus#6369](https://github.com/filecoin-project/lotus/pull/6369))
|
||||||
|
- Use new actor tags ([filecoin-project/lotus#6291](https://github.com/filecoin-project/lotus/pull/6291))
|
||||||
|
- chore: update go-libp2p ([filecoin-project/lotus#6231](https://github.com/filecoin-project/lotus/pull/6231))
|
||||||
|
- Update ffi to proofs v7 ([filecoin-project/lotus#6150](https://github.com/filecoin-project/lotus/pull/6150))
|
||||||
|
|
||||||
|
## Others
|
||||||
|
- Initial draft: basic build instructions on Readme ([filecoin-project/lotus#6498](https://github.com/filecoin-project/lotus/pull/6498))
|
||||||
|
- Remove rc changelog, compile the new changelog for final release only ([filecoin-project/lotus#6444](https://github.com/filecoin-project/lotus/pull/6444))
|
||||||
|
- updated configuration comments for docs ([filecoin-project/lotus#6440](https://github.com/filecoin-project/lotus/pull/6440))
|
||||||
|
- Set ntwk v13 HyperDrive Calibration upgrade epoch ([filecoin-project/lotus#6441](https://github.com/filecoin-project/lotus/pull/6441))
|
||||||
|
- build snapcraft ([filecoin-project/lotus#6388](https://github.com/filecoin-project/lotus/pull/6388))
|
||||||
|
- Fix the doc errors of the sealing config funcs ([filecoin-project/lotus#6399](https://github.com/filecoin-project/lotus/pull/6399))
|
||||||
|
- Add doc on gas balancing ([filecoin-project/lotus#6392](https://github.com/filecoin-project/lotus/pull/6392))
|
||||||
|
- Add interop network ([filecoin-project/lotus#6387](https://github.com/filecoin-project/lotus/pull/6387))
|
||||||
|
- Network version 13 (v1.11) ([filecoin-project/lotus#6342](https://github.com/filecoin-project/lotus/pull/6342))
|
||||||
|
- Add a warning to the release issue template ([filecoin-project/lotus#6374](https://github.com/filecoin-project/lotus/pull/6374))
|
||||||
|
- Update RELEASE_ISSUE_TEMPLATE.md ([filecoin-project/lotus#6236](https://github.com/filecoin-project/lotus/pull/6236))
|
||||||
|
- Delete CODEOWNERS ([filecoin-project/lotus#6289](https://github.com/filecoin-project/lotus/pull/6289))
|
||||||
|
- Feat/nerpa v4 ([filecoin-project/lotus#6248](https://github.com/filecoin-project/lotus/pull/6248))
|
||||||
|
- Introduce a release issue template ([filecoin-project/lotus#5826](https://github.com/filecoin-project/lotus/pull/5826))
|
||||||
|
- This is a 1:1 forward-port of PR#6183 from 1.9.x to master ([filecoin-project/lotus#6196](https://github.com/filecoin-project/lotus/pull/6196))
|
||||||
|
- Update cli gen ([filecoin-project/lotus#6155](https://github.com/filecoin-project/lotus/pull/6155))
|
||||||
|
- Generate CLI docs ([filecoin-project/lotus#6145](https://github.com/filecoin-project/lotus/pull/6145))
|
||||||
|
|
||||||
|
## Contributors
|
||||||
|
|
||||||
|
| Contributor | Commits | Lines ± | Files Changed |
|
||||||
|
|-------------|---------|---------|---------------|
|
||||||
|
| @raulk | 118 | +11972/-10860 | 472 |
|
||||||
|
| @magik6k | 65 | +10824/-4158 | 353 |
|
||||||
|
| @aarshkshah1992 | 59 | +8057/-3355 | 224 |
|
||||||
|
| @arajasek | 41 | +8786/-1691 | 331 |
|
||||||
|
| @Stebalien | 106 | +7653/-2718 | 273 |
|
||||||
| dirkmc | 11 | +2580/-1371 | 77 |
|
| dirkmc | 11 | +2580/-1371 | 77 |
|
||||||
| Dirk McCormick | 39 | +1865/-1194 | 79 |
|
| @dirkmc | 39 | +1865/-1194 | 79 |
|
||||||
| Jakub Sztandera | 19 | +1973/-485 | 81 |
|
| @Kubuxu | 19 | +1973/-485 | 81 |
|
||||||
| vyzo | 4 | +1748/-330 | 50 |
|
| @vyzo | 4 | +1748/-330 | 50 |
|
||||||
| Aarsh Shah | 5 | +1462/-213 | 27 |
|
| @aarshkshah1992 | 5 | +1462/-213 | 27 |
|
||||||
| Cory Schwartz | 35 | +568/-206 | 59 |
|
| @coryschwartz | 35 | +568/-206 | 59 |
|
||||||
| chadwick2143 | 3 | +739/-1 | 4 |
|
| @chadwick2143 | 3 | +739/-1 | 4 |
|
||||||
| Peter Rabbitson | 21 | +487/-164 | 36 |
|
| @ribasushi | 21 | +487/-164 | 36 |
|
||||||
| hannahhoward | 5 | +544/-5 | 19 |
|
| @hannahhoward | 5 | +544/-5 | 19 |
|
||||||
| Jennifer Wang | 9 | +241/-174 | 19 |
|
| @jennijuju | 9 | +241/-174 | 19 |
|
||||||
| frrist | 1 | +137/-88 | 7 |
|
| @frrist | 1 | +137/-88 | 7 |
|
||||||
| Travis Person | 3 | +175/-6 | 7 |
|
| @travisperson | 3 | +175/-6 | 7 |
|
||||||
| Alex Wade | 1 | +48/-129 | 1 |
|
| @wadeAlexC | 1 | +48/-129 | 1 |
|
||||||
| whyrusleeping | 8 | +161/-13 | 11 |
|
| @whyrusleeping | 8 | +161/-13 | 11 |
|
||||||
| lotus | 1 | +114/-46 | 1 |
|
| lotus | 1 | +114/-46 | 1 |
|
||||||
| Anton Evangelatov | 8 | +107/-53 | 20 |
|
| @nonsense | 8 | +107/-53 | 20 |
|
||||||
| Rjan | 4 | +115/-33 | 4 |
|
| @rjan90 | 4 | +115/-33 | 4 |
|
||||||
| ZenGround0 | 3 | +114/-1 | 4 |
|
| @ZenGround0 | 3 | +114/-1 | 4 |
|
||||||
| Aloxaf | 1 | +43/-61 | 7 |
|
| @Aloxaf | 1 | +43/-61 | 7 |
|
||||||
| yaohcn | 4 | +89/-9 | 5 |
|
| @yaohcn | 4 | +89/-9 | 5 |
|
||||||
| mitchellsoo | 1 | +51/-0 | 1 |
|
| @mitchellsoo | 1 | +51/-0 | 1 |
|
||||||
| Mike Greenberg | 3 | +28/-18 | 4 |
|
| @placer14 | 3 | +28/-18 | 4 |
|
||||||
| Jennifer | 6 | +9/-14 | 6 |
|
| @jennijuju | 6 | +9/-14 | 6 |
|
||||||
| Frank | 2 | +11/-10 | 2 |
|
| @Frank | 2 | +11/-10 | 2 |
|
||||||
| wangchao | 3 | +5/-4 | 4 |
|
| @wangchao | 3 | +5/-4 | 4 |
|
||||||
| Steve Loeppky | 1 | +7/-1 | 1 |
|
| @Steve Loeppky | 1 | +7/-1 | 1 |
|
||||||
| Lion | 1 | +4/-2 | 1 |
|
| @Lion | 1 | +4/-2 | 1 |
|
||||||
| Mimir | 1 | +2/-2 | 1 |
|
| @Mimir | 1 | +2/-2 | 1 |
|
||||||
| raulk | 1 | +1/-1 | 1 |
|
| @raulk | 1 | +1/-1 | 1 |
|
||||||
| Jack Yao | 1 | +1/-1 | 1 |
|
| @Jack Yao | 1 | +1/-1 | 1 |
|
||||||
| IPFSUnion | 1 | +1/-1 | 1 |
|
| @IPFSUnion | 1 | +1/-1 | 1 |
|
||||||
|
|
||||||
# 1.10.1-rc1 / 2021-07-02
|
# 1.10.1 / 2021-07-05
|
||||||
|
|
||||||
This is an optional, but **highly recommended** release of Lotus that have many bug fixes and improvements based on the feedbacks we got from the community since HyperDrive.
|
This is an optional but **highly recommended** release of Lotus for lotus miners that has many bug fixes and improvements based on the feedback we got from the community since HyperDrive.
|
||||||
|
|
||||||
## New Features
|
## New Features
|
||||||
- commit batch: AggregateAboveBaseFee config #6650
|
- commit batch: AggregateAboveBaseFee config #6650
|
||||||
- `AggregateAboveBaseFee` is added to miner sealing configuration for setting the network base fee to start aggregating proofs. When the network base fee is lower than this value, the prove commits will be submitted individually via `ProveCommitSector`. According to the [Batch Incentive Alignment](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0013. md#batch-incentive-alignment) introduced in FIP-0013, we recommend miners to set this value to 0.15 nanoFIL(which is also the default) to avoid unexpected aggregation fee in burn and enjoy the most benefits of aggregation!
|
- `AggregateAboveBaseFee` is added to miner sealing configuration for setting the network base fee to start aggregating proofs. When the network base fee is lower than this value, the prove commits will be submitted individually via `ProveCommitSector`. According to the [Batch Incentive Alignment](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0013.md#batch-incentive-alignment) introduced in FIP-0013, we recommend miners to set this value to 0.15 nanoFIL(which is the default value) to avoid unexpected aggregation fee in burn and enjoy the most benefits of aggregation!
|
||||||
|
|
||||||
## Bug Fixes
|
## Bug Fixes
|
||||||
- storage: Fix FinalizeSector with sectors in storage paths #6652
|
- storage: Fix FinalizeSector with sectors in storage paths #6652
|
||||||
@@ -247,14 +392,53 @@ Contributors
|
|||||||
|
|
||||||
| Contributor | Commits | Lines ± | Files Changed |
|
| Contributor | Commits | Lines ± | Files Changed |
|
||||||
|-------------|---------|---------|---------------|
|
|-------------|---------|---------|---------------|
|
||||||
| Łukasz Magiera | 7 | +151/-56 | 21 |
|
| @magik6k| 7 | +151/-56 | 21 |
|
||||||
| llifezou | 4 | +59/-20 | 4 |
|
| @llifezou | 4 | +59/-20 | 4 |
|
||||||
| johnli-helloworld | 2 | +45/-14 | 4 |
|
| @johnli-helloworld | 2 | +45/-14 | 4 |
|
||||||
| wangchao | 1 | +1/-27 | 1 |
|
| @wangchao | 1 | +1/-27 | 1 |
|
||||||
| Jerry | 2 | +9/-4 | 2 |
|
| Jerry | 2 | +9/-4 | 2 |
|
||||||
| zhoutian527 | 1 | +2/-2 | 1 |
|
| @zhoutian527 | 1 | +2/-2 | 1 |
|
||||||
| Peter Rabbitson | 1 | +1/-1 | 1 |
|
| @ribasushi| 1 | +1/-1 | 1 |
|
||||||
|
|
||||||
|
# 1.10.1 / 2021-07-05
|
||||||
|
|
||||||
|
This is an optional but **highly recommended** release of Lotus for lotus miners that has many bug fixes and improvements based on the feedback we got from the community since HyperDrive.
|
||||||
|
|
||||||
|
## New Features
|
||||||
|
- commit batch: AggregateAboveBaseFee config #6650
|
||||||
|
- `AggregateAboveBaseFee` is added to miner sealing configuration for setting the network base fee to start aggregating proofs. When the network base fee is lower than this value, the prove commits will be submitted individually via `ProveCommitSector`. According to the [Batch Incentive Alignment](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0013.md#batch-incentive-alignment) introduced in FIP-0013, we recommend miners to set this value to 0.15 nanoFIL(which is the default value) to avoid unexpected aggregation fee in burn and enjoy the most benefits of aggregation!
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
- storage: Fix FinalizeSector with sectors in storage paths #6652
|
||||||
|
- Fix tiny error in check-client-datacap #6664
|
||||||
|
- Fix: precommit_batch method used the wrong cfg.PreCommitBatchWait #6658
|
||||||
|
- to optimize the batchwait #6636
|
||||||
|
- fix getTicket: sector precommitted but expired case #6635
|
||||||
|
- handleSubmitCommitAggregate() exception handling #6595
|
||||||
|
- remove precommit check in handleCommitFailed #6634
|
||||||
|
- ensure agg fee is adequate
|
||||||
|
- fix: miner balance is not enough, so that ProveCommitAggregate msg exec failed #6623
|
||||||
|
- commit batch: Initialize the FailedSectors map #6647
|
||||||
|
|
||||||
|
Contributors
|
||||||
|
|
||||||
|
| Contributor | Commits | Lines ± | Files Changed |
|
||||||
|
|-------------|---------|---------|---------------|
|
||||||
|
| @magik6k| 7 | +151/-56 | 21 |
|
||||||
|
| @llifezou | 4 | +59/-20 | 4 |
|
||||||
|
| @johnli-helloworld | 2 | +45/-14 | 4 |
|
||||||
|
| @wangchao | 1 | +1/-27 | 1 |
|
||||||
|
| Jerry | 2 | +9/-4 | 2 |
|
||||||
|
| @zhoutian527 | 1 | +2/-2 | 1 |
|
||||||
|
| @ribasushi| 1 | +1/-1 | 1 |
|
||||||
|
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
|
||||||| merged common ancestors
|
||||||
|
>>>>>>>>> Temporary merge branch 2
|
||||||
|
=======
|
||||||
|
>>>>>>> releases
|
||||||
|
>>>>>>> releases
|
||||||
# 1.10.0 / 2021-06-23
|
# 1.10.0 / 2021-06-23
|
||||||
|
|
||||||
This is a mandatory release of Lotus that introduces Filecoin network v13, codenamed the HyperDrive upgrade. The
|
This is a mandatory release of Lotus that introduces Filecoin network v13, codenamed the HyperDrive upgrade. The
|
||||||
|
|||||||
+158
-4
@@ -36,7 +36,7 @@ WORKDIR /opt/filecoin
|
|||||||
ARG RUSTFLAGS=""
|
ARG RUSTFLAGS=""
|
||||||
ARG GOFLAGS=""
|
ARG GOFLAGS=""
|
||||||
|
|
||||||
RUN make deps lotus lotus-miner lotus-worker lotus-shed lotus-chainwatch lotus-stats
|
RUN make lotus lotus-miner lotus-worker lotus-shed lotus-wallet lotus-gateway
|
||||||
|
|
||||||
|
|
||||||
FROM ubuntu:20.04 AS base
|
FROM ubuntu:20.04 AS base
|
||||||
@@ -56,19 +56,173 @@ COPY --from=builder /usr/lib/x86_64-linux-gnu/libOpenCL.so.1 /lib/
|
|||||||
RUN useradd -r -u 532 -U fc
|
RUN useradd -r -u 532 -U fc
|
||||||
|
|
||||||
|
|
||||||
|
###
|
||||||
FROM base AS lotus
|
FROM base AS lotus
|
||||||
MAINTAINER Lotus Development Team
|
MAINTAINER Lotus Development Team
|
||||||
|
|
||||||
COPY --from=builder /opt/filecoin/lotus /usr/local/bin/
|
COPY --from=builder /opt/filecoin/lotus /usr/local/bin/
|
||||||
COPY --from=builder /opt/filecoin/lotus-shed /usr/local/bin/
|
COPY --from=builder /opt/filecoin/lotus-shed /usr/local/bin/
|
||||||
|
COPY scripts/docker-lotus-entrypoint.sh /
|
||||||
|
|
||||||
ENV FILECOIN_PARAMETER_CACHE /var/tmp/filecoin-proof-parameters
|
ENV FILECOIN_PARAMETER_CACHE /var/tmp/filecoin-proof-parameters
|
||||||
ENV LOTUS_PATH /var/lib/lotus
|
ENV LOTUS_PATH /var/lib/lotus
|
||||||
|
ENV LOTUS_JAEGER_AGENT_HOST 127.0.0.1
|
||||||
|
ENV LOTUS_JAEGER_AGENT_PORT 6831
|
||||||
|
ENV DOCKER_LOTUS_IMPORT_SNAPSHOT https://fil-chain-snapshots-fallback.s3.amazonaws.com/mainnet/minimal_finality_stateroots_latest.car
|
||||||
|
ENV DOCKER_LOTUS_IMPORT_WALLET ""
|
||||||
|
|
||||||
RUN mkdir /var/lib/lotus /var/tmp/filecoin-proof-parameters && chown fc /var/lib/lotus /var/tmp/filecoin-proof-parameters
|
RUN mkdir /var/lib/lotus /var/tmp/filecoin-proof-parameters
|
||||||
|
RUN chown fc: /var/lib/lotus /var/tmp/filecoin-proof-parameters
|
||||||
|
|
||||||
|
VOLUME /var/lib/lotus
|
||||||
|
VOLUME /var/tmp/filecoin-proof-parameters
|
||||||
|
|
||||||
USER fc
|
USER fc
|
||||||
|
|
||||||
ENTRYPOINT ["/usr/local/bin/lotus"]
|
EXPOSE 1234
|
||||||
|
|
||||||
|
ENTRYPOINT ["/docker-lotus-entrypoint.sh"]
|
||||||
|
|
||||||
CMD ["-help"]
|
CMD ["-help"]
|
||||||
|
|
||||||
|
###
|
||||||
|
FROM base AS lotus-wallet
|
||||||
|
MAINTAINER Lotus Development Team
|
||||||
|
|
||||||
|
COPY --from=builder /opt/filecoin/lotus-wallet /usr/local/bin/
|
||||||
|
|
||||||
|
ENV WALLET_PATH /var/lib/lotus-wallet
|
||||||
|
ENV LOTUS_JAEGER_AGENT_HOST 127.0.0.1
|
||||||
|
ENV LOTUS_JAEGER_AGENT_PORT 6831
|
||||||
|
|
||||||
|
RUN mkdir /var/lib/lotus-wallet
|
||||||
|
RUN chown fc: /var/lib/lotus-wallet
|
||||||
|
|
||||||
|
VOLUME /var/lib/lotus-wallet
|
||||||
|
|
||||||
|
USER fc
|
||||||
|
|
||||||
|
EXPOSE 1777
|
||||||
|
|
||||||
|
ENTRYPOINT ["/usr/local/bin/lotus-wallet"]
|
||||||
|
|
||||||
|
CMD ["-help"]
|
||||||
|
|
||||||
|
###
|
||||||
|
FROM base AS lotus-gateway
|
||||||
|
MAINTAINER Lotus Development Team
|
||||||
|
|
||||||
|
COPY --from=builder /opt/filecoin/lotus-gateway /usr/local/bin/
|
||||||
|
|
||||||
|
ENV LOTUS_JAEGER_AGENT_HOST 127.0.0.1
|
||||||
|
ENV LOTUS_JAEGER_AGENT_PORT 6831
|
||||||
|
ENV FULLNODE_API_INFO /ip4/127.0.0.1/tcp/1234/http
|
||||||
|
|
||||||
|
USER fc
|
||||||
|
|
||||||
|
EXPOSE 1234
|
||||||
|
|
||||||
|
ENTRYPOINT ["/usr/local/bin/lotus-gateway"]
|
||||||
|
|
||||||
|
CMD ["-help"]
|
||||||
|
|
||||||
|
|
||||||
|
###
|
||||||
|
FROM base AS lotus-miner
|
||||||
|
MAINTAINER Lotus Development Team
|
||||||
|
|
||||||
|
COPY --from=builder /opt/filecoin/lotus-miner /usr/local/bin/
|
||||||
|
COPY scripts/docker-lotus-miner-entrypoint.sh /
|
||||||
|
|
||||||
|
ENV FILECOIN_PARAMETER_CACHE /var/tmp/filecoin-proof-parameters
|
||||||
|
ENV FULLNODE_API_INFO /ip4/127.0.0.1/tcp/1234/http
|
||||||
|
ENV LOTUS_MINER_PATH /var/lib/lotus-miner
|
||||||
|
ENV LOTUS_JAEGER_AGENT_HOST 127.0.0.1
|
||||||
|
ENV LOTUS_JAEGER_AGENT_PORT 6831
|
||||||
|
ENV DOCKER_LOTUS_MINER_INIT true
|
||||||
|
|
||||||
|
RUN mkdir /var/lib/lotus-miner /var/tmp/filecoin-proof-parameters
|
||||||
|
RUN chown fc: /var/lib/lotus-miner /var/tmp/filecoin-proof-parameters
|
||||||
|
|
||||||
|
VOLUME /var/lib/lotus-miner
|
||||||
|
VOLUME /var/tmp/filecoin-proof-parameters
|
||||||
|
|
||||||
|
USER fc
|
||||||
|
|
||||||
|
EXPOSE 2345
|
||||||
|
|
||||||
|
ENTRYPOINT ["/docker-lotus-miner-entrypoint.sh"]
|
||||||
|
|
||||||
|
CMD ["-help"]
|
||||||
|
|
||||||
|
|
||||||
|
###
|
||||||
|
FROM base AS lotus-worker
|
||||||
|
MAINTAINER Lotus Development Team
|
||||||
|
|
||||||
|
COPY --from=builder /opt/filecoin/lotus-worker /usr/local/bin/
|
||||||
|
|
||||||
|
ENV FILECOIN_PARAMETER_CACHE /var/tmp/filecoin-proof-parameters
|
||||||
|
ENV MINER_API_INFO /ip4/127.0.0.1/tcp/2345/http
|
||||||
|
ENV LOTUS_WORKER_PATH /var/lib/lotus-worker
|
||||||
|
ENV LOTUS_JAEGER_AGENT_HOST 127.0.0.1
|
||||||
|
ENV LOTUS_JAEGER_AGENT_PORT 6831
|
||||||
|
|
||||||
|
RUN mkdir /var/lib/lotus-worker
|
||||||
|
RUN chown fc: /var/lib/lotus-worker
|
||||||
|
|
||||||
|
VOLUME /var/lib/lotus-worker
|
||||||
|
|
||||||
|
USER fc
|
||||||
|
|
||||||
|
EXPOSE 3456
|
||||||
|
|
||||||
|
ENTRYPOINT ["/usr/local/bin/lotus-worker"]
|
||||||
|
|
||||||
|
CMD ["-help"]
|
||||||
|
|
||||||
|
|
||||||
|
###
|
||||||
|
from base as lotus-all-in-one
|
||||||
|
|
||||||
|
ENV FILECOIN_PARAMETER_CACHE /var/tmp/filecoin-proof-parameters
|
||||||
|
ENV FULLNODE_API_INFO /ip4/127.0.0.1/tcp/1234/http
|
||||||
|
ENV LOTUS_JAEGER_AGENT_HOST 127.0.0.1
|
||||||
|
ENV LOTUS_JAEGER_AGENT_PORT 6831
|
||||||
|
ENV LOTUS_MINER_PATH /var/lib/lotus-miner
|
||||||
|
ENV LOTUS_PATH /var/lib/lotus
|
||||||
|
ENV LOTUS_WORKER_PATH /var/lib/lotus-worker
|
||||||
|
ENV MINER_API_INFO /ip4/127.0.0.1/tcp/2345/http
|
||||||
|
ENV WALLET_PATH /var/lib/lotus-wallet
|
||||||
|
ENV DOCKER_LOTUS_IMPORT_SNAPSHOT https://fil-chain-snapshots-fallback.s3.amazonaws.com/mainnet/minimal_finality_stateroots_latest.car
|
||||||
|
ENV DOCKER_LOTUS_MINER_INIT true
|
||||||
|
|
||||||
|
COPY --from=builder /opt/filecoin/lotus /usr/local/bin/
|
||||||
|
COPY --from=builder /opt/filecoin/lotus-shed /usr/local/bin/
|
||||||
|
COPY --from=builder /opt/filecoin/lotus-wallet /usr/local/bin/
|
||||||
|
COPY --from=builder /opt/filecoin/lotus-gateway /usr/local/bin/
|
||||||
|
COPY --from=builder /opt/filecoin/lotus-miner /usr/local/bin/
|
||||||
|
COPY --from=builder /opt/filecoin/lotus-worker /usr/local/bin/
|
||||||
|
|
||||||
|
RUN mkdir /var/tmp/filecoin-proof-parameters
|
||||||
|
RUN mkdir /var/lib/lotus
|
||||||
|
RUN mkdir /var/lib/lotus-miner
|
||||||
|
RUN mkdir /var/lib/lotus-worker
|
||||||
|
RUN mkdir /var/lib/lotus-wallet
|
||||||
|
RUN chown fc: /var/tmp/filecoin-proof-parameters
|
||||||
|
RUN chown fc: /var/lib/lotus
|
||||||
|
RUN chown fc: /var/lib/lotus-miner
|
||||||
|
RUN chown fc: /var/lib/lotus-worker
|
||||||
|
RUN chown fc: /var/lib/lotus-wallet
|
||||||
|
|
||||||
|
|
||||||
|
VOLUME /var/tmp/filecoin-proof-parameters
|
||||||
|
VOLUME /var/lib/lotus
|
||||||
|
VOLUME /var/lib/lotus-miner
|
||||||
|
VOLUME /var/lib/lotus-worker
|
||||||
|
VOLUME /var/lib/lotus-wallet
|
||||||
|
|
||||||
|
EXPOSE 1234
|
||||||
|
EXPOSE 2345
|
||||||
|
EXPOSE 3456
|
||||||
|
EXPOSE 1777
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ BINS+=lotus
|
|||||||
|
|
||||||
lotus-miner: $(BUILD_DEPS)
|
lotus-miner: $(BUILD_DEPS)
|
||||||
rm -f lotus-miner
|
rm -f lotus-miner
|
||||||
go build $(GOFLAGS) -o lotus-miner ./cmd/lotus-storage-miner
|
go build $(GOFLAGS) -o lotus-miner ./cmd/lotus-miner
|
||||||
.PHONY: lotus-miner
|
.PHONY: lotus-miner
|
||||||
BINS+=lotus-miner
|
BINS+=lotus-miner
|
||||||
|
|
||||||
@@ -131,6 +131,9 @@ install-miner:
|
|||||||
install-worker:
|
install-worker:
|
||||||
install -C ./lotus-worker /usr/local/bin/lotus-worker
|
install -C ./lotus-worker /usr/local/bin/lotus-worker
|
||||||
|
|
||||||
|
install-app:
|
||||||
|
install -C ./$(APP) /usr/local/bin/$(APP)
|
||||||
|
|
||||||
# TOOLS
|
# TOOLS
|
||||||
|
|
||||||
lotus-seed: $(BUILD_DEPS)
|
lotus-seed: $(BUILD_DEPS)
|
||||||
@@ -333,6 +336,9 @@ api-gen:
|
|||||||
goimports -w api
|
goimports -w api
|
||||||
.PHONY: api-gen
|
.PHONY: api-gen
|
||||||
|
|
||||||
|
cfgdoc-gen:
|
||||||
|
go run ./node/config/cfgdocgen > ./node/config/doc_gen.go
|
||||||
|
|
||||||
appimage: lotus
|
appimage: lotus
|
||||||
rm -rf appimage-builder-cache || true
|
rm -rf appimage-builder-cache || true
|
||||||
rm AppDir/io.filecoin.lotus.desktop || true
|
rm AppDir/io.filecoin.lotus.desktop || true
|
||||||
@@ -370,7 +376,7 @@ docsgen-openrpc-worker: docsgen-openrpc-bin
|
|||||||
|
|
||||||
.PHONY: docsgen docsgen-md-bin docsgen-openrpc-bin
|
.PHONY: docsgen docsgen-md-bin docsgen-openrpc-bin
|
||||||
|
|
||||||
gen: actors-gen type-gen method-gen docsgen api-gen circleci
|
gen: actors-gen type-gen method-gen cfgdoc-gen docsgen api-gen circleci
|
||||||
@echo ">>> IF YOU'VE MODIFIED THE CLI, REMEMBER TO ALSO MAKE docsgen-cli"
|
@echo ">>> IF YOU'VE MODIFIED THE CLI, REMEMBER TO ALSO MAKE docsgen-cli"
|
||||||
.PHONY: gen
|
.PHONY: gen
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ Lotus is an implementation of the Filecoin Distributed Storage Network. For more
|
|||||||
|
|
||||||
## Building & Documentation
|
## Building & Documentation
|
||||||
|
|
||||||
|
> Note: The default `master` branch is the dev branch, please use with caution. For the latest stable version, checkout the most recent [`Latest release`](https://github.com/filecoin-project/lotus/releases).
|
||||||
|
|
||||||
For complete instructions on how to build, install and setup lotus, please visit [https://docs.filecoin.io/get-started/lotus](https://docs.filecoin.io/get-started/lotus/). Basic build instructions can be found further down in this readme.
|
For complete instructions on how to build, install and setup lotus, please visit [https://docs.filecoin.io/get-started/lotus](https://docs.filecoin.io/get-started/lotus/). Basic build instructions can be found further down in this readme.
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
## Reporting a Vulnerability
|
||||||
|
|||||||
+7
-48
@@ -4,15 +4,11 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
apitypes "github.com/filecoin-project/lotus/api/types"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-jsonrpc/auth"
|
"github.com/filecoin-project/go-jsonrpc/auth"
|
||||||
metrics "github.com/libp2p/go-libp2p-core/metrics"
|
|
||||||
"github.com/libp2p/go-libp2p-core/network"
|
|
||||||
"github.com/libp2p/go-libp2p-core/peer"
|
|
||||||
protocol "github.com/libp2p/go-libp2p-core/protocol"
|
|
||||||
|
|
||||||
apitypes "github.com/filecoin-project/lotus/api/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// MODIFYING THE API INTERFACE
|
// MODIFYING THE API INTERFACE
|
||||||
@@ -27,55 +23,23 @@ import (
|
|||||||
// * Generate openrpc blobs
|
// * Generate openrpc blobs
|
||||||
|
|
||||||
type Common interface {
|
type Common interface {
|
||||||
|
|
||||||
// MethodGroup: Auth
|
// MethodGroup: Auth
|
||||||
|
|
||||||
AuthVerify(ctx context.Context, token string) ([]auth.Permission, error) //perm:read
|
AuthVerify(ctx context.Context, token string) ([]auth.Permission, error) //perm:read
|
||||||
AuthNew(ctx context.Context, perms []auth.Permission) ([]byte, error) //perm:admin
|
AuthNew(ctx context.Context, perms []auth.Permission) ([]byte, error) //perm:admin
|
||||||
|
|
||||||
// MethodGroup: Net
|
// MethodGroup: Log
|
||||||
|
|
||||||
NetConnectedness(context.Context, peer.ID) (network.Connectedness, error) //perm:read
|
LogList(context.Context) ([]string, error) //perm:write
|
||||||
NetPeers(context.Context) ([]peer.AddrInfo, error) //perm:read
|
LogSetLevel(context.Context, string, string) error //perm:write
|
||||||
NetConnect(context.Context, peer.AddrInfo) error //perm:write
|
|
||||||
NetAddrsListen(context.Context) (peer.AddrInfo, error) //perm:read
|
|
||||||
NetDisconnect(context.Context, peer.ID) error //perm:write
|
|
||||||
NetFindPeer(context.Context, peer.ID) (peer.AddrInfo, error) //perm:read
|
|
||||||
NetPubsubScores(context.Context) ([]PubsubScore, error) //perm:read
|
|
||||||
NetAutoNatStatus(context.Context) (NatInfo, error) //perm:read
|
|
||||||
NetAgentVersion(ctx context.Context, p peer.ID) (string, error) //perm:read
|
|
||||||
NetPeerInfo(context.Context, peer.ID) (*ExtendedPeerInfo, error) //perm:read
|
|
||||||
|
|
||||||
// NetBandwidthStats returns statistics about the nodes total bandwidth
|
|
||||||
// usage and current rate across all peers and protocols.
|
|
||||||
NetBandwidthStats(ctx context.Context) (metrics.Stats, error) //perm:read
|
|
||||||
|
|
||||||
// NetBandwidthStatsByPeer returns statistics about the nodes bandwidth
|
|
||||||
// usage and current rate per peer
|
|
||||||
NetBandwidthStatsByPeer(ctx context.Context) (map[string]metrics.Stats, error) //perm:read
|
|
||||||
|
|
||||||
// NetBandwidthStatsByProtocol returns statistics about the nodes bandwidth
|
|
||||||
// usage and current rate per protocol
|
|
||||||
NetBandwidthStatsByProtocol(ctx context.Context) (map[protocol.ID]metrics.Stats, error) //perm:read
|
|
||||||
|
|
||||||
// ConnectionGater API
|
|
||||||
NetBlockAdd(ctx context.Context, acl NetBlockList) error //perm:admin
|
|
||||||
NetBlockRemove(ctx context.Context, acl NetBlockList) error //perm:admin
|
|
||||||
NetBlockList(ctx context.Context) (NetBlockList, error) //perm:read
|
|
||||||
|
|
||||||
// MethodGroup: Common
|
// MethodGroup: Common
|
||||||
|
|
||||||
// Discover returns an OpenRPC document describing an RPC API.
|
|
||||||
Discover(ctx context.Context) (apitypes.OpenRPCDocument, error) //perm:read
|
|
||||||
|
|
||||||
// ID returns peerID of libp2p node backing this API
|
|
||||||
ID(context.Context) (peer.ID, error) //perm:read
|
|
||||||
|
|
||||||
// Version provides information about API provider
|
// Version provides information about API provider
|
||||||
Version(context.Context) (APIVersion, error) //perm:read
|
Version(context.Context) (APIVersion, error) //perm:read
|
||||||
|
|
||||||
LogList(context.Context) ([]string, error) //perm:write
|
// Discover returns an OpenRPC document describing an RPC API.
|
||||||
LogSetLevel(context.Context, string, string) error //perm:write
|
Discover(ctx context.Context) (apitypes.OpenRPCDocument, error) //perm:read
|
||||||
|
|
||||||
// trigger graceful shutdown
|
// trigger graceful shutdown
|
||||||
Shutdown(context.Context) error //perm:admin
|
Shutdown(context.Context) error //perm:admin
|
||||||
@@ -105,8 +69,3 @@ type APIVersion struct {
|
|||||||
func (v APIVersion) String() string {
|
func (v APIVersion) String() string {
|
||||||
return fmt.Sprintf("%s+api%s", v.Version, v.APIVersion.String())
|
return fmt.Sprintf("%s+api%s", v.Version, v.APIVersion.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
type NatInfo struct {
|
|
||||||
Reachability network.Reachability
|
|
||||||
PublicAddr string
|
|
||||||
}
|
|
||||||
|
|||||||
+20
-8
@@ -6,6 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/node/repo/importmgr"
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
"github.com/libp2p/go-libp2p-core/peer"
|
"github.com/libp2p/go-libp2p-core/peer"
|
||||||
|
|
||||||
@@ -14,7 +15,6 @@ import (
|
|||||||
datatransfer "github.com/filecoin-project/go-data-transfer"
|
datatransfer "github.com/filecoin-project/go-data-transfer"
|
||||||
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
||||||
"github.com/filecoin-project/go-fil-markets/storagemarket"
|
"github.com/filecoin-project/go-fil-markets/storagemarket"
|
||||||
"github.com/filecoin-project/go-multistore"
|
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
"github.com/filecoin-project/go-state-types/big"
|
"github.com/filecoin-project/go-state-types/big"
|
||||||
"github.com/filecoin-project/go-state-types/crypto"
|
"github.com/filecoin-project/go-state-types/crypto"
|
||||||
@@ -58,6 +58,7 @@ const LookbackNoLimit = abi.ChainEpoch(-1)
|
|||||||
// FullNode API is a low-level interface to the Filecoin network full node
|
// FullNode API is a low-level interface to the Filecoin network full node
|
||||||
type FullNode interface {
|
type FullNode interface {
|
||||||
Common
|
Common
|
||||||
|
Net
|
||||||
|
|
||||||
// MethodGroup: Chain
|
// MethodGroup: Chain
|
||||||
// The Chain method group contains methods for interacting with the
|
// The Chain method group contains methods for interacting with the
|
||||||
@@ -104,6 +105,9 @@ type FullNode interface {
|
|||||||
// specified block.
|
// specified block.
|
||||||
ChainGetParentMessages(ctx context.Context, blockCid cid.Cid) ([]Message, error) //perm:read
|
ChainGetParentMessages(ctx context.Context, blockCid cid.Cid) ([]Message, error) //perm:read
|
||||||
|
|
||||||
|
// ChainGetMessagesInTipset returns message stores in current tipset
|
||||||
|
ChainGetMessagesInTipset(ctx context.Context, tsk types.TipSetKey) ([]Message, error) //perm:read
|
||||||
|
|
||||||
// ChainGetTipSetByHeight looks back for a tipset at the specified epoch.
|
// ChainGetTipSetByHeight looks back for a tipset at the specified epoch.
|
||||||
// If there are no blocks at the specified epoch, a tipset at an earlier epoch
|
// If there are no blocks at the specified epoch, a tipset at an earlier epoch
|
||||||
// will be returned.
|
// will be returned.
|
||||||
@@ -160,6 +164,13 @@ type FullNode interface {
|
|||||||
// If oldmsgskip is set, messages from before the requested roots are also not included.
|
// If oldmsgskip is set, messages from before the requested roots are also not included.
|
||||||
ChainExport(ctx context.Context, nroots abi.ChainEpoch, oldmsgskip bool, tsk types.TipSetKey) (<-chan []byte, error) //perm:read
|
ChainExport(ctx context.Context, nroots abi.ChainEpoch, oldmsgskip bool, tsk types.TipSetKey) (<-chan []byte, error) //perm:read
|
||||||
|
|
||||||
|
// ChainCheckBlockstore performs an (asynchronous) health check on the chain/state blockstore
|
||||||
|
// if supported by the underlying implementation.
|
||||||
|
ChainCheckBlockstore(context.Context) error //perm:admin
|
||||||
|
|
||||||
|
// ChainBlockstoreInfo returns some basic information about the blockstore
|
||||||
|
ChainBlockstoreInfo(context.Context) (map[string]interface{}, error) //perm:read
|
||||||
|
|
||||||
// MethodGroup: Beacon
|
// MethodGroup: Beacon
|
||||||
// The Beacon method group contains methods for interacting with the random beacon (DRAND)
|
// The Beacon method group contains methods for interacting with the random beacon (DRAND)
|
||||||
|
|
||||||
@@ -320,7 +331,7 @@ type FullNode interface {
|
|||||||
// ClientImport imports file under the specified path into filestore.
|
// ClientImport imports file under the specified path into filestore.
|
||||||
ClientImport(ctx context.Context, ref FileRef) (*ImportRes, error) //perm:admin
|
ClientImport(ctx context.Context, ref FileRef) (*ImportRes, error) //perm:admin
|
||||||
// ClientRemoveImport removes file import
|
// ClientRemoveImport removes file import
|
||||||
ClientRemoveImport(ctx context.Context, importID multistore.StoreID) error //perm:admin
|
ClientRemoveImport(ctx context.Context, importID importmgr.ImportID) error //perm:admin
|
||||||
// ClientStartDeal proposes a deal with a miner.
|
// ClientStartDeal proposes a deal with a miner.
|
||||||
ClientStartDeal(ctx context.Context, params *StartDealParams) (*cid.Cid, error) //perm:admin
|
ClientStartDeal(ctx context.Context, params *StartDealParams) (*cid.Cid, error) //perm:admin
|
||||||
// ClientStatelessDeal fire-and-forget-proposes an offline deal to a miner without subsequent tracking.
|
// ClientStatelessDeal fire-and-forget-proposes an offline deal to a miner without subsequent tracking.
|
||||||
@@ -712,16 +723,17 @@ type MinerSectors struct {
|
|||||||
|
|
||||||
type ImportRes struct {
|
type ImportRes struct {
|
||||||
Root cid.Cid
|
Root cid.Cid
|
||||||
ImportID multistore.StoreID
|
ImportID importmgr.ImportID
|
||||||
}
|
}
|
||||||
|
|
||||||
type Import struct {
|
type Import struct {
|
||||||
Key multistore.StoreID
|
Key importmgr.ImportID
|
||||||
Err string
|
Err string
|
||||||
|
|
||||||
Root *cid.Cid
|
Root *cid.Cid
|
||||||
Source string
|
Source string
|
||||||
FilePath string
|
FilePath string
|
||||||
|
CARv2FilePath string
|
||||||
}
|
}
|
||||||
|
|
||||||
type DealInfo struct {
|
type DealInfo struct {
|
||||||
@@ -904,7 +916,7 @@ type RetrievalOrder struct {
|
|||||||
Piece *cid.Cid
|
Piece *cid.Cid
|
||||||
Size uint64
|
Size uint64
|
||||||
|
|
||||||
LocalStore *multistore.StoreID // if specified, get data from local store
|
LocalCARV2FilePath string // if specified, get data from a local CARv2 file.
|
||||||
// TODO: support offset
|
// TODO: support offset
|
||||||
Total types.BigInt
|
Total types.BigInt
|
||||||
UnsealPrice types.BigInt
|
UnsealPrice types.BigInt
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ type Gateway interface {
|
|||||||
StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
||||||
StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (DealCollateralBounds, error)
|
StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (DealCollateralBounds, error)
|
||||||
StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
|
StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
|
||||||
|
StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*ActorState, error) //perm:read
|
||||||
StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error)
|
StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error)
|
||||||
StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
||||||
StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (MarketBalance, error)
|
StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (MarketBalance, error)
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
metrics "github.com/libp2p/go-libp2p-core/metrics"
|
||||||
|
"github.com/libp2p/go-libp2p-core/network"
|
||||||
|
"github.com/libp2p/go-libp2p-core/peer"
|
||||||
|
"github.com/libp2p/go-libp2p-core/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MODIFYING THE API INTERFACE
|
||||||
|
//
|
||||||
|
// When adding / changing methods in this file:
|
||||||
|
// * Do the change here
|
||||||
|
// * Adjust implementation in `node/impl/`
|
||||||
|
// * Run `make gen` - this will:
|
||||||
|
// * Generate proxy structs
|
||||||
|
// * Generate mocks
|
||||||
|
// * Generate markdown docs
|
||||||
|
// * Generate openrpc blobs
|
||||||
|
|
||||||
|
type Net interface {
|
||||||
|
// MethodGroup: Net
|
||||||
|
|
||||||
|
NetConnectedness(context.Context, peer.ID) (network.Connectedness, error) //perm:read
|
||||||
|
NetPeers(context.Context) ([]peer.AddrInfo, error) //perm:read
|
||||||
|
NetConnect(context.Context, peer.AddrInfo) error //perm:write
|
||||||
|
NetAddrsListen(context.Context) (peer.AddrInfo, error) //perm:read
|
||||||
|
NetDisconnect(context.Context, peer.ID) error //perm:write
|
||||||
|
NetFindPeer(context.Context, peer.ID) (peer.AddrInfo, error) //perm:read
|
||||||
|
NetPubsubScores(context.Context) ([]PubsubScore, error) //perm:read
|
||||||
|
NetAutoNatStatus(context.Context) (NatInfo, error) //perm:read
|
||||||
|
NetAgentVersion(ctx context.Context, p peer.ID) (string, error) //perm:read
|
||||||
|
NetPeerInfo(context.Context, peer.ID) (*ExtendedPeerInfo, error) //perm:read
|
||||||
|
|
||||||
|
// NetBandwidthStats returns statistics about the nodes total bandwidth
|
||||||
|
// usage and current rate across all peers and protocols.
|
||||||
|
NetBandwidthStats(ctx context.Context) (metrics.Stats, error) //perm:read
|
||||||
|
|
||||||
|
// NetBandwidthStatsByPeer returns statistics about the nodes bandwidth
|
||||||
|
// usage and current rate per peer
|
||||||
|
NetBandwidthStatsByPeer(ctx context.Context) (map[string]metrics.Stats, error) //perm:read
|
||||||
|
|
||||||
|
// NetBandwidthStatsByProtocol returns statistics about the nodes bandwidth
|
||||||
|
// usage and current rate per protocol
|
||||||
|
NetBandwidthStatsByProtocol(ctx context.Context) (map[protocol.ID]metrics.Stats, error) //perm:read
|
||||||
|
|
||||||
|
// ConnectionGater API
|
||||||
|
NetBlockAdd(ctx context.Context, acl NetBlockList) error //perm:admin
|
||||||
|
NetBlockRemove(ctx context.Context, acl NetBlockList) error //perm:admin
|
||||||
|
NetBlockList(ctx context.Context) (NetBlockList, error) //perm:read
|
||||||
|
|
||||||
|
// ID returns peerID of libp2p node backing this API
|
||||||
|
ID(context.Context) (peer.ID, error) //perm:read
|
||||||
|
}
|
||||||
|
|
||||||
|
type CommonNet interface {
|
||||||
|
Common
|
||||||
|
Net
|
||||||
|
}
|
||||||
|
|
||||||
|
type NatInfo struct {
|
||||||
|
Reachability network.Reachability
|
||||||
|
PublicAddr string
|
||||||
|
}
|
||||||
+40
-4
@@ -41,6 +41,7 @@ import (
|
|||||||
// StorageMiner is a low-level interface to the Filecoin network storage miner node
|
// StorageMiner is a low-level interface to the Filecoin network storage miner node
|
||||||
type StorageMiner interface {
|
type StorageMiner interface {
|
||||||
Common
|
Common
|
||||||
|
Net
|
||||||
|
|
||||||
ActorAddress(context.Context) (address.Address, error) //perm:read
|
ActorAddress(context.Context) (address.Address, error) //perm:read
|
||||||
|
|
||||||
@@ -55,6 +56,13 @@ type StorageMiner interface {
|
|||||||
// Get the status of a given sector by ID
|
// Get the status of a given sector by ID
|
||||||
SectorsStatus(ctx context.Context, sid abi.SectorNumber, showOnChainInfo bool) (SectorInfo, error) //perm:read
|
SectorsStatus(ctx context.Context, sid abi.SectorNumber, showOnChainInfo bool) (SectorInfo, error) //perm:read
|
||||||
|
|
||||||
|
// Add piece to an open sector. If no sectors with enough space are open,
|
||||||
|
// either a new sector will be created, or this call will block until more
|
||||||
|
// sectors can be created.
|
||||||
|
SectorAddPieceToAny(ctx context.Context, size abi.UnpaddedPieceSize, r storage.Data, d PieceDealInfo) (SectorOffset, error) //perm:admin
|
||||||
|
|
||||||
|
SectorsUnsealPiece(ctx context.Context, sector storage.SectorRef, offset storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, randomness abi.SealRandomness, commd *cid.Cid) error //perm:admin
|
||||||
|
|
||||||
// List all staged sectors
|
// List all staged sectors
|
||||||
SectorsList(context.Context) ([]abi.SectorNumber, error) //perm:read
|
SectorsList(context.Context) ([]abi.SectorNumber, error) //perm:read
|
||||||
|
|
||||||
@@ -135,8 +143,8 @@ type StorageMiner interface {
|
|||||||
StorageBestAlloc(ctx context.Context, allocate storiface.SectorFileType, ssize abi.SectorSize, pathType storiface.PathType) ([]stores.StorageInfo, error) //perm:admin
|
StorageBestAlloc(ctx context.Context, allocate storiface.SectorFileType, ssize abi.SectorSize, pathType storiface.PathType) ([]stores.StorageInfo, error) //perm:admin
|
||||||
StorageLock(ctx context.Context, sector abi.SectorID, read storiface.SectorFileType, write storiface.SectorFileType) error //perm:admin
|
StorageLock(ctx context.Context, sector abi.SectorID, read storiface.SectorFileType, write storiface.SectorFileType) error //perm:admin
|
||||||
StorageTryLock(ctx context.Context, sector abi.SectorID, read storiface.SectorFileType, write storiface.SectorFileType) (bool, error) //perm:admin
|
StorageTryLock(ctx context.Context, sector abi.SectorID, read storiface.SectorFileType, write storiface.SectorFileType) (bool, error) //perm:admin
|
||||||
|
StorageList(ctx context.Context) (map[stores.ID][]stores.Decl, error) //perm:admin
|
||||||
|
|
||||||
StorageList(ctx context.Context) (map[stores.ID][]stores.Decl, error) //perm:admin
|
|
||||||
StorageLocal(ctx context.Context) (map[stores.ID]string, error) //perm:admin
|
StorageLocal(ctx context.Context) (map[stores.ID]string, error) //perm:admin
|
||||||
StorageStat(ctx context.Context, id stores.ID) (fsutil.FsStat, error) //perm:admin
|
StorageStat(ctx context.Context, id stores.ID) (fsutil.FsStat, error) //perm:admin
|
||||||
|
|
||||||
@@ -158,6 +166,10 @@ type StorageMiner interface {
|
|||||||
MarketPendingDeals(ctx context.Context) (PendingDealInfo, error) //perm:write
|
MarketPendingDeals(ctx context.Context) (PendingDealInfo, error) //perm:write
|
||||||
MarketPublishPendingDeals(ctx context.Context) error //perm:admin
|
MarketPublishPendingDeals(ctx context.Context) error //perm:admin
|
||||||
|
|
||||||
|
// RuntimeSubsystems returns the subsystems that are enabled
|
||||||
|
// in this instance.
|
||||||
|
RuntimeSubsystems(ctx context.Context) (MinerSubsystems, error) //perm:read
|
||||||
|
|
||||||
DealsImportData(ctx context.Context, dealPropCid cid.Cid, file string) error //perm:admin
|
DealsImportData(ctx context.Context, dealPropCid cid.Cid, file string) error //perm:admin
|
||||||
DealsList(ctx context.Context) ([]MarketDeal, error) //perm:admin
|
DealsList(ctx context.Context) ([]MarketDeal, error) //perm:admin
|
||||||
DealsConsiderOnlineStorageDeals(context.Context) (bool, error) //perm:admin
|
DealsConsiderOnlineStorageDeals(context.Context) (bool, error) //perm:admin
|
||||||
@@ -279,15 +291,17 @@ type AddrUse int
|
|||||||
const (
|
const (
|
||||||
PreCommitAddr AddrUse = iota
|
PreCommitAddr AddrUse = iota
|
||||||
CommitAddr
|
CommitAddr
|
||||||
|
DealPublishAddr
|
||||||
PoStAddr
|
PoStAddr
|
||||||
|
|
||||||
TerminateSectorsAddr
|
TerminateSectorsAddr
|
||||||
)
|
)
|
||||||
|
|
||||||
type AddressConfig struct {
|
type AddressConfig struct {
|
||||||
PreCommitControl []address.Address
|
PreCommitControl []address.Address
|
||||||
CommitControl []address.Address
|
CommitControl []address.Address
|
||||||
TerminateControl []address.Address
|
TerminateControl []address.Address
|
||||||
|
DealPublishControl []address.Address
|
||||||
|
|
||||||
DisableOwnerFallback bool
|
DisableOwnerFallback bool
|
||||||
DisableWorkerFallback bool
|
DisableWorkerFallback bool
|
||||||
@@ -300,3 +314,25 @@ type PendingDealInfo struct {
|
|||||||
PublishPeriodStart time.Time
|
PublishPeriodStart time.Time
|
||||||
PublishPeriod time.Duration
|
PublishPeriod time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SectorOffset struct {
|
||||||
|
Sector abi.SectorNumber
|
||||||
|
Offset abi.PaddedPieceSize
|
||||||
|
}
|
||||||
|
|
||||||
|
// DealInfo is a tuple of deal identity and its schedule
|
||||||
|
type PieceDealInfo struct {
|
||||||
|
PublishCid *cid.Cid
|
||||||
|
DealID abi.DealID
|
||||||
|
DealProposal *market.DealProposal
|
||||||
|
DealSchedule DealSchedule
|
||||||
|
KeepUnsealed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// DealSchedule communicates the time interval of a storage deal. The deal must
|
||||||
|
// appear in a sealed (proven) sector no later than StartEpoch, otherwise it
|
||||||
|
// is invalid.
|
||||||
|
type DealSchedule struct {
|
||||||
|
StartEpoch abi.ChainEpoch
|
||||||
|
EndEpoch abi.ChainEpoch
|
||||||
|
}
|
||||||
|
|||||||
+381
@@ -5,9 +5,11 @@ package api
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"math"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
abi "github.com/filecoin-project/go-state-types/abi"
|
abi "github.com/filecoin-project/go-state-types/abi"
|
||||||
|
market "github.com/filecoin-project/specs-actors/actors/builtin/market"
|
||||||
paych "github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
paych "github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
||||||
cid "github.com/ipfs/go-cid"
|
cid "github.com/ipfs/go-cid"
|
||||||
cbg "github.com/whyrusleeping/cbor-gen"
|
cbg "github.com/whyrusleeping/cbor-gen"
|
||||||
@@ -16,6 +18,7 @@ import (
|
|||||||
|
|
||||||
var _ = xerrors.Errorf
|
var _ = xerrors.Errorf
|
||||||
var _ = cid.Undef
|
var _ = cid.Undef
|
||||||
|
var _ = math.E
|
||||||
var _ = sort.Sort
|
var _ = sort.Sort
|
||||||
|
|
||||||
func (t *PaymentInfo) MarshalCBOR(w io.Writer) error {
|
func (t *PaymentInfo) MarshalCBOR(w io.Writer) error {
|
||||||
@@ -738,3 +741,381 @@ func (t *SealSeed) UnmarshalCBOR(r io.Reader) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
func (t *PieceDealInfo) MarshalCBOR(w io.Writer) error {
|
||||||
|
if t == nil {
|
||||||
|
_, err := w.Write(cbg.CborNull)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := w.Write([]byte{165}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
scratch := make([]byte, 9)
|
||||||
|
|
||||||
|
// t.PublishCid (cid.Cid) (struct)
|
||||||
|
if len("PublishCid") > cbg.MaxLength {
|
||||||
|
return xerrors.Errorf("Value in field \"PublishCid\" was too long")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("PublishCid"))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := io.WriteString(w, string("PublishCid")); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if t.PublishCid == nil {
|
||||||
|
if _, err := w.Write(cbg.CborNull); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := cbg.WriteCidBuf(scratch, w, *t.PublishCid); err != nil {
|
||||||
|
return xerrors.Errorf("failed to write cid field t.PublishCid: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.DealID (abi.DealID) (uint64)
|
||||||
|
if len("DealID") > cbg.MaxLength {
|
||||||
|
return xerrors.Errorf("Value in field \"DealID\" was too long")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("DealID"))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := io.WriteString(w, string("DealID")); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.DealID)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.DealProposal (market.DealProposal) (struct)
|
||||||
|
if len("DealProposal") > cbg.MaxLength {
|
||||||
|
return xerrors.Errorf("Value in field \"DealProposal\" was too long")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("DealProposal"))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := io.WriteString(w, string("DealProposal")); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := t.DealProposal.MarshalCBOR(w); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.DealSchedule (api.DealSchedule) (struct)
|
||||||
|
if len("DealSchedule") > cbg.MaxLength {
|
||||||
|
return xerrors.Errorf("Value in field \"DealSchedule\" was too long")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("DealSchedule"))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := io.WriteString(w, string("DealSchedule")); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := t.DealSchedule.MarshalCBOR(w); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.KeepUnsealed (bool) (bool)
|
||||||
|
if len("KeepUnsealed") > cbg.MaxLength {
|
||||||
|
return xerrors.Errorf("Value in field \"KeepUnsealed\" was too long")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("KeepUnsealed"))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := io.WriteString(w, string("KeepUnsealed")); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := cbg.WriteBool(w, t.KeepUnsealed); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *PieceDealInfo) UnmarshalCBOR(r io.Reader) error {
|
||||||
|
*t = PieceDealInfo{}
|
||||||
|
|
||||||
|
br := cbg.GetPeeker(r)
|
||||||
|
scratch := make([]byte, 8)
|
||||||
|
|
||||||
|
maj, extra, err := cbg.CborReadHeaderBuf(br, scratch)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if maj != cbg.MajMap {
|
||||||
|
return fmt.Errorf("cbor input should be of type map")
|
||||||
|
}
|
||||||
|
|
||||||
|
if extra > cbg.MaxLength {
|
||||||
|
return fmt.Errorf("PieceDealInfo: map struct too large (%d)", extra)
|
||||||
|
}
|
||||||
|
|
||||||
|
var name string
|
||||||
|
n := extra
|
||||||
|
|
||||||
|
for i := uint64(0); i < n; i++ {
|
||||||
|
|
||||||
|
{
|
||||||
|
sval, err := cbg.ReadStringBuf(br, scratch)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
name = string(sval)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch name {
|
||||||
|
// t.PublishCid (cid.Cid) (struct)
|
||||||
|
case "PublishCid":
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
b, err := br.ReadByte()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if b != cbg.CborNull[0] {
|
||||||
|
if err := br.UnreadByte(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := cbg.ReadCid(br)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("failed to read cid field t.PublishCid: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.PublishCid = &c
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// t.DealID (abi.DealID) (uint64)
|
||||||
|
case "DealID":
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
maj, extra, err = cbg.CborReadHeaderBuf(br, scratch)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if maj != cbg.MajUnsignedInt {
|
||||||
|
return fmt.Errorf("wrong type for uint64 field")
|
||||||
|
}
|
||||||
|
t.DealID = abi.DealID(extra)
|
||||||
|
|
||||||
|
}
|
||||||
|
// t.DealProposal (market.DealProposal) (struct)
|
||||||
|
case "DealProposal":
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
b, err := br.ReadByte()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if b != cbg.CborNull[0] {
|
||||||
|
if err := br.UnreadByte(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
t.DealProposal = new(market.DealProposal)
|
||||||
|
if err := t.DealProposal.UnmarshalCBOR(br); err != nil {
|
||||||
|
return xerrors.Errorf("unmarshaling t.DealProposal pointer: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// t.DealSchedule (api.DealSchedule) (struct)
|
||||||
|
case "DealSchedule":
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
if err := t.DealSchedule.UnmarshalCBOR(br); err != nil {
|
||||||
|
return xerrors.Errorf("unmarshaling t.DealSchedule: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// t.KeepUnsealed (bool) (bool)
|
||||||
|
case "KeepUnsealed":
|
||||||
|
|
||||||
|
maj, extra, err = cbg.CborReadHeaderBuf(br, scratch)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if maj != cbg.MajOther {
|
||||||
|
return fmt.Errorf("booleans must be major type 7")
|
||||||
|
}
|
||||||
|
switch extra {
|
||||||
|
case 20:
|
||||||
|
t.KeepUnsealed = false
|
||||||
|
case 21:
|
||||||
|
t.KeepUnsealed = true
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("booleans are either major type 7, value 20 or 21 (got %d)", extra)
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Field doesn't exist on this type, so ignore it
|
||||||
|
cbg.ScanForLinks(r, func(cid.Cid) {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (t *DealSchedule) MarshalCBOR(w io.Writer) error {
|
||||||
|
if t == nil {
|
||||||
|
_, err := w.Write(cbg.CborNull)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := w.Write([]byte{162}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
scratch := make([]byte, 9)
|
||||||
|
|
||||||
|
// t.StartEpoch (abi.ChainEpoch) (int64)
|
||||||
|
if len("StartEpoch") > cbg.MaxLength {
|
||||||
|
return xerrors.Errorf("Value in field \"StartEpoch\" was too long")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("StartEpoch"))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := io.WriteString(w, string("StartEpoch")); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if t.StartEpoch >= 0 {
|
||||||
|
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.StartEpoch)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajNegativeInt, uint64(-t.StartEpoch-1)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.EndEpoch (abi.ChainEpoch) (int64)
|
||||||
|
if len("EndEpoch") > cbg.MaxLength {
|
||||||
|
return xerrors.Errorf("Value in field \"EndEpoch\" was too long")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("EndEpoch"))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := io.WriteString(w, string("EndEpoch")); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if t.EndEpoch >= 0 {
|
||||||
|
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.EndEpoch)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajNegativeInt, uint64(-t.EndEpoch-1)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *DealSchedule) UnmarshalCBOR(r io.Reader) error {
|
||||||
|
*t = DealSchedule{}
|
||||||
|
|
||||||
|
br := cbg.GetPeeker(r)
|
||||||
|
scratch := make([]byte, 8)
|
||||||
|
|
||||||
|
maj, extra, err := cbg.CborReadHeaderBuf(br, scratch)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if maj != cbg.MajMap {
|
||||||
|
return fmt.Errorf("cbor input should be of type map")
|
||||||
|
}
|
||||||
|
|
||||||
|
if extra > cbg.MaxLength {
|
||||||
|
return fmt.Errorf("DealSchedule: map struct too large (%d)", extra)
|
||||||
|
}
|
||||||
|
|
||||||
|
var name string
|
||||||
|
n := extra
|
||||||
|
|
||||||
|
for i := uint64(0); i < n; i++ {
|
||||||
|
|
||||||
|
{
|
||||||
|
sval, err := cbg.ReadStringBuf(br, scratch)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
name = string(sval)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch name {
|
||||||
|
// t.StartEpoch (abi.ChainEpoch) (int64)
|
||||||
|
case "StartEpoch":
|
||||||
|
{
|
||||||
|
maj, extra, err := cbg.CborReadHeaderBuf(br, scratch)
|
||||||
|
var extraI int64
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
switch maj {
|
||||||
|
case cbg.MajUnsignedInt:
|
||||||
|
extraI = int64(extra)
|
||||||
|
if extraI < 0 {
|
||||||
|
return fmt.Errorf("int64 positive overflow")
|
||||||
|
}
|
||||||
|
case cbg.MajNegativeInt:
|
||||||
|
extraI = int64(extra)
|
||||||
|
if extraI < 0 {
|
||||||
|
return fmt.Errorf("int64 negative oveflow")
|
||||||
|
}
|
||||||
|
extraI = -1 - extraI
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("wrong type for int64 field: %d", maj)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.StartEpoch = abi.ChainEpoch(extraI)
|
||||||
|
}
|
||||||
|
// t.EndEpoch (abi.ChainEpoch) (int64)
|
||||||
|
case "EndEpoch":
|
||||||
|
{
|
||||||
|
maj, extra, err := cbg.CborReadHeaderBuf(br, scratch)
|
||||||
|
var extraI int64
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
switch maj {
|
||||||
|
case cbg.MajUnsignedInt:
|
||||||
|
extraI = int64(extra)
|
||||||
|
if extraI < 0 {
|
||||||
|
return fmt.Errorf("int64 positive overflow")
|
||||||
|
}
|
||||||
|
case cbg.MajNegativeInt:
|
||||||
|
extraI = int64(extra)
|
||||||
|
if extraI < 0 {
|
||||||
|
return fmt.Errorf("int64 negative oveflow")
|
||||||
|
}
|
||||||
|
extraI = -1 - extraI
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("wrong type for int64 field: %d", maj)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.EndEpoch = abi.ChainEpoch(extraI)
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Field doesn't exist on this type, so ignore it
|
||||||
|
cbg.ScanForLinks(r, func(cid.Cid) {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
+39
-46
@@ -16,14 +16,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// NewCommonRPCV0 creates a new http jsonrpc client.
|
// NewCommonRPCV0 creates a new http jsonrpc client.
|
||||||
func NewCommonRPCV0(ctx context.Context, addr string, requestHeader http.Header) (api.Common, jsonrpc.ClientCloser, error) {
|
func NewCommonRPCV0(ctx context.Context, addr string, requestHeader http.Header) (api.CommonNet, jsonrpc.ClientCloser, error) {
|
||||||
var res v0api.CommonStruct
|
var res v0api.CommonNetStruct
|
||||||
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
|
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
|
||||||
[]interface{}{
|
api.GetInternalStructs(&res), requestHeader)
|
||||||
&res.Internal,
|
|
||||||
},
|
|
||||||
requestHeader,
|
|
||||||
)
|
|
||||||
|
|
||||||
return &res, closer, err
|
return &res, closer, err
|
||||||
}
|
}
|
||||||
@@ -31,11 +27,9 @@ func NewCommonRPCV0(ctx context.Context, addr string, requestHeader http.Header)
|
|||||||
// NewFullNodeRPCV0 creates a new http jsonrpc client.
|
// NewFullNodeRPCV0 creates a new http jsonrpc client.
|
||||||
func NewFullNodeRPCV0(ctx context.Context, addr string, requestHeader http.Header) (v0api.FullNode, jsonrpc.ClientCloser, error) {
|
func NewFullNodeRPCV0(ctx context.Context, addr string, requestHeader http.Header) (v0api.FullNode, jsonrpc.ClientCloser, error) {
|
||||||
var res v0api.FullNodeStruct
|
var res v0api.FullNodeStruct
|
||||||
|
|
||||||
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
|
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
|
||||||
[]interface{}{
|
api.GetInternalStructs(&res), requestHeader)
|
||||||
&res.CommonStruct.Internal,
|
|
||||||
&res.Internal,
|
|
||||||
}, requestHeader)
|
|
||||||
|
|
||||||
return &res, closer, err
|
return &res, closer, err
|
||||||
}
|
}
|
||||||
@@ -44,51 +38,56 @@ func NewFullNodeRPCV0(ctx context.Context, addr string, requestHeader http.Heade
|
|||||||
func NewFullNodeRPCV1(ctx context.Context, addr string, requestHeader http.Header) (api.FullNode, jsonrpc.ClientCloser, error) {
|
func NewFullNodeRPCV1(ctx context.Context, addr string, requestHeader http.Header) (api.FullNode, jsonrpc.ClientCloser, error) {
|
||||||
var res v1api.FullNodeStruct
|
var res v1api.FullNodeStruct
|
||||||
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
|
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
|
||||||
[]interface{}{
|
api.GetInternalStructs(&res), requestHeader)
|
||||||
&res.CommonStruct.Internal,
|
|
||||||
&res.Internal,
|
|
||||||
}, requestHeader)
|
|
||||||
|
|
||||||
return &res, closer, err
|
return &res, closer, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getPushUrl(addr string) (string, error) {
|
||||||
|
pushUrl, err := url.Parse(addr)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
switch pushUrl.Scheme {
|
||||||
|
case "ws":
|
||||||
|
pushUrl.Scheme = "http"
|
||||||
|
case "wss":
|
||||||
|
pushUrl.Scheme = "https"
|
||||||
|
}
|
||||||
|
///rpc/v0 -> /rpc/streams/v0/push
|
||||||
|
|
||||||
|
pushUrl.Path = path.Join(pushUrl.Path, "../streams/v0/push")
|
||||||
|
return pushUrl.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
// NewStorageMinerRPCV0 creates a new http jsonrpc client for miner
|
// NewStorageMinerRPCV0 creates a new http jsonrpc client for miner
|
||||||
func NewStorageMinerRPCV0(ctx context.Context, addr string, requestHeader http.Header, opts ...jsonrpc.Option) (v0api.StorageMiner, jsonrpc.ClientCloser, error) {
|
func NewStorageMinerRPCV0(ctx context.Context, addr string, requestHeader http.Header, opts ...jsonrpc.Option) (v0api.StorageMiner, jsonrpc.ClientCloser, error) {
|
||||||
|
pushUrl, err := getPushUrl(addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
var res v0api.StorageMinerStruct
|
var res v0api.StorageMinerStruct
|
||||||
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
|
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
|
||||||
[]interface{}{
|
api.GetInternalStructs(&res), requestHeader,
|
||||||
&res.CommonStruct.Internal,
|
append([]jsonrpc.Option{
|
||||||
&res.Internal,
|
rpcenc.ReaderParamEncoder(pushUrl),
|
||||||
},
|
}, opts...)...)
|
||||||
requestHeader,
|
|
||||||
opts...,
|
|
||||||
)
|
|
||||||
|
|
||||||
return &res, closer, err
|
return &res, closer, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewWorkerRPCV0(ctx context.Context, addr string, requestHeader http.Header) (api.Worker, jsonrpc.ClientCloser, error) {
|
func NewWorkerRPCV0(ctx context.Context, addr string, requestHeader http.Header) (v0api.Worker, jsonrpc.ClientCloser, error) {
|
||||||
u, err := url.Parse(addr)
|
pushUrl, err := getPushUrl(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
switch u.Scheme {
|
|
||||||
case "ws":
|
|
||||||
u.Scheme = "http"
|
|
||||||
case "wss":
|
|
||||||
u.Scheme = "https"
|
|
||||||
}
|
|
||||||
///rpc/v0 -> /rpc/streams/v0/push
|
|
||||||
|
|
||||||
u.Path = path.Join(u.Path, "../streams/v0/push")
|
|
||||||
|
|
||||||
var res api.WorkerStruct
|
var res api.WorkerStruct
|
||||||
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
|
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
|
||||||
[]interface{}{
|
api.GetInternalStructs(&res),
|
||||||
&res.Internal,
|
|
||||||
},
|
|
||||||
requestHeader,
|
requestHeader,
|
||||||
rpcenc.ReaderParamEncoder(u.String()),
|
rpcenc.ReaderParamEncoder(pushUrl),
|
||||||
jsonrpc.WithNoReconnect(),
|
jsonrpc.WithNoReconnect(),
|
||||||
jsonrpc.WithTimeout(30*time.Second),
|
jsonrpc.WithTimeout(30*time.Second),
|
||||||
)
|
)
|
||||||
@@ -100,9 +99,7 @@ func NewWorkerRPCV0(ctx context.Context, addr string, requestHeader http.Header)
|
|||||||
func NewGatewayRPCV1(ctx context.Context, addr string, requestHeader http.Header, opts ...jsonrpc.Option) (api.Gateway, jsonrpc.ClientCloser, error) {
|
func NewGatewayRPCV1(ctx context.Context, addr string, requestHeader http.Header, opts ...jsonrpc.Option) (api.Gateway, jsonrpc.ClientCloser, error) {
|
||||||
var res api.GatewayStruct
|
var res api.GatewayStruct
|
||||||
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
|
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
|
||||||
[]interface{}{
|
api.GetInternalStructs(&res),
|
||||||
&res.Internal,
|
|
||||||
},
|
|
||||||
requestHeader,
|
requestHeader,
|
||||||
opts...,
|
opts...,
|
||||||
)
|
)
|
||||||
@@ -114,9 +111,7 @@ func NewGatewayRPCV1(ctx context.Context, addr string, requestHeader http.Header
|
|||||||
func NewGatewayRPCV0(ctx context.Context, addr string, requestHeader http.Header, opts ...jsonrpc.Option) (v0api.Gateway, jsonrpc.ClientCloser, error) {
|
func NewGatewayRPCV0(ctx context.Context, addr string, requestHeader http.Header, opts ...jsonrpc.Option) (v0api.Gateway, jsonrpc.ClientCloser, error) {
|
||||||
var res v0api.GatewayStruct
|
var res v0api.GatewayStruct
|
||||||
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
|
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
|
||||||
[]interface{}{
|
api.GetInternalStructs(&res),
|
||||||
&res.Internal,
|
|
||||||
},
|
|
||||||
requestHeader,
|
requestHeader,
|
||||||
opts...,
|
opts...,
|
||||||
)
|
)
|
||||||
@@ -127,9 +122,7 @@ func NewGatewayRPCV0(ctx context.Context, addr string, requestHeader http.Header
|
|||||||
func NewWalletRPCV0(ctx context.Context, addr string, requestHeader http.Header) (api.Wallet, jsonrpc.ClientCloser, error) {
|
func NewWalletRPCV0(ctx context.Context, addr string, requestHeader http.Header) (api.Wallet, jsonrpc.ClientCloser, error) {
|
||||||
var res api.WalletStruct
|
var res api.WalletStruct
|
||||||
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
|
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
|
||||||
[]interface{}{
|
api.GetInternalStructs(&res),
|
||||||
&res.Internal,
|
|
||||||
},
|
|
||||||
requestHeader,
|
requestHeader,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ func main() {
|
|||||||
|
|
||||||
doc := docgen_openrpc.NewLotusOpenRPCDocument(Comments, GroupDocs)
|
doc := docgen_openrpc.NewLotusOpenRPCDocument(Comments, GroupDocs)
|
||||||
|
|
||||||
i, _, _, _ := docgen.GetAPIType(os.Args[2], os.Args[3])
|
i, _, _ := docgen.GetAPIType(os.Args[2], os.Args[3])
|
||||||
doc.RegisterReceiverName("Filecoin", i)
|
doc.RegisterReceiverName("Filecoin", i)
|
||||||
|
|
||||||
out, err := doc.Discover()
|
out, err := doc.Discover()
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -15,7 +16,7 @@ func main() {
|
|||||||
|
|
||||||
groups := make(map[string]*docgen.MethodGroup)
|
groups := make(map[string]*docgen.MethodGroup)
|
||||||
|
|
||||||
_, t, permStruct, commonPermStruct := docgen.GetAPIType(os.Args[2], os.Args[3])
|
_, t, permStruct := docgen.GetAPIType(os.Args[2], os.Args[3])
|
||||||
|
|
||||||
for i := 0; i < t.NumMethod(); i++ {
|
for i := 0; i < t.NumMethod(); i++ {
|
||||||
m := t.Method(i)
|
m := t.Method(i)
|
||||||
@@ -88,13 +89,17 @@ func main() {
|
|||||||
fmt.Printf("### %s\n", m.Name)
|
fmt.Printf("### %s\n", m.Name)
|
||||||
fmt.Printf("%s\n\n", m.Comment)
|
fmt.Printf("%s\n\n", m.Comment)
|
||||||
|
|
||||||
meth, ok := permStruct.FieldByName(m.Name)
|
var meth reflect.StructField
|
||||||
if !ok {
|
var ok bool
|
||||||
meth, ok = commonPermStruct.FieldByName(m.Name)
|
for _, ps := range permStruct {
|
||||||
if !ok {
|
meth, ok = ps.FieldByName(m.Name)
|
||||||
panic("no perms for method: " + m.Name)
|
if ok {
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !ok {
|
||||||
|
panic("no perms for method: " + m.Name)
|
||||||
|
}
|
||||||
|
|
||||||
perms := meth.Tag.Get("perm")
|
perms := meth.Tag.Get("perm")
|
||||||
|
|
||||||
|
|||||||
+32
-18
@@ -13,13 +13,15 @@ import (
|
|||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/go-bitfield"
|
"github.com/filecoin-project/go-bitfield"
|
||||||
|
"github.com/filecoin-project/go-multistore"
|
||||||
|
"github.com/filecoin-project/lotus/node/repo/importmgr"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
"github.com/ipfs/go-filestore"
|
"github.com/ipfs/go-filestore"
|
||||||
metrics "github.com/libp2p/go-libp2p-core/metrics"
|
"github.com/libp2p/go-libp2p-core/metrics"
|
||||||
"github.com/libp2p/go-libp2p-core/network"
|
"github.com/libp2p/go-libp2p-core/network"
|
||||||
"github.com/libp2p/go-libp2p-core/peer"
|
"github.com/libp2p/go-libp2p-core/peer"
|
||||||
protocol "github.com/libp2p/go-libp2p-core/protocol"
|
"github.com/libp2p/go-libp2p-core/protocol"
|
||||||
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
||||||
"github.com/multiformats/go-multiaddr"
|
"github.com/multiformats/go-multiaddr"
|
||||||
|
|
||||||
@@ -27,7 +29,6 @@ import (
|
|||||||
filestore2 "github.com/filecoin-project/go-fil-markets/filestore"
|
filestore2 "github.com/filecoin-project/go-fil-markets/filestore"
|
||||||
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
||||||
"github.com/filecoin-project/go-jsonrpc/auth"
|
"github.com/filecoin-project/go-jsonrpc/auth"
|
||||||
"github.com/filecoin-project/go-multistore"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
"github.com/filecoin-project/go-state-types/crypto"
|
"github.com/filecoin-project/go-state-types/crypto"
|
||||||
@@ -46,11 +47,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var ExampleValues = map[reflect.Type]interface{}{
|
var ExampleValues = map[reflect.Type]interface{}{
|
||||||
reflect.TypeOf(auth.Permission("")): auth.Permission("write"),
|
reflect.TypeOf(api.MinerSubsystem(0)): api.MinerSubsystem(1),
|
||||||
reflect.TypeOf(""): "string value",
|
reflect.TypeOf(auth.Permission("")): auth.Permission("write"),
|
||||||
reflect.TypeOf(uint64(42)): uint64(42),
|
reflect.TypeOf(""): "string value",
|
||||||
reflect.TypeOf(byte(7)): byte(7),
|
reflect.TypeOf(uint64(42)): uint64(42),
|
||||||
reflect.TypeOf([]byte{}): []byte("byte array"),
|
reflect.TypeOf(byte(7)): byte(7),
|
||||||
|
reflect.TypeOf([]byte{}): []byte("byte array"),
|
||||||
}
|
}
|
||||||
|
|
||||||
func addExample(v interface{}) {
|
func addExample(v interface{}) {
|
||||||
@@ -89,6 +91,7 @@ func init() {
|
|||||||
addExample(&pid)
|
addExample(&pid)
|
||||||
|
|
||||||
multistoreIDExample := multistore.StoreID(50)
|
multistoreIDExample := multistore.StoreID(50)
|
||||||
|
storeIDExample := importmgr.ImportID(50)
|
||||||
|
|
||||||
addExample(bitfield.NewFromSet([]uint64{5}))
|
addExample(bitfield.NewFromSet([]uint64{5}))
|
||||||
addExample(abi.RegisteredSealProof_StackedDrg32GiBV1_1)
|
addExample(abi.RegisteredSealProof_StackedDrg32GiBV1_1)
|
||||||
@@ -119,6 +122,8 @@ func init() {
|
|||||||
addExample(time.Minute)
|
addExample(time.Minute)
|
||||||
addExample(datatransfer.TransferID(3))
|
addExample(datatransfer.TransferID(3))
|
||||||
addExample(datatransfer.Ongoing)
|
addExample(datatransfer.Ongoing)
|
||||||
|
addExample(storeIDExample)
|
||||||
|
addExample(&storeIDExample)
|
||||||
addExample(multistoreIDExample)
|
addExample(multistoreIDExample)
|
||||||
addExample(&multistoreIDExample)
|
addExample(&multistoreIDExample)
|
||||||
addExample(retrievalmarket.ClientEventDealAccepted)
|
addExample(retrievalmarket.ClientEventDealAccepted)
|
||||||
@@ -175,7 +180,7 @@ func init() {
|
|||||||
|
|
||||||
// miner specific
|
// miner specific
|
||||||
addExample(filestore2.Path(".lotusminer/fstmp123"))
|
addExample(filestore2.Path(".lotusminer/fstmp123"))
|
||||||
si := multistore.StoreID(12)
|
si := uint64(12)
|
||||||
addExample(&si)
|
addExample(&si)
|
||||||
addExample(retrievalmarket.DealID(5))
|
addExample(retrievalmarket.DealID(5))
|
||||||
addExample(abi.ActorID(1000))
|
addExample(abi.ActorID(1000))
|
||||||
@@ -264,27 +269,35 @@ func init() {
|
|||||||
|
|
||||||
addExample(api.CheckStatusCode(0))
|
addExample(api.CheckStatusCode(0))
|
||||||
addExample(map[string]interface{}{"abc": 123})
|
addExample(map[string]interface{}{"abc": 123})
|
||||||
|
addExample(api.MinerSubsystems{
|
||||||
|
api.SubsystemMining,
|
||||||
|
api.SubsystemSealing,
|
||||||
|
api.SubsystemSectorStorage,
|
||||||
|
api.SubsystemMarkets,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetAPIType(name, pkg string) (i interface{}, t, permStruct, commonPermStruct reflect.Type) {
|
func GetAPIType(name, pkg string) (i interface{}, t reflect.Type, permStruct []reflect.Type) {
|
||||||
|
|
||||||
switch pkg {
|
switch pkg {
|
||||||
case "api": // latest
|
case "api": // latest
|
||||||
switch name {
|
switch name {
|
||||||
case "FullNode":
|
case "FullNode":
|
||||||
i = &api.FullNodeStruct{}
|
i = &api.FullNodeStruct{}
|
||||||
t = reflect.TypeOf(new(struct{ api.FullNode })).Elem()
|
t = reflect.TypeOf(new(struct{ api.FullNode })).Elem()
|
||||||
permStruct = reflect.TypeOf(api.FullNodeStruct{}.Internal)
|
permStruct = append(permStruct, reflect.TypeOf(api.FullNodeStruct{}.Internal))
|
||||||
commonPermStruct = reflect.TypeOf(api.CommonStruct{}.Internal)
|
permStruct = append(permStruct, reflect.TypeOf(api.CommonStruct{}.Internal))
|
||||||
|
permStruct = append(permStruct, reflect.TypeOf(api.NetStruct{}.Internal))
|
||||||
case "StorageMiner":
|
case "StorageMiner":
|
||||||
i = &api.StorageMinerStruct{}
|
i = &api.StorageMinerStruct{}
|
||||||
t = reflect.TypeOf(new(struct{ api.StorageMiner })).Elem()
|
t = reflect.TypeOf(new(struct{ api.StorageMiner })).Elem()
|
||||||
permStruct = reflect.TypeOf(api.StorageMinerStruct{}.Internal)
|
permStruct = append(permStruct, reflect.TypeOf(api.StorageMinerStruct{}.Internal))
|
||||||
commonPermStruct = reflect.TypeOf(api.CommonStruct{}.Internal)
|
permStruct = append(permStruct, reflect.TypeOf(api.CommonStruct{}.Internal))
|
||||||
|
permStruct = append(permStruct, reflect.TypeOf(api.NetStruct{}.Internal))
|
||||||
case "Worker":
|
case "Worker":
|
||||||
i = &api.WorkerStruct{}
|
i = &api.WorkerStruct{}
|
||||||
t = reflect.TypeOf(new(struct{ api.Worker })).Elem()
|
t = reflect.TypeOf(new(struct{ api.Worker })).Elem()
|
||||||
permStruct = reflect.TypeOf(api.WorkerStruct{}.Internal)
|
permStruct = append(permStruct, reflect.TypeOf(api.WorkerStruct{}.Internal))
|
||||||
commonPermStruct = reflect.TypeOf(api.WorkerStruct{}.Internal)
|
|
||||||
default:
|
default:
|
||||||
panic("unknown type")
|
panic("unknown type")
|
||||||
}
|
}
|
||||||
@@ -293,8 +306,9 @@ func GetAPIType(name, pkg string) (i interface{}, t, permStruct, commonPermStruc
|
|||||||
case "FullNode":
|
case "FullNode":
|
||||||
i = v0api.FullNodeStruct{}
|
i = v0api.FullNodeStruct{}
|
||||||
t = reflect.TypeOf(new(struct{ v0api.FullNode })).Elem()
|
t = reflect.TypeOf(new(struct{ v0api.FullNode })).Elem()
|
||||||
permStruct = reflect.TypeOf(v0api.FullNodeStruct{}.Internal)
|
permStruct = append(permStruct, reflect.TypeOf(v0api.FullNodeStruct{}.Internal))
|
||||||
commonPermStruct = reflect.TypeOf(v0api.CommonStruct{}.Internal)
|
permStruct = append(permStruct, reflect.TypeOf(v0api.CommonStruct{}.Internal))
|
||||||
|
permStruct = append(permStruct, reflect.TypeOf(v0api.NetStruct{}.Internal))
|
||||||
default:
|
default:
|
||||||
panic("unknown type")
|
panic("unknown type")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MinerSubsystem represents a miner subsystem. Int and string values are not
|
||||||
|
// guaranteed to be stable over time is not
|
||||||
|
// guaranteed to be stable over time.
|
||||||
|
type MinerSubsystem int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// SubsystemUnknown is a placeholder for the zero value. It should never
|
||||||
|
// be used.
|
||||||
|
SubsystemUnknown MinerSubsystem = iota
|
||||||
|
// SubsystemMarkets signifies the storage and retrieval
|
||||||
|
// deal-making subsystem.
|
||||||
|
SubsystemMarkets
|
||||||
|
// SubsystemMining signifies the mining subsystem.
|
||||||
|
SubsystemMining
|
||||||
|
// SubsystemSealing signifies the sealing subsystem.
|
||||||
|
SubsystemSealing
|
||||||
|
// SubsystemSectorStorage signifies the sector storage subsystem.
|
||||||
|
SubsystemSectorStorage
|
||||||
|
)
|
||||||
|
|
||||||
|
var MinerSubsystemToString = map[MinerSubsystem]string{
|
||||||
|
SubsystemUnknown: "Unknown",
|
||||||
|
SubsystemMarkets: "Markets",
|
||||||
|
SubsystemMining: "Mining",
|
||||||
|
SubsystemSealing: "Sealing",
|
||||||
|
SubsystemSectorStorage: "SectorStorage",
|
||||||
|
}
|
||||||
|
|
||||||
|
var MinerSubsystemToID = map[string]MinerSubsystem{
|
||||||
|
"Unknown": SubsystemUnknown,
|
||||||
|
"Markets": SubsystemMarkets,
|
||||||
|
"Mining": SubsystemMining,
|
||||||
|
"Sealing": SubsystemSealing,
|
||||||
|
"SectorStorage": SubsystemSectorStorage,
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ms MinerSubsystem) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(MinerSubsystemToString[ms])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ms *MinerSubsystem) UnmarshalJSON(b []byte) error {
|
||||||
|
var j string
|
||||||
|
err := json.Unmarshal(b, &j)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s, ok := MinerSubsystemToID[j]
|
||||||
|
if !ok {
|
||||||
|
*ms = SubsystemUnknown
|
||||||
|
} else {
|
||||||
|
*ms = s
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type MinerSubsystems []MinerSubsystem
|
||||||
|
|
||||||
|
func (ms MinerSubsystems) Has(entry MinerSubsystem) bool {
|
||||||
|
for _, v := range ms {
|
||||||
|
if v == entry {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ms MinerSubsystem) String() string {
|
||||||
|
s, ok := MinerSubsystemToString[ms]
|
||||||
|
if !ok {
|
||||||
|
return MinerSubsystemToString[SubsystemUnknown]
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
+46
-2
@@ -14,7 +14,6 @@ import (
|
|||||||
retrievalmarket "github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
retrievalmarket "github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
||||||
storagemarket "github.com/filecoin-project/go-fil-markets/storagemarket"
|
storagemarket "github.com/filecoin-project/go-fil-markets/storagemarket"
|
||||||
auth "github.com/filecoin-project/go-jsonrpc/auth"
|
auth "github.com/filecoin-project/go-jsonrpc/auth"
|
||||||
multistore "github.com/filecoin-project/go-multistore"
|
|
||||||
abi "github.com/filecoin-project/go-state-types/abi"
|
abi "github.com/filecoin-project/go-state-types/abi"
|
||||||
big "github.com/filecoin-project/go-state-types/big"
|
big "github.com/filecoin-project/go-state-types/big"
|
||||||
crypto "github.com/filecoin-project/go-state-types/crypto"
|
crypto "github.com/filecoin-project/go-state-types/crypto"
|
||||||
@@ -26,6 +25,7 @@ import (
|
|||||||
types "github.com/filecoin-project/lotus/chain/types"
|
types "github.com/filecoin-project/lotus/chain/types"
|
||||||
marketevents "github.com/filecoin-project/lotus/markets/loggers"
|
marketevents "github.com/filecoin-project/lotus/markets/loggers"
|
||||||
dtypes "github.com/filecoin-project/lotus/node/modules/dtypes"
|
dtypes "github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||||
|
importmgr "github.com/filecoin-project/lotus/node/repo/importmgr"
|
||||||
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
||||||
paych "github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
paych "github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
@@ -105,6 +105,35 @@ func (mr *MockFullNodeMockRecorder) BeaconGetEntry(arg0, arg1 interface{}) *gomo
|
|||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BeaconGetEntry", reflect.TypeOf((*MockFullNode)(nil).BeaconGetEntry), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BeaconGetEntry", reflect.TypeOf((*MockFullNode)(nil).BeaconGetEntry), arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ChainBlockstoreInfo mocks base method.
|
||||||
|
func (m *MockFullNode) ChainBlockstoreInfo(arg0 context.Context) (map[string]interface{}, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "ChainBlockstoreInfo", arg0)
|
||||||
|
ret0, _ := ret[0].(map[string]interface{})
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChainBlockstoreInfo indicates an expected call of ChainBlockstoreInfo.
|
||||||
|
func (mr *MockFullNodeMockRecorder) ChainBlockstoreInfo(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainBlockstoreInfo", reflect.TypeOf((*MockFullNode)(nil).ChainBlockstoreInfo), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChainCheckBlockstore mocks base method.
|
||||||
|
func (m *MockFullNode) ChainCheckBlockstore(arg0 context.Context) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "ChainCheckBlockstore", arg0)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChainCheckBlockstore indicates an expected call of ChainCheckBlockstore.
|
||||||
|
func (mr *MockFullNodeMockRecorder) ChainCheckBlockstore(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainCheckBlockstore", reflect.TypeOf((*MockFullNode)(nil).ChainCheckBlockstore), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
// ChainDeleteObj mocks base method.
|
// ChainDeleteObj mocks base method.
|
||||||
func (m *MockFullNode) ChainDeleteObj(arg0 context.Context, arg1 cid.Cid) error {
|
func (m *MockFullNode) ChainDeleteObj(arg0 context.Context, arg1 cid.Cid) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
@@ -194,6 +223,21 @@ func (mr *MockFullNodeMockRecorder) ChainGetMessage(arg0, arg1 interface{}) *gom
|
|||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainGetMessage", reflect.TypeOf((*MockFullNode)(nil).ChainGetMessage), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainGetMessage", reflect.TypeOf((*MockFullNode)(nil).ChainGetMessage), arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ChainGetMessagesInTipset mocks base method.
|
||||||
|
func (m *MockFullNode) ChainGetMessagesInTipset(arg0 context.Context, arg1 types.TipSetKey) ([]api.Message, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "ChainGetMessagesInTipset", arg0, arg1)
|
||||||
|
ret0, _ := ret[0].([]api.Message)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChainGetMessagesInTipset indicates an expected call of ChainGetMessagesInTipset.
|
||||||
|
func (mr *MockFullNodeMockRecorder) ChainGetMessagesInTipset(arg0, arg1 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainGetMessagesInTipset", reflect.TypeOf((*MockFullNode)(nil).ChainGetMessagesInTipset), arg0, arg1)
|
||||||
|
}
|
||||||
|
|
||||||
// ChainGetNode mocks base method.
|
// ChainGetNode mocks base method.
|
||||||
func (m *MockFullNode) ChainGetNode(arg0 context.Context, arg1 string) (*api.IpldObject, error) {
|
func (m *MockFullNode) ChainGetNode(arg0 context.Context, arg1 string) (*api.IpldObject, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
@@ -716,7 +760,7 @@ func (mr *MockFullNodeMockRecorder) ClientQueryAsk(arg0, arg1, arg2 interface{})
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ClientRemoveImport mocks base method.
|
// ClientRemoveImport mocks base method.
|
||||||
func (m *MockFullNode) ClientRemoveImport(arg0 context.Context, arg1 multistore.StoreID) error {
|
func (m *MockFullNode) ClientRemoveImport(arg0 context.Context, arg1 importmgr.ImportID) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "ClientRemoveImport", arg0, arg1)
|
ret := m.ctrl.Call(m, "ClientRemoveImport", arg0, arg1)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
|
|||||||
+11
-6
@@ -16,28 +16,33 @@ const (
|
|||||||
var AllPermissions = []auth.Permission{PermRead, PermWrite, PermSign, PermAdmin}
|
var AllPermissions = []auth.Permission{PermRead, PermWrite, PermSign, PermAdmin}
|
||||||
var DefaultPerms = []auth.Permission{PermRead}
|
var DefaultPerms = []auth.Permission{PermRead}
|
||||||
|
|
||||||
|
func permissionedProxies(in, out interface{}) {
|
||||||
|
outs := GetInternalStructs(out)
|
||||||
|
for _, o := range outs {
|
||||||
|
auth.PermissionedProxy(AllPermissions, DefaultPerms, in, o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func PermissionedStorMinerAPI(a StorageMiner) StorageMiner {
|
func PermissionedStorMinerAPI(a StorageMiner) StorageMiner {
|
||||||
var out StorageMinerStruct
|
var out StorageMinerStruct
|
||||||
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.Internal)
|
permissionedProxies(a, &out)
|
||||||
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.CommonStruct.Internal)
|
|
||||||
return &out
|
return &out
|
||||||
}
|
}
|
||||||
|
|
||||||
func PermissionedFullAPI(a FullNode) FullNode {
|
func PermissionedFullAPI(a FullNode) FullNode {
|
||||||
var out FullNodeStruct
|
var out FullNodeStruct
|
||||||
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.Internal)
|
permissionedProxies(a, &out)
|
||||||
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.CommonStruct.Internal)
|
|
||||||
return &out
|
return &out
|
||||||
}
|
}
|
||||||
|
|
||||||
func PermissionedWorkerAPI(a Worker) Worker {
|
func PermissionedWorkerAPI(a Worker) Worker {
|
||||||
var out WorkerStruct
|
var out WorkerStruct
|
||||||
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.Internal)
|
permissionedProxies(a, &out)
|
||||||
return &out
|
return &out
|
||||||
}
|
}
|
||||||
|
|
||||||
func PermissionedWalletAPI(a Wallet) Wallet {
|
func PermissionedWalletAPI(a Wallet) Wallet {
|
||||||
var out WalletStruct
|
var out WalletStruct
|
||||||
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.Internal)
|
permissionedProxies(a, &out)
|
||||||
return &out
|
return &out
|
||||||
}
|
}
|
||||||
|
|||||||
+1715
-516
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,30 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import "reflect"
|
||||||
|
|
||||||
|
var _internalField = "Internal"
|
||||||
|
|
||||||
|
// GetInternalStructs extracts all pointers to 'Internal' sub-structs from the provided pointer to a proxy struct
|
||||||
|
func GetInternalStructs(in interface{}) []interface{} {
|
||||||
|
return getInternalStructs(reflect.ValueOf(in).Elem())
|
||||||
|
}
|
||||||
|
|
||||||
|
func getInternalStructs(rv reflect.Value) []interface{} {
|
||||||
|
var out []interface{}
|
||||||
|
|
||||||
|
internal := rv.FieldByName(_internalField)
|
||||||
|
ii := internal.Addr().Interface()
|
||||||
|
out = append(out, ii)
|
||||||
|
|
||||||
|
for i := 0; i < rv.NumField(); i++ {
|
||||||
|
if rv.Type().Field(i).Name == _internalField {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
sub := getInternalStructs(rv.Field(i))
|
||||||
|
|
||||||
|
out = append(out, sub...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
type StrA struct {
|
||||||
|
StrB
|
||||||
|
|
||||||
|
Internal struct {
|
||||||
|
A int
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type StrB struct {
|
||||||
|
Internal struct {
|
||||||
|
B int
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type StrC struct {
|
||||||
|
Internal struct {
|
||||||
|
Internal struct {
|
||||||
|
C int
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetInternalStructs(t *testing.T) {
|
||||||
|
var proxy StrA
|
||||||
|
|
||||||
|
sts := GetInternalStructs(&proxy)
|
||||||
|
require.Len(t, sts, 2)
|
||||||
|
|
||||||
|
sa := sts[0].(*struct{ A int })
|
||||||
|
sa.A = 3
|
||||||
|
sb := sts[1].(*struct{ B int })
|
||||||
|
sb.B = 4
|
||||||
|
|
||||||
|
require.Equal(t, 3, proxy.Internal.A)
|
||||||
|
require.Equal(t, 4, proxy.StrB.Internal.B)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNestedInternalStructs(t *testing.T) {
|
||||||
|
var proxy StrC
|
||||||
|
|
||||||
|
// check that only the top-level internal struct gets picked up
|
||||||
|
|
||||||
|
sts := GetInternalStructs(&proxy)
|
||||||
|
require.Len(t, sts, 1)
|
||||||
|
|
||||||
|
sa := sts[0].(*struct {
|
||||||
|
Internal struct {
|
||||||
|
C int
|
||||||
|
}
|
||||||
|
})
|
||||||
|
sa.Internal.C = 5
|
||||||
|
|
||||||
|
require.Equal(t, 5, proxy.Internal.Internal.C)
|
||||||
|
}
|
||||||
+6
-2
@@ -8,10 +8,10 @@ import (
|
|||||||
datatransfer "github.com/filecoin-project/go-data-transfer"
|
datatransfer "github.com/filecoin-project/go-data-transfer"
|
||||||
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
||||||
"github.com/filecoin-project/go-fil-markets/storagemarket"
|
"github.com/filecoin-project/go-fil-markets/storagemarket"
|
||||||
"github.com/filecoin-project/go-multistore"
|
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
"github.com/filecoin-project/go-state-types/crypto"
|
"github.com/filecoin-project/go-state-types/crypto"
|
||||||
"github.com/filecoin-project/go-state-types/dline"
|
"github.com/filecoin-project/go-state-types/dline"
|
||||||
|
"github.com/filecoin-project/lotus/node/repo/importmgr"
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
"github.com/libp2p/go-libp2p-core/peer"
|
"github.com/libp2p/go-libp2p-core/peer"
|
||||||
|
|
||||||
@@ -46,6 +46,7 @@ import (
|
|||||||
// FullNode API is a low-level interface to the Filecoin network full node
|
// FullNode API is a low-level interface to the Filecoin network full node
|
||||||
type FullNode interface {
|
type FullNode interface {
|
||||||
Common
|
Common
|
||||||
|
Net
|
||||||
|
|
||||||
// MethodGroup: Chain
|
// MethodGroup: Chain
|
||||||
// The Chain method group contains methods for interacting with the
|
// The Chain method group contains methods for interacting with the
|
||||||
@@ -92,6 +93,9 @@ type FullNode interface {
|
|||||||
// specified block.
|
// specified block.
|
||||||
ChainGetParentMessages(ctx context.Context, blockCid cid.Cid) ([]api.Message, error) //perm:read
|
ChainGetParentMessages(ctx context.Context, blockCid cid.Cid) ([]api.Message, error) //perm:read
|
||||||
|
|
||||||
|
// ChainGetMessagesInTipset returns message stores in current tipset
|
||||||
|
ChainGetMessagesInTipset(ctx context.Context, tsk types.TipSetKey) ([]api.Message, error) //perm:read
|
||||||
|
|
||||||
// ChainGetTipSetByHeight looks back for a tipset at the specified epoch.
|
// ChainGetTipSetByHeight looks back for a tipset at the specified epoch.
|
||||||
// If there are no blocks at the specified epoch, a tipset at an earlier epoch
|
// If there are no blocks at the specified epoch, a tipset at an earlier epoch
|
||||||
// will be returned.
|
// will be returned.
|
||||||
@@ -301,7 +305,7 @@ type FullNode interface {
|
|||||||
// ClientImport imports file under the specified path into filestore.
|
// ClientImport imports file under the specified path into filestore.
|
||||||
ClientImport(ctx context.Context, ref api.FileRef) (*api.ImportRes, error) //perm:admin
|
ClientImport(ctx context.Context, ref api.FileRef) (*api.ImportRes, error) //perm:admin
|
||||||
// ClientRemoveImport removes file import
|
// ClientRemoveImport removes file import
|
||||||
ClientRemoveImport(ctx context.Context, importID multistore.StoreID) error //perm:admin
|
ClientRemoveImport(ctx context.Context, importID importmgr.ImportID) error //perm:admin
|
||||||
// ClientStartDeal proposes a deal with a miner.
|
// ClientStartDeal proposes a deal with a miner.
|
||||||
ClientStartDeal(ctx context.Context, params *api.StartDealParams) (*cid.Cid, error) //perm:admin
|
ClientStartDeal(ctx context.Context, params *api.StartDealParams) (*cid.Cid, error) //perm:admin
|
||||||
// ClientStatelessDeal fire-and-forget-proposes an offline deal to a miner without subsequent tracking.
|
// ClientStatelessDeal fire-and-forget-proposes an offline deal to a miner without subsequent tracking.
|
||||||
|
|||||||
@@ -5,8 +5,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Common = api.Common
|
type Common = api.Common
|
||||||
|
type Net = api.Net
|
||||||
|
type CommonNet = api.CommonNet
|
||||||
|
|
||||||
type CommonStruct = api.CommonStruct
|
type CommonStruct = api.CommonStruct
|
||||||
type CommonStub = api.CommonStub
|
type CommonStub = api.CommonStub
|
||||||
|
type NetStruct = api.NetStruct
|
||||||
|
type NetStub = api.NetStub
|
||||||
|
type CommonNetStruct = api.CommonNetStruct
|
||||||
|
type CommonNetStub = api.CommonNetStub
|
||||||
|
|
||||||
type StorageMiner = api.StorageMiner
|
type StorageMiner = api.StorageMiner
|
||||||
type StorageMinerStruct = api.StorageMinerStruct
|
type StorageMinerStruct = api.StorageMinerStruct
|
||||||
|
|||||||
+851
-211
File diff suppressed because it is too large
Load Diff
@@ -14,7 +14,6 @@ import (
|
|||||||
retrievalmarket "github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
retrievalmarket "github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
||||||
storagemarket "github.com/filecoin-project/go-fil-markets/storagemarket"
|
storagemarket "github.com/filecoin-project/go-fil-markets/storagemarket"
|
||||||
auth "github.com/filecoin-project/go-jsonrpc/auth"
|
auth "github.com/filecoin-project/go-jsonrpc/auth"
|
||||||
multistore "github.com/filecoin-project/go-multistore"
|
|
||||||
abi "github.com/filecoin-project/go-state-types/abi"
|
abi "github.com/filecoin-project/go-state-types/abi"
|
||||||
big "github.com/filecoin-project/go-state-types/big"
|
big "github.com/filecoin-project/go-state-types/big"
|
||||||
crypto "github.com/filecoin-project/go-state-types/crypto"
|
crypto "github.com/filecoin-project/go-state-types/crypto"
|
||||||
@@ -26,6 +25,7 @@ import (
|
|||||||
types "github.com/filecoin-project/lotus/chain/types"
|
types "github.com/filecoin-project/lotus/chain/types"
|
||||||
marketevents "github.com/filecoin-project/lotus/markets/loggers"
|
marketevents "github.com/filecoin-project/lotus/markets/loggers"
|
||||||
dtypes "github.com/filecoin-project/lotus/node/modules/dtypes"
|
dtypes "github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||||
|
importmgr "github.com/filecoin-project/lotus/node/repo/importmgr"
|
||||||
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
||||||
paych "github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
paych "github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
@@ -194,6 +194,21 @@ func (mr *MockFullNodeMockRecorder) ChainGetMessage(arg0, arg1 interface{}) *gom
|
|||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainGetMessage", reflect.TypeOf((*MockFullNode)(nil).ChainGetMessage), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainGetMessage", reflect.TypeOf((*MockFullNode)(nil).ChainGetMessage), arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ChainGetMessagesInTipset mocks base method.
|
||||||
|
func (m *MockFullNode) ChainGetMessagesInTipset(arg0 context.Context, arg1 types.TipSetKey) ([]api.Message, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "ChainGetMessagesInTipset", arg0, arg1)
|
||||||
|
ret0, _ := ret[0].([]api.Message)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChainGetMessagesInTipset indicates an expected call of ChainGetMessagesInTipset.
|
||||||
|
func (mr *MockFullNodeMockRecorder) ChainGetMessagesInTipset(arg0, arg1 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainGetMessagesInTipset", reflect.TypeOf((*MockFullNode)(nil).ChainGetMessagesInTipset), arg0, arg1)
|
||||||
|
}
|
||||||
|
|
||||||
// ChainGetNode mocks base method.
|
// ChainGetNode mocks base method.
|
||||||
func (m *MockFullNode) ChainGetNode(arg0 context.Context, arg1 string) (*api.IpldObject, error) {
|
func (m *MockFullNode) ChainGetNode(arg0 context.Context, arg1 string) (*api.IpldObject, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
@@ -716,7 +731,7 @@ func (mr *MockFullNodeMockRecorder) ClientQueryAsk(arg0, arg1, arg2 interface{})
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ClientRemoveImport mocks base method.
|
// ClientRemoveImport mocks base method.
|
||||||
func (m *MockFullNode) ClientRemoveImport(arg0 context.Context, arg1 multistore.StoreID) error {
|
func (m *MockFullNode) ClientRemoveImport(arg0 context.Context, arg1 importmgr.ImportID) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "ClientRemoveImport", arg0, arg1)
|
ret := m.ctrl.Call(m, "ClientRemoveImport", arg0, arg1)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
|
|||||||
+3
-3
@@ -54,10 +54,10 @@ func VersionForType(nodeType NodeType) (Version, error) {
|
|||||||
|
|
||||||
// semver versions of the rpc api exposed
|
// semver versions of the rpc api exposed
|
||||||
var (
|
var (
|
||||||
FullAPIVersion0 = newVer(1, 3, 0)
|
FullAPIVersion0 = newVer(1, 3, 1)
|
||||||
FullAPIVersion1 = newVer(2, 1, 0)
|
FullAPIVersion1 = newVer(2, 1, 1)
|
||||||
|
|
||||||
MinerAPIVersion0 = newVer(1, 1, 0)
|
MinerAPIVersion0 = newVer(1, 2, 0)
|
||||||
WorkerAPIVersion0 = newVer(1, 1, 0)
|
WorkerAPIVersion0 = newVer(1, 1, 0)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+560
-71
@@ -4,11 +4,15 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sync/atomic"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/dgraph-io/badger/v2"
|
"github.com/dgraph-io/badger/v2"
|
||||||
"github.com/dgraph-io/badger/v2/options"
|
"github.com/dgraph-io/badger/v2/options"
|
||||||
|
"github.com/dgraph-io/badger/v2/pb"
|
||||||
"github.com/multiformats/go-base32"
|
"github.com/multiformats/go-base32"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
@@ -72,23 +76,45 @@ func (b *badgerLogger) Warningf(format string, args ...interface{}) {
|
|||||||
b.skip2.Warnf(format, args...)
|
b.skip2.Warnf(format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bsState is the current blockstore state
|
||||||
|
type bsState int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
stateOpen int64 = iota
|
// stateOpen signifies an open blockstore
|
||||||
|
stateOpen bsState = iota
|
||||||
|
// stateClosing signifies a blockstore that is currently closing
|
||||||
stateClosing
|
stateClosing
|
||||||
|
// stateClosed signifies a blockstore that has been colosed
|
||||||
stateClosed
|
stateClosed
|
||||||
)
|
)
|
||||||
|
|
||||||
// Blockstore is a badger-backed IPLD blockstore.
|
type bsMoveState int
|
||||||
//
|
|
||||||
// NOTE: once Close() is called, methods will try their best to return
|
|
||||||
// ErrBlockstoreClosed. This will guaranteed to happen for all subsequent
|
|
||||||
// operation calls after Close() has returned, but it may not happen for
|
|
||||||
// operations in progress. Those are likely to fail with a different error.
|
|
||||||
type Blockstore struct {
|
|
||||||
// state is accessed atomically
|
|
||||||
state int64
|
|
||||||
|
|
||||||
DB *badger.DB
|
const (
|
||||||
|
// moveStateNone signifies that there is no move in progress
|
||||||
|
moveStateNone bsMoveState = iota
|
||||||
|
// moveStateMoving signifies that there is a move in a progress
|
||||||
|
moveStateMoving
|
||||||
|
// moveStateCleanup signifies that a move has completed or aborted and we are cleaning up
|
||||||
|
moveStateCleanup
|
||||||
|
// moveStateLock signifies that an exclusive lock has been acquired
|
||||||
|
moveStateLock
|
||||||
|
)
|
||||||
|
|
||||||
|
// Blockstore is a badger-backed IPLD blockstore.
|
||||||
|
type Blockstore struct {
|
||||||
|
stateLk sync.RWMutex
|
||||||
|
state bsState
|
||||||
|
viewers sync.WaitGroup
|
||||||
|
|
||||||
|
moveMx sync.Mutex
|
||||||
|
moveCond sync.Cond
|
||||||
|
moveState bsMoveState
|
||||||
|
rlock int
|
||||||
|
|
||||||
|
db *badger.DB
|
||||||
|
dbNext *badger.DB // when moving
|
||||||
|
opts Options
|
||||||
|
|
||||||
prefixing bool
|
prefixing bool
|
||||||
prefix []byte
|
prefix []byte
|
||||||
@@ -97,6 +123,9 @@ type Blockstore struct {
|
|||||||
|
|
||||||
var _ blockstore.Blockstore = (*Blockstore)(nil)
|
var _ blockstore.Blockstore = (*Blockstore)(nil)
|
||||||
var _ blockstore.Viewer = (*Blockstore)(nil)
|
var _ blockstore.Viewer = (*Blockstore)(nil)
|
||||||
|
var _ blockstore.BlockstoreIterator = (*Blockstore)(nil)
|
||||||
|
var _ blockstore.BlockstoreGC = (*Blockstore)(nil)
|
||||||
|
var _ blockstore.BlockstoreSize = (*Blockstore)(nil)
|
||||||
var _ io.Closer = (*Blockstore)(nil)
|
var _ io.Closer = (*Blockstore)(nil)
|
||||||
|
|
||||||
// Open creates a new badger-backed blockstore, with the supplied options.
|
// Open creates a new badger-backed blockstore, with the supplied options.
|
||||||
@@ -111,73 +140,406 @@ func Open(opts Options) (*Blockstore, error) {
|
|||||||
return nil, fmt.Errorf("failed to open badger blockstore: %w", err)
|
return nil, fmt.Errorf("failed to open badger blockstore: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
bs := &Blockstore{DB: db}
|
bs := &Blockstore{db: db, opts: opts}
|
||||||
if p := opts.Prefix; p != "" {
|
if p := opts.Prefix; p != "" {
|
||||||
bs.prefixing = true
|
bs.prefixing = true
|
||||||
bs.prefix = []byte(p)
|
bs.prefix = []byte(p)
|
||||||
bs.prefixLen = len(bs.prefix)
|
bs.prefixLen = len(bs.prefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bs.moveCond.L = &bs.moveMx
|
||||||
|
|
||||||
return bs, nil
|
return bs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close closes the store. If the store has already been closed, this noops and
|
// Close closes the store. If the store has already been closed, this noops and
|
||||||
// returns an error, even if the first closure resulted in error.
|
// returns an error, even if the first closure resulted in error.
|
||||||
func (b *Blockstore) Close() error {
|
func (b *Blockstore) Close() error {
|
||||||
if !atomic.CompareAndSwapInt64(&b.state, stateOpen, stateClosing) {
|
b.stateLk.Lock()
|
||||||
|
if b.state != stateOpen {
|
||||||
|
b.stateLk.Unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
b.state = stateClosing
|
||||||
|
b.stateLk.Unlock()
|
||||||
|
|
||||||
defer atomic.StoreInt64(&b.state, stateClosed)
|
defer func() {
|
||||||
return b.DB.Close()
|
b.stateLk.Lock()
|
||||||
|
b.state = stateClosed
|
||||||
|
b.stateLk.Unlock()
|
||||||
|
}()
|
||||||
|
|
||||||
|
// wait for all accesses to complete
|
||||||
|
b.viewers.Wait()
|
||||||
|
|
||||||
|
return b.db.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// CollectGarbage runs garbage collection on the value log
|
func (b *Blockstore) access() error {
|
||||||
func (b *Blockstore) CollectGarbage() error {
|
b.stateLk.RLock()
|
||||||
if atomic.LoadInt64(&b.state) != stateOpen {
|
defer b.stateLk.RUnlock()
|
||||||
|
|
||||||
|
if b.state != stateOpen {
|
||||||
return ErrBlockstoreClosed
|
return ErrBlockstoreClosed
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
b.viewers.Add(1)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Blockstore) isOpen() bool {
|
||||||
|
b.stateLk.RLock()
|
||||||
|
defer b.stateLk.RUnlock()
|
||||||
|
|
||||||
|
return b.state == stateOpen
|
||||||
|
}
|
||||||
|
|
||||||
|
// lockDB/unlockDB implement a recursive lock contingent on move state
|
||||||
|
func (b *Blockstore) lockDB() {
|
||||||
|
b.moveMx.Lock()
|
||||||
|
defer b.moveMx.Unlock()
|
||||||
|
|
||||||
|
if b.rlock == 0 {
|
||||||
|
for b.moveState == moveStateLock {
|
||||||
|
b.moveCond.Wait()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b.rlock++
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Blockstore) unlockDB() {
|
||||||
|
b.moveMx.Lock()
|
||||||
|
defer b.moveMx.Unlock()
|
||||||
|
|
||||||
|
b.rlock--
|
||||||
|
if b.rlock == 0 && b.moveState == moveStateLock {
|
||||||
|
b.moveCond.Broadcast()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// lockMove/unlockMove implement an exclusive lock of move state
|
||||||
|
func (b *Blockstore) lockMove() {
|
||||||
|
b.moveMx.Lock()
|
||||||
|
b.moveState = moveStateLock
|
||||||
|
for b.rlock > 0 {
|
||||||
|
b.moveCond.Wait()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Blockstore) unlockMove(state bsMoveState) {
|
||||||
|
b.moveState = state
|
||||||
|
b.moveCond.Broadcast()
|
||||||
|
b.moveMx.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// movingGC moves the blockstore to a new path, adjacent to the current path, and creates
|
||||||
|
// a symlink from the current path to the new path; the old blockstore is deleted.
|
||||||
|
//
|
||||||
|
// The blockstore MUST accept new writes during the move and ensure that these
|
||||||
|
// are persisted to the new blockstore; if a failure occurs aboring the move,
|
||||||
|
// then they must be peristed to the old blockstore.
|
||||||
|
// In short, the blockstore must not lose data from new writes during the move.
|
||||||
|
func (b *Blockstore) movingGC() error {
|
||||||
|
// this inlines moveLock/moveUnlock for the initial state check to prevent a second move
|
||||||
|
// while one is in progress without clobbering state
|
||||||
|
b.moveMx.Lock()
|
||||||
|
if b.moveState != moveStateNone {
|
||||||
|
b.moveMx.Unlock()
|
||||||
|
return fmt.Errorf("move in progress")
|
||||||
|
}
|
||||||
|
|
||||||
|
b.moveState = moveStateLock
|
||||||
|
for b.rlock > 0 {
|
||||||
|
b.moveCond.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
b.moveState = moveStateMoving
|
||||||
|
b.moveCond.Broadcast()
|
||||||
|
b.moveMx.Unlock()
|
||||||
|
|
||||||
|
var newPath string
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
b.lockMove()
|
||||||
|
|
||||||
|
dbNext := b.dbNext
|
||||||
|
b.dbNext = nil
|
||||||
|
|
||||||
|
var state bsMoveState
|
||||||
|
if dbNext != nil {
|
||||||
|
state = moveStateCleanup
|
||||||
|
} else {
|
||||||
|
state = moveStateNone
|
||||||
|
}
|
||||||
|
|
||||||
|
b.unlockMove(state)
|
||||||
|
|
||||||
|
if dbNext != nil {
|
||||||
|
// the move failed and we have a left-over db; delete it.
|
||||||
|
err := dbNext.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("error closing badger db: %s", err)
|
||||||
|
}
|
||||||
|
b.deleteDB(newPath)
|
||||||
|
|
||||||
|
b.lockMove()
|
||||||
|
b.unlockMove(moveStateNone)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// we resolve symlinks to create the new path in the adjacent to the old path.
|
||||||
|
// this allows the user to symlink the db directory into a separate filesystem.
|
||||||
|
basePath := b.opts.Dir
|
||||||
|
linkPath, err := filepath.EvalSymlinks(basePath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error resolving symlink %s: %w", basePath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if basePath == linkPath {
|
||||||
|
newPath = basePath
|
||||||
|
} else {
|
||||||
|
// we do this dance to create a name adjacent to the current one, while avoiding clown
|
||||||
|
// shoes with multiple moves (i.e. we can't just take the basename of the linkPath, as it
|
||||||
|
// could have been created in a previous move and have the timestamp suffix, which would then
|
||||||
|
// perpetuate itself.
|
||||||
|
name := filepath.Base(basePath)
|
||||||
|
dir := filepath.Dir(linkPath)
|
||||||
|
newPath = filepath.Join(dir, name)
|
||||||
|
}
|
||||||
|
newPath = fmt.Sprintf("%s.%d", newPath, time.Now().UnixNano())
|
||||||
|
|
||||||
|
log.Infof("moving blockstore from %s to %s", b.opts.Dir, newPath)
|
||||||
|
|
||||||
|
opts := b.opts
|
||||||
|
opts.Dir = newPath
|
||||||
|
opts.ValueDir = newPath
|
||||||
|
|
||||||
|
dbNew, err := badger.Open(opts.Options)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to open badger blockstore in %s: %w", newPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.lockMove()
|
||||||
|
b.dbNext = dbNew
|
||||||
|
b.unlockMove(moveStateMoving)
|
||||||
|
|
||||||
|
log.Info("copying blockstore")
|
||||||
|
err = b.doCopy(b.db, b.dbNext)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error moving badger blockstore to %s: %w", newPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.lockMove()
|
||||||
|
dbOld := b.db
|
||||||
|
b.db = b.dbNext
|
||||||
|
b.dbNext = nil
|
||||||
|
b.unlockMove(moveStateCleanup)
|
||||||
|
|
||||||
|
err = dbOld.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("error closing old badger db: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is the canonical db path; this is where our db lives.
|
||||||
|
dbPath := b.opts.Dir
|
||||||
|
|
||||||
|
// we first move the existing db out of the way, and only delete it after we have symlinked the
|
||||||
|
// new db to the canonical path
|
||||||
|
backupPath := fmt.Sprintf("%s.old.%d", dbPath, time.Now().Unix())
|
||||||
|
if err = os.Rename(dbPath, backupPath); err != nil {
|
||||||
|
// this is not catastrophic in the sense that we have not lost any data.
|
||||||
|
// but it is pretty bad, as the db path points to the old db, while we are now using to the new
|
||||||
|
// db; we can't continue and leave a ticking bomb for the next restart.
|
||||||
|
// so a panic is appropriate and user can fix.
|
||||||
|
panic(fmt.Errorf("error renaming old badger db dir from %s to %s: %w; USER ACTION REQUIRED", dbPath, backupPath, err)) //nolint
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = symlink(newPath, dbPath); err != nil {
|
||||||
|
// same here; the db path is pointing to the void. panic and let the user fix.
|
||||||
|
panic(fmt.Errorf("error symlinking new badger db dir from %s to %s: %w; USER ACTION REQUIRED", newPath, dbPath, err)) //nolint
|
||||||
|
}
|
||||||
|
|
||||||
|
// the delete follows symlinks
|
||||||
|
b.deleteDB(backupPath)
|
||||||
|
|
||||||
|
log.Info("moving blockstore done")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// symlink creates a symlink from path to linkTo; the link is relative if the two are
|
||||||
|
// in the same directory
|
||||||
|
func symlink(path, linkTo string) error {
|
||||||
|
resolvedPathDir, err := filepath.EvalSymlinks(filepath.Dir(path))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error resolving links in %s: %w", path, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resolvedLinkDir, err := filepath.EvalSymlinks(filepath.Dir(linkTo))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error resolving links in %s: %w", linkTo, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if resolvedPathDir == resolvedLinkDir {
|
||||||
|
path = filepath.Base(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
return os.Symlink(path, linkTo)
|
||||||
|
}
|
||||||
|
|
||||||
|
// doCopy copies a badger blockstore to another, with an optional filter; if the filter
|
||||||
|
// is not nil, then only cids that satisfy the filter will be copied.
|
||||||
|
func (b *Blockstore) doCopy(from, to *badger.DB) error {
|
||||||
|
workers := runtime.NumCPU() / 2
|
||||||
|
if workers < 2 {
|
||||||
|
workers = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
stream := from.NewStream()
|
||||||
|
stream.NumGo = workers
|
||||||
|
stream.LogPrefix = "doCopy"
|
||||||
|
stream.Send = func(list *pb.KVList) error {
|
||||||
|
batch := to.NewWriteBatch()
|
||||||
|
defer batch.Cancel()
|
||||||
|
|
||||||
|
for _, kv := range list.Kv {
|
||||||
|
if kv.Key == nil || kv.Value == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err := batch.Set(kv.Key, kv.Value); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return batch.Flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
return stream.Orchestrate(context.Background())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Blockstore) deleteDB(path string) {
|
||||||
|
// follow symbolic links, otherwise the data wil be left behind
|
||||||
|
linkPath, err := filepath.EvalSymlinks(path)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("error resolving symlinks in %s", path)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof("removing data directory %s", linkPath)
|
||||||
|
if err := os.RemoveAll(linkPath); err != nil {
|
||||||
|
log.Warnf("error deleting db at %s: %s", linkPath, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if path != linkPath {
|
||||||
|
log.Infof("removing link %s", path)
|
||||||
|
if err := os.Remove(path); err != nil {
|
||||||
|
log.Warnf("error removing symbolic link %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Blockstore) onlineGC() error {
|
||||||
|
b.lockDB()
|
||||||
|
defer b.unlockDB()
|
||||||
|
|
||||||
|
// compact first to gather the necessary statistics for GC
|
||||||
|
nworkers := runtime.NumCPU() / 2
|
||||||
|
if nworkers < 2 {
|
||||||
|
nworkers = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
err := b.db.Flatten(nworkers)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
for err == nil {
|
for err == nil {
|
||||||
err = b.DB.RunValueLogGC(0.125)
|
err = b.db.RunValueLogGC(0.125)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err == badger.ErrNoRewrite {
|
if err == badger.ErrNoRewrite {
|
||||||
// not really an error in this case
|
// not really an error in this case, it signals the end of GC
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compact runs a synchronous compaction
|
// CollectGarbage compacts and runs garbage collection on the value log;
|
||||||
func (b *Blockstore) Compact() error {
|
// implements the BlockstoreGC trait
|
||||||
if atomic.LoadInt64(&b.state) != stateOpen {
|
func (b *Blockstore) CollectGarbage(opts ...blockstore.BlockstoreGCOption) error {
|
||||||
return ErrBlockstoreClosed
|
if err := b.access(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer b.viewers.Done()
|
||||||
|
|
||||||
|
var options blockstore.BlockstoreGCOptions
|
||||||
|
for _, opt := range opts {
|
||||||
|
err := opt(&options)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nworkers := runtime.NumCPU() / 2
|
if options.FullGC {
|
||||||
if nworkers < 2 {
|
return b.movingGC()
|
||||||
nworkers = 2
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return b.DB.Flatten(nworkers)
|
return b.onlineGC()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns the aggregate size of the blockstore
|
||||||
|
func (b *Blockstore) Size() (int64, error) {
|
||||||
|
if err := b.access(); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
defer b.viewers.Done()
|
||||||
|
|
||||||
|
b.lockDB()
|
||||||
|
defer b.unlockDB()
|
||||||
|
|
||||||
|
lsm, vlog := b.db.Size()
|
||||||
|
size := lsm + vlog
|
||||||
|
|
||||||
|
if size == 0 {
|
||||||
|
// badger reports a 0 size on symlinked directories... sigh
|
||||||
|
dir := b.opts.Dir
|
||||||
|
entries, err := os.ReadDir(dir)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, e := range entries {
|
||||||
|
path := filepath.Join(dir, e.Name())
|
||||||
|
finfo, err := os.Stat(path)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
size += finfo.Size()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return size, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// View implements blockstore.Viewer, which leverages zero-copy read-only
|
// View implements blockstore.Viewer, which leverages zero-copy read-only
|
||||||
// access to values.
|
// access to values.
|
||||||
func (b *Blockstore) View(cid cid.Cid, fn func([]byte) error) error {
|
func (b *Blockstore) View(cid cid.Cid, fn func([]byte) error) error {
|
||||||
if atomic.LoadInt64(&b.state) != stateOpen {
|
if err := b.access(); err != nil {
|
||||||
return ErrBlockstoreClosed
|
return err
|
||||||
}
|
}
|
||||||
|
defer b.viewers.Done()
|
||||||
|
|
||||||
|
b.lockDB()
|
||||||
|
defer b.unlockDB()
|
||||||
|
|
||||||
k, pooled := b.PooledStorageKey(cid)
|
k, pooled := b.PooledStorageKey(cid)
|
||||||
if pooled {
|
if pooled {
|
||||||
defer KeyPool.Put(k)
|
defer KeyPool.Put(k)
|
||||||
}
|
}
|
||||||
|
|
||||||
return b.DB.View(func(txn *badger.Txn) error {
|
return b.db.View(func(txn *badger.Txn) error {
|
||||||
switch item, err := txn.Get(k); err {
|
switch item, err := txn.Get(k); err {
|
||||||
case nil:
|
case nil:
|
||||||
return item.Value(fn)
|
return item.Value(fn)
|
||||||
@@ -191,16 +553,20 @@ func (b *Blockstore) View(cid cid.Cid, fn func([]byte) error) error {
|
|||||||
|
|
||||||
// Has implements Blockstore.Has.
|
// Has implements Blockstore.Has.
|
||||||
func (b *Blockstore) Has(cid cid.Cid) (bool, error) {
|
func (b *Blockstore) Has(cid cid.Cid) (bool, error) {
|
||||||
if atomic.LoadInt64(&b.state) != stateOpen {
|
if err := b.access(); err != nil {
|
||||||
return false, ErrBlockstoreClosed
|
return false, err
|
||||||
}
|
}
|
||||||
|
defer b.viewers.Done()
|
||||||
|
|
||||||
|
b.lockDB()
|
||||||
|
defer b.unlockDB()
|
||||||
|
|
||||||
k, pooled := b.PooledStorageKey(cid)
|
k, pooled := b.PooledStorageKey(cid)
|
||||||
if pooled {
|
if pooled {
|
||||||
defer KeyPool.Put(k)
|
defer KeyPool.Put(k)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := b.DB.View(func(txn *badger.Txn) error {
|
err := b.db.View(func(txn *badger.Txn) error {
|
||||||
_, err := txn.Get(k)
|
_, err := txn.Get(k)
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
@@ -221,9 +587,13 @@ func (b *Blockstore) Get(cid cid.Cid) (blocks.Block, error) {
|
|||||||
return nil, blockstore.ErrNotFound
|
return nil, blockstore.ErrNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
if atomic.LoadInt64(&b.state) != stateOpen {
|
if err := b.access(); err != nil {
|
||||||
return nil, ErrBlockstoreClosed
|
return nil, err
|
||||||
}
|
}
|
||||||
|
defer b.viewers.Done()
|
||||||
|
|
||||||
|
b.lockDB()
|
||||||
|
defer b.unlockDB()
|
||||||
|
|
||||||
k, pooled := b.PooledStorageKey(cid)
|
k, pooled := b.PooledStorageKey(cid)
|
||||||
if pooled {
|
if pooled {
|
||||||
@@ -231,7 +601,7 @@ func (b *Blockstore) Get(cid cid.Cid) (blocks.Block, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var val []byte
|
var val []byte
|
||||||
err := b.DB.View(func(txn *badger.Txn) error {
|
err := b.db.View(func(txn *badger.Txn) error {
|
||||||
switch item, err := txn.Get(k); err {
|
switch item, err := txn.Get(k); err {
|
||||||
case nil:
|
case nil:
|
||||||
val, err = item.ValueCopy(nil)
|
val, err = item.ValueCopy(nil)
|
||||||
@@ -250,9 +620,13 @@ func (b *Blockstore) Get(cid cid.Cid) (blocks.Block, error) {
|
|||||||
|
|
||||||
// GetSize implements Blockstore.GetSize.
|
// GetSize implements Blockstore.GetSize.
|
||||||
func (b *Blockstore) GetSize(cid cid.Cid) (int, error) {
|
func (b *Blockstore) GetSize(cid cid.Cid) (int, error) {
|
||||||
if atomic.LoadInt64(&b.state) != stateOpen {
|
if err := b.access(); err != nil {
|
||||||
return -1, ErrBlockstoreClosed
|
return 0, err
|
||||||
}
|
}
|
||||||
|
defer b.viewers.Done()
|
||||||
|
|
||||||
|
b.lockDB()
|
||||||
|
defer b.unlockDB()
|
||||||
|
|
||||||
k, pooled := b.PooledStorageKey(cid)
|
k, pooled := b.PooledStorageKey(cid)
|
||||||
if pooled {
|
if pooled {
|
||||||
@@ -260,7 +634,7 @@ func (b *Blockstore) GetSize(cid cid.Cid) (int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var size int
|
var size int
|
||||||
err := b.DB.View(func(txn *badger.Txn) error {
|
err := b.db.View(func(txn *badger.Txn) error {
|
||||||
switch item, err := txn.Get(k); err {
|
switch item, err := txn.Get(k); err {
|
||||||
case nil:
|
case nil:
|
||||||
size = int(item.ValueSize())
|
size = int(item.ValueSize())
|
||||||
@@ -279,29 +653,52 @@ func (b *Blockstore) GetSize(cid cid.Cid) (int, error) {
|
|||||||
|
|
||||||
// Put implements Blockstore.Put.
|
// Put implements Blockstore.Put.
|
||||||
func (b *Blockstore) Put(block blocks.Block) error {
|
func (b *Blockstore) Put(block blocks.Block) error {
|
||||||
if atomic.LoadInt64(&b.state) != stateOpen {
|
if err := b.access(); err != nil {
|
||||||
return ErrBlockstoreClosed
|
return err
|
||||||
}
|
}
|
||||||
|
defer b.viewers.Done()
|
||||||
|
|
||||||
|
b.lockDB()
|
||||||
|
defer b.unlockDB()
|
||||||
|
|
||||||
k, pooled := b.PooledStorageKey(block.Cid())
|
k, pooled := b.PooledStorageKey(block.Cid())
|
||||||
if pooled {
|
if pooled {
|
||||||
defer KeyPool.Put(k)
|
defer KeyPool.Put(k)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := b.DB.Update(func(txn *badger.Txn) error {
|
put := func(db *badger.DB) error {
|
||||||
return txn.Set(k, block.RawData())
|
err := db.Update(func(txn *badger.Txn) error {
|
||||||
})
|
return txn.Set(k, block.RawData())
|
||||||
if err != nil {
|
})
|
||||||
err = fmt.Errorf("failed to put block in badger blockstore: %w", err)
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to put block in badger blockstore: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
return err
|
|
||||||
|
if err := put(b.db); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.dbNext != nil {
|
||||||
|
if err := put(b.dbNext); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PutMany implements Blockstore.PutMany.
|
// PutMany implements Blockstore.PutMany.
|
||||||
func (b *Blockstore) PutMany(blocks []blocks.Block) error {
|
func (b *Blockstore) PutMany(blocks []blocks.Block) error {
|
||||||
if atomic.LoadInt64(&b.state) != stateOpen {
|
if err := b.access(); err != nil {
|
||||||
return ErrBlockstoreClosed
|
return err
|
||||||
}
|
}
|
||||||
|
defer b.viewers.Done()
|
||||||
|
|
||||||
|
b.lockDB()
|
||||||
|
defer b.unlockDB()
|
||||||
|
|
||||||
// toReturn tracks the byte slices to return to the pool, if we're using key
|
// toReturn tracks the byte slices to return to the pool, if we're using key
|
||||||
// prefixing. we can't return each slice to the pool after each Set, because
|
// prefixing. we can't return each slice to the pool after each Set, because
|
||||||
@@ -316,46 +713,75 @@ func (b *Blockstore) PutMany(blocks []blocks.Block) error {
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
batch := b.DB.NewWriteBatch()
|
keys := make([][]byte, 0, len(blocks))
|
||||||
defer batch.Cancel()
|
|
||||||
|
|
||||||
for _, block := range blocks {
|
for _, block := range blocks {
|
||||||
k, pooled := b.PooledStorageKey(block.Cid())
|
k, pooled := b.PooledStorageKey(block.Cid())
|
||||||
if pooled {
|
if pooled {
|
||||||
toReturn = append(toReturn, k)
|
toReturn = append(toReturn, k)
|
||||||
}
|
}
|
||||||
if err := batch.Set(k, block.RawData()); err != nil {
|
keys = append(keys, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
put := func(db *badger.DB) error {
|
||||||
|
batch := db.NewWriteBatch()
|
||||||
|
defer batch.Cancel()
|
||||||
|
|
||||||
|
for i, block := range blocks {
|
||||||
|
k := keys[i]
|
||||||
|
if err := batch.Set(k, block.RawData()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err := batch.Flush()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to put blocks in badger blockstore: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := put(b.db); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.dbNext != nil {
|
||||||
|
if err := put(b.dbNext); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err := batch.Flush()
|
return nil
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("failed to put blocks in badger blockstore: %w", err)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteBlock implements Blockstore.DeleteBlock.
|
// DeleteBlock implements Blockstore.DeleteBlock.
|
||||||
func (b *Blockstore) DeleteBlock(cid cid.Cid) error {
|
func (b *Blockstore) DeleteBlock(cid cid.Cid) error {
|
||||||
if atomic.LoadInt64(&b.state) != stateOpen {
|
if err := b.access(); err != nil {
|
||||||
return ErrBlockstoreClosed
|
return err
|
||||||
}
|
}
|
||||||
|
defer b.viewers.Done()
|
||||||
|
|
||||||
|
b.lockDB()
|
||||||
|
defer b.unlockDB()
|
||||||
|
|
||||||
k, pooled := b.PooledStorageKey(cid)
|
k, pooled := b.PooledStorageKey(cid)
|
||||||
if pooled {
|
if pooled {
|
||||||
defer KeyPool.Put(k)
|
defer KeyPool.Put(k)
|
||||||
}
|
}
|
||||||
|
|
||||||
return b.DB.Update(func(txn *badger.Txn) error {
|
return b.db.Update(func(txn *badger.Txn) error {
|
||||||
return txn.Delete(k)
|
return txn.Delete(k)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Blockstore) DeleteMany(cids []cid.Cid) error {
|
func (b *Blockstore) DeleteMany(cids []cid.Cid) error {
|
||||||
if atomic.LoadInt64(&b.state) != stateOpen {
|
if err := b.access(); err != nil {
|
||||||
return ErrBlockstoreClosed
|
return err
|
||||||
}
|
}
|
||||||
|
defer b.viewers.Done()
|
||||||
|
|
||||||
|
b.lockDB()
|
||||||
|
defer b.unlockDB()
|
||||||
|
|
||||||
// toReturn tracks the byte slices to return to the pool, if we're using key
|
// toReturn tracks the byte slices to return to the pool, if we're using key
|
||||||
// prefixing. we can't return each slice to the pool after each Set, because
|
// prefixing. we can't return each slice to the pool after each Set, because
|
||||||
@@ -370,7 +796,7 @@ func (b *Blockstore) DeleteMany(cids []cid.Cid) error {
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
batch := b.DB.NewWriteBatch()
|
batch := b.db.NewWriteBatch()
|
||||||
defer batch.Cancel()
|
defer batch.Cancel()
|
||||||
|
|
||||||
for _, cid := range cids {
|
for _, cid := range cids {
|
||||||
@@ -392,11 +818,14 @@ func (b *Blockstore) DeleteMany(cids []cid.Cid) error {
|
|||||||
|
|
||||||
// AllKeysChan implements Blockstore.AllKeysChan.
|
// AllKeysChan implements Blockstore.AllKeysChan.
|
||||||
func (b *Blockstore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
|
func (b *Blockstore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
|
||||||
if atomic.LoadInt64(&b.state) != stateOpen {
|
if err := b.access(); err != nil {
|
||||||
return nil, ErrBlockstoreClosed
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
txn := b.DB.NewTransaction(false)
|
b.lockDB()
|
||||||
|
defer b.unlockDB()
|
||||||
|
|
||||||
|
txn := b.db.NewTransaction(false)
|
||||||
opts := badger.IteratorOptions{PrefetchSize: 100}
|
opts := badger.IteratorOptions{PrefetchSize: 100}
|
||||||
if b.prefixing {
|
if b.prefixing {
|
||||||
opts.Prefix = b.prefix
|
opts.Prefix = b.prefix
|
||||||
@@ -405,6 +834,7 @@ func (b *Blockstore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
|
|||||||
|
|
||||||
ch := make(chan cid.Cid)
|
ch := make(chan cid.Cid)
|
||||||
go func() {
|
go func() {
|
||||||
|
defer b.viewers.Done()
|
||||||
defer close(ch)
|
defer close(ch)
|
||||||
defer iter.Close()
|
defer iter.Close()
|
||||||
|
|
||||||
@@ -415,7 +845,7 @@ func (b *Blockstore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
|
|||||||
if ctx.Err() != nil {
|
if ctx.Err() != nil {
|
||||||
return // context has fired.
|
return // context has fired.
|
||||||
}
|
}
|
||||||
if atomic.LoadInt64(&b.state) != stateOpen {
|
if !b.isOpen() {
|
||||||
// open iterators will run even after the database is closed...
|
// open iterators will run even after the database is closed...
|
||||||
return // closing, yield.
|
return // closing, yield.
|
||||||
}
|
}
|
||||||
@@ -442,6 +872,59 @@ func (b *Blockstore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
|
|||||||
return ch, nil
|
return ch, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Implementation of BlockstoreIterator interface
|
||||||
|
func (b *Blockstore) ForEachKey(f func(cid.Cid) error) error {
|
||||||
|
if err := b.access(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer b.viewers.Done()
|
||||||
|
|
||||||
|
b.lockDB()
|
||||||
|
defer b.unlockDB()
|
||||||
|
|
||||||
|
txn := b.db.NewTransaction(false)
|
||||||
|
defer txn.Discard()
|
||||||
|
|
||||||
|
opts := badger.IteratorOptions{PrefetchSize: 100}
|
||||||
|
if b.prefixing {
|
||||||
|
opts.Prefix = b.prefix
|
||||||
|
}
|
||||||
|
|
||||||
|
iter := txn.NewIterator(opts)
|
||||||
|
defer iter.Close()
|
||||||
|
|
||||||
|
var buf []byte
|
||||||
|
for iter.Rewind(); iter.Valid(); iter.Next() {
|
||||||
|
if !b.isOpen() {
|
||||||
|
return ErrBlockstoreClosed
|
||||||
|
}
|
||||||
|
|
||||||
|
k := iter.Item().Key()
|
||||||
|
if b.prefixing {
|
||||||
|
k = k[b.prefixLen:]
|
||||||
|
}
|
||||||
|
|
||||||
|
klen := base32.RawStdEncoding.DecodedLen(len(k))
|
||||||
|
if klen > len(buf) {
|
||||||
|
buf = make([]byte, klen)
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err := base32.RawStdEncoding.Decode(buf, k)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c := cid.NewCidV1(cid.Raw, buf[:n])
|
||||||
|
|
||||||
|
err = f(c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// HashOnRead implements Blockstore.HashOnRead. It is not supported by this
|
// HashOnRead implements Blockstore.HashOnRead. It is not supported by this
|
||||||
// blockstore.
|
// blockstore.
|
||||||
func (b *Blockstore) HashOnRead(_ bool) {
|
func (b *Blockstore) HashOnRead(_ bool) {
|
||||||
@@ -494,3 +977,9 @@ func (b *Blockstore) StorageKey(dst []byte, cid cid.Cid) []byte {
|
|||||||
}
|
}
|
||||||
return dst[:reqsize]
|
return dst[:reqsize]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this method is added for lotus-shed needs
|
||||||
|
// WARNING: THIS IS COMPLETELY UNSAFE; DONT USE THIS IN PRODUCTION CODE
|
||||||
|
func (b *Blockstore) DB() *badger.DB {
|
||||||
|
return b.db
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,12 +1,19 @@
|
|||||||
package badgerbs
|
package badgerbs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
blocks "github.com/ipfs/go-block-format"
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
|
||||||
|
blocks "github.com/ipfs/go-block-format"
|
||||||
|
cid "github.com/ipfs/go-cid"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/blockstore"
|
"github.com/filecoin-project/lotus/blockstore"
|
||||||
)
|
)
|
||||||
@@ -89,3 +96,180 @@ func openBlockstore(optsSupplier func(path string) Options) func(tb testing.TB,
|
|||||||
return Open(optsSupplier(path))
|
return Open(optsSupplier(path))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testMove(t *testing.T, optsF func(string) Options) {
|
||||||
|
basePath, err := ioutil.TempDir("", "")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dbPath := filepath.Join(basePath, "db")
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
_ = os.RemoveAll(basePath)
|
||||||
|
})
|
||||||
|
|
||||||
|
db, err := Open(optsF(dbPath))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer db.Close() //nolint
|
||||||
|
|
||||||
|
var have []blocks.Block
|
||||||
|
var deleted []cid.Cid
|
||||||
|
|
||||||
|
// add some blocks
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
blk := blocks.NewBlock([]byte(fmt.Sprintf("some data %d", i)))
|
||||||
|
err := db.Put(blk)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
have = append(have, blk)
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete some of them
|
||||||
|
for i := 5; i < 10; i++ {
|
||||||
|
c := have[i].Cid()
|
||||||
|
err := db.DeleteBlock(c)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
deleted = append(deleted, c)
|
||||||
|
}
|
||||||
|
have = have[:5]
|
||||||
|
|
||||||
|
// start a move concurrent with some more puts
|
||||||
|
g := new(errgroup.Group)
|
||||||
|
g.Go(func() error {
|
||||||
|
for i := 10; i < 1000; i++ {
|
||||||
|
blk := blocks.NewBlock([]byte(fmt.Sprintf("some data %d", i)))
|
||||||
|
err := db.Put(blk)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
have = append(have, blk)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
g.Go(func() error {
|
||||||
|
return db.CollectGarbage(blockstore.WithFullGC(true))
|
||||||
|
})
|
||||||
|
|
||||||
|
err = g.Wait()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// now check that we have all the blocks in have and none in the deleted lists
|
||||||
|
checkBlocks := func() {
|
||||||
|
for _, blk := range have {
|
||||||
|
has, err := db.Has(blk.Cid())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !has {
|
||||||
|
t.Fatal("missing block")
|
||||||
|
}
|
||||||
|
|
||||||
|
blk2, err := db.Get(blk.Cid())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bytes.Equal(blk.RawData(), blk2.RawData()) {
|
||||||
|
t.Fatal("data mismatch")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range deleted {
|
||||||
|
has, err := db.Has(c)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if has {
|
||||||
|
t.Fatal("resurrected block")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkBlocks()
|
||||||
|
|
||||||
|
// check the basePath -- it should contain a directory with name db.{timestamp}, soft-linked
|
||||||
|
// to db and nothing else
|
||||||
|
checkPath := func() {
|
||||||
|
entries, err := os.ReadDir(basePath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(entries) != 2 {
|
||||||
|
t.Fatalf("too many entries; expected %d but got %d", 2, len(entries))
|
||||||
|
}
|
||||||
|
|
||||||
|
var haveDB, haveDBLink bool
|
||||||
|
for _, e := range entries {
|
||||||
|
if e.Name() == "db" {
|
||||||
|
if (e.Type() & os.ModeSymlink) == 0 {
|
||||||
|
t.Fatal("found db, but it's not a symlink")
|
||||||
|
}
|
||||||
|
haveDBLink = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(e.Name(), "db.") {
|
||||||
|
if !e.Type().IsDir() {
|
||||||
|
t.Fatal("found db prefix, but it's not a directory")
|
||||||
|
}
|
||||||
|
haveDB = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !haveDB {
|
||||||
|
t.Fatal("db directory is missing")
|
||||||
|
}
|
||||||
|
if !haveDBLink {
|
||||||
|
t.Fatal("db link is missing")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkPath()
|
||||||
|
|
||||||
|
// now do another FullGC to test the double move and following of symlinks
|
||||||
|
if err := db.CollectGarbage(blockstore.WithFullGC(true)); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
checkBlocks()
|
||||||
|
checkPath()
|
||||||
|
|
||||||
|
// reopen the db to make sure our relative link works:
|
||||||
|
err = db.Close()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
db, err = Open(optsF(dbPath))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// db.Close() is already deferred
|
||||||
|
|
||||||
|
checkBlocks()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMoveNoPrefix(t *testing.T) {
|
||||||
|
testMove(t, DefaultOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMoveWithPrefix(t *testing.T) {
|
||||||
|
testMove(t, func(path string) Options {
|
||||||
|
opts := DefaultOptions(path)
|
||||||
|
opts.Prefix = "/prefixed/"
|
||||||
|
return opts
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -30,6 +30,36 @@ type BatchDeleter interface {
|
|||||||
DeleteMany(cids []cid.Cid) error
|
DeleteMany(cids []cid.Cid) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BlockstoreIterator is a trait for efficient iteration
|
||||||
|
type BlockstoreIterator interface {
|
||||||
|
ForEachKey(func(cid.Cid) error) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlockstoreGC is a trait for blockstores that support online garbage collection
|
||||||
|
type BlockstoreGC interface {
|
||||||
|
CollectGarbage(options ...BlockstoreGCOption) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlockstoreGCOption is a functional interface for controlling blockstore GC options
|
||||||
|
type BlockstoreGCOption = func(*BlockstoreGCOptions) error
|
||||||
|
|
||||||
|
// BlockstoreGCOptions is a struct with GC options
|
||||||
|
type BlockstoreGCOptions struct {
|
||||||
|
FullGC bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithFullGC(fullgc bool) BlockstoreGCOption {
|
||||||
|
return func(opts *BlockstoreGCOptions) error {
|
||||||
|
opts.FullGC = fullgc
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlockstoreSize is a trait for on-disk blockstores that can report their size
|
||||||
|
type BlockstoreSize interface {
|
||||||
|
Size() (int64, error)
|
||||||
|
}
|
||||||
|
|
||||||
// WrapIDStore wraps the underlying blockstore in an "identity" blockstore.
|
// WrapIDStore wraps the underlying blockstore in an "identity" blockstore.
|
||||||
// The ID store filters out all puts for blocks with CIDs using the "identity"
|
// The ID store filters out all puts for blocks with CIDs using the "identity"
|
||||||
// hash function. It also extracts inlined blocks from CIDs using the identity
|
// hash function. It also extracts inlined blocks from CIDs using the identity
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package blockstore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
blocks "github.com/ipfs/go-block-format"
|
||||||
|
cid "github.com/ipfs/go-cid"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ Blockstore = (*discardstore)(nil)
|
||||||
|
|
||||||
|
type discardstore struct {
|
||||||
|
bs Blockstore
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDiscardStore(bs Blockstore) Blockstore {
|
||||||
|
return &discardstore{bs: bs}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *discardstore) Has(cid cid.Cid) (bool, error) {
|
||||||
|
return b.bs.Has(cid)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *discardstore) HashOnRead(hor bool) {
|
||||||
|
b.bs.HashOnRead(hor)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *discardstore) Get(cid cid.Cid) (blocks.Block, error) {
|
||||||
|
return b.bs.Get(cid)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *discardstore) GetSize(cid cid.Cid) (int, error) {
|
||||||
|
return b.bs.GetSize(cid)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *discardstore) View(cid cid.Cid, f func([]byte) error) error {
|
||||||
|
return b.bs.View(cid, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *discardstore) Put(blk blocks.Block) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *discardstore) PutMany(blks []blocks.Block) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *discardstore) DeleteBlock(cid cid.Cid) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *discardstore) DeleteMany(cids []cid.Cid) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *discardstore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
|
||||||
|
return b.bs.AllKeysChan(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *discardstore) Close() error {
|
||||||
|
if c, ok := b.bs.(io.Closer); ok {
|
||||||
|
return c.Close()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
# SplitStore: An actively scalable blockstore for the Filecoin chain
|
||||||
|
|
||||||
|
The SplitStore was first introduced in lotus v1.5.1, as an experiment
|
||||||
|
in reducing the performance impact of large blockstores.
|
||||||
|
|
||||||
|
With lotus v1.11.1, we introduce the next iteration in design and
|
||||||
|
implementation, which we call SplitStore v1.
|
||||||
|
|
||||||
|
The new design (see [#6474](https://github.com/filecoin-project/lotus/pull/6474)
|
||||||
|
evolves the splitstore to be a freestanding compacting blockstore that
|
||||||
|
allows us to keep a small (60-100GB) working set in a hot blockstore
|
||||||
|
and reliably archive out of scope objects in a coldstore. The
|
||||||
|
coldstore can also be a discard store, whereby out of scope objects
|
||||||
|
are discarded or a regular badger blockstore (the default), which can
|
||||||
|
be periodically garbage collected according to configurable user
|
||||||
|
retention policies.
|
||||||
|
|
||||||
|
To enable the splitstore, edit `.lotus/config.toml` and add the following:
|
||||||
|
```
|
||||||
|
[Chainstore]
|
||||||
|
EnableSplitstore = true
|
||||||
|
```
|
||||||
|
|
||||||
|
If you intend to use the discard coldstore, your also need to add the following:
|
||||||
|
```
|
||||||
|
[Chainstore.Splitstore]
|
||||||
|
ColdStoreType = "discard"
|
||||||
|
```
|
||||||
|
In general you _should not_ have to use the discard store, unless you
|
||||||
|
are running a network assistive node (like a bootstrapper or booster)
|
||||||
|
or have very constrained hardware with not enough disk space to
|
||||||
|
maintain a coldstore, even with garbage collection. It is also appropriate
|
||||||
|
for small nodes that are simply watching the chain.
|
||||||
|
|
||||||
|
*Warning:* Using the discard store for a general purpose node is discouraged, unless
|
||||||
|
you really know what you are doing. Use it at your own risk.
|
||||||
|
|
||||||
|
## Configuration Options
|
||||||
|
|
||||||
|
These are options in the `[Chainstore.Splitstore]` section of the configuration:
|
||||||
|
|
||||||
|
- `HotStoreType` -- specifies the type of hotstore to use.
|
||||||
|
The only currently supported option is `"badger"`.
|
||||||
|
- `ColdStoreType` -- specifies the type of coldstore to use.
|
||||||
|
The default value is `"universal"`, which will use the initial monolith blockstore
|
||||||
|
as the coldstore.
|
||||||
|
The other possible value is `"discard"`, as outlined above, which is specialized for
|
||||||
|
running without a coldstore. Note that the discard store wraps the initial monolith
|
||||||
|
blockstore and discards writes; this is necessary to support syncing from a snapshot.
|
||||||
|
- `MarkSetType` -- specifies the type of markset to use during compaction.
|
||||||
|
The markset is the data structure used by compaction/gc to track live objects.
|
||||||
|
The default value is `"map"`, which will use an in-memory map; if you are limited
|
||||||
|
in memory (or indeed see compaction run out of memory), you can also specify
|
||||||
|
`"badger"` which will use an disk backed markset, using badger. This will use
|
||||||
|
much less memory, but will also make compaction slower.
|
||||||
|
- `HotStoreMessageRetention` -- specifies how many finalities, beyond the 4
|
||||||
|
finalities maintained by default, to maintain messages and message receipts in the
|
||||||
|
hotstore. This is useful for assistive nodes that want to support syncing for other
|
||||||
|
nodes beyond 4 finalities, while running with the discard coldstore option.
|
||||||
|
It is also useful for miners who accept deals and need to lookback messages beyond
|
||||||
|
the 4 finalities, which would otherwise hit the coldstore.
|
||||||
|
- `HotStoreFullGCFrequency` -- specifies how frequenty to garbage collect the hotstore
|
||||||
|
using full (moving) GC.
|
||||||
|
The default value is 20, which uses full GC every 20 compactions (about once a week);
|
||||||
|
set to 0 to disable full GC altogether.
|
||||||
|
Rationale: badger supports online GC, and this is used by default. However it has proven to
|
||||||
|
be ineffective in practice with the hotstore size slowly creeping up. In order to address this,
|
||||||
|
we have added moving GC support in our badger wrapper, which can effectively reclaim all space.
|
||||||
|
The downside is that it takes a bit longer to perform a moving GC and you also need enough
|
||||||
|
space to house the new hotstore while the old one is still live.
|
||||||
|
|
||||||
|
|
||||||
|
## Operation
|
||||||
|
|
||||||
|
When the splitstore is first enabled, the existing blockstore becomes
|
||||||
|
the coldstore and a fresh hotstore is initialized.
|
||||||
|
|
||||||
|
The hotstore is warmed up on first startup so as to load all chain
|
||||||
|
headers and state roots in the current head. This allows us to
|
||||||
|
immediately gain the performance benefits of a smallerblockstore which
|
||||||
|
can be substantial for full archival nodes.
|
||||||
|
|
||||||
|
All new writes are directed to the hotstore, while reads first hit the
|
||||||
|
hotstore, with fallback to the coldstore.
|
||||||
|
|
||||||
|
Once 5 finalities have ellapsed, and every finality henceforth, the
|
||||||
|
blockstore _compacts_. Compaction is the process of moving all
|
||||||
|
unreachable objects within the last 4 finalities from the hotstore to
|
||||||
|
the coldstore. If the system is configured with a discard coldstore,
|
||||||
|
these objects are discarded. Note that chain headers, all the way to
|
||||||
|
genesis, are considered reachable. Stateroots and messages are
|
||||||
|
considered reachable only within the last 4 finalities, unless there
|
||||||
|
is a live reference to them.
|
||||||
|
|
||||||
|
## Compaction
|
||||||
|
|
||||||
|
Compaction works transactionally with the following algorithm:
|
||||||
|
- We prepare a transaction, whereby all i/o referenced objects through the API are tracked.
|
||||||
|
- We walk the chain and mark reachable objects, keeping 4 finalities of state roots and messages and all headers all the way to genesis.
|
||||||
|
- Once the chain walk is complete, we begin full transaction protection with concurrent marking; we walk and mark all references created during the chain walk. On the same time, all I/O through the API concurrently marks objects as live references.
|
||||||
|
- We collect cold objects by iterating through the hotstore and checking the mark set; if an object is not marked, then it is candidate for purge.
|
||||||
|
- When running with a coldstore, we next copy all cold objects to the coldstore.
|
||||||
|
- At this point we are ready to begin purging:
|
||||||
|
- We sort cold objects heaviest first, so as to never delete the consituents of a DAG before the DAG itself (which would leave dangling references)
|
||||||
|
- We delete in small batches taking a lock; each batch is checked again for marks, from the concurrent transactional mark, so as to never delete anything live
|
||||||
|
- We then end the transaction and compact/gc the hotstore.
|
||||||
|
|
||||||
|
## Garbage Collection
|
||||||
|
|
||||||
|
TBD -- see [#6577](https://github.com/filecoin-project/lotus/issues/6577)
|
||||||
|
|
||||||
|
## Utilities
|
||||||
|
|
||||||
|
`lotus-shed` has a `splitstore` command which provides some utilities:
|
||||||
|
|
||||||
|
- `rollback` -- rolls back a splitstore installation.
|
||||||
|
This command copies the hotstore on top of the coldstore, and then deletes the splitstore
|
||||||
|
directory and associated metadata keys.
|
||||||
|
It can also optionally compact/gc the coldstore after the copy (with the `--gc-coldstore` flag)
|
||||||
|
and automatically rewrite the lotus config to disable splitstore (with the `--rewrite-config` flag).
|
||||||
|
Note: the node *must be stopped* before running this command.
|
||||||
|
- `check` -- asynchronously runs a basic healthcheck on the splitstore.
|
||||||
|
The results are appended to `<lotus-repo>/datastore/splitstore/check.txt`.
|
||||||
|
- `info` -- prints some basic information about the splitstore.
|
||||||
@@ -0,0 +1,273 @@
|
|||||||
|
package splitstore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime/debug"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.uber.org/multierr"
|
||||||
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
|
blocks "github.com/ipfs/go-block-format"
|
||||||
|
cid "github.com/ipfs/go-cid"
|
||||||
|
)
|
||||||
|
|
||||||
|
type debugLog struct {
|
||||||
|
readLog, writeLog, deleteLog, stackLog *debugLogOp
|
||||||
|
|
||||||
|
stackMx sync.Mutex
|
||||||
|
stackMap map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
type debugLogOp struct {
|
||||||
|
path string
|
||||||
|
mx sync.Mutex
|
||||||
|
log *os.File
|
||||||
|
count int
|
||||||
|
}
|
||||||
|
|
||||||
|
func openDebugLog(path string) (*debugLog, error) {
|
||||||
|
basePath := filepath.Join(path, "debug")
|
||||||
|
err := os.MkdirAll(basePath, 0755)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
readLog, err := openDebugLogOp(basePath, "read.log")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
writeLog, err := openDebugLogOp(basePath, "write.log")
|
||||||
|
if err != nil {
|
||||||
|
_ = readLog.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteLog, err := openDebugLogOp(basePath, "delete.log")
|
||||||
|
if err != nil {
|
||||||
|
_ = readLog.Close()
|
||||||
|
_ = writeLog.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
stackLog, err := openDebugLogOp(basePath, "stack.log")
|
||||||
|
if err != nil {
|
||||||
|
_ = readLog.Close()
|
||||||
|
_ = writeLog.Close()
|
||||||
|
_ = deleteLog.Close()
|
||||||
|
return nil, xerrors.Errorf("error opening stack log: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &debugLog{
|
||||||
|
readLog: readLog,
|
||||||
|
writeLog: writeLog,
|
||||||
|
deleteLog: deleteLog,
|
||||||
|
stackLog: stackLog,
|
||||||
|
stackMap: make(map[string]string),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *debugLog) LogReadMiss(cid cid.Cid) {
|
||||||
|
if d == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
stack := d.getStack()
|
||||||
|
err := d.readLog.Log("%s %s %s\n", d.timestamp(), cid, stack)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("error writing read log: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *debugLog) LogWrite(blk blocks.Block) {
|
||||||
|
if d == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var stack string
|
||||||
|
if enableDebugLogWriteTraces {
|
||||||
|
stack = " " + d.getStack()
|
||||||
|
}
|
||||||
|
|
||||||
|
err := d.writeLog.Log("%s %s%s\n", d.timestamp(), blk.Cid(), stack)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("error writing write log: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *debugLog) LogWriteMany(blks []blocks.Block) {
|
||||||
|
if d == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var stack string
|
||||||
|
if enableDebugLogWriteTraces {
|
||||||
|
stack = " " + d.getStack()
|
||||||
|
}
|
||||||
|
|
||||||
|
now := d.timestamp()
|
||||||
|
for _, blk := range blks {
|
||||||
|
err := d.writeLog.Log("%s %s%s\n", now, blk.Cid(), stack)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("error writing write log: %s", err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *debugLog) LogDelete(cids []cid.Cid) {
|
||||||
|
if d == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
now := d.timestamp()
|
||||||
|
for _, c := range cids {
|
||||||
|
err := d.deleteLog.Log("%s %s\n", now, c)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("error writing delete log: %s", err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *debugLog) Flush() {
|
||||||
|
if d == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// rotate non-empty logs
|
||||||
|
d.readLog.Rotate()
|
||||||
|
d.writeLog.Rotate()
|
||||||
|
d.deleteLog.Rotate()
|
||||||
|
d.stackLog.Rotate()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *debugLog) Close() error {
|
||||||
|
if d == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err1 := d.readLog.Close()
|
||||||
|
err2 := d.writeLog.Close()
|
||||||
|
err3 := d.deleteLog.Close()
|
||||||
|
err4 := d.stackLog.Close()
|
||||||
|
|
||||||
|
return multierr.Combine(err1, err2, err3, err4)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *debugLog) getStack() string {
|
||||||
|
sk := d.getNormalizedStackTrace()
|
||||||
|
hash := sha256.Sum256([]byte(sk))
|
||||||
|
key := string(hash[:])
|
||||||
|
|
||||||
|
d.stackMx.Lock()
|
||||||
|
repr, ok := d.stackMap[key]
|
||||||
|
if !ok {
|
||||||
|
repr = hex.EncodeToString(hash[:])
|
||||||
|
d.stackMap[key] = repr
|
||||||
|
|
||||||
|
err := d.stackLog.Log("%s\n%s\n", repr, sk)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("error writing stack trace for %s: %s", repr, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d.stackMx.Unlock()
|
||||||
|
|
||||||
|
return repr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *debugLog) getNormalizedStackTrace() string {
|
||||||
|
sk := string(debug.Stack())
|
||||||
|
|
||||||
|
// Normalization for deduplication
|
||||||
|
// skip first line -- it's the goroutine
|
||||||
|
// for each line that ends in a ), remove the call args -- these are the registers
|
||||||
|
lines := strings.Split(sk, "\n")[1:]
|
||||||
|
for i, line := range lines {
|
||||||
|
if len(line) > 0 && line[len(line)-1] == ')' {
|
||||||
|
idx := strings.LastIndex(line, "(")
|
||||||
|
if idx < 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
lines[i] = line[:idx]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Join(lines, "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *debugLog) timestamp() string {
|
||||||
|
ts, _ := time.Now().MarshalText()
|
||||||
|
return string(ts)
|
||||||
|
}
|
||||||
|
|
||||||
|
func openDebugLogOp(basePath, name string) (*debugLogOp, error) {
|
||||||
|
path := filepath.Join(basePath, name)
|
||||||
|
file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("error opening %s: %w", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &debugLogOp{path: path, log: file}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *debugLogOp) Close() error {
|
||||||
|
d.mx.Lock()
|
||||||
|
defer d.mx.Unlock()
|
||||||
|
|
||||||
|
return d.log.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *debugLogOp) Log(template string, arg ...interface{}) error {
|
||||||
|
d.mx.Lock()
|
||||||
|
defer d.mx.Unlock()
|
||||||
|
|
||||||
|
d.count++
|
||||||
|
_, err := fmt.Fprintf(d.log, template, arg...)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *debugLogOp) Rotate() {
|
||||||
|
d.mx.Lock()
|
||||||
|
defer d.mx.Unlock()
|
||||||
|
|
||||||
|
if d.count == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err := d.log.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("error closing log (file: %s): %s", d.path, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
arxivPath := fmt.Sprintf("%s-%d", d.path, time.Now().Unix())
|
||||||
|
err = os.Rename(d.path, arxivPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("error moving log (file: %s): %s", d.path, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
cmd := exec.Command("gzip", arxivPath)
|
||||||
|
err := cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("error compressing log (file: %s): %s", arxivPath, err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
d.count = 0
|
||||||
|
d.log, err = os.OpenFile(d.path, os.O_WRONLY|os.O_CREATE, 0644)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("error opening log (file: %s): %s", d.path, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,26 +1,26 @@
|
|||||||
package splitstore
|
package splitstore
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"path/filepath"
|
"errors"
|
||||||
|
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
cid "github.com/ipfs/go-cid"
|
cid "github.com/ipfs/go-cid"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var errMarkSetClosed = errors.New("markset closed")
|
||||||
|
|
||||||
// MarkSet is a utility to keep track of seen CID, and later query for them.
|
// MarkSet is a utility to keep track of seen CID, and later query for them.
|
||||||
//
|
//
|
||||||
// * If the expected dataset is large, it can be backed by a datastore (e.g. bbolt).
|
// * If the expected dataset is large, it can be backed by a datastore (e.g. bbolt).
|
||||||
// * If a probabilistic result is acceptable, it can be backed by a bloom filter (default).
|
// * If a probabilistic result is acceptable, it can be backed by a bloom filter
|
||||||
type MarkSet interface {
|
type MarkSet interface {
|
||||||
Mark(cid.Cid) error
|
Mark(cid.Cid) error
|
||||||
Has(cid.Cid) (bool, error)
|
Has(cid.Cid) (bool, error)
|
||||||
Close() error
|
Close() error
|
||||||
|
SetConcurrent()
|
||||||
}
|
}
|
||||||
|
|
||||||
// markBytes is deliberately a non-nil empty byte slice for serialization.
|
|
||||||
var markBytes = []byte{}
|
|
||||||
|
|
||||||
type MarkSetEnv interface {
|
type MarkSetEnv interface {
|
||||||
Create(name string, sizeHint int64) (MarkSet, error)
|
Create(name string, sizeHint int64) (MarkSet, error)
|
||||||
Close() error
|
Close() error
|
||||||
@@ -28,10 +28,12 @@ type MarkSetEnv interface {
|
|||||||
|
|
||||||
func OpenMarkSetEnv(path string, mtype string) (MarkSetEnv, error) {
|
func OpenMarkSetEnv(path string, mtype string) (MarkSetEnv, error) {
|
||||||
switch mtype {
|
switch mtype {
|
||||||
case "", "bloom":
|
case "bloom":
|
||||||
return NewBloomMarkSetEnv()
|
return NewBloomMarkSetEnv()
|
||||||
case "bolt":
|
case "map":
|
||||||
return NewBoltMarkSetEnv(filepath.Join(path, "markset.bolt"))
|
return NewMapMarkSetEnv()
|
||||||
|
case "badger":
|
||||||
|
return NewBadgerMarkSetEnv(path)
|
||||||
default:
|
default:
|
||||||
return nil, xerrors.Errorf("unknown mark set type %s", mtype)
|
return nil, xerrors.Errorf("unknown mark set type %s", mtype)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,230 @@
|
|||||||
|
package splitstore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
|
"github.com/dgraph-io/badger/v2"
|
||||||
|
"github.com/dgraph-io/badger/v2/options"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
|
||||||
|
cid "github.com/ipfs/go-cid"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BadgerMarkSetEnv struct {
|
||||||
|
path string
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ MarkSetEnv = (*BadgerMarkSetEnv)(nil)
|
||||||
|
|
||||||
|
type BadgerMarkSet struct {
|
||||||
|
mx sync.RWMutex
|
||||||
|
cond sync.Cond
|
||||||
|
pend map[string]struct{}
|
||||||
|
writing map[int]map[string]struct{}
|
||||||
|
writers int
|
||||||
|
seqno int
|
||||||
|
|
||||||
|
db *badger.DB
|
||||||
|
path string
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ MarkSet = (*BadgerMarkSet)(nil)
|
||||||
|
|
||||||
|
var badgerMarkSetBatchSize = 16384
|
||||||
|
|
||||||
|
func NewBadgerMarkSetEnv(path string) (MarkSetEnv, error) {
|
||||||
|
msPath := filepath.Join(path, "markset.badger")
|
||||||
|
err := os.MkdirAll(msPath, 0755) //nolint:gosec
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("error creating markset directory: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &BadgerMarkSetEnv{path: msPath}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *BadgerMarkSetEnv) Create(name string, sizeHint int64) (MarkSet, error) {
|
||||||
|
path := filepath.Join(e.path, name)
|
||||||
|
|
||||||
|
// clean up first
|
||||||
|
err := os.RemoveAll(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("error clearing markset directory: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.MkdirAll(path, 0755) //nolint:gosec
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("error creating markset directory: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
opts := badger.DefaultOptions(path)
|
||||||
|
opts.SyncWrites = false
|
||||||
|
opts.CompactL0OnClose = false
|
||||||
|
opts.Compression = options.None
|
||||||
|
// Note: We use FileIO for loading modes to avoid memory thrashing and interference
|
||||||
|
// between the system blockstore and the markset.
|
||||||
|
// It was observed that using the default memory mapped option resulted in
|
||||||
|
// significant interference and unacceptably high block validation times once the markset
|
||||||
|
// exceeded 1GB in size.
|
||||||
|
opts.TableLoadingMode = options.FileIO
|
||||||
|
opts.ValueLogLoadingMode = options.FileIO
|
||||||
|
opts.Logger = &badgerLogger{
|
||||||
|
SugaredLogger: log.Desugar().WithOptions(zap.AddCallerSkip(1)).Sugar(),
|
||||||
|
skip2: log.Desugar().WithOptions(zap.AddCallerSkip(2)).Sugar(),
|
||||||
|
}
|
||||||
|
|
||||||
|
db, err := badger.Open(opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("error creating badger markset: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ms := &BadgerMarkSet{
|
||||||
|
pend: make(map[string]struct{}),
|
||||||
|
writing: make(map[int]map[string]struct{}),
|
||||||
|
db: db,
|
||||||
|
path: path,
|
||||||
|
}
|
||||||
|
ms.cond.L = &ms.mx
|
||||||
|
|
||||||
|
return ms, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *BadgerMarkSetEnv) Close() error {
|
||||||
|
return os.RemoveAll(e.path)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *BadgerMarkSet) Mark(c cid.Cid) error {
|
||||||
|
s.mx.Lock()
|
||||||
|
|
||||||
|
if s.pend == nil {
|
||||||
|
s.mx.Unlock()
|
||||||
|
return errMarkSetClosed
|
||||||
|
}
|
||||||
|
|
||||||
|
s.pend[string(c.Hash())] = struct{}{}
|
||||||
|
|
||||||
|
if len(s.pend) < badgerMarkSetBatchSize {
|
||||||
|
s.mx.Unlock()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
pend := s.pend
|
||||||
|
seqno := s.seqno
|
||||||
|
s.seqno++
|
||||||
|
s.writing[seqno] = pend
|
||||||
|
s.pend = make(map[string]struct{})
|
||||||
|
s.writers++
|
||||||
|
s.mx.Unlock()
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
s.mx.Lock()
|
||||||
|
defer s.mx.Unlock()
|
||||||
|
|
||||||
|
delete(s.writing, seqno)
|
||||||
|
s.writers--
|
||||||
|
if s.writers == 0 {
|
||||||
|
s.cond.Broadcast()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
empty := []byte{} // not nil
|
||||||
|
|
||||||
|
batch := s.db.NewWriteBatch()
|
||||||
|
defer batch.Cancel()
|
||||||
|
|
||||||
|
for k := range pend {
|
||||||
|
if err := batch.Set([]byte(k), empty); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err := batch.Flush()
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("error flushing batch to badger markset: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *BadgerMarkSet) Has(c cid.Cid) (bool, error) {
|
||||||
|
s.mx.RLock()
|
||||||
|
defer s.mx.RUnlock()
|
||||||
|
|
||||||
|
if s.pend == nil {
|
||||||
|
return false, errMarkSetClosed
|
||||||
|
}
|
||||||
|
|
||||||
|
key := c.Hash()
|
||||||
|
pendKey := string(key)
|
||||||
|
_, ok := s.pend[pendKey]
|
||||||
|
if ok {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, wr := range s.writing {
|
||||||
|
_, ok := wr[pendKey]
|
||||||
|
if ok {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err := s.db.View(func(txn *badger.Txn) error {
|
||||||
|
_, err := txn.Get(key)
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
return true, nil
|
||||||
|
|
||||||
|
case badger.ErrKeyNotFound:
|
||||||
|
return false, nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false, xerrors.Errorf("error checking badger markset: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *BadgerMarkSet) Close() error {
|
||||||
|
s.mx.Lock()
|
||||||
|
defer s.mx.Unlock()
|
||||||
|
|
||||||
|
if s.pend == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for s.writers > 0 {
|
||||||
|
s.cond.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
s.pend = nil
|
||||||
|
db := s.db
|
||||||
|
s.db = nil
|
||||||
|
|
||||||
|
err := db.Close()
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("error closing badger markset: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.RemoveAll(s.path)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("error deleting badger markset: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *BadgerMarkSet) SetConcurrent() {}
|
||||||
|
|
||||||
|
// badger logging through go-log
|
||||||
|
type badgerLogger struct {
|
||||||
|
*zap.SugaredLogger
|
||||||
|
skip2 *zap.SugaredLogger
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *badgerLogger) Warningf(format string, args ...interface{}) {}
|
||||||
|
func (b *badgerLogger) Infof(format string, args ...interface{}) {}
|
||||||
|
func (b *badgerLogger) Debugf(format string, args ...interface{}) {}
|
||||||
@@ -3,6 +3,7 @@ package splitstore
|
|||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
@@ -21,7 +22,9 @@ var _ MarkSetEnv = (*BloomMarkSetEnv)(nil)
|
|||||||
|
|
||||||
type BloomMarkSet struct {
|
type BloomMarkSet struct {
|
||||||
salt []byte
|
salt []byte
|
||||||
|
mx sync.RWMutex
|
||||||
bf *bbloom.Bloom
|
bf *bbloom.Bloom
|
||||||
|
ts bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ MarkSet = (*BloomMarkSet)(nil)
|
var _ MarkSet = (*BloomMarkSet)(nil)
|
||||||
@@ -64,14 +67,41 @@ func (s *BloomMarkSet) saltedKey(cid cid.Cid) []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *BloomMarkSet) Mark(cid cid.Cid) error {
|
func (s *BloomMarkSet) Mark(cid cid.Cid) error {
|
||||||
|
if s.ts {
|
||||||
|
s.mx.Lock()
|
||||||
|
defer s.mx.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.bf == nil {
|
||||||
|
return errMarkSetClosed
|
||||||
|
}
|
||||||
|
|
||||||
s.bf.Add(s.saltedKey(cid))
|
s.bf.Add(s.saltedKey(cid))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *BloomMarkSet) Has(cid cid.Cid) (bool, error) {
|
func (s *BloomMarkSet) Has(cid cid.Cid) (bool, error) {
|
||||||
|
if s.ts {
|
||||||
|
s.mx.RLock()
|
||||||
|
defer s.mx.RUnlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.bf == nil {
|
||||||
|
return false, errMarkSetClosed
|
||||||
|
}
|
||||||
|
|
||||||
return s.bf.Has(s.saltedKey(cid)), nil
|
return s.bf.Has(s.saltedKey(cid)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *BloomMarkSet) Close() error {
|
func (s *BloomMarkSet) Close() error {
|
||||||
|
if s.ts {
|
||||||
|
s.mx.Lock()
|
||||||
|
defer s.mx.Unlock()
|
||||||
|
}
|
||||||
|
s.bf = nil
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *BloomMarkSet) SetConcurrent() {
|
||||||
|
s.ts = true
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,81 +0,0 @@
|
|||||||
package splitstore
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"golang.org/x/xerrors"
|
|
||||||
|
|
||||||
cid "github.com/ipfs/go-cid"
|
|
||||||
bolt "go.etcd.io/bbolt"
|
|
||||||
)
|
|
||||||
|
|
||||||
type BoltMarkSetEnv struct {
|
|
||||||
db *bolt.DB
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ MarkSetEnv = (*BoltMarkSetEnv)(nil)
|
|
||||||
|
|
||||||
type BoltMarkSet struct {
|
|
||||||
db *bolt.DB
|
|
||||||
bucketId []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ MarkSet = (*BoltMarkSet)(nil)
|
|
||||||
|
|
||||||
func NewBoltMarkSetEnv(path string) (*BoltMarkSetEnv, error) {
|
|
||||||
db, err := bolt.Open(path, 0644,
|
|
||||||
&bolt.Options{
|
|
||||||
Timeout: 1 * time.Second,
|
|
||||||
NoSync: true,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &BoltMarkSetEnv{db: db}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *BoltMarkSetEnv) Create(name string, hint int64) (MarkSet, error) {
|
|
||||||
bucketId := []byte(name)
|
|
||||||
err := e.db.Update(func(tx *bolt.Tx) error {
|
|
||||||
_, err := tx.CreateBucketIfNotExists(bucketId)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("error creating bolt db bucket %s: %w", name, err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &BoltMarkSet{db: e.db, bucketId: bucketId}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *BoltMarkSetEnv) Close() error {
|
|
||||||
return e.db.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *BoltMarkSet) Mark(cid cid.Cid) error {
|
|
||||||
return s.db.Update(func(tx *bolt.Tx) error {
|
|
||||||
b := tx.Bucket(s.bucketId)
|
|
||||||
return b.Put(cid.Hash(), markBytes)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *BoltMarkSet) Has(cid cid.Cid) (result bool, err error) {
|
|
||||||
err = s.db.View(func(tx *bolt.Tx) error {
|
|
||||||
b := tx.Bucket(s.bucketId)
|
|
||||||
v := b.Get(cid.Hash())
|
|
||||||
result = v != nil
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *BoltMarkSet) Close() error {
|
|
||||||
return s.db.Update(func(tx *bolt.Tx) error {
|
|
||||||
return tx.DeleteBucket(s.bucketId)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
package splitstore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
cid "github.com/ipfs/go-cid"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MapMarkSetEnv struct{}
|
||||||
|
|
||||||
|
var _ MarkSetEnv = (*MapMarkSetEnv)(nil)
|
||||||
|
|
||||||
|
type MapMarkSet struct {
|
||||||
|
mx sync.RWMutex
|
||||||
|
set map[string]struct{}
|
||||||
|
|
||||||
|
ts bool
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ MarkSet = (*MapMarkSet)(nil)
|
||||||
|
|
||||||
|
func NewMapMarkSetEnv() (*MapMarkSetEnv, error) {
|
||||||
|
return &MapMarkSetEnv{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *MapMarkSetEnv) Create(name string, sizeHint int64) (MarkSet, error) {
|
||||||
|
return &MapMarkSet{
|
||||||
|
set: make(map[string]struct{}, sizeHint),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *MapMarkSetEnv) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MapMarkSet) Mark(cid cid.Cid) error {
|
||||||
|
if s.ts {
|
||||||
|
s.mx.Lock()
|
||||||
|
defer s.mx.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.set == nil {
|
||||||
|
return errMarkSetClosed
|
||||||
|
}
|
||||||
|
|
||||||
|
s.set[string(cid.Hash())] = struct{}{}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MapMarkSet) Has(cid cid.Cid) (bool, error) {
|
||||||
|
if s.ts {
|
||||||
|
s.mx.RLock()
|
||||||
|
defer s.mx.RUnlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.set == nil {
|
||||||
|
return false, errMarkSetClosed
|
||||||
|
}
|
||||||
|
|
||||||
|
_, ok := s.set[string(cid.Hash())]
|
||||||
|
return ok, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MapMarkSet) Close() error {
|
||||||
|
if s.ts {
|
||||||
|
s.mx.Lock()
|
||||||
|
defer s.mx.Unlock()
|
||||||
|
}
|
||||||
|
s.set = nil
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MapMarkSet) SetConcurrent() {
|
||||||
|
s.ts = true
|
||||||
|
}
|
||||||
@@ -8,14 +8,23 @@ import (
|
|||||||
"github.com/multiformats/go-multihash"
|
"github.com/multiformats/go-multihash"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestBoltMarkSet(t *testing.T) {
|
func TestMapMarkSet(t *testing.T) {
|
||||||
testMarkSet(t, "bolt")
|
testMarkSet(t, "map")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBloomMarkSet(t *testing.T) {
|
func TestBloomMarkSet(t *testing.T) {
|
||||||
testMarkSet(t, "bloom")
|
testMarkSet(t, "bloom")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBadgerMarkSet(t *testing.T) {
|
||||||
|
bs := badgerMarkSetBatchSize
|
||||||
|
badgerMarkSetBatchSize = 1
|
||||||
|
t.Cleanup(func() {
|
||||||
|
badgerMarkSetBatchSize = bs
|
||||||
|
})
|
||||||
|
testMarkSet(t, "badger")
|
||||||
|
}
|
||||||
|
|
||||||
func testMarkSet(t *testing.T, lsType string) {
|
func testMarkSet(t *testing.T, lsType string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
|
|||||||
+293
-798
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,150 @@
|
|||||||
|
package splitstore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
|
cid "github.com/ipfs/go-cid"
|
||||||
|
|
||||||
|
bstore "github.com/filecoin-project/lotus/blockstore"
|
||||||
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// performs an asynchronous health-check on the splitstore; results are appended to
|
||||||
|
// <splitstore-path>/check.txt
|
||||||
|
func (s *SplitStore) Check() error {
|
||||||
|
s.headChangeMx.Lock()
|
||||||
|
defer s.headChangeMx.Unlock()
|
||||||
|
|
||||||
|
// try to take compaction lock and inhibit compaction while the health-check is running
|
||||||
|
if !atomic.CompareAndSwapInt32(&s.compacting, 0, 1) {
|
||||||
|
return xerrors.Errorf("can't acquire compaction lock; compacting operation in progress")
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.compactionIndex == 0 {
|
||||||
|
atomic.StoreInt32(&s.compacting, 0)
|
||||||
|
return xerrors.Errorf("splitstore hasn't compacted yet; health check is not meaningful")
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if we are actually closing first
|
||||||
|
if err := s.checkClosing(); err != nil {
|
||||||
|
atomic.StoreInt32(&s.compacting, 0)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
curTs := s.chain.GetHeaviestTipSet()
|
||||||
|
go func() {
|
||||||
|
defer atomic.StoreInt32(&s.compacting, 0)
|
||||||
|
|
||||||
|
log.Info("checking splitstore health")
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
|
err := s.doCheck(curTs)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("error checking splitstore health: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infow("health check done", "took", time.Since(start))
|
||||||
|
}()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SplitStore) doCheck(curTs *types.TipSet) error {
|
||||||
|
currentEpoch := curTs.Height()
|
||||||
|
boundaryEpoch := currentEpoch - CompactionBoundary
|
||||||
|
|
||||||
|
outputPath := filepath.Join(s.path, "check.txt")
|
||||||
|
output, err := os.OpenFile(outputPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("error opening check output file %s: %w", outputPath, err)
|
||||||
|
}
|
||||||
|
defer output.Close() //nolint:errcheck
|
||||||
|
|
||||||
|
write := func(format string, args ...interface{}) {
|
||||||
|
_, err := fmt.Fprintf(output, format+"\n", args...)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("error writing check output: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ts, _ := time.Now().MarshalText()
|
||||||
|
write("---------------------------------------------")
|
||||||
|
write("start check at %s", ts)
|
||||||
|
write("current epoch: %d", currentEpoch)
|
||||||
|
write("boundary epoch: %d", boundaryEpoch)
|
||||||
|
write("compaction index: %d", s.compactionIndex)
|
||||||
|
write("--")
|
||||||
|
|
||||||
|
var coldCnt, missingCnt int64
|
||||||
|
err = s.walkChain(curTs, boundaryEpoch, boundaryEpoch,
|
||||||
|
func(c cid.Cid) error {
|
||||||
|
if isUnitaryObject(c) {
|
||||||
|
return errStopWalk
|
||||||
|
}
|
||||||
|
|
||||||
|
has, err := s.hot.Has(c)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("error checking hotstore: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if has {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
has, err = s.cold.Has(c)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("error checking coldstore: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if has {
|
||||||
|
coldCnt++
|
||||||
|
write("cold object reference: %s", c)
|
||||||
|
} else {
|
||||||
|
missingCnt++
|
||||||
|
write("missing object reference: %s", c)
|
||||||
|
return errStopWalk
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
err = xerrors.Errorf("error walking chain: %w", err)
|
||||||
|
write("ERROR: %s", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infow("check done", "cold", coldCnt, "missing", missingCnt)
|
||||||
|
write("--")
|
||||||
|
write("cold: %d missing: %d", coldCnt, missingCnt)
|
||||||
|
write("DONE")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// provides some basic information about the splitstore
|
||||||
|
func (s *SplitStore) Info() map[string]interface{} {
|
||||||
|
info := make(map[string]interface{})
|
||||||
|
info["base epoch"] = s.baseEpoch
|
||||||
|
info["warmup epoch"] = s.warmupEpoch
|
||||||
|
info["compactions"] = s.compactionIndex
|
||||||
|
|
||||||
|
sizer, ok := s.hot.(bstore.BlockstoreSize)
|
||||||
|
if ok {
|
||||||
|
size, err := sizer.Size()
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("error getting hotstore size: %s", err)
|
||||||
|
} else {
|
||||||
|
info["hotstore size"] = size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return info
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,114 @@
|
|||||||
|
package splitstore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
blocks "github.com/ipfs/go-block-format"
|
||||||
|
cid "github.com/ipfs/go-cid"
|
||||||
|
|
||||||
|
bstore "github.com/filecoin-project/lotus/blockstore"
|
||||||
|
)
|
||||||
|
|
||||||
|
type exposedSplitStore struct {
|
||||||
|
s *SplitStore
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ bstore.Blockstore = (*exposedSplitStore)(nil)
|
||||||
|
|
||||||
|
func (s *SplitStore) Expose() bstore.Blockstore {
|
||||||
|
return &exposedSplitStore{s: s}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (es *exposedSplitStore) DeleteBlock(_ cid.Cid) error {
|
||||||
|
return errors.New("DeleteBlock: operation not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (es *exposedSplitStore) DeleteMany(_ []cid.Cid) error {
|
||||||
|
return errors.New("DeleteMany: operation not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (es *exposedSplitStore) Has(c cid.Cid) (bool, error) {
|
||||||
|
if isIdentiyCid(c) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
has, err := es.s.hot.Has(c)
|
||||||
|
if has || err != nil {
|
||||||
|
return has, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return es.s.cold.Has(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (es *exposedSplitStore) Get(c cid.Cid) (blocks.Block, error) {
|
||||||
|
if isIdentiyCid(c) {
|
||||||
|
data, err := decodeIdentityCid(c)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return blocks.NewBlockWithCid(data, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
blk, err := es.s.hot.Get(c)
|
||||||
|
switch err {
|
||||||
|
case bstore.ErrNotFound:
|
||||||
|
return es.s.cold.Get(c)
|
||||||
|
default:
|
||||||
|
return blk, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (es *exposedSplitStore) GetSize(c cid.Cid) (int, error) {
|
||||||
|
if isIdentiyCid(c) {
|
||||||
|
data, err := decodeIdentityCid(c)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return len(data), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
size, err := es.s.hot.GetSize(c)
|
||||||
|
switch err {
|
||||||
|
case bstore.ErrNotFound:
|
||||||
|
return es.s.cold.GetSize(c)
|
||||||
|
default:
|
||||||
|
return size, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (es *exposedSplitStore) Put(blk blocks.Block) error {
|
||||||
|
return es.s.Put(blk)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (es *exposedSplitStore) PutMany(blks []blocks.Block) error {
|
||||||
|
return es.s.PutMany(blks)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (es *exposedSplitStore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
|
||||||
|
return es.s.AllKeysChan(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (es *exposedSplitStore) HashOnRead(enabled bool) {}
|
||||||
|
|
||||||
|
func (es *exposedSplitStore) View(c cid.Cid, f func([]byte) error) error {
|
||||||
|
if isIdentiyCid(c) {
|
||||||
|
data, err := decodeIdentityCid(c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return f(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := es.s.hot.View(c, f)
|
||||||
|
switch err {
|
||||||
|
case bstore.ErrNotFound:
|
||||||
|
return es.s.cold.View(c, f)
|
||||||
|
|
||||||
|
default:
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package splitstore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
bstore "github.com/filecoin-project/lotus/blockstore"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *SplitStore) gcHotstore() {
|
||||||
|
var opts []bstore.BlockstoreGCOption
|
||||||
|
if s.cfg.HotStoreFullGCFrequency > 0 && s.compactionIndex%int64(s.cfg.HotStoreFullGCFrequency) == 0 {
|
||||||
|
opts = append(opts, bstore.WithFullGC(true))
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.gcBlockstore(s.hot, opts); err != nil {
|
||||||
|
log.Warnf("error garbage collecting hostore: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SplitStore) gcBlockstore(b bstore.Blockstore, opts []bstore.BlockstoreGCOption) error {
|
||||||
|
if gc, ok := b.(bstore.BlockstoreGC); ok {
|
||||||
|
log.Info("garbage collecting blockstore")
|
||||||
|
startGC := time.Now()
|
||||||
|
|
||||||
|
if err := gc.CollectGarbage(opts...); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infow("garbage collecting hotstore done", "took", time.Since(startGC))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("blockstore doesn't support garbage collection: %T", b)
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ package splitstore
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
@@ -13,6 +14,7 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/filecoin-project/lotus/chain/types/mock"
|
"github.com/filecoin-project/lotus/chain/types/mock"
|
||||||
|
|
||||||
|
blocks "github.com/ipfs/go-block-format"
|
||||||
cid "github.com/ipfs/go-cid"
|
cid "github.com/ipfs/go-cid"
|
||||||
datastore "github.com/ipfs/go-datastore"
|
datastore "github.com/ipfs/go-datastore"
|
||||||
dssync "github.com/ipfs/go-datastore/sync"
|
dssync "github.com/ipfs/go-datastore/sync"
|
||||||
@@ -21,22 +23,35 @@ import (
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
CompactionThreshold = 5
|
CompactionThreshold = 5
|
||||||
CompactionCold = 1
|
|
||||||
CompactionBoundary = 2
|
CompactionBoundary = 2
|
||||||
|
WarmupBoundary = 0
|
||||||
logging.SetLogLevel("splitstore", "DEBUG")
|
logging.SetLogLevel("splitstore", "DEBUG")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testSplitStore(t *testing.T, cfg *Config) {
|
func testSplitStore(t *testing.T, cfg *Config) {
|
||||||
chain := &mockChain{t: t}
|
chain := &mockChain{t: t}
|
||||||
// genesis
|
|
||||||
genBlock := mock.MkBlock(nil, 0, 0)
|
|
||||||
genTs := mock.TipSet(genBlock)
|
|
||||||
chain.push(genTs)
|
|
||||||
|
|
||||||
// the myriads of stores
|
// the myriads of stores
|
||||||
ds := dssync.MutexWrap(datastore.NewMapDatastore())
|
ds := dssync.MutexWrap(datastore.NewMapDatastore())
|
||||||
hot := blockstore.NewMemorySync()
|
hot := newMockStore()
|
||||||
cold := blockstore.NewMemorySync()
|
cold := newMockStore()
|
||||||
|
|
||||||
|
// this is necessary to avoid the garbage mock puts in the blocks
|
||||||
|
garbage := blocks.NewBlock([]byte{1, 2, 3})
|
||||||
|
err := cold.Put(garbage)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// genesis
|
||||||
|
genBlock := mock.MkBlock(nil, 0, 0)
|
||||||
|
genBlock.Messages = garbage.Cid()
|
||||||
|
genBlock.ParentMessageReceipts = garbage.Cid()
|
||||||
|
genBlock.ParentStateRoot = garbage.Cid()
|
||||||
|
genBlock.Timestamp = uint64(time.Now().Unix())
|
||||||
|
|
||||||
|
genTs := mock.TipSet(genBlock)
|
||||||
|
chain.push(genTs)
|
||||||
|
|
||||||
// put the genesis block to cold store
|
// put the genesis block to cold store
|
||||||
blk, err := genBlock.ToStorageBlock()
|
blk, err := genBlock.ToStorageBlock()
|
||||||
@@ -49,6 +64,20 @@ func testSplitStore(t *testing.T, cfg *Config) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create a garbage block that is protected with a rgistered protector
|
||||||
|
protected := blocks.NewBlock([]byte("protected!"))
|
||||||
|
err = hot.Put(protected)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// and another one that is not protected
|
||||||
|
unprotected := blocks.NewBlock([]byte("unprotected!"))
|
||||||
|
err = hot.Put(unprotected)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
// open the splitstore
|
// open the splitstore
|
||||||
ss, err := Open("", ds, hot, cold, cfg)
|
ss, err := Open("", ds, hot, cold, cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -56,18 +85,33 @@ func testSplitStore(t *testing.T, cfg *Config) {
|
|||||||
}
|
}
|
||||||
defer ss.Close() //nolint
|
defer ss.Close() //nolint
|
||||||
|
|
||||||
|
// register our protector
|
||||||
|
ss.AddProtector(func(protect func(cid.Cid) error) error {
|
||||||
|
return protect(protected.Cid())
|
||||||
|
})
|
||||||
|
|
||||||
err = ss.Start(chain)
|
err = ss.Start(chain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// make some tipsets, but not enough to cause compaction
|
// make some tipsets, but not enough to cause compaction
|
||||||
mkBlock := func(curTs *types.TipSet, i int) *types.TipSet {
|
mkBlock := func(curTs *types.TipSet, i int, stateRoot blocks.Block) *types.TipSet {
|
||||||
blk := mock.MkBlock(curTs, uint64(i), uint64(i))
|
blk := mock.MkBlock(curTs, uint64(i), uint64(i))
|
||||||
|
|
||||||
|
blk.Messages = garbage.Cid()
|
||||||
|
blk.ParentMessageReceipts = garbage.Cid()
|
||||||
|
blk.ParentStateRoot = stateRoot.Cid()
|
||||||
|
blk.Timestamp = uint64(time.Now().Unix())
|
||||||
|
|
||||||
sblk, err := blk.ToStorageBlock()
|
sblk, err := blk.ToStorageBlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
err = ss.Put(stateRoot)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
err = ss.Put(sblk)
|
err = ss.Put(sblk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -78,18 +122,6 @@ func testSplitStore(t *testing.T, cfg *Config) {
|
|||||||
return ts
|
return ts
|
||||||
}
|
}
|
||||||
|
|
||||||
mkGarbageBlock := func(curTs *types.TipSet, i int) {
|
|
||||||
blk := mock.MkBlock(curTs, uint64(i), uint64(i))
|
|
||||||
sblk, err := blk.ToStorageBlock()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
err = ss.Put(sblk)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
waitForCompaction := func() {
|
waitForCompaction := func() {
|
||||||
for atomic.LoadInt32(&ss.compacting) == 1 {
|
for atomic.LoadInt32(&ss.compacting) == 1 {
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
@@ -98,105 +130,101 @@ func testSplitStore(t *testing.T, cfg *Config) {
|
|||||||
|
|
||||||
curTs := genTs
|
curTs := genTs
|
||||||
for i := 1; i < 5; i++ {
|
for i := 1; i < 5; i++ {
|
||||||
curTs = mkBlock(curTs, i)
|
stateRoot := blocks.NewBlock([]byte{byte(i), 3, 3, 7})
|
||||||
|
curTs = mkBlock(curTs, i, stateRoot)
|
||||||
waitForCompaction()
|
waitForCompaction()
|
||||||
}
|
}
|
||||||
|
|
||||||
mkGarbageBlock(genTs, 1)
|
|
||||||
|
|
||||||
// count objects in the cold and hot stores
|
// count objects in the cold and hot stores
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
countBlocks := func(bs blockstore.Blockstore) int {
|
countBlocks := func(bs blockstore.Blockstore) int {
|
||||||
count := 0
|
count := 0
|
||||||
ch, err := bs.AllKeysChan(ctx)
|
_ = bs.(blockstore.BlockstoreIterator).ForEachKey(func(_ cid.Cid) error {
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
for range ch {
|
|
||||||
count++
|
count++
|
||||||
}
|
return nil
|
||||||
|
})
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
coldCnt := countBlocks(cold)
|
coldCnt := countBlocks(cold)
|
||||||
hotCnt := countBlocks(hot)
|
hotCnt := countBlocks(hot)
|
||||||
|
|
||||||
if coldCnt != 1 {
|
if coldCnt != 2 {
|
||||||
t.Errorf("expected %d blocks, but got %d", 1, coldCnt)
|
t.Errorf("expected %d blocks, but got %d", 2, coldCnt)
|
||||||
}
|
}
|
||||||
|
|
||||||
if hotCnt != 5 {
|
if hotCnt != 12 {
|
||||||
t.Errorf("expected %d blocks, but got %d", 5, hotCnt)
|
t.Errorf("expected %d blocks, but got %d", 12, hotCnt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// trigger a compaction
|
// trigger a compaction
|
||||||
for i := 5; i < 10; i++ {
|
for i := 5; i < 10; i++ {
|
||||||
curTs = mkBlock(curTs, i)
|
stateRoot := blocks.NewBlock([]byte{byte(i), 3, 3, 7})
|
||||||
|
curTs = mkBlock(curTs, i, stateRoot)
|
||||||
waitForCompaction()
|
waitForCompaction()
|
||||||
}
|
}
|
||||||
|
|
||||||
coldCnt = countBlocks(cold)
|
coldCnt = countBlocks(cold)
|
||||||
hotCnt = countBlocks(hot)
|
hotCnt = countBlocks(hot)
|
||||||
|
|
||||||
if !cfg.EnableFullCompaction {
|
if coldCnt != 6 {
|
||||||
if coldCnt != 5 {
|
t.Errorf("expected %d cold blocks, but got %d", 6, coldCnt)
|
||||||
t.Errorf("expected %d cold blocks, but got %d", 5, coldCnt)
|
|
||||||
}
|
|
||||||
|
|
||||||
if hotCnt != 5 {
|
|
||||||
t.Errorf("expected %d hot blocks, but got %d", 5, hotCnt)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.EnableFullCompaction && !cfg.EnableGC {
|
if hotCnt != 18 {
|
||||||
if coldCnt != 3 {
|
t.Errorf("expected %d hot blocks, but got %d", 18, hotCnt)
|
||||||
t.Errorf("expected %d cold blocks, but got %d", 3, coldCnt)
|
|
||||||
}
|
|
||||||
|
|
||||||
if hotCnt != 7 {
|
|
||||||
t.Errorf("expected %d hot blocks, but got %d", 7, hotCnt)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.EnableFullCompaction && cfg.EnableGC {
|
// ensure our protected block is still there
|
||||||
if coldCnt != 2 {
|
has, err := hot.Has(protected.Cid())
|
||||||
t.Errorf("expected %d cold blocks, but got %d", 2, coldCnt)
|
if err != nil {
|
||||||
}
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
if hotCnt != 7 {
|
if !has {
|
||||||
t.Errorf("expected %d hot blocks, but got %d", 7, hotCnt)
|
t.Fatal("protected block is missing from hotstore")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ensure our unprotected block is in the coldstore now
|
||||||
|
has, err = hot.Has(unprotected.Cid())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if has {
|
||||||
|
t.Fatal("unprotected block is still in hotstore")
|
||||||
|
}
|
||||||
|
|
||||||
|
has, err = cold.Has(unprotected.Cid())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !has {
|
||||||
|
t.Fatal("unprotected block is missing from coldstore")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we can revert without panicking.
|
// Make sure we can revert without panicking.
|
||||||
chain.revert(2)
|
chain.revert(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSplitStoreSimpleCompaction(t *testing.T) {
|
func TestSplitStoreCompaction(t *testing.T) {
|
||||||
testSplitStore(t, &Config{TrackingStoreType: "mem"})
|
testSplitStore(t, &Config{MarkSetType: "map"})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSplitStoreFullCompactionWithoutGC(t *testing.T) {
|
func TestSplitStoreCompactionWithBadger(t *testing.T) {
|
||||||
testSplitStore(t, &Config{
|
bs := badgerMarkSetBatchSize
|
||||||
TrackingStoreType: "mem",
|
badgerMarkSetBatchSize = 1
|
||||||
EnableFullCompaction: true,
|
t.Cleanup(func() {
|
||||||
})
|
badgerMarkSetBatchSize = bs
|
||||||
}
|
|
||||||
|
|
||||||
func TestSplitStoreFullCompactionWithGC(t *testing.T) {
|
|
||||||
testSplitStore(t, &Config{
|
|
||||||
TrackingStoreType: "mem",
|
|
||||||
EnableFullCompaction: true,
|
|
||||||
EnableGC: true,
|
|
||||||
})
|
})
|
||||||
|
testSplitStore(t, &Config{MarkSetType: "badger"})
|
||||||
}
|
}
|
||||||
|
|
||||||
type mockChain struct {
|
type mockChain struct {
|
||||||
t testing.TB
|
t testing.TB
|
||||||
|
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
|
genesis *types.BlockHeader
|
||||||
tipsets []*types.TipSet
|
tipsets []*types.TipSet
|
||||||
listener func(revert []*types.TipSet, apply []*types.TipSet) error
|
listener func(revert []*types.TipSet, apply []*types.TipSet) error
|
||||||
}
|
}
|
||||||
@@ -204,6 +232,9 @@ type mockChain struct {
|
|||||||
func (c *mockChain) push(ts *types.TipSet) {
|
func (c *mockChain) push(ts *types.TipSet) {
|
||||||
c.Lock()
|
c.Lock()
|
||||||
c.tipsets = append(c.tipsets, ts)
|
c.tipsets = append(c.tipsets, ts)
|
||||||
|
if c.genesis == nil {
|
||||||
|
c.genesis = ts.Blocks()[0]
|
||||||
|
}
|
||||||
c.Unlock()
|
c.Unlock()
|
||||||
|
|
||||||
if c.listener != nil {
|
if c.listener != nil {
|
||||||
@@ -242,7 +273,7 @@ func (c *mockChain) GetTipsetByHeight(_ context.Context, epoch abi.ChainEpoch, _
|
|||||||
return nil, fmt.Errorf("bad epoch %d", epoch)
|
return nil, fmt.Errorf("bad epoch %d", epoch)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.tipsets[iEpoch-1], nil
|
return c.tipsets[iEpoch], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *mockChain) GetHeaviestTipSet() *types.TipSet {
|
func (c *mockChain) GetHeaviestTipSet() *types.TipSet {
|
||||||
@@ -256,24 +287,105 @@ func (c *mockChain) SubscribeHeadChanges(change func(revert []*types.TipSet, app
|
|||||||
c.listener = change
|
c.listener = change
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *mockChain) WalkSnapshot(_ context.Context, ts *types.TipSet, epochs abi.ChainEpoch, _ bool, _ bool, f func(cid.Cid) error) error {
|
type mockStore struct {
|
||||||
c.Lock()
|
mx sync.Mutex
|
||||||
defer c.Unlock()
|
set map[cid.Cid]blocks.Block
|
||||||
|
}
|
||||||
|
|
||||||
start := int(ts.Height()) - 1
|
func newMockStore() *mockStore {
|
||||||
end := start - int(epochs)
|
return &mockStore{set: make(map[cid.Cid]blocks.Block)}
|
||||||
if end < 0 {
|
}
|
||||||
end = -1
|
|
||||||
|
func (b *mockStore) Has(cid cid.Cid) (bool, error) {
|
||||||
|
b.mx.Lock()
|
||||||
|
defer b.mx.Unlock()
|
||||||
|
_, ok := b.set[cid]
|
||||||
|
return ok, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *mockStore) HashOnRead(hor bool) {}
|
||||||
|
|
||||||
|
func (b *mockStore) Get(cid cid.Cid) (blocks.Block, error) {
|
||||||
|
b.mx.Lock()
|
||||||
|
defer b.mx.Unlock()
|
||||||
|
|
||||||
|
blk, ok := b.set[cid]
|
||||||
|
if !ok {
|
||||||
|
return nil, blockstore.ErrNotFound
|
||||||
}
|
}
|
||||||
for i := start; i > end; i-- {
|
return blk, nil
|
||||||
ts := c.tipsets[i]
|
}
|
||||||
for _, cid := range ts.Cids() {
|
|
||||||
err := f(cid)
|
func (b *mockStore) GetSize(cid cid.Cid) (int, error) {
|
||||||
if err != nil {
|
blk, err := b.Get(cid)
|
||||||
return err
|
if err != nil {
|
||||||
}
|
return 0, err
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return len(blk.RawData()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *mockStore) View(cid cid.Cid, f func([]byte) error) error {
|
||||||
|
blk, err := b.Get(cid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return f(blk.RawData())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *mockStore) Put(blk blocks.Block) error {
|
||||||
|
b.mx.Lock()
|
||||||
|
defer b.mx.Unlock()
|
||||||
|
|
||||||
|
b.set[blk.Cid()] = blk
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *mockStore) PutMany(blks []blocks.Block) error {
|
||||||
|
b.mx.Lock()
|
||||||
|
defer b.mx.Unlock()
|
||||||
|
|
||||||
|
for _, blk := range blks {
|
||||||
|
b.set[blk.Cid()] = blk
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *mockStore) DeleteBlock(cid cid.Cid) error {
|
||||||
|
b.mx.Lock()
|
||||||
|
defer b.mx.Unlock()
|
||||||
|
|
||||||
|
delete(b.set, cid)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *mockStore) DeleteMany(cids []cid.Cid) error {
|
||||||
|
b.mx.Lock()
|
||||||
|
defer b.mx.Unlock()
|
||||||
|
|
||||||
|
for _, c := range cids {
|
||||||
|
delete(b.set, c)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *mockStore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
|
||||||
|
return nil, errors.New("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *mockStore) ForEachKey(f func(cid.Cid) error) error {
|
||||||
|
b.mx.Lock()
|
||||||
|
defer b.mx.Unlock()
|
||||||
|
|
||||||
|
for c := range b.set {
|
||||||
|
err := f(c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *mockStore) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
package splitstore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
|
||||||
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
|
cid "github.com/ipfs/go-cid"
|
||||||
|
mh "github.com/multiformats/go-multihash"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
|
)
|
||||||
|
|
||||||
|
func epochToBytes(epoch abi.ChainEpoch) []byte {
|
||||||
|
return uint64ToBytes(uint64(epoch))
|
||||||
|
}
|
||||||
|
|
||||||
|
func bytesToEpoch(buf []byte) abi.ChainEpoch {
|
||||||
|
return abi.ChainEpoch(bytesToUint64(buf))
|
||||||
|
}
|
||||||
|
|
||||||
|
func int64ToBytes(i int64) []byte {
|
||||||
|
return uint64ToBytes(uint64(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
func bytesToInt64(buf []byte) int64 {
|
||||||
|
return int64(bytesToUint64(buf))
|
||||||
|
}
|
||||||
|
|
||||||
|
func uint64ToBytes(i uint64) []byte {
|
||||||
|
buf := make([]byte, 16)
|
||||||
|
n := binary.PutUvarint(buf, i)
|
||||||
|
return buf[:n]
|
||||||
|
}
|
||||||
|
|
||||||
|
func bytesToUint64(buf []byte) uint64 {
|
||||||
|
i, _ := binary.Uvarint(buf)
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
func isUnitaryObject(c cid.Cid) bool {
|
||||||
|
pre := c.Prefix()
|
||||||
|
switch pre.Codec {
|
||||||
|
case cid.FilCommitmentSealed, cid.FilCommitmentUnsealed:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return pre.MhType == mh.IDENTITY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isIdentiyCid(c cid.Cid) bool {
|
||||||
|
return c.Prefix().MhType == mh.IDENTITY
|
||||||
|
}
|
||||||
|
|
||||||
|
func decodeIdentityCid(c cid.Cid) ([]byte, error) {
|
||||||
|
dmh, err := mh.Decode(c.Hash())
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("error decoding identity cid %s: %w", c, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// sanity check
|
||||||
|
if dmh.Code != mh.IDENTITY {
|
||||||
|
return nil, xerrors.Errorf("error decoding identity cid %s: hash type is not identity", c)
|
||||||
|
}
|
||||||
|
|
||||||
|
return dmh.Digest, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
package splitstore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
|
blocks "github.com/ipfs/go-block-format"
|
||||||
|
cid "github.com/ipfs/go-cid"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
|
bstore "github.com/filecoin-project/lotus/blockstore"
|
||||||
|
"github.com/filecoin-project/lotus/build"
|
||||||
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// WarmupBoundary is the number of epochs to load state during warmup.
|
||||||
|
WarmupBoundary = build.Finality
|
||||||
|
)
|
||||||
|
|
||||||
|
// warmup acuiqres the compaction lock and spawns a goroutine to warm up the hotstore;
|
||||||
|
// this is necessary when we sync from a snapshot or when we enable the splitstore
|
||||||
|
// on top of an existing blockstore (which becomes the coldstore).
|
||||||
|
func (s *SplitStore) warmup(curTs *types.TipSet) error {
|
||||||
|
if !atomic.CompareAndSwapInt32(&s.compacting, 0, 1) {
|
||||||
|
return xerrors.Errorf("error locking compaction")
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer atomic.StoreInt32(&s.compacting, 0)
|
||||||
|
|
||||||
|
log.Info("warming up hotstore")
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
|
err := s.doWarmup(curTs)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("error warming up hotstore: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infow("warm up done", "took", time.Since(start))
|
||||||
|
}()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// the actual warmup procedure; it walks the chain loading all state roots at the boundary
|
||||||
|
// and headers all the way up to genesis.
|
||||||
|
// objects are written in batches so as to minimize overhead.
|
||||||
|
func (s *SplitStore) doWarmup(curTs *types.TipSet) error {
|
||||||
|
var boundaryEpoch abi.ChainEpoch
|
||||||
|
epoch := curTs.Height()
|
||||||
|
if WarmupBoundary < epoch {
|
||||||
|
boundaryEpoch = epoch - WarmupBoundary
|
||||||
|
}
|
||||||
|
batchHot := make([]blocks.Block, 0, batchSize)
|
||||||
|
count := int64(0)
|
||||||
|
xcount := int64(0)
|
||||||
|
missing := int64(0)
|
||||||
|
err := s.walkChain(curTs, boundaryEpoch, epoch+1, // we don't load messages/receipts in warmup
|
||||||
|
func(c cid.Cid) error {
|
||||||
|
if isUnitaryObject(c) {
|
||||||
|
return errStopWalk
|
||||||
|
}
|
||||||
|
|
||||||
|
count++
|
||||||
|
|
||||||
|
has, err := s.hot.Has(c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if has {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
blk, err := s.cold.Get(c)
|
||||||
|
if err != nil {
|
||||||
|
if err == bstore.ErrNotFound {
|
||||||
|
missing++
|
||||||
|
return errStopWalk
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
xcount++
|
||||||
|
|
||||||
|
batchHot = append(batchHot, blk)
|
||||||
|
if len(batchHot) == batchSize {
|
||||||
|
err = s.hot.PutMany(batchHot)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
batchHot = batchHot[:0]
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(batchHot) > 0 {
|
||||||
|
err = s.hot.PutMany(batchHot)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infow("warmup stats", "visited", count, "warm", xcount, "missing", missing)
|
||||||
|
|
||||||
|
s.markSetSize = count + count>>2 // overestimate a bit
|
||||||
|
err = s.ds.Put(markSetSizeKey, int64ToBytes(s.markSetSize))
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("error saving mark set size: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// save the warmup epoch
|
||||||
|
err = s.ds.Put(warmupEpochKey, epochToBytes(epoch))
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("error saving warm up epoch: %w", err)
|
||||||
|
}
|
||||||
|
s.mx.Lock()
|
||||||
|
s.warmupEpoch = epoch
|
||||||
|
s.mx.Unlock()
|
||||||
|
|
||||||
|
// also save the compactionIndex, as this is used as an indicator of warmup for upgraded nodes
|
||||||
|
err = s.ds.Put(compactionIndexKey, int64ToBytes(s.compactionIndex))
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("error saving compaction index: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
package splitstore
|
|
||||||
|
|
||||||
import (
|
|
||||||
"path/filepath"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"golang.org/x/xerrors"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
|
||||||
cid "github.com/ipfs/go-cid"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TrackingStore is a persistent store that tracks blocks that are added
|
|
||||||
// to the hotstore, tracking the epoch at which they are written.
|
|
||||||
type TrackingStore interface {
|
|
||||||
Put(cid.Cid, abi.ChainEpoch) error
|
|
||||||
PutBatch([]cid.Cid, abi.ChainEpoch) error
|
|
||||||
Get(cid.Cid) (abi.ChainEpoch, error)
|
|
||||||
Delete(cid.Cid) error
|
|
||||||
DeleteBatch([]cid.Cid) error
|
|
||||||
ForEach(func(cid.Cid, abi.ChainEpoch) error) error
|
|
||||||
Sync() error
|
|
||||||
Close() error
|
|
||||||
}
|
|
||||||
|
|
||||||
// OpenTrackingStore opens a tracking store of the specified type in the
|
|
||||||
// specified path.
|
|
||||||
func OpenTrackingStore(path string, ttype string) (TrackingStore, error) {
|
|
||||||
switch ttype {
|
|
||||||
case "", "bolt":
|
|
||||||
return OpenBoltTrackingStore(filepath.Join(path, "tracker.bolt"))
|
|
||||||
case "mem":
|
|
||||||
return NewMemTrackingStore(), nil
|
|
||||||
default:
|
|
||||||
return nil, xerrors.Errorf("unknown tracking store type %s", ttype)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewMemTrackingStore creates an in-memory tracking store.
|
|
||||||
// This is only useful for test or situations where you don't want to open the
|
|
||||||
// real tracking store (eg concurrent read only access on a node's datastore)
|
|
||||||
func NewMemTrackingStore() *MemTrackingStore {
|
|
||||||
return &MemTrackingStore{tab: make(map[cid.Cid]abi.ChainEpoch)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MemTrackingStore is a simple in-memory tracking store
|
|
||||||
type MemTrackingStore struct {
|
|
||||||
sync.Mutex
|
|
||||||
tab map[cid.Cid]abi.ChainEpoch
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ TrackingStore = (*MemTrackingStore)(nil)
|
|
||||||
|
|
||||||
func (s *MemTrackingStore) Put(cid cid.Cid, epoch abi.ChainEpoch) error {
|
|
||||||
s.Lock()
|
|
||||||
defer s.Unlock()
|
|
||||||
s.tab[cid] = epoch
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *MemTrackingStore) PutBatch(cids []cid.Cid, epoch abi.ChainEpoch) error {
|
|
||||||
s.Lock()
|
|
||||||
defer s.Unlock()
|
|
||||||
for _, cid := range cids {
|
|
||||||
s.tab[cid] = epoch
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *MemTrackingStore) Get(cid cid.Cid) (abi.ChainEpoch, error) {
|
|
||||||
s.Lock()
|
|
||||||
defer s.Unlock()
|
|
||||||
epoch, ok := s.tab[cid]
|
|
||||||
if ok {
|
|
||||||
return epoch, nil
|
|
||||||
}
|
|
||||||
return 0, xerrors.Errorf("missing tracking epoch for %s", cid)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *MemTrackingStore) Delete(cid cid.Cid) error {
|
|
||||||
s.Lock()
|
|
||||||
defer s.Unlock()
|
|
||||||
delete(s.tab, cid)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *MemTrackingStore) DeleteBatch(cids []cid.Cid) error {
|
|
||||||
s.Lock()
|
|
||||||
defer s.Unlock()
|
|
||||||
for _, cid := range cids {
|
|
||||||
delete(s.tab, cid)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *MemTrackingStore) ForEach(f func(cid.Cid, abi.ChainEpoch) error) error {
|
|
||||||
s.Lock()
|
|
||||||
defer s.Unlock()
|
|
||||||
for cid, epoch := range s.tab {
|
|
||||||
err := f(cid, epoch)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *MemTrackingStore) Sync() error { return nil }
|
|
||||||
func (s *MemTrackingStore) Close() error { return nil }
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
package splitstore
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"golang.org/x/xerrors"
|
|
||||||
|
|
||||||
cid "github.com/ipfs/go-cid"
|
|
||||||
bolt "go.etcd.io/bbolt"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
|
||||||
)
|
|
||||||
|
|
||||||
type BoltTrackingStore struct {
|
|
||||||
db *bolt.DB
|
|
||||||
bucketId []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ TrackingStore = (*BoltTrackingStore)(nil)
|
|
||||||
|
|
||||||
func OpenBoltTrackingStore(path string) (*BoltTrackingStore, error) {
|
|
||||||
opts := &bolt.Options{
|
|
||||||
Timeout: 1 * time.Second,
|
|
||||||
NoSync: true,
|
|
||||||
}
|
|
||||||
db, err := bolt.Open(path, 0644, opts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
bucketId := []byte("tracker")
|
|
||||||
err = db.Update(func(tx *bolt.Tx) error {
|
|
||||||
_, err := tx.CreateBucketIfNotExists(bucketId)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("error creating bolt db bucket %s: %w", string(bucketId), err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
_ = db.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &BoltTrackingStore{db: db, bucketId: bucketId}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *BoltTrackingStore) Put(cid cid.Cid, epoch abi.ChainEpoch) error {
|
|
||||||
val := epochToBytes(epoch)
|
|
||||||
return s.db.Batch(func(tx *bolt.Tx) error {
|
|
||||||
b := tx.Bucket(s.bucketId)
|
|
||||||
return b.Put(cid.Hash(), val)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *BoltTrackingStore) PutBatch(cids []cid.Cid, epoch abi.ChainEpoch) error {
|
|
||||||
val := epochToBytes(epoch)
|
|
||||||
return s.db.Batch(func(tx *bolt.Tx) error {
|
|
||||||
b := tx.Bucket(s.bucketId)
|
|
||||||
for _, cid := range cids {
|
|
||||||
err := b.Put(cid.Hash(), val)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *BoltTrackingStore) Get(cid cid.Cid) (epoch abi.ChainEpoch, err error) {
|
|
||||||
err = s.db.View(func(tx *bolt.Tx) error {
|
|
||||||
b := tx.Bucket(s.bucketId)
|
|
||||||
val := b.Get(cid.Hash())
|
|
||||||
if val == nil {
|
|
||||||
return xerrors.Errorf("missing tracking epoch for %s", cid)
|
|
||||||
}
|
|
||||||
epoch = bytesToEpoch(val)
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
return epoch, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *BoltTrackingStore) Delete(cid cid.Cid) error {
|
|
||||||
return s.db.Batch(func(tx *bolt.Tx) error {
|
|
||||||
b := tx.Bucket(s.bucketId)
|
|
||||||
return b.Delete(cid.Hash())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *BoltTrackingStore) DeleteBatch(cids []cid.Cid) error {
|
|
||||||
return s.db.Batch(func(tx *bolt.Tx) error {
|
|
||||||
b := tx.Bucket(s.bucketId)
|
|
||||||
for _, cid := range cids {
|
|
||||||
err := b.Delete(cid.Hash())
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("error deleting %s", cid)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *BoltTrackingStore) ForEach(f func(cid.Cid, abi.ChainEpoch) error) error {
|
|
||||||
return s.db.View(func(tx *bolt.Tx) error {
|
|
||||||
b := tx.Bucket(s.bucketId)
|
|
||||||
return b.ForEach(func(k, v []byte) error {
|
|
||||||
cid := cid.NewCidV1(cid.Raw, k)
|
|
||||||
epoch := bytesToEpoch(v)
|
|
||||||
return f(cid, epoch)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *BoltTrackingStore) Sync() error {
|
|
||||||
return s.db.Sync()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *BoltTrackingStore) Close() error {
|
|
||||||
return s.db.Close()
|
|
||||||
}
|
|
||||||
@@ -1,130 +0,0 @@
|
|||||||
package splitstore
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/ioutil"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
cid "github.com/ipfs/go-cid"
|
|
||||||
"github.com/multiformats/go-multihash"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestBoltTrackingStore(t *testing.T) {
|
|
||||||
testTrackingStore(t, "bolt")
|
|
||||||
}
|
|
||||||
|
|
||||||
func testTrackingStore(t *testing.T, tsType string) {
|
|
||||||
t.Helper()
|
|
||||||
|
|
||||||
makeCid := func(key string) cid.Cid {
|
|
||||||
h, err := multihash.Sum([]byte(key), multihash.SHA2_256, -1)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return cid.NewCidV1(cid.Raw, h)
|
|
||||||
}
|
|
||||||
|
|
||||||
mustHave := func(s TrackingStore, cid cid.Cid, epoch abi.ChainEpoch) {
|
|
||||||
val, err := s.Get(cid)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if val != epoch {
|
|
||||||
t.Fatal("epoch mismatch")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mustNotHave := func(s TrackingStore, cid cid.Cid) {
|
|
||||||
_, err := s.Get(cid)
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("expected error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
path, err := ioutil.TempDir("", "snoop-test.*")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
s, err := OpenTrackingStore(path, tsType)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
k1 := makeCid("a")
|
|
||||||
k2 := makeCid("b")
|
|
||||||
k3 := makeCid("c")
|
|
||||||
k4 := makeCid("d")
|
|
||||||
|
|
||||||
s.Put(k1, 1) //nolint
|
|
||||||
s.Put(k2, 2) //nolint
|
|
||||||
s.Put(k3, 3) //nolint
|
|
||||||
s.Put(k4, 4) //nolint
|
|
||||||
|
|
||||||
mustHave(s, k1, 1)
|
|
||||||
mustHave(s, k2, 2)
|
|
||||||
mustHave(s, k3, 3)
|
|
||||||
mustHave(s, k4, 4)
|
|
||||||
|
|
||||||
s.Delete(k1) // nolint
|
|
||||||
s.Delete(k2) // nolint
|
|
||||||
|
|
||||||
mustNotHave(s, k1)
|
|
||||||
mustNotHave(s, k2)
|
|
||||||
mustHave(s, k3, 3)
|
|
||||||
mustHave(s, k4, 4)
|
|
||||||
|
|
||||||
s.PutBatch([]cid.Cid{k1}, 1) //nolint
|
|
||||||
s.PutBatch([]cid.Cid{k2}, 2) //nolint
|
|
||||||
|
|
||||||
mustHave(s, k1, 1)
|
|
||||||
mustHave(s, k2, 2)
|
|
||||||
mustHave(s, k3, 3)
|
|
||||||
mustHave(s, k4, 4)
|
|
||||||
|
|
||||||
allKeys := map[string]struct{}{
|
|
||||||
k1.String(): {},
|
|
||||||
k2.String(): {},
|
|
||||||
k3.String(): {},
|
|
||||||
k4.String(): {},
|
|
||||||
}
|
|
||||||
|
|
||||||
err = s.ForEach(func(k cid.Cid, _ abi.ChainEpoch) error {
|
|
||||||
_, ok := allKeys[k.String()]
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("unexpected key")
|
|
||||||
}
|
|
||||||
|
|
||||||
delete(allKeys, k.String())
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(allKeys) != 0 {
|
|
||||||
t.Fatal("not all keys were returned")
|
|
||||||
}
|
|
||||||
|
|
||||||
// no close and reopen and ensure the keys still exist
|
|
||||||
err = s.Close()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
s, err = OpenTrackingStore(path, tsType)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
mustHave(s, k1, 1)
|
|
||||||
mustHave(s, k2, 2)
|
|
||||||
mustHave(s, k3, 3)
|
|
||||||
mustHave(s, k4, 4)
|
|
||||||
|
|
||||||
s.Close() //nolint:errcheck
|
|
||||||
}
|
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
/dns4/bootstrap-0.interop.fildev.network/tcp/1347/p2p/12D3KooWN86wA54r3v9M8bBYbc1vK9W1ehHDxVGPRaoeUYuXF8R7
|
/dns4/bootstrap-0.interop.fildev.network/tcp/1347/p2p/12D3KooWLGPq9JL1xwL6gHok7HSNxtK1Q5kyfg4Hk69ifRPghn4i
|
||||||
/dns4/bootstrap-1.interop.fildev.network/tcp/1347/p2p/12D3KooWNZ41kev8mtBZgWe43qam1VX9pJyf87jnaisQP2urZZ2M
|
/dns4/bootstrap-1.interop.fildev.network/tcp/1347/p2p/12D3KooWFYS1f31zafv8mqqYu8U3hEqYvaZ6avWzYU3BmZdpyH3h
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+9
-8
@@ -28,18 +28,19 @@ var UpgradeAssemblyHeight = abi.ChainEpoch(-5)
|
|||||||
var UpgradeLiftoffHeight = abi.ChainEpoch(-6)
|
var UpgradeLiftoffHeight = abi.ChainEpoch(-6)
|
||||||
|
|
||||||
var UpgradeKumquatHeight = abi.ChainEpoch(-7)
|
var UpgradeKumquatHeight = abi.ChainEpoch(-7)
|
||||||
var UpgradeCalicoHeight = abi.ChainEpoch(-8)
|
var UpgradePricelistOopsHeight = abi.ChainEpoch(-8)
|
||||||
var UpgradePersianHeight = abi.ChainEpoch(-9)
|
var UpgradeCalicoHeight = abi.ChainEpoch(-9)
|
||||||
var UpgradeOrangeHeight = abi.ChainEpoch(-10)
|
var UpgradePersianHeight = abi.ChainEpoch(-10)
|
||||||
var UpgradeClausHeight = abi.ChainEpoch(-11)
|
var UpgradeOrangeHeight = abi.ChainEpoch(-11)
|
||||||
|
var UpgradeClausHeight = abi.ChainEpoch(-12)
|
||||||
|
|
||||||
var UpgradeTrustHeight = abi.ChainEpoch(-12)
|
var UpgradeTrustHeight = abi.ChainEpoch(-13)
|
||||||
|
|
||||||
var UpgradeNorwegianHeight = abi.ChainEpoch(-13)
|
var UpgradeNorwegianHeight = abi.ChainEpoch(-14)
|
||||||
|
|
||||||
var UpgradeTurboHeight = abi.ChainEpoch(-14)
|
var UpgradeTurboHeight = abi.ChainEpoch(-15)
|
||||||
|
|
||||||
var UpgradeHyperdriveHeight = abi.ChainEpoch(-15)
|
var UpgradeHyperdriveHeight = abi.ChainEpoch(-16)
|
||||||
|
|
||||||
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||||
0: DrandMainnet,
|
0: DrandMainnet,
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ var UpgradeAssemblyHeight = abi.ChainEpoch(30)
|
|||||||
const UpgradeTapeHeight = 60
|
const UpgradeTapeHeight = 60
|
||||||
const UpgradeLiftoffHeight = -5
|
const UpgradeLiftoffHeight = -5
|
||||||
const UpgradeKumquatHeight = 90
|
const UpgradeKumquatHeight = 90
|
||||||
|
const UpgradePricelistOopsHeight = 119
|
||||||
const UpgradeCalicoHeight = 120
|
const UpgradeCalicoHeight = 120
|
||||||
const UpgradePersianHeight = 150
|
const UpgradePersianHeight = 150
|
||||||
const UpgradeClausHeight = 180
|
const UpgradeClausHeight = 180
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ const UpgradeLiftoffHeight = -5
|
|||||||
|
|
||||||
const UpgradeKumquatHeight = 90
|
const UpgradeKumquatHeight = 90
|
||||||
|
|
||||||
|
const UpgradePricelistOopsHeight = 119
|
||||||
|
|
||||||
const UpgradeCalicoHeight = 120
|
const UpgradeCalicoHeight = 120
|
||||||
const UpgradePersianHeight = UpgradeCalicoHeight + (builtin2.EpochsInHour * 1)
|
const UpgradePersianHeight = UpgradeCalicoHeight + (builtin2.EpochsInHour * 1)
|
||||||
|
|
||||||
|
|||||||
@@ -31,18 +31,19 @@ var UpgradeAssemblyHeight = abi.ChainEpoch(-5)
|
|||||||
var UpgradeLiftoffHeight = abi.ChainEpoch(-6)
|
var UpgradeLiftoffHeight = abi.ChainEpoch(-6)
|
||||||
|
|
||||||
var UpgradeKumquatHeight = abi.ChainEpoch(-7)
|
var UpgradeKumquatHeight = abi.ChainEpoch(-7)
|
||||||
var UpgradeCalicoHeight = abi.ChainEpoch(-8)
|
var UpgradePricelistOopsHeight = abi.ChainEpoch(-8)
|
||||||
var UpgradePersianHeight = abi.ChainEpoch(-9)
|
var UpgradeCalicoHeight = abi.ChainEpoch(-9)
|
||||||
var UpgradeOrangeHeight = abi.ChainEpoch(-10)
|
var UpgradePersianHeight = abi.ChainEpoch(-10)
|
||||||
var UpgradeClausHeight = abi.ChainEpoch(-11)
|
var UpgradeOrangeHeight = abi.ChainEpoch(-11)
|
||||||
|
var UpgradeClausHeight = abi.ChainEpoch(-12)
|
||||||
|
|
||||||
var UpgradeTrustHeight = abi.ChainEpoch(-12)
|
var UpgradeTrustHeight = abi.ChainEpoch(-13)
|
||||||
|
|
||||||
var UpgradeNorwegianHeight = abi.ChainEpoch(-13)
|
var UpgradeNorwegianHeight = abi.ChainEpoch(-14)
|
||||||
|
|
||||||
var UpgradeTurboHeight = abi.ChainEpoch(-14)
|
var UpgradeTurboHeight = abi.ChainEpoch(-15)
|
||||||
|
|
||||||
var UpgradeHyperdriveHeight = abi.ChainEpoch(-15)
|
var UpgradeHyperdriveHeight = abi.ChainEpoch(-16)
|
||||||
|
|
||||||
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||||
0: DrandMainnet,
|
0: DrandMainnet,
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ const UpgradeLiftoffHeight = 148888
|
|||||||
|
|
||||||
const UpgradeKumquatHeight = 170000
|
const UpgradeKumquatHeight = 170000
|
||||||
|
|
||||||
|
const UpgradePricelistOopsHeight = 265199
|
||||||
const UpgradeCalicoHeight = 265200
|
const UpgradeCalicoHeight = 265200
|
||||||
const UpgradePersianHeight = UpgradeCalicoHeight + (builtin2.EpochsInHour * 60)
|
const UpgradePersianHeight = UpgradeCalicoHeight + (builtin2.EpochsInHour * 60)
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ const UpgradeTapeHeight = 60
|
|||||||
|
|
||||||
const UpgradeKumquatHeight = 90
|
const UpgradeKumquatHeight = 90
|
||||||
|
|
||||||
|
const UpgradePricelistOopsHeight = 99
|
||||||
const UpgradeCalicoHeight = 100
|
const UpgradeCalicoHeight = 100
|
||||||
const UpgradePersianHeight = UpgradeCalicoHeight + (builtin2.EpochsInHour * 1)
|
const UpgradePersianHeight = UpgradeCalicoHeight + (builtin2.EpochsInHour * 1)
|
||||||
|
|
||||||
@@ -42,7 +43,7 @@ const UpgradeOrangeHeight = 300
|
|||||||
const UpgradeTrustHeight = 600
|
const UpgradeTrustHeight = 600
|
||||||
const UpgradeNorwegianHeight = 201000
|
const UpgradeNorwegianHeight = 201000
|
||||||
const UpgradeTurboHeight = 203000
|
const UpgradeTurboHeight = 203000
|
||||||
const UpgradeHyperdriveHeight = 999999999
|
const UpgradeHyperdriveHeight = 379178
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// Minimum block production power is set to 4 TiB
|
// Minimum block production power is set to 4 TiB
|
||||||
|
|||||||
+16
-15
@@ -82,21 +82,22 @@ var (
|
|||||||
UpgradeBreezeHeight abi.ChainEpoch = -1
|
UpgradeBreezeHeight abi.ChainEpoch = -1
|
||||||
BreezeGasTampingDuration abi.ChainEpoch = 0
|
BreezeGasTampingDuration abi.ChainEpoch = 0
|
||||||
|
|
||||||
UpgradeSmokeHeight abi.ChainEpoch = -1
|
UpgradeSmokeHeight abi.ChainEpoch = -1
|
||||||
UpgradeIgnitionHeight abi.ChainEpoch = -2
|
UpgradeIgnitionHeight abi.ChainEpoch = -2
|
||||||
UpgradeRefuelHeight abi.ChainEpoch = -3
|
UpgradeRefuelHeight abi.ChainEpoch = -3
|
||||||
UpgradeTapeHeight abi.ChainEpoch = -4
|
UpgradeTapeHeight abi.ChainEpoch = -4
|
||||||
UpgradeAssemblyHeight abi.ChainEpoch = 10
|
UpgradeAssemblyHeight abi.ChainEpoch = 10
|
||||||
UpgradeLiftoffHeight abi.ChainEpoch = -5
|
UpgradeLiftoffHeight abi.ChainEpoch = -5
|
||||||
UpgradeKumquatHeight abi.ChainEpoch = -6
|
UpgradeKumquatHeight abi.ChainEpoch = -6
|
||||||
UpgradeCalicoHeight abi.ChainEpoch = -7
|
UpgradePricelistOopsHeight abi.ChainEpoch = -7
|
||||||
UpgradePersianHeight abi.ChainEpoch = -8
|
UpgradeCalicoHeight abi.ChainEpoch = -8
|
||||||
UpgradeOrangeHeight abi.ChainEpoch = -9
|
UpgradePersianHeight abi.ChainEpoch = -9
|
||||||
UpgradeClausHeight abi.ChainEpoch = -10
|
UpgradeOrangeHeight abi.ChainEpoch = -10
|
||||||
UpgradeTrustHeight abi.ChainEpoch = -11
|
UpgradeClausHeight abi.ChainEpoch = -11
|
||||||
UpgradeNorwegianHeight abi.ChainEpoch = -12
|
UpgradeTrustHeight abi.ChainEpoch = -12
|
||||||
UpgradeTurboHeight abi.ChainEpoch = -13
|
UpgradeNorwegianHeight abi.ChainEpoch = -13
|
||||||
UpgradeHyperdriveHeight abi.ChainEpoch = -13
|
UpgradeTurboHeight abi.ChainEpoch = -14
|
||||||
|
UpgradeHyperdriveHeight abi.ChainEpoch = -15
|
||||||
|
|
||||||
DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||||
0: DrandMainnet,
|
0: DrandMainnet,
|
||||||
|
|||||||
+1
-1
@@ -34,7 +34,7 @@ func buildType() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// BuildVersion is the local build version, set by build system
|
// BuildVersion is the local build version, set by build system
|
||||||
const BuildVersion = "1.11.0-rc2"
|
const BuildVersion = "1.11.1-rc1"
|
||||||
|
|
||||||
func UserVersion() string {
|
func UserVersion() string {
|
||||||
if os.Getenv("LOTUS_VERSION_IGNORE_COMMIT") == "1" {
|
if os.Getenv("LOTUS_VERSION_IGNORE_COMMIT") == "1" {
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ type State interface {
|
|||||||
// UnallocatedSectorNumbers returns up to count unallocated sector numbers (or less than
|
// UnallocatedSectorNumbers returns up to count unallocated sector numbers (or less than
|
||||||
// count if there aren't enough).
|
// count if there aren't enough).
|
||||||
UnallocatedSectorNumbers(count int) ([]abi.SectorNumber, error)
|
UnallocatedSectorNumbers(count int) ([]abi.SectorNumber, error)
|
||||||
|
GetAllocatedSectors() (*bitfield.BitField, error)
|
||||||
|
|
||||||
// Note that ProvingPeriodStart is deprecated and will be renamed / removed in a future version of actors
|
// Note that ProvingPeriodStart is deprecated and will be renamed / removed in a future version of actors
|
||||||
GetProvingPeriodStart() (abi.ChainEpoch, error)
|
GetProvingPeriodStart() (abi.ChainEpoch, error)
|
||||||
|
|||||||
@@ -164,6 +164,7 @@ type State interface {
|
|||||||
// UnallocatedSectorNumbers returns up to count unallocated sector numbers (or less than
|
// UnallocatedSectorNumbers returns up to count unallocated sector numbers (or less than
|
||||||
// count if there aren't enough).
|
// count if there aren't enough).
|
||||||
UnallocatedSectorNumbers(count int) ([]abi.SectorNumber, error)
|
UnallocatedSectorNumbers(count int) ([]abi.SectorNumber, error)
|
||||||
|
GetAllocatedSectors() (*bitfield.BitField, error)
|
||||||
|
|
||||||
// Note that ProvingPeriodStart is deprecated and will be renamed / removed in a future version of actors
|
// Note that ProvingPeriodStart is deprecated and will be renamed / removed in a future version of actors
|
||||||
GetProvingPeriodStart() (abi.ChainEpoch, error)
|
GetProvingPeriodStart() (abi.ChainEpoch, error)
|
||||||
|
|||||||
@@ -318,6 +318,15 @@ func (s *state{{.v}}) UnallocatedSectorNumbers(count int) ([]abi.SectorNumber, e
|
|||||||
return sectors, nil
|
return sectors, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *state{{.v}}) GetAllocatedSectors() (*bitfield.BitField, error) {
|
||||||
|
var allocatedSectors bitfield.BitField
|
||||||
|
if err := s.store.Get(s.store.Context(), s.State.AllocatedSectors, &allocatedSectors); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &allocatedSectors, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *state{{.v}}) LoadDeadline(idx uint64) (Deadline, error) {
|
func (s *state{{.v}}) LoadDeadline(idx uint64) (Deadline, error) {
|
||||||
dls, err := s.State.LoadDeadlines(s.store)
|
dls, err := s.State.LoadDeadlines(s.store)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -311,6 +311,15 @@ func (s *state0) UnallocatedSectorNumbers(count int) ([]abi.SectorNumber, error)
|
|||||||
return sectors, nil
|
return sectors, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *state0) GetAllocatedSectors() (*bitfield.BitField, error) {
|
||||||
|
var allocatedSectors bitfield.BitField
|
||||||
|
if err := s.store.Get(s.store.Context(), s.State.AllocatedSectors, &allocatedSectors); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &allocatedSectors, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *state0) LoadDeadline(idx uint64) (Deadline, error) {
|
func (s *state0) LoadDeadline(idx uint64) (Deadline, error) {
|
||||||
dls, err := s.State.LoadDeadlines(s.store)
|
dls, err := s.State.LoadDeadlines(s.store)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -309,6 +309,15 @@ func (s *state2) UnallocatedSectorNumbers(count int) ([]abi.SectorNumber, error)
|
|||||||
return sectors, nil
|
return sectors, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *state2) GetAllocatedSectors() (*bitfield.BitField, error) {
|
||||||
|
var allocatedSectors bitfield.BitField
|
||||||
|
if err := s.store.Get(s.store.Context(), s.State.AllocatedSectors, &allocatedSectors); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &allocatedSectors, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *state2) LoadDeadline(idx uint64) (Deadline, error) {
|
func (s *state2) LoadDeadline(idx uint64) (Deadline, error) {
|
||||||
dls, err := s.State.LoadDeadlines(s.store)
|
dls, err := s.State.LoadDeadlines(s.store)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -311,6 +311,15 @@ func (s *state3) UnallocatedSectorNumbers(count int) ([]abi.SectorNumber, error)
|
|||||||
return sectors, nil
|
return sectors, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *state3) GetAllocatedSectors() (*bitfield.BitField, error) {
|
||||||
|
var allocatedSectors bitfield.BitField
|
||||||
|
if err := s.store.Get(s.store.Context(), s.State.AllocatedSectors, &allocatedSectors); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &allocatedSectors, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *state3) LoadDeadline(idx uint64) (Deadline, error) {
|
func (s *state3) LoadDeadline(idx uint64) (Deadline, error) {
|
||||||
dls, err := s.State.LoadDeadlines(s.store)
|
dls, err := s.State.LoadDeadlines(s.store)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -311,6 +311,15 @@ func (s *state4) UnallocatedSectorNumbers(count int) ([]abi.SectorNumber, error)
|
|||||||
return sectors, nil
|
return sectors, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *state4) GetAllocatedSectors() (*bitfield.BitField, error) {
|
||||||
|
var allocatedSectors bitfield.BitField
|
||||||
|
if err := s.store.Get(s.store.Context(), s.State.AllocatedSectors, &allocatedSectors); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &allocatedSectors, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *state4) LoadDeadline(idx uint64) (Deadline, error) {
|
func (s *state4) LoadDeadline(idx uint64) (Deadline, error) {
|
||||||
dls, err := s.State.LoadDeadlines(s.store)
|
dls, err := s.State.LoadDeadlines(s.store)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -311,6 +311,15 @@ func (s *state5) UnallocatedSectorNumbers(count int) ([]abi.SectorNumber, error)
|
|||||||
return sectors, nil
|
return sectors, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *state5) GetAllocatedSectors() (*bitfield.BitField, error) {
|
||||||
|
var allocatedSectors bitfield.BitField
|
||||||
|
if err := s.store.Get(s.store.Context(), s.State.AllocatedSectors, &allocatedSectors); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &allocatedSectors, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *state5) LoadDeadline(idx uint64) (Deadline, error) {
|
func (s *state5) LoadDeadline(idx uint64) (Deadline, error) {
|
||||||
dls, err := s.State.LoadDeadlines(s.store)
|
dls, err := s.State.LoadDeadlines(s.store)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -196,6 +196,33 @@ func GetMaxProveCommitDuration(ver actors.Version, t abi.RegisteredSealProof) ab
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetProviderCollateralSupplyTarget sets the percentage of normalized circulating
|
||||||
|
// supply that must be covered by provider collateral in a deal. This should
|
||||||
|
// only be used for testing.
|
||||||
|
func SetProviderCollateralSupplyTarget(num, denom big.Int) {
|
||||||
|
|
||||||
|
market2.ProviderCollateralSupplyTarget = builtin2.BigFrac{
|
||||||
|
Numerator: num,
|
||||||
|
Denominator: denom,
|
||||||
|
}
|
||||||
|
|
||||||
|
market3.ProviderCollateralSupplyTarget = builtin3.BigFrac{
|
||||||
|
Numerator: num,
|
||||||
|
Denominator: denom,
|
||||||
|
}
|
||||||
|
|
||||||
|
market4.ProviderCollateralSupplyTarget = builtin4.BigFrac{
|
||||||
|
Numerator: num,
|
||||||
|
Denominator: denom,
|
||||||
|
}
|
||||||
|
|
||||||
|
market5.ProviderCollateralSupplyTarget = builtin5.BigFrac{
|
||||||
|
Numerator: num,
|
||||||
|
Denominator: denom,
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func DealProviderCollateralBounds(
|
func DealProviderCollateralBounds(
|
||||||
size abi.PaddedPieceSize, verified bool,
|
size abi.PaddedPieceSize, verified bool,
|
||||||
rawBytePower, qaPower, baselinePower abi.StoragePower,
|
rawBytePower, qaPower, baselinePower abi.StoragePower,
|
||||||
|
|||||||
@@ -132,6 +132,20 @@ func GetMaxProveCommitDuration(ver actors.Version, t abi.RegisteredSealProof) ab
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetProviderCollateralSupplyTarget sets the percentage of normalized circulating
|
||||||
|
// supply that must be covered by provider collateral in a deal. This should
|
||||||
|
// only be used for testing.
|
||||||
|
func SetProviderCollateralSupplyTarget(num, denom big.Int) {
|
||||||
|
{{range .versions}}
|
||||||
|
{{if (ge . 2)}}
|
||||||
|
market{{.}}.ProviderCollateralSupplyTarget = builtin{{.}}.BigFrac{
|
||||||
|
Numerator: num,
|
||||||
|
Denominator: denom,
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
}
|
||||||
|
|
||||||
func DealProviderCollateralBounds(
|
func DealProviderCollateralBounds(
|
||||||
size abi.PaddedPieceSize, verified bool,
|
size abi.PaddedPieceSize, verified bool,
|
||||||
rawBytePower, qaPower, baselinePower abi.StoragePower,
|
rawBytePower, qaPower, baselinePower abi.StoragePower,
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ func VersionForNetwork(version network.Version) Version {
|
|||||||
switch version {
|
switch version {
|
||||||
case network.Version0, network.Version1, network.Version2, network.Version3:
|
case network.Version0, network.Version1, network.Version2, network.Version3:
|
||||||
return Version0
|
return Version0
|
||||||
case network.Version4, network.Version5, network.Version6, network.Version7, network.Version8, network.Version9:
|
case network.Version4, network.Version5, network.Version6, network.Version6AndAHalf, network.Version7, network.Version8, network.Version9:
|
||||||
return Version2
|
return Version2
|
||||||
case network.Version10, network.Version11:
|
case network.Version10, network.Version11:
|
||||||
return Version3
|
return Version3
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/api"
|
||||||
|
lru "github.com/hashicorp/golang-lru"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
@@ -464,14 +467,20 @@ type messageEvents struct {
|
|||||||
|
|
||||||
lk sync.RWMutex
|
lk sync.RWMutex
|
||||||
matchers map[triggerID]MsgMatchFunc
|
matchers map[triggerID]MsgMatchFunc
|
||||||
|
|
||||||
|
blockMsgLk sync.Mutex
|
||||||
|
blockMsgCache *lru.ARCCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMessageEvents(ctx context.Context, hcAPI headChangeAPI, cs EventAPI) messageEvents {
|
func newMessageEvents(ctx context.Context, hcAPI headChangeAPI, cs EventAPI) messageEvents {
|
||||||
|
blsMsgCache, _ := lru.NewARC(500)
|
||||||
return messageEvents{
|
return messageEvents{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
cs: cs,
|
cs: cs,
|
||||||
hcAPI: hcAPI,
|
hcAPI: hcAPI,
|
||||||
matchers: make(map[triggerID]MsgMatchFunc),
|
matchers: make(map[triggerID]MsgMatchFunc),
|
||||||
|
blockMsgLk: sync.Mutex{},
|
||||||
|
blockMsgCache: blsMsgCache,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -515,14 +524,21 @@ func (me *messageEvents) messagesForTs(ts *types.TipSet, consume func(*types.Mes
|
|||||||
seen := map[cid.Cid]struct{}{}
|
seen := map[cid.Cid]struct{}{}
|
||||||
|
|
||||||
for _, tsb := range ts.Blocks() {
|
for _, tsb := range ts.Blocks() {
|
||||||
|
me.blockMsgLk.Lock()
|
||||||
msgs, err := me.cs.ChainGetBlockMessages(context.TODO(), tsb.Cid())
|
msgsI, ok := me.blockMsgCache.Get(tsb.Cid())
|
||||||
if err != nil {
|
var err error
|
||||||
log.Errorf("messagesForTs MessagesForBlock failed (ts.H=%d, Bcid:%s, B.Mcid:%s): %s", ts.Height(), tsb.Cid(), tsb.Messages, err)
|
if !ok {
|
||||||
// this is quite bad, but probably better than missing all the other updates
|
msgsI, err = me.cs.ChainGetBlockMessages(context.TODO(), tsb.Cid())
|
||||||
continue
|
if err != nil {
|
||||||
|
log.Errorf("messagesForTs MessagesForBlock failed (ts.H=%d, Bcid:%s, B.Mcid:%s): %s", ts.Height(), tsb.Cid(), tsb.Messages, err)
|
||||||
|
// this is quite bad, but probably better than missing all the other updates
|
||||||
|
me.blockMsgLk.Unlock()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
me.blockMsgCache.Add(tsb.Cid(), msgsI)
|
||||||
}
|
}
|
||||||
|
me.blockMsgLk.Unlock()
|
||||||
|
msgs := msgsI.(*api.BlockMessages)
|
||||||
for _, m := range msgs.BlsMessages {
|
for _, m := range msgs.BlsMessages {
|
||||||
_, ok := seen[m.Cid()]
|
_, ok := seen[m.Cid()]
|
||||||
if ok {
|
if ok {
|
||||||
|
|||||||
+129
-61
@@ -6,6 +6,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"gotest.tools/assert"
|
||||||
|
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
"github.com/multiformats/go-multihash"
|
"github.com/multiformats/go-multihash"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@@ -44,25 +46,43 @@ type fakeCS struct {
|
|||||||
tipsets map[types.TipSetKey]*types.TipSet
|
tipsets map[types.TipSetKey]*types.TipSet
|
||||||
|
|
||||||
sub func(rev, app []*types.TipSet)
|
sub func(rev, app []*types.TipSet)
|
||||||
|
|
||||||
|
callNumberLk sync.Mutex
|
||||||
|
callNumber map[string]int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fcs *fakeCS) ChainHead(ctx context.Context) (*types.TipSet, error) {
|
func (fcs *fakeCS) ChainHead(ctx context.Context) (*types.TipSet, error) {
|
||||||
|
fcs.callNumberLk.Lock()
|
||||||
|
defer fcs.callNumberLk.Unlock()
|
||||||
|
fcs.callNumber["ChainHead"] = fcs.callNumber["ChainHead"] + 1
|
||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fcs *fakeCS) ChainGetTipSet(ctx context.Context, key types.TipSetKey) (*types.TipSet, error) {
|
func (fcs *fakeCS) ChainGetTipSet(ctx context.Context, key types.TipSetKey) (*types.TipSet, error) {
|
||||||
|
fcs.callNumberLk.Lock()
|
||||||
|
defer fcs.callNumberLk.Unlock()
|
||||||
|
fcs.callNumber["ChainGetTipSet"] = fcs.callNumber["ChainGetTipSet"] + 1
|
||||||
return fcs.tipsets[key], nil
|
return fcs.tipsets[key], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fcs *fakeCS) StateSearchMsg(ctx context.Context, from types.TipSetKey, msg cid.Cid, limit abi.ChainEpoch, allowReplaced bool) (*api.MsgLookup, error) {
|
func (fcs *fakeCS) StateSearchMsg(ctx context.Context, from types.TipSetKey, msg cid.Cid, limit abi.ChainEpoch, allowReplaced bool) (*api.MsgLookup, error) {
|
||||||
|
fcs.callNumberLk.Lock()
|
||||||
|
defer fcs.callNumberLk.Unlock()
|
||||||
|
fcs.callNumber["StateSearchMsg"] = fcs.callNumber["StateSearchMsg"] + 1
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fcs *fakeCS) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) {
|
func (fcs *fakeCS) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) {
|
||||||
|
fcs.callNumberLk.Lock()
|
||||||
|
defer fcs.callNumberLk.Unlock()
|
||||||
|
fcs.callNumber["StateGetActor"] = fcs.callNumber["StateGetActor"] + 1
|
||||||
panic("Not Implemented")
|
panic("Not Implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fcs *fakeCS) ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) {
|
func (fcs *fakeCS) ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) {
|
||||||
|
fcs.callNumberLk.Lock()
|
||||||
|
defer fcs.callNumberLk.Unlock()
|
||||||
|
fcs.callNumber["ChainGetTipSetByHeight"] = fcs.callNumber["ChainGetTipSetByHeight"] + 1
|
||||||
panic("Not Implemented")
|
panic("Not Implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,6 +133,10 @@ func (fcs *fakeCS) makeTs(t *testing.T, parents []cid.Cid, h abi.ChainEpoch, msg
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fcs *fakeCS) ChainNotify(context.Context) (<-chan []*api.HeadChange, error) {
|
func (fcs *fakeCS) ChainNotify(context.Context) (<-chan []*api.HeadChange, error) {
|
||||||
|
fcs.callNumberLk.Lock()
|
||||||
|
defer fcs.callNumberLk.Unlock()
|
||||||
|
fcs.callNumber["ChainNotify"] = fcs.callNumber["ChainNotify"] + 1
|
||||||
|
|
||||||
out := make(chan []*api.HeadChange, 1)
|
out := make(chan []*api.HeadChange, 1)
|
||||||
best, err := fcs.tsc.best()
|
best, err := fcs.tsc.best()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -143,6 +167,9 @@ func (fcs *fakeCS) ChainNotify(context.Context) (<-chan []*api.HeadChange, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fcs *fakeCS) ChainGetBlockMessages(ctx context.Context, blk cid.Cid) (*api.BlockMessages, error) {
|
func (fcs *fakeCS) ChainGetBlockMessages(ctx context.Context, blk cid.Cid) (*api.BlockMessages, error) {
|
||||||
|
fcs.callNumberLk.Lock()
|
||||||
|
defer fcs.callNumberLk.Unlock()
|
||||||
|
fcs.callNumber["ChainGetBlockMessages"] = fcs.callNumber["ChainGetBlockMessages"] + 1
|
||||||
messages, ok := fcs.blkMsgs[blk]
|
messages, ok := fcs.blkMsgs[blk]
|
||||||
if !ok {
|
if !ok {
|
||||||
return &api.BlockMessages{}, nil
|
return &api.BlockMessages{}, nil
|
||||||
@@ -152,8 +179,8 @@ func (fcs *fakeCS) ChainGetBlockMessages(ctx context.Context, blk cid.Cid) (*api
|
|||||||
if !ok {
|
if !ok {
|
||||||
return &api.BlockMessages{}, nil
|
return &api.BlockMessages{}, nil
|
||||||
}
|
}
|
||||||
return &api.BlockMessages{BlsMessages: ms.bmsgs, SecpkMessages: ms.smsgs}, nil
|
|
||||||
|
|
||||||
|
return &api.BlockMessages{BlsMessages: ms.bmsgs, SecpkMessages: ms.smsgs}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fcs *fakeCS) fakeMsgs(m fakeMsg) cid.Cid {
|
func (fcs *fakeCS) fakeMsgs(m fakeMsg) cid.Cid {
|
||||||
@@ -233,9 +260,10 @@ var _ EventAPI = &fakeCS{}
|
|||||||
|
|
||||||
func TestAt(t *testing.T) {
|
func TestAt(t *testing.T) {
|
||||||
fcs := &fakeCS{
|
fcs := &fakeCS{
|
||||||
t: t,
|
t: t,
|
||||||
h: 1,
|
h: 1,
|
||||||
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
||||||
|
callNumber: map[string]int{},
|
||||||
}
|
}
|
||||||
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
||||||
|
|
||||||
@@ -298,9 +326,10 @@ func TestAt(t *testing.T) {
|
|||||||
|
|
||||||
func TestAtDoubleTrigger(t *testing.T) {
|
func TestAtDoubleTrigger(t *testing.T) {
|
||||||
fcs := &fakeCS{
|
fcs := &fakeCS{
|
||||||
t: t,
|
t: t,
|
||||||
h: 1,
|
h: 1,
|
||||||
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
||||||
|
callNumber: map[string]int{},
|
||||||
}
|
}
|
||||||
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
||||||
|
|
||||||
@@ -340,9 +369,10 @@ func TestAtDoubleTrigger(t *testing.T) {
|
|||||||
|
|
||||||
func TestAtNullTrigger(t *testing.T) {
|
func TestAtNullTrigger(t *testing.T) {
|
||||||
fcs := &fakeCS{
|
fcs := &fakeCS{
|
||||||
t: t,
|
t: t,
|
||||||
h: 1,
|
h: 1,
|
||||||
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
||||||
|
callNumber: map[string]int{},
|
||||||
}
|
}
|
||||||
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
||||||
|
|
||||||
@@ -374,9 +404,10 @@ func TestAtNullTrigger(t *testing.T) {
|
|||||||
|
|
||||||
func TestAtNullConf(t *testing.T) {
|
func TestAtNullConf(t *testing.T) {
|
||||||
fcs := &fakeCS{
|
fcs := &fakeCS{
|
||||||
t: t,
|
t: t,
|
||||||
h: 1,
|
h: 1,
|
||||||
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
||||||
|
callNumber: map[string]int{},
|
||||||
}
|
}
|
||||||
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
||||||
|
|
||||||
@@ -413,9 +444,10 @@ func TestAtNullConf(t *testing.T) {
|
|||||||
|
|
||||||
func TestAtStart(t *testing.T) {
|
func TestAtStart(t *testing.T) {
|
||||||
fcs := &fakeCS{
|
fcs := &fakeCS{
|
||||||
t: t,
|
t: t,
|
||||||
h: 1,
|
h: 1,
|
||||||
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
||||||
|
callNumber: map[string]int{},
|
||||||
}
|
}
|
||||||
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
||||||
|
|
||||||
@@ -447,9 +479,10 @@ func TestAtStart(t *testing.T) {
|
|||||||
|
|
||||||
func TestAtStartConfidence(t *testing.T) {
|
func TestAtStartConfidence(t *testing.T) {
|
||||||
fcs := &fakeCS{
|
fcs := &fakeCS{
|
||||||
t: t,
|
t: t,
|
||||||
h: 1,
|
h: 1,
|
||||||
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
||||||
|
callNumber: map[string]int{},
|
||||||
}
|
}
|
||||||
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
||||||
|
|
||||||
@@ -477,9 +510,10 @@ func TestAtStartConfidence(t *testing.T) {
|
|||||||
|
|
||||||
func TestAtChained(t *testing.T) {
|
func TestAtChained(t *testing.T) {
|
||||||
fcs := &fakeCS{
|
fcs := &fakeCS{
|
||||||
t: t,
|
t: t,
|
||||||
h: 1,
|
h: 1,
|
||||||
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
||||||
|
callNumber: map[string]int{},
|
||||||
}
|
}
|
||||||
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
||||||
|
|
||||||
@@ -511,9 +545,10 @@ func TestAtChained(t *testing.T) {
|
|||||||
|
|
||||||
func TestAtChainedConfidence(t *testing.T) {
|
func TestAtChainedConfidence(t *testing.T) {
|
||||||
fcs := &fakeCS{
|
fcs := &fakeCS{
|
||||||
t: t,
|
t: t,
|
||||||
h: 1,
|
h: 1,
|
||||||
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
||||||
|
callNumber: map[string]int{},
|
||||||
}
|
}
|
||||||
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
||||||
|
|
||||||
@@ -545,9 +580,10 @@ func TestAtChainedConfidence(t *testing.T) {
|
|||||||
|
|
||||||
func TestAtChainedConfidenceNull(t *testing.T) {
|
func TestAtChainedConfidenceNull(t *testing.T) {
|
||||||
fcs := &fakeCS{
|
fcs := &fakeCS{
|
||||||
t: t,
|
t: t,
|
||||||
h: 1,
|
h: 1,
|
||||||
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
||||||
|
callNumber: map[string]int{},
|
||||||
}
|
}
|
||||||
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
||||||
|
|
||||||
@@ -583,9 +619,10 @@ func TestCalled(t *testing.T) {
|
|||||||
t: t,
|
t: t,
|
||||||
h: 1,
|
h: 1,
|
||||||
|
|
||||||
msgs: map[cid.Cid]fakeMsg{},
|
msgs: map[cid.Cid]fakeMsg{},
|
||||||
blkMsgs: map[cid.Cid]cid.Cid{},
|
blkMsgs: map[cid.Cid]cid.Cid{},
|
||||||
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
||||||
|
callNumber: map[string]int{},
|
||||||
}
|
}
|
||||||
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
||||||
|
|
||||||
@@ -795,9 +832,10 @@ func TestCalledTimeout(t *testing.T) {
|
|||||||
t: t,
|
t: t,
|
||||||
h: 1,
|
h: 1,
|
||||||
|
|
||||||
msgs: map[cid.Cid]fakeMsg{},
|
msgs: map[cid.Cid]fakeMsg{},
|
||||||
blkMsgs: map[cid.Cid]cid.Cid{},
|
blkMsgs: map[cid.Cid]cid.Cid{},
|
||||||
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
||||||
|
callNumber: map[string]int{},
|
||||||
}
|
}
|
||||||
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
||||||
|
|
||||||
@@ -835,9 +873,10 @@ func TestCalledTimeout(t *testing.T) {
|
|||||||
t: t,
|
t: t,
|
||||||
h: 1,
|
h: 1,
|
||||||
|
|
||||||
msgs: map[cid.Cid]fakeMsg{},
|
msgs: map[cid.Cid]fakeMsg{},
|
||||||
blkMsgs: map[cid.Cid]cid.Cid{},
|
blkMsgs: map[cid.Cid]cid.Cid{},
|
||||||
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
callNumber: map[string]int{},
|
||||||
|
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
||||||
}
|
}
|
||||||
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
||||||
|
|
||||||
@@ -869,9 +908,10 @@ func TestCalledOrder(t *testing.T) {
|
|||||||
t: t,
|
t: t,
|
||||||
h: 1,
|
h: 1,
|
||||||
|
|
||||||
msgs: map[cid.Cid]fakeMsg{},
|
msgs: map[cid.Cid]fakeMsg{},
|
||||||
blkMsgs: map[cid.Cid]cid.Cid{},
|
blkMsgs: map[cid.Cid]cid.Cid{},
|
||||||
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
||||||
|
callNumber: map[string]int{},
|
||||||
}
|
}
|
||||||
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
||||||
|
|
||||||
@@ -932,9 +972,10 @@ func TestCalledNull(t *testing.T) {
|
|||||||
t: t,
|
t: t,
|
||||||
h: 1,
|
h: 1,
|
||||||
|
|
||||||
msgs: map[cid.Cid]fakeMsg{},
|
msgs: map[cid.Cid]fakeMsg{},
|
||||||
blkMsgs: map[cid.Cid]cid.Cid{},
|
blkMsgs: map[cid.Cid]cid.Cid{},
|
||||||
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
||||||
|
callNumber: map[string]int{},
|
||||||
}
|
}
|
||||||
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
||||||
|
|
||||||
@@ -997,9 +1038,10 @@ func TestRemoveTriggersOnMessage(t *testing.T) {
|
|||||||
t: t,
|
t: t,
|
||||||
h: 1,
|
h: 1,
|
||||||
|
|
||||||
msgs: map[cid.Cid]fakeMsg{},
|
msgs: map[cid.Cid]fakeMsg{},
|
||||||
blkMsgs: map[cid.Cid]cid.Cid{},
|
blkMsgs: map[cid.Cid]cid.Cid{},
|
||||||
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
||||||
|
callNumber: map[string]int{},
|
||||||
}
|
}
|
||||||
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
||||||
|
|
||||||
@@ -1087,9 +1129,10 @@ func TestStateChanged(t *testing.T) {
|
|||||||
t: t,
|
t: t,
|
||||||
h: 1,
|
h: 1,
|
||||||
|
|
||||||
msgs: map[cid.Cid]fakeMsg{},
|
msgs: map[cid.Cid]fakeMsg{},
|
||||||
blkMsgs: map[cid.Cid]cid.Cid{},
|
blkMsgs: map[cid.Cid]cid.Cid{},
|
||||||
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
||||||
|
callNumber: map[string]int{},
|
||||||
}
|
}
|
||||||
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
||||||
|
|
||||||
@@ -1175,9 +1218,10 @@ func TestStateChangedRevert(t *testing.T) {
|
|||||||
t: t,
|
t: t,
|
||||||
h: 1,
|
h: 1,
|
||||||
|
|
||||||
msgs: map[cid.Cid]fakeMsg{},
|
msgs: map[cid.Cid]fakeMsg{},
|
||||||
blkMsgs: map[cid.Cid]cid.Cid{},
|
blkMsgs: map[cid.Cid]cid.Cid{},
|
||||||
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
||||||
|
callNumber: map[string]int{},
|
||||||
}
|
}
|
||||||
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
||||||
|
|
||||||
@@ -1253,9 +1297,10 @@ func TestStateChangedTimeout(t *testing.T) {
|
|||||||
t: t,
|
t: t,
|
||||||
h: 1,
|
h: 1,
|
||||||
|
|
||||||
msgs: map[cid.Cid]fakeMsg{},
|
msgs: map[cid.Cid]fakeMsg{},
|
||||||
blkMsgs: map[cid.Cid]cid.Cid{},
|
blkMsgs: map[cid.Cid]cid.Cid{},
|
||||||
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
||||||
|
callNumber: map[string]int{},
|
||||||
}
|
}
|
||||||
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
||||||
|
|
||||||
@@ -1293,9 +1338,10 @@ func TestStateChangedTimeout(t *testing.T) {
|
|||||||
t: t,
|
t: t,
|
||||||
h: 1,
|
h: 1,
|
||||||
|
|
||||||
msgs: map[cid.Cid]fakeMsg{},
|
msgs: map[cid.Cid]fakeMsg{},
|
||||||
blkMsgs: map[cid.Cid]cid.Cid{},
|
blkMsgs: map[cid.Cid]cid.Cid{},
|
||||||
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
callNumber: map[string]int{},
|
||||||
|
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
||||||
}
|
}
|
||||||
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
||||||
|
|
||||||
@@ -1329,9 +1375,10 @@ func TestCalledMultiplePerEpoch(t *testing.T) {
|
|||||||
t: t,
|
t: t,
|
||||||
h: 1,
|
h: 1,
|
||||||
|
|
||||||
msgs: map[cid.Cid]fakeMsg{},
|
msgs: map[cid.Cid]fakeMsg{},
|
||||||
blkMsgs: map[cid.Cid]cid.Cid{},
|
blkMsgs: map[cid.Cid]cid.Cid{},
|
||||||
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
callNumber: map[string]int{},
|
||||||
|
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
||||||
}
|
}
|
||||||
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
||||||
|
|
||||||
@@ -1382,3 +1429,24 @@ func TestCalledMultiplePerEpoch(t *testing.T) {
|
|||||||
|
|
||||||
fcs.advance(9, 1, nil)
|
fcs.advance(9, 1, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCachedSameBlock(t *testing.T) {
|
||||||
|
fcs := &fakeCS{
|
||||||
|
t: t,
|
||||||
|
h: 1,
|
||||||
|
|
||||||
|
msgs: map[cid.Cid]fakeMsg{},
|
||||||
|
blkMsgs: map[cid.Cid]cid.Cid{},
|
||||||
|
callNumber: map[string]int{},
|
||||||
|
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
||||||
|
}
|
||||||
|
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
|
||||||
|
|
||||||
|
_ = NewEvents(context.Background(), fcs)
|
||||||
|
|
||||||
|
fcs.advance(0, 10, map[int]cid.Cid{})
|
||||||
|
assert.Assert(t, fcs.callNumber["ChainGetBlockMessages"] == 20, "expect call ChainGetBlockMessages %d but got ", 20, fcs.callNumber["ChainGetBlockMessages"])
|
||||||
|
|
||||||
|
fcs.advance(5, 10, map[int]cid.Cid{})
|
||||||
|
assert.Assert(t, fcs.callNumber["ChainGetBlockMessages"] == 30, "expect call ChainGetBlockMessages %d but got ", 30, fcs.callNumber["ChainGetBlockMessages"])
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import (
|
|||||||
market2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/market"
|
market2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/market"
|
||||||
miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner"
|
miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner"
|
||||||
adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt"
|
adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt"
|
||||||
tutils "github.com/filecoin-project/specs-actors/v2/support/testing"
|
tutils "github.com/filecoin-project/specs-actors/v5/support/testing"
|
||||||
|
|
||||||
bstore "github.com/filecoin-project/lotus/blockstore"
|
bstore "github.com/filecoin-project/lotus/blockstore"
|
||||||
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
|
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package exchange
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"math"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
types "github.com/filecoin-project/lotus/chain/types"
|
types "github.com/filecoin-project/lotus/chain/types"
|
||||||
@@ -15,6 +16,7 @@ import (
|
|||||||
|
|
||||||
var _ = xerrors.Errorf
|
var _ = xerrors.Errorf
|
||||||
var _ = cid.Undef
|
var _ = cid.Undef
|
||||||
|
var _ = math.E
|
||||||
var _ = sort.Sort
|
var _ = sort.Sort
|
||||||
|
|
||||||
var lengthBufRequest = []byte{131}
|
var lengthBufRequest = []byte{131}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package market
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"math"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
cid "github.com/ipfs/go-cid"
|
cid "github.com/ipfs/go-cid"
|
||||||
@@ -14,6 +15,7 @@ import (
|
|||||||
|
|
||||||
var _ = xerrors.Errorf
|
var _ = xerrors.Errorf
|
||||||
var _ = cid.Undef
|
var _ = cid.Undef
|
||||||
|
var _ = math.E
|
||||||
var _ = sort.Sort
|
var _ = sort.Sort
|
||||||
|
|
||||||
var lengthBufFundedAddressState = []byte{131}
|
var lengthBufFundedAddressState = []byte{131}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import (
|
|||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/go-state-types/big"
|
"github.com/filecoin-project/go-state-types/big"
|
||||||
"github.com/filecoin-project/lotus/api"
|
"github.com/filecoin-project/lotus/api"
|
||||||
"github.com/filecoin-project/lotus/build"
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/filecoin-project/lotus/chain/vm"
|
"github.com/filecoin-project/lotus/chain/vm"
|
||||||
)
|
)
|
||||||
@@ -259,8 +258,14 @@ func (mp *MessagePool) checkMessages(ctx context.Context, msgs []*types.Message,
|
|||||||
Code: api.CheckStatusMessageValidity,
|
Code: api.CheckStatusMessageValidity,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
nv, err := mp.getNtwkVersion(epoch)
|
||||||
if err := m.ValidForBlockInclusion(0, build.NewestNetworkVersion); err != nil {
|
if err != nil {
|
||||||
|
check.OK = false
|
||||||
|
check.Err = fmt.Sprintf("error retrieving network version: %s", err.Error())
|
||||||
|
} else {
|
||||||
|
check.OK = true
|
||||||
|
}
|
||||||
|
if err := m.ValidForBlockInclusion(0, nv); err != nil {
|
||||||
check.OK = false
|
check.OK = false
|
||||||
check.Err = fmt.Sprintf("syntactically invalid message: %s", err.Error())
|
check.Err = fmt.Sprintf("syntactically invalid message: %s", err.Error())
|
||||||
} else {
|
} else {
|
||||||
@@ -276,7 +281,7 @@ func (mp *MessagePool) checkMessages(ctx context.Context, msgs []*types.Message,
|
|||||||
// gas checks
|
// gas checks
|
||||||
|
|
||||||
// 4. Min Gas
|
// 4. Min Gas
|
||||||
minGas := vm.PricelistByEpoch(epoch).OnChainMessage(m.ChainLength())
|
minGas := vm.PricelistByVersion(nv).OnChainMessage(m.ChainLength())
|
||||||
|
|
||||||
check = api.MessageCheckStatus{
|
check = api.MessageCheckStatus{
|
||||||
Cid: m.Cid(),
|
Cid: m.Cid(),
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/filecoin-project/go-state-types/abi"
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
"github.com/filecoin-project/go-state-types/big"
|
"github.com/filecoin-project/go-state-types/big"
|
||||||
"github.com/filecoin-project/go-state-types/crypto"
|
"github.com/filecoin-project/go-state-types/crypto"
|
||||||
|
"github.com/filecoin-project/go-state-types/network"
|
||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
lru "github.com/hashicorp/golang-lru"
|
lru "github.com/hashicorp/golang-lru"
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
@@ -29,6 +30,7 @@ import (
|
|||||||
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
"github.com/filecoin-project/lotus/api"
|
||||||
"github.com/filecoin-project/lotus/build"
|
"github.com/filecoin-project/lotus/build"
|
||||||
|
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||||
"github.com/filecoin-project/lotus/chain/store"
|
"github.com/filecoin-project/lotus/chain/store"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/filecoin-project/lotus/chain/vm"
|
"github.com/filecoin-project/lotus/chain/vm"
|
||||||
@@ -147,6 +149,8 @@ type MessagePool struct {
|
|||||||
|
|
||||||
minGasPrice types.BigInt
|
minGasPrice types.BigInt
|
||||||
|
|
||||||
|
getNtwkVersion func(abi.ChainEpoch) (network.Version, error)
|
||||||
|
|
||||||
currentSize int
|
currentSize int
|
||||||
|
|
||||||
// pruneTrigger is a channel used to trigger a mempool pruning
|
// pruneTrigger is a channel used to trigger a mempool pruning
|
||||||
@@ -362,26 +366,28 @@ func New(api Provider, ds dtypes.MetadataDS, netName dtypes.NetworkName, j journ
|
|||||||
if j == nil {
|
if j == nil {
|
||||||
j = journal.NilJournal()
|
j = journal.NilJournal()
|
||||||
}
|
}
|
||||||
|
us := stmgr.DefaultUpgradeSchedule()
|
||||||
|
|
||||||
mp := &MessagePool{
|
mp := &MessagePool{
|
||||||
ds: ds,
|
ds: ds,
|
||||||
addSema: make(chan struct{}, 1),
|
addSema: make(chan struct{}, 1),
|
||||||
closer: make(chan struct{}),
|
closer: make(chan struct{}),
|
||||||
repubTk: build.Clock.Ticker(RepublishInterval),
|
repubTk: build.Clock.Ticker(RepublishInterval),
|
||||||
repubTrigger: make(chan struct{}, 1),
|
repubTrigger: make(chan struct{}, 1),
|
||||||
localAddrs: make(map[address.Address]struct{}),
|
localAddrs: make(map[address.Address]struct{}),
|
||||||
pending: make(map[address.Address]*msgSet),
|
pending: make(map[address.Address]*msgSet),
|
||||||
keyCache: make(map[address.Address]address.Address),
|
keyCache: make(map[address.Address]address.Address),
|
||||||
minGasPrice: types.NewInt(0),
|
minGasPrice: types.NewInt(0),
|
||||||
pruneTrigger: make(chan struct{}, 1),
|
getNtwkVersion: us.GetNtwkVersion,
|
||||||
pruneCooldown: make(chan struct{}, 1),
|
pruneTrigger: make(chan struct{}, 1),
|
||||||
blsSigCache: cache,
|
pruneCooldown: make(chan struct{}, 1),
|
||||||
sigValCache: verifcache,
|
blsSigCache: cache,
|
||||||
changes: lps.New(50),
|
sigValCache: verifcache,
|
||||||
localMsgs: namespace.Wrap(ds, datastore.NewKey(localMsgsDs)),
|
changes: lps.New(50),
|
||||||
api: api,
|
localMsgs: namespace.Wrap(ds, datastore.NewKey(localMsgsDs)),
|
||||||
netName: netName,
|
api: api,
|
||||||
cfg: cfg,
|
netName: netName,
|
||||||
|
cfg: cfg,
|
||||||
evtTypes: [...]journal.EventType{
|
evtTypes: [...]journal.EventType{
|
||||||
evtTypeMpoolAdd: j.RegisterEventType("mpool", "add"),
|
evtTypeMpoolAdd: j.RegisterEventType("mpool", "add"),
|
||||||
evtTypeMpoolRemove: j.RegisterEventType("mpool", "remove"),
|
evtTypeMpoolRemove: j.RegisterEventType("mpool", "remove"),
|
||||||
@@ -426,6 +432,27 @@ func New(api Provider, ds dtypes.MetadataDS, netName dtypes.NetworkName, j journ
|
|||||||
return mp, nil
|
return mp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (mp *MessagePool) ForEachPendingMessage(f func(cid.Cid) error) error {
|
||||||
|
mp.lk.Lock()
|
||||||
|
defer mp.lk.Unlock()
|
||||||
|
|
||||||
|
for _, mset := range mp.pending {
|
||||||
|
for _, m := range mset.msgs {
|
||||||
|
err := f(m.Cid())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = f(m.Message.Cid())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (mp *MessagePool) resolveToKey(ctx context.Context, addr address.Address) (address.Address, error) {
|
func (mp *MessagePool) resolveToKey(ctx context.Context, addr address.Address) (address.Address, error) {
|
||||||
// check the cache
|
// check the cache
|
||||||
a, f := mp.keyCache[addr]
|
a, f := mp.keyCache[addr]
|
||||||
@@ -589,8 +616,7 @@ func (mp *MessagePool) addLocal(ctx context.Context, m *types.SignedMessage) err
|
|||||||
// For non local messages, if the message cannot be included in the next 20 blocks it returns
|
// For non local messages, if the message cannot be included in the next 20 blocks it returns
|
||||||
// a (soft) validation error.
|
// a (soft) validation error.
|
||||||
func (mp *MessagePool) verifyMsgBeforeAdd(m *types.SignedMessage, curTs *types.TipSet, local bool) (bool, error) {
|
func (mp *MessagePool) verifyMsgBeforeAdd(m *types.SignedMessage, curTs *types.TipSet, local bool) (bool, error) {
|
||||||
epoch := curTs.Height()
|
minGas := vm.PricelistByVersion(build.NewestNetworkVersion).OnChainMessage(m.ChainLength())
|
||||||
minGas := vm.PricelistByEpoch(epoch).OnChainMessage(m.ChainLength())
|
|
||||||
|
|
||||||
if err := m.VMMessage().ValidForBlockInclusion(minGas.Total(), build.NewestNetworkVersion); err != nil {
|
if err := m.VMMessage().ValidForBlockInclusion(minGas.Total(), build.NewestNetworkVersion); err != nil {
|
||||||
return false, xerrors.Errorf("message will not be included in a block: %w", err)
|
return false, xerrors.Errorf("message will not be included in a block: %w", err)
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ func (tma *testMpoolAPI) SubscribeHeadChanges(cb func(rev, app []*types.TipSet)
|
|||||||
func (tma *testMpoolAPI) PutMessage(m types.ChainMsg) (cid.Cid, error) {
|
func (tma *testMpoolAPI) PutMessage(m types.ChainMsg) (cid.Cid, error) {
|
||||||
return cid.Undef, nil
|
return cid.Undef, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tma *testMpoolAPI) IsLite() bool {
|
func (tma *testMpoolAPI) IsLite() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -286,7 +287,7 @@ func TestCheckMessageBig(t *testing.T) {
|
|||||||
From: from,
|
From: from,
|
||||||
Value: types.NewInt(1),
|
Value: types.NewInt(1),
|
||||||
Nonce: 0,
|
Nonce: 0,
|
||||||
GasLimit: 50000000,
|
GasLimit: 60000000,
|
||||||
GasFeeCap: types.NewInt(100),
|
GasFeeCap: types.NewInt(100),
|
||||||
GasPremium: types.NewInt(1),
|
GasPremium: types.NewInt(1),
|
||||||
Params: make([]byte, 41<<10), // 41KiB payload
|
Params: make([]byte, 41<<10), // 41KiB payload
|
||||||
|
|||||||
@@ -749,7 +749,7 @@ func (mp *MessagePool) createMessageChains(actor address.Address, mset map[uint6
|
|||||||
}
|
}
|
||||||
curNonce++
|
curNonce++
|
||||||
|
|
||||||
minGas := vm.PricelistByEpoch(ts.Height()).OnChainMessage(m.ChainLength()).Total()
|
minGas := vm.PricelistByVersion(build.NewestNetworkVersion).OnChainMessage(m.ChainLength()).Total()
|
||||||
if m.Message.GasLimit < minGas {
|
if m.Message.GasLimit < minGas {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
+31
-26
@@ -547,7 +547,7 @@ func (st *StateTree) Version() types.StateTreeVersion {
|
|||||||
return st.version
|
return st.version
|
||||||
}
|
}
|
||||||
|
|
||||||
func Diff(oldTree, newTree *StateTree) (map[string]types.Actor, error) {
|
func Diff(ctx context.Context, oldTree, newTree *StateTree) (map[string]types.Actor, error) {
|
||||||
out := map[string]types.Actor{}
|
out := map[string]types.Actor{}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -555,33 +555,38 @@ func Diff(oldTree, newTree *StateTree) (map[string]types.Actor, error) {
|
|||||||
buf = bytes.NewReader(nil)
|
buf = bytes.NewReader(nil)
|
||||||
)
|
)
|
||||||
if err := newTree.root.ForEach(&ncval, func(k string) error {
|
if err := newTree.root.ForEach(&ncval, func(k string) error {
|
||||||
var act types.Actor
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
default:
|
||||||
|
var act types.Actor
|
||||||
|
|
||||||
addr, err := address.NewFromBytes([]byte(k))
|
addr, err := address.NewFromBytes([]byte(k))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("address in state tree was not valid: %w", err)
|
return xerrors.Errorf("address in state tree was not valid: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
found, err := oldTree.root.Get(abi.AddrKey(addr), &ocval)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if found && bytes.Equal(ocval.Raw, ncval.Raw) {
|
||||||
|
return nil // not changed
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.Reset(ncval.Raw)
|
||||||
|
err = act.UnmarshalCBOR(buf)
|
||||||
|
buf.Reset(nil)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
out[addr.String()] = act
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
found, err := oldTree.root.Get(abi.AddrKey(addr), &ocval)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if found && bytes.Equal(ocval.Raw, ncval.Raw) {
|
|
||||||
return nil // not changed
|
|
||||||
}
|
|
||||||
|
|
||||||
buf.Reset(ncval.Raw)
|
|
||||||
err = act.UnmarshalCBOR(buf)
|
|
||||||
buf.Reset(nil)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
out[addr.String()] = act
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -161,6 +161,10 @@ func DefaultUpgradeSchedule() UpgradeSchedule {
|
|||||||
Height: build.UpgradeKumquatHeight,
|
Height: build.UpgradeKumquatHeight,
|
||||||
Network: network.Version6,
|
Network: network.Version6,
|
||||||
Migration: nil,
|
Migration: nil,
|
||||||
|
}, {
|
||||||
|
Height: build.UpgradePricelistOopsHeight,
|
||||||
|
Network: network.Version6AndAHalf,
|
||||||
|
Migration: nil,
|
||||||
}, {
|
}, {
|
||||||
Height: build.UpgradeCalicoHeight,
|
Height: build.UpgradeCalicoHeight,
|
||||||
Network: network.Version7,
|
Network: network.Version7,
|
||||||
@@ -292,6 +296,18 @@ func (us UpgradeSchedule) Validate() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (us UpgradeSchedule) GetNtwkVersion(e abi.ChainEpoch) (network.Version, error) {
|
||||||
|
// Traverse from newest to oldest returning upgrade active during epoch e
|
||||||
|
for i := len(us) - 1; i >= 0; i-- {
|
||||||
|
u := us[i]
|
||||||
|
// u.Height is the last epoch before u.Network becomes the active version
|
||||||
|
if u.Height < e {
|
||||||
|
return u.Network, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return network.Version0, xerrors.Errorf("Epoch %d has no defined network version", e)
|
||||||
|
}
|
||||||
|
|
||||||
func (sm *StateManager) handleStateForks(ctx context.Context, root cid.Cid, height abi.ChainEpoch, cb ExecMonitor, ts *types.TipSet) (cid.Cid, error) {
|
func (sm *StateManager) handleStateForks(ctx context.Context, root cid.Cid, height abi.ChainEpoch, cb ExecMonitor, ts *types.TipSet) (cid.Cid, error) {
|
||||||
retCid := root
|
retCid := root
|
||||||
var err error
|
var err error
|
||||||
|
|||||||
+16
-11
@@ -17,6 +17,7 @@ import (
|
|||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
"github.com/filecoin-project/go-state-types/cbor"
|
"github.com/filecoin-project/go-state-types/cbor"
|
||||||
|
"github.com/filecoin-project/go-state-types/network"
|
||||||
|
|
||||||
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
|
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
|
||||||
init2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/init"
|
init2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/init"
|
||||||
@@ -121,7 +122,7 @@ func TestForkHeightTriggers(t *testing.T) {
|
|||||||
|
|
||||||
sm, err := NewStateManagerWithUpgradeSchedule(
|
sm, err := NewStateManagerWithUpgradeSchedule(
|
||||||
cg.ChainStore(), UpgradeSchedule{{
|
cg.ChainStore(), UpgradeSchedule{{
|
||||||
Network: 1,
|
Network: network.Version1,
|
||||||
Height: testForkHeight,
|
Height: testForkHeight,
|
||||||
Migration: func(ctx context.Context, sm *StateManager, cache MigrationCache, cb ExecMonitor,
|
Migration: func(ctx context.Context, sm *StateManager, cache MigrationCache, cb ExecMonitor,
|
||||||
root cid.Cid, height abi.ChainEpoch, ts *types.TipSet) (cid.Cid, error) {
|
root cid.Cid, height abi.ChainEpoch, ts *types.TipSet) (cid.Cid, error) {
|
||||||
@@ -250,7 +251,7 @@ func TestForkRefuseCall(t *testing.T) {
|
|||||||
|
|
||||||
sm, err := NewStateManagerWithUpgradeSchedule(
|
sm, err := NewStateManagerWithUpgradeSchedule(
|
||||||
cg.ChainStore(), UpgradeSchedule{{
|
cg.ChainStore(), UpgradeSchedule{{
|
||||||
Network: 1,
|
Network: network.Version1,
|
||||||
Expensive: true,
|
Expensive: true,
|
||||||
Height: testForkHeight,
|
Height: testForkHeight,
|
||||||
Migration: func(ctx context.Context, sm *StateManager, cache MigrationCache, cb ExecMonitor,
|
Migration: func(ctx context.Context, sm *StateManager, cache MigrationCache, cb ExecMonitor,
|
||||||
@@ -297,22 +298,26 @@ func TestForkRefuseCall(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pts, err := cg.ChainStore().LoadTipSet(ts.TipSet.TipSet().Parents())
|
||||||
|
require.NoError(t, err)
|
||||||
|
parentHeight := pts.Height()
|
||||||
|
currentHeight := ts.TipSet.TipSet().Height()
|
||||||
|
|
||||||
|
// CallWithGas calls _at_ the current tipset.
|
||||||
ret, err := sm.CallWithGas(ctx, m, nil, ts.TipSet.TipSet())
|
ret, err := sm.CallWithGas(ctx, m, nil, ts.TipSet.TipSet())
|
||||||
switch ts.TipSet.TipSet().Height() {
|
if parentHeight <= testForkHeight && currentHeight >= testForkHeight {
|
||||||
case testForkHeight, testForkHeight + 1:
|
|
||||||
// If I had a fork, or I _will_ have a fork, it should fail.
|
// If I had a fork, or I _will_ have a fork, it should fail.
|
||||||
require.Equal(t, ErrExpensiveFork, err)
|
require.Equal(t, ErrExpensiveFork, err)
|
||||||
default:
|
} else {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.True(t, ret.MsgRct.ExitCode.IsSuccess())
|
require.True(t, ret.MsgRct.ExitCode.IsSuccess())
|
||||||
}
|
}
|
||||||
// Call just runs on the parent state for a tipset, so we only
|
|
||||||
// expect an error at the fork height.
|
// Call always applies the message to the "next block" after the tipset's parent state.
|
||||||
ret, err = sm.Call(ctx, m, ts.TipSet.TipSet())
|
ret, err = sm.Call(ctx, m, ts.TipSet.TipSet())
|
||||||
switch ts.TipSet.TipSet().Height() {
|
if parentHeight == testForkHeight {
|
||||||
case testForkHeight + 1:
|
|
||||||
require.Equal(t, ErrExpensiveFork, err)
|
require.Equal(t, ErrExpensiveFork, err)
|
||||||
default:
|
} else {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.True(t, ret.MsgRct.ExitCode.IsSuccess())
|
require.True(t, ret.MsgRct.ExitCode.IsSuccess())
|
||||||
}
|
}
|
||||||
@@ -361,7 +366,7 @@ func TestForkPreMigration(t *testing.T) {
|
|||||||
|
|
||||||
sm, err := NewStateManagerWithUpgradeSchedule(
|
sm, err := NewStateManagerWithUpgradeSchedule(
|
||||||
cg.ChainStore(), UpgradeSchedule{{
|
cg.ChainStore(), UpgradeSchedule{{
|
||||||
Network: 1,
|
Network: network.Version1,
|
||||||
Height: testForkHeight,
|
Height: testForkHeight,
|
||||||
Migration: func(ctx context.Context, sm *StateManager, cache MigrationCache, cb ExecMonitor,
|
Migration: func(ctx context.Context, sm *StateManager, cache MigrationCache, cb ExecMonitor,
|
||||||
root cid.Cid, height abi.ChainEpoch, ts *types.TipSet) (cid.Cid, error) {
|
root cid.Cid, height abi.ChainEpoch, ts *types.TipSet) (cid.Cid, error) {
|
||||||
|
|||||||
+9
-3
@@ -727,6 +727,11 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock, use
|
|||||||
}
|
}
|
||||||
|
|
||||||
// fast checks first
|
// fast checks first
|
||||||
|
|
||||||
|
if h.Height <= baseTs.Height() {
|
||||||
|
return xerrors.Errorf("block height not greater than parent height: %d != %d", h.Height, baseTs.Height())
|
||||||
|
}
|
||||||
|
|
||||||
nulls := h.Height - (baseTs.Height() + 1)
|
nulls := h.Height - (baseTs.Height() + 1)
|
||||||
if tgtTs := baseTs.MinTimestamp() + build.BlockDelaySecs*uint64(nulls+1); h.Timestamp != tgtTs {
|
if tgtTs := baseTs.MinTimestamp() + build.BlockDelaySecs*uint64(nulls+1); h.Timestamp != tgtTs {
|
||||||
return xerrors.Errorf("block has wrong timestamp: %d != %d", h.Timestamp, tgtTs)
|
return xerrors.Errorf("block has wrong timestamp: %d != %d", h.Timestamp, tgtTs)
|
||||||
@@ -1054,14 +1059,15 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock
|
|||||||
return xerrors.Errorf("failed to load base state tree: %w", err)
|
return xerrors.Errorf("failed to load base state tree: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pl := vm.PricelistByEpoch(baseTs.Height())
|
nv := syncer.sm.GetNtwkVersion(ctx, b.Header.Height)
|
||||||
|
pl := vm.PricelistByVersion(nv)
|
||||||
var sumGasLimit int64
|
var sumGasLimit int64
|
||||||
checkMsg := func(msg types.ChainMsg) error {
|
checkMsg := func(msg types.ChainMsg) error {
|
||||||
m := msg.VMMessage()
|
m := msg.VMMessage()
|
||||||
|
|
||||||
// Phase 1: syntactic validation, as defined in the spec
|
// Phase 1: syntactic validation, as defined in the spec
|
||||||
minGas := pl.OnChainMessage(msg.ChainLength())
|
minGas := pl.OnChainMessage(msg.ChainLength())
|
||||||
if err := m.ValidForBlockInclusion(minGas.Total(), syncer.sm.GetNtwkVersion(ctx, b.Header.Height)); err != nil {
|
if err := m.ValidForBlockInclusion(minGas.Total(), nv); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1075,7 +1081,7 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock
|
|||||||
// Phase 2: (Partial) semantic validation:
|
// Phase 2: (Partial) semantic validation:
|
||||||
// the sender exists and is an account actor, and the nonces make sense
|
// the sender exists and is an account actor, and the nonces make sense
|
||||||
var sender address.Address
|
var sender address.Address
|
||||||
if syncer.sm.GetNtwkVersion(ctx, b.Header.Height) >= network.Version13 {
|
if nv >= network.Version13 {
|
||||||
sender, err = st.LookupID(m.From)
|
sender, err = st.LookupID(m.From)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user