Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c56017dbb | ||
|
|
5019fa4cdd | ||
|
|
f1ded63d60 | ||
|
|
3fc23a785c | ||
|
|
96d7efee6e | ||
|
|
301b5a25fc | ||
|
|
f7757376d0 | ||
|
|
a49b21b94a | ||
|
|
72c410cd8f | ||
|
|
01bf3a89f4 | ||
|
|
b734e5a232 | ||
|
|
ded4ff43f4 | ||
|
|
4600b51330 | ||
|
|
37e0526918 | ||
|
|
41efbc000d | ||
|
|
a59e36d213 | ||
|
|
15e8ea1966 | ||
|
|
09ef832183 | ||
|
|
fd140c3eaf | ||
|
|
f357530efc | ||
|
|
b9f240e463 | ||
|
|
99a82d83aa | ||
|
|
0b3ca48c05 | ||
|
|
9c3f66bd8b | ||
|
|
cea46e5f53 | ||
|
|
c1600ad6d1 | ||
|
|
197c9ac996 | ||
|
|
3e6dcb578b | ||
|
|
b55ca92d33 | ||
|
|
b54a58c6e2 | ||
|
|
c340750672 | ||
|
|
9afb5ff944 | ||
|
|
d0243904f7 | ||
|
|
68d808705d | ||
|
|
189dc479c2 | ||
|
|
881c722025 | ||
|
|
8546e56d38 | ||
|
|
a1b6a2f011 | ||
|
|
31154ed294 | ||
|
|
ea58bee3f5 | ||
|
|
3be4984d9d | ||
|
|
6d88ea83e7 | ||
|
|
4f82421c7c | ||
|
|
edccf2457f | ||
|
|
728d86cd36 | ||
|
|
097c65d0bb | ||
|
|
9095babf8c | ||
|
|
ebc3556487 | ||
|
|
3fbfb7a0d1 | ||
|
|
a977cc2189 | ||
|
|
c0d1f4478a | ||
|
|
84f721e373 | ||
|
|
1673362795 | ||
|
|
6315523fe9 | ||
|
|
504affd266 | ||
|
|
bd8864ae43 | ||
|
|
3f1054daf4 | ||
|
|
4abb333611 | ||
|
|
a0d7604e7c | ||
|
|
cc490b983a | ||
|
|
7fbb4bdd3b | ||
|
|
5125aa05a5 | ||
|
|
ca3d22683a | ||
|
|
2b380c96a5 | ||
|
|
05274943c9 | ||
|
|
40fdf6c180 | ||
|
|
df0a8d9507 | ||
|
|
d11f2def6e | ||
|
|
ea4a54e083 | ||
|
|
57fe04ba6e | ||
|
|
268abb5318 | ||
|
|
b7fab5f937 | ||
|
|
47064f987c | ||
|
|
bdafdf8060 | ||
|
|
58cacda733 | ||
|
|
0a513952c8 | ||
|
|
d4a981f327 | ||
|
|
b4eefd7220 | ||
|
|
9f7d3ed340 | ||
|
|
ca7e70bf3a | ||
|
|
1c62d7a40f | ||
|
|
2642ddcf50 | ||
|
|
ae6410d02f | ||
|
|
1755fc2d98 | ||
|
|
05e03dc259 | ||
|
|
5304df52ca | ||
|
|
dedf0bac16 | ||
|
|
6addd9afcc | ||
|
|
6d2e8d721d | ||
|
|
4231e4396d | ||
|
|
9f2015e850 | ||
|
|
5388f3e6f8 | ||
|
|
c49c6fd514 | ||
|
|
58d7627168 | ||
|
|
06b360325a | ||
|
|
6591af960f | ||
|
|
305c2ec77d | ||
|
|
3a2e9887bd | ||
|
|
b13046293f | ||
|
|
51ed4c7b48 | ||
|
|
7c7b107e97 | ||
|
|
90741da019 | ||
|
|
c52dae45c5 | ||
|
|
3bd77701d8 | ||
|
|
3d1b855f20 | ||
|
|
8a5cd21034 | ||
|
|
52de95d344 | ||
|
|
8562a9bb82 | ||
|
|
5df45adb7a | ||
|
|
afb527ff30 | ||
|
|
3ee87a8af8 | ||
|
|
6d398f2507 | ||
|
|
64646de761 | ||
|
|
667fffb302 | ||
|
|
444b84d181 | ||
|
|
4a74f752c0 | ||
|
|
fc03a0773b | ||
|
|
6534280673 | ||
|
|
279f9e6fec | ||
|
|
dbbcb1423f | ||
|
|
e7a1d72ba8 | ||
|
|
b4ca7928f1 | ||
|
|
a4a21b5b89 | ||
|
|
58e49e3259 | ||
|
|
e85391b46c | ||
|
|
09f5ba177a | ||
|
|
0a2f2cf00d | ||
|
|
2b32c2e597 | ||
|
|
99d21573da | ||
|
|
c58df3f079 | ||
|
|
9bd009d795 | ||
|
|
17be7d3919 | ||
|
|
aff0f1ed4c | ||
|
|
5fb6a907cb | ||
|
|
98a7b884fe | ||
|
|
fdd877534f | ||
|
|
508fcb9d26 | ||
|
|
47d8c87486 | ||
|
|
11b2f41804 | ||
|
|
6b680d112b | ||
|
|
6b8c60a659 | ||
|
|
d2d0980532 | ||
|
|
70ebb2ad8d | ||
|
|
006c55a7c9 | ||
|
|
06d8ea10b1 | ||
|
|
4c05ec28ba | ||
|
|
ab52e34e6a | ||
|
|
86fdad2e31 | ||
|
|
2ff5aec80e | ||
|
|
8a55b73146 | ||
|
|
86b73d651e | ||
|
|
dd0c308427 | ||
|
|
6014273e69 | ||
|
|
c762536dcb | ||
|
|
5184bc5c40 | ||
|
|
68213a92cb | ||
|
|
35d466d847 | ||
|
|
f651f43c5e | ||
|
|
4b1e1f4b52 | ||
|
|
48f253328d | ||
|
|
ce68b9b229 | ||
|
|
8cfba5b092 | ||
|
|
b1b452bc0f | ||
|
|
b9400c590f | ||
|
|
e612fff1fe | ||
|
|
748dd962d8 | ||
|
|
cb36d5b6a4 | ||
|
|
1a804fbdec | ||
|
|
1b51c10d78 | ||
|
|
3733456bca | ||
|
|
0fc2f3a26f | ||
|
|
3282f856ec | ||
|
|
99c6e4f48f | ||
|
|
cae5ddce88 | ||
|
|
5639261e44 | ||
|
|
7587ab6234 | ||
|
|
e582f0b713 | ||
|
|
05fee27840 | ||
|
|
f62999d2b8 | ||
|
|
44aadb931a | ||
|
|
88849201ff | ||
|
|
f5ce7957f3 | ||
|
|
f4c6bc6a86 | ||
|
|
4cc672d0c5 | ||
|
|
97abbe1eca | ||
|
|
aba6530411 | ||
|
|
09cd1175a1 | ||
|
|
e52c709d8a | ||
|
|
2426ffb277 | ||
|
|
2f26026991 | ||
|
|
783dcda19c | ||
|
|
364076c1ea | ||
|
|
73259aa350 | ||
|
|
2e4d45ef07 | ||
|
|
f1c61c4753 | ||
|
|
b83994797a | ||
|
|
2c1a9781cf | ||
|
|
27a9b974db | ||
|
|
cb1789ea6e | ||
|
|
68b6f913c7 | ||
|
|
923a3db4b0 | ||
|
|
8f0ddac41a | ||
|
|
e79445123f | ||
|
|
9977f5c3ec | ||
|
|
ee751f88cd | ||
|
|
99c7d8e3eb | ||
|
|
8e12377e69 | ||
|
|
31268ba685 | ||
|
|
5068d51ac3 | ||
|
|
d44719dbd3 | ||
|
|
842ec43c2f | ||
|
|
a586d42c3b | ||
|
|
7044e623f9 | ||
|
|
f6c930d0aa | ||
|
|
95befa1e41 | ||
|
|
723e48b399 | ||
|
|
874ecd3573 | ||
|
|
ca8a673b5f | ||
|
|
69a88d41b6 | ||
|
|
cdf5bd0500 | ||
|
|
ea05fd9d86 | ||
|
|
d91b60df91 | ||
|
|
b9f8a3d587 | ||
|
|
c89ab1a990 | ||
|
|
2080e467ba | ||
|
|
5872f246ff | ||
|
|
877ecab960 | ||
|
|
5b4e6b7b26 | ||
|
|
58a8434825 | ||
|
|
8b0087524f | ||
|
|
76d6edbb52 | ||
|
|
1a23b1f6af | ||
|
|
6e51e6db9a | ||
|
|
3f8da19a34 | ||
|
|
ce41e394dc | ||
|
|
843fd09a62 | ||
|
|
f44cf0f2c4 | ||
|
|
facdc555b1 | ||
|
|
3912694fb7 | ||
|
|
622b4f7d9d | ||
|
|
e07c6c71c0 | ||
|
|
e87ce6cb60 | ||
|
|
b0f48b500f | ||
|
|
0af7b16ad5 | ||
|
|
37e391f133 | ||
|
|
5db314f422 | ||
|
|
d20cbc0c28 | ||
|
|
da478832cb | ||
|
|
4763397281 | ||
|
|
0d7476c5b2 | ||
|
|
83f8a0ab12 | ||
|
|
5043f31adf | ||
|
|
3f92a000c7 | ||
|
|
df856b7315 | ||
|
|
0bf1a78b39 | ||
|
|
17bc5fcd85 | ||
|
|
2c9b58aaec | ||
|
|
c1b1a9ce2a | ||
|
|
3083d80f5e | ||
|
|
101e5c6540 | ||
|
|
b945747eb2 | ||
|
|
2bed6c94cd | ||
|
|
c2cc198316 | ||
|
|
fd08786048 | ||
|
|
b192adfd2e | ||
|
|
c8f1139e0d | ||
|
|
6577cc8ea6 | ||
|
|
d53c700d18 | ||
|
|
9f721bfde5 | ||
|
|
046eb284b9 | ||
|
|
fe230f901e | ||
|
|
374bd9b578 | ||
|
|
92c55147c2 | ||
|
|
e05dc4ec80 | ||
|
|
10076d5698 | ||
|
|
fb78d5095f | ||
|
|
d80b0d9c2e | ||
|
|
2d5a6dab30 | ||
|
|
448813d2fe | ||
|
|
22e465ba9c | ||
|
|
1ac0c9a926 | ||
|
|
68b8e8e9cb | ||
|
|
2047a74958 | ||
|
|
b1c348b4a7 | ||
|
|
61005e61e9 | ||
|
|
b9d7de595a | ||
|
|
a39f4809a3 | ||
|
|
cd1a2e3413 | ||
|
|
ced455bba9 | ||
|
|
9850e786e8 | ||
|
|
57642697bc | ||
|
|
2f496b3ad7 | ||
|
|
8bd5173a54 | ||
|
|
5fe37404bc | ||
|
|
3f5b17dcfc | ||
|
|
b34b4e0374 | ||
|
|
3795cc2bd2 | ||
|
|
853de3daf7 | ||
|
|
45a650c012 | ||
|
|
8b17a4766d | ||
|
|
9f0c68bb70 | ||
|
|
7f0f7d0b36 | ||
|
|
8601e5da3a | ||
|
|
191a05da48 | ||
|
|
48bce386cd | ||
|
|
81fcffcf3c | ||
|
|
31898af076 | ||
|
|
5b4f93cffa | ||
|
|
fe69b561a6 | ||
|
|
10e1b26580 | ||
|
|
29c9fa3137 | ||
|
|
c69f884116 | ||
|
|
b48ea9610f | ||
|
|
f5d819ba53 | ||
|
|
e49a412f6d | ||
|
|
247a086cbf | ||
|
|
92b605466f | ||
|
|
9ceda488e1 | ||
|
|
f697ca7e1e | ||
|
|
481f17fd55 | ||
|
|
857cb815b1 | ||
|
|
a1b1bb90e8 | ||
|
|
fca183161a | ||
|
|
6b9478f862 | ||
|
|
cec0a6e790 | ||
|
|
de80b1e433 | ||
|
|
c9c26ee282 | ||
|
|
ccebc4f53c | ||
|
|
3c9e376474 | ||
|
|
55b85f3148 | ||
|
|
d8bb112bcd | ||
|
|
4cec0375b9 | ||
|
|
303a0fec87 | ||
|
|
5dd7e418d6 | ||
|
|
bebc11522e | ||
|
|
7721ea20ba | ||
|
|
a3a78fc705 | ||
|
|
ac06abb964 | ||
|
|
2b9ed9fa3d | ||
|
|
7148a5558f | ||
|
|
0de363131e | ||
|
|
6b8cbad31a | ||
|
|
35759fa07e | ||
|
|
a8b40b77fa | ||
|
|
7046e2721a | ||
|
|
a03506cf82 | ||
|
|
d1abc3cb5f | ||
|
|
b177e67a7a | ||
|
|
39a8edbe4b | ||
|
|
5cf58e291b | ||
|
|
cf606196e3 | ||
|
|
7bb948dd8a | ||
|
|
b60a63ebd9 | ||
|
|
c9ed293657 | ||
|
|
f47dcfacde | ||
|
|
6732758d0f | ||
|
|
60b7f56297 | ||
|
|
df32f5d060 | ||
|
|
00f9cf3f2a | ||
|
|
26399dba70 | ||
|
|
f2578a8e83 | ||
|
|
4f6700a4ee | ||
|
|
bb4609a764 | ||
|
|
aee5edb904 | ||
|
|
b756550ebf | ||
|
|
96b4b828f7 | ||
|
|
a0fedf8bdb | ||
|
|
2ca70e600d | ||
|
|
5aff54161a | ||
|
|
a8ae3a1909 | ||
|
|
1c4c9f262a | ||
|
|
37b1fb97fb | ||
|
|
607d1bc6f7 | ||
|
|
afd5828d74 | ||
|
|
83bd8ebf65 | ||
|
|
3de893542b | ||
|
|
bad67acb4b | ||
|
|
9553b32d52 | ||
|
|
b13428bf11 | ||
|
|
28bed9ac54 | ||
|
|
3f66e731fa | ||
|
|
d8c9712383 | ||
|
|
6559cdfa6a | ||
|
|
a674062fa8 | ||
|
|
76349510eb | ||
|
|
61eb91ff37 | ||
|
|
d12545af6f | ||
|
|
f76fcef3f8 | ||
|
|
c2cb7d8911 | ||
|
|
5f998038c7 | ||
|
|
f358af6f56 | ||
|
|
90b8612cf4 | ||
|
|
bcd3e92281 | ||
|
|
0ffdc5df05 | ||
|
|
9ebeafb174 | ||
|
|
d1843ecca1 | ||
|
|
5ad4d72fe0 | ||
|
|
b6c75d6b11 | ||
|
|
39ad3d3b27 | ||
|
|
a8464a345b | ||
|
|
fd90c03018 | ||
|
|
f719765069 | ||
|
|
46b880a6b9 | ||
|
|
fc5e243c92 | ||
|
|
dd82729f60 | ||
|
|
ea7ea72f60 | ||
|
|
a6e3856776 | ||
|
|
6e14bd8f6d | ||
|
|
dd26b68eec | ||
|
|
95a542e45a | ||
|
|
1b21a718c4 | ||
|
|
bb7fabb439 | ||
|
|
6b6f0acaf0 | ||
|
|
50d6db3978 | ||
|
|
06cc1eb155 | ||
|
|
59733da383 | ||
|
|
6907e5879d | ||
|
|
7111e924cc | ||
|
|
95e47cf998 | ||
|
|
cca076b05c | ||
|
|
0c6aef221d | ||
|
|
fcbd9950ca | ||
|
|
332dc2154c | ||
|
|
cc0d281604 | ||
|
|
39540b8a0a | ||
|
|
577368ca03 | ||
|
|
044972ebdc | ||
|
|
b6c9ddccff | ||
|
|
039ca9f3b4 | ||
|
|
6d4caa0163 | ||
|
|
b17f644ab9 | ||
|
|
e387f3810e | ||
|
|
59f814028f | ||
|
|
e27a530cbc | ||
|
|
5a3b983954 | ||
|
|
c77ce704cb | ||
|
|
a4d953e2c3 | ||
|
|
307fc14093 | ||
|
|
e92b8b24b1 | ||
|
|
adeb4cefee | ||
|
|
811fb44dd0 | ||
|
|
55007a0c4e | ||
|
|
e3bf42cf15 | ||
|
|
2f1aef17cc | ||
|
|
ff6216486e | ||
|
|
6c2762f7bb | ||
|
|
8dcc008135 | ||
|
|
d09db15ddd | ||
|
|
d09f6f947a | ||
|
|
791267f72e | ||
|
|
3f112d065b | ||
|
|
eb03422c93 | ||
|
|
891971edec | ||
|
|
cc91eab0fd | ||
|
|
764a08b980 | ||
|
|
0afe7325f6 | ||
|
|
614844dc94 | ||
|
|
af45b299e7 | ||
|
|
bdb85d6115 | ||
|
|
6de62411c6 | ||
|
|
9f546c2d1c | ||
|
|
3ff6a6f59f | ||
|
|
a4ddf9225f | ||
|
|
1b65f48808 | ||
|
|
ec58099cc7 | ||
|
|
cfa73f34e4 | ||
|
|
3228ae5672 | ||
|
|
b3f4e50c58 | ||
|
|
01e30e0665 | ||
|
|
4676fd6753 | ||
|
|
33c1283880 | ||
|
|
2c772d6fda | ||
|
|
8f603717a6 | ||
|
|
52bfed1739 | ||
|
|
dc6392db49 | ||
|
|
0760676f65 | ||
|
|
641eeb4783 | ||
|
|
ab5345860c | ||
|
|
06d3892e38 | ||
|
|
047de13929 | ||
|
|
a001033687 | ||
|
|
e7a63b7dd5 | ||
|
|
b938ac4cc8 | ||
|
|
6baddccff2 | ||
|
|
ebfde330dd | ||
|
|
0efb4ca3a7 | ||
|
|
ba571794dc | ||
|
|
2462f77711 | ||
|
|
2505ed051e | ||
|
|
6e7fcb7ee6 | ||
|
|
9b65793509 | ||
|
|
d64f4e84d5 | ||
|
|
1e7a107484 | ||
|
|
fb6c4d5c76 | ||
|
|
c678822490 | ||
|
|
fc8ee481a8 | ||
|
|
05bf177686 | ||
|
|
6a63e6f448 | ||
|
|
5c6988a7c1 | ||
|
|
c59e2fea5b | ||
|
|
332ea8a126 | ||
|
|
20e92da062 | ||
|
|
2b0022f1a7 | ||
|
|
3ced11c31f | ||
|
|
fc6938badb | ||
|
|
ed6ccef5cf | ||
|
|
a19d6ce8a3 | ||
|
|
b7555fdc22 | ||
|
|
b2eb014900 | ||
|
|
d4da53dda8 | ||
|
|
987f41011a | ||
|
|
6c045b4c43 | ||
|
|
feb24c9684 | ||
|
|
4937fb925e | ||
|
|
fed3e82ff8 | ||
|
|
b1dfd41c19 | ||
|
|
56a9d05491 | ||
|
|
9053efd344 | ||
|
|
a541a2500a | ||
|
|
7c7301f701 | ||
|
|
5cfae0f1e8 | ||
|
|
d9e0d474d1 | ||
|
|
bb4e3e49ea | ||
|
|
3df25df3ab | ||
|
|
35d1e3d1e0 | ||
|
|
d1104fec4c | ||
|
|
af429dba0f | ||
|
|
e02fdf5064 | ||
|
|
52a610650a | ||
|
|
7e692a5dc9 | ||
|
|
1cca0ff9e2 | ||
|
|
8ed726f9e3 | ||
|
|
b0cbc932bd | ||
|
|
c09571984a | ||
|
|
b4ad2e5e93 | ||
|
|
53271729b6 | ||
|
|
2f3c912ad9 | ||
|
|
e9eecad2c5 | ||
|
|
0a0fc47655 | ||
|
|
608793314f | ||
|
|
ba94f271db | ||
|
|
4f128accc4 | ||
|
|
389e6eb70b | ||
|
|
94009f247f | ||
|
|
3634bdcfa5 | ||
|
|
7e55c44d4e | ||
|
|
33336ab919 | ||
|
|
a9ea06dc1e | ||
|
|
e2eb3e6e35 | ||
|
|
997e7d18d9 | ||
|
|
9a3c24df1e | ||
|
|
a9a65e05d8 | ||
|
|
b76fae37e0 | ||
|
|
887d40bcbb | ||
|
|
4890d83acb | ||
|
|
39d4f6780d | ||
|
|
bceb246080 | ||
|
|
cffeb1a590 | ||
|
|
f8ef6a41cb | ||
|
|
9574db6d0a | ||
|
|
eab50e061a | ||
|
|
aebf3cd64c | ||
|
|
9a03c003fe | ||
|
|
56054b0ad3 | ||
|
|
854385168d | ||
|
|
716f10e570 | ||
|
|
35d6a40071 | ||
|
|
4072f24bf2 | ||
|
|
ed3e0869c3 | ||
|
|
05026a23b9 | ||
|
|
32059d0cbf | ||
|
|
b08abc12ba | ||
|
|
6362887ce3 | ||
|
|
77117a0be5 | ||
|
|
f65d179f2c | ||
|
|
8d05c5d62c | ||
|
|
8986a2002d | ||
|
|
8d3cc632ac | ||
|
|
d443836e25 | ||
|
|
7905c3bbd8 | ||
|
|
ac616eb340 | ||
|
|
d4c7b63aac | ||
|
|
a1da1dab85 | ||
|
|
dbbd1d7a45 | ||
|
|
d5addf7173 | ||
|
|
613df60f4a | ||
|
|
77fa3d6ca7 | ||
|
|
fabcbb621d | ||
|
|
422f0991e9 | ||
|
|
fd68551d83 | ||
|
|
29d3d746a3 | ||
|
|
cb187ac093 | ||
|
|
67780346e2 | ||
|
|
260908015f | ||
|
|
ce3af308ed | ||
|
|
e4f4fa2c7d | ||
|
|
519b5e191e | ||
|
|
a2b91a5627 | ||
|
|
9827ec3730 | ||
|
|
bd6321d2c0 | ||
|
|
adac340f3f | ||
|
|
1b494acc9e | ||
|
|
6d368179e1 | ||
|
|
9b62e224d5 | ||
|
|
f235beeaf7 | ||
|
|
19fb40a72c | ||
|
|
a816d22538 | ||
|
|
ff62b64b4d | ||
|
|
7c9b9e3657 | ||
|
|
0a294f146f | ||
|
|
8de4e5e005 | ||
|
|
735d30af55 | ||
|
|
0131b077be | ||
|
|
94089a6a15 | ||
|
|
d6c06881ee | ||
|
|
fdbb1d8f3b | ||
|
|
8c7fda4441 | ||
|
|
db2a45d07a | ||
|
|
9e611d5f4d | ||
|
|
cc423ee4d2 | ||
|
|
9e63e5979e | ||
|
|
aa53f5b7d7 | ||
|
|
1b67eed82c | ||
|
|
d0a1c5251c | ||
|
|
0ba1306969 | ||
|
|
46b92be281 | ||
|
|
61aae567bb | ||
|
|
d412ccdb3f | ||
|
|
c27ec4ed22 | ||
|
|
bd00c505b2 | ||
|
|
f10b13ff32 | ||
|
|
5a5e49dcd7 | ||
|
|
c5d3b979cb | ||
|
|
b00efcd701 | ||
|
|
6ce5f2736e | ||
|
|
a1e6781f0c | ||
|
|
ab4f135208 | ||
|
|
026d236252 | ||
|
|
fe5b5702f9 | ||
|
|
f1719d1e23 | ||
|
|
bf48728875 | ||
|
|
03cd3760bb | ||
|
|
fb5f3c5703 | ||
|
|
82eee15955 | ||
|
|
dffa514518 | ||
|
|
64e805926f | ||
|
|
aa9eef48f0 | ||
|
|
95f68d0161 | ||
|
|
c8bfbd4f28 | ||
|
|
f6a0da3751 | ||
|
|
99ea5b62ea | ||
|
|
126a5c1cf8 | ||
|
|
1f62c07789 | ||
|
|
1a790f5ee3 | ||
|
|
9d2c430138 | ||
|
|
8dc49db30d | ||
|
|
c05df6dc1d | ||
|
|
4de56d5eac | ||
|
|
7882b0163b | ||
|
|
c31f5130e3 | ||
|
|
95c57d0ce3 | ||
|
|
be1f15052c | ||
|
|
9ce63c1211 | ||
|
|
06f13f8e00 | ||
|
|
76abbb8938 | ||
|
|
ee99e68614 | ||
|
|
abb388512e | ||
|
|
9d06a8b116 | ||
|
|
0bb3aed53c | ||
|
|
ab90a3b2bc | ||
|
|
82635f2515 | ||
|
|
b4f479affd | ||
|
|
378f169f14 | ||
|
|
3961e3daf8 | ||
|
|
ba3b32cfe7 | ||
|
|
1070ad2289 | ||
|
|
29b076ad69 | ||
|
|
ec4deb7e28 | ||
|
|
1336d8855d | ||
|
|
df14f156e1 | ||
|
|
b9a9f23204 | ||
|
|
f96f12c836 | ||
|
|
069766ecc4 | ||
|
|
270f2935a9 | ||
|
|
fd67a41c75 | ||
|
|
9857ad8378 | ||
|
|
e5814dac4f | ||
|
|
542357a1df | ||
|
|
239d6f8f4d | ||
|
|
e77df95157 | ||
|
|
143164fb70 | ||
|
|
ea85a2457e | ||
|
|
b9adf95010 | ||
|
|
de0a452282 | ||
|
|
42b481fb61 | ||
|
|
e5efe57c90 | ||
|
|
23ce0645ed | ||
|
|
4cdb7ba1d3 | ||
|
|
fb27969d14 | ||
|
|
790bcc7830 | ||
|
|
24cc70f18e | ||
|
|
e3262da915 | ||
|
|
a9c0263db6 | ||
|
|
5d89d6d3e7 | ||
|
|
931cfe1ed1 | ||
|
|
1a582230cb | ||
|
|
0ca29acf22 | ||
|
|
3d9eb226fa | ||
|
|
187a499cca | ||
|
|
fb92e1d764 | ||
|
|
7a042ab21f | ||
|
|
46fb39c755 | ||
|
|
1206154718 | ||
|
|
ebaa721e44 | ||
|
|
685a0fdc9c | ||
|
|
e0209c74ad | ||
|
|
48c6c55f68 | ||
|
|
0a85dc6232 | ||
|
|
560a127ce6 | ||
|
|
834a6148b0 | ||
|
|
16d07d3f18 | ||
|
|
0579aecac4 | ||
|
|
388c53e637 | ||
|
|
db45a848f5 | ||
|
|
6bccdcc177 | ||
|
|
901079e880 | ||
|
|
827a473391 | ||
|
|
ab1a52c632 | ||
|
|
29bdd94b12 | ||
|
|
41e9345da0 | ||
|
|
2b3d66da3b | ||
|
|
69eb2163d2 | ||
|
|
eeadfedbe6 | ||
|
|
0eaa6d9983 | ||
|
|
38f9559080 | ||
|
|
10b2ec55b5 | ||
|
|
7747bcd859 | ||
|
|
476df99179 | ||
|
|
80b8d4b9d7 | ||
|
|
1e53ed6a82 | ||
|
|
32885e1129 | ||
|
|
9632a3836a | ||
|
|
835fd4b23c | ||
|
|
4a114150f0 | ||
|
|
4015ddbb4f | ||
|
|
49abdd7d7d | ||
|
|
5453e70cab | ||
|
|
18d38ca42f | ||
|
|
7ddf1d1feb | ||
|
|
f01f1d377b | ||
|
|
785b660724 | ||
|
|
144b5a1350 | ||
|
|
7d2adc383f | ||
|
|
3224c84fb1 | ||
|
|
1cfb73cc3b | ||
|
|
1564db1fce | ||
|
|
3522c8d45a | ||
|
|
db977a2f91 | ||
|
|
174c595acc | ||
|
|
c3d94f8aa9 | ||
|
|
20c715d507 | ||
|
|
b6bcd978e7 | ||
|
|
b33bf16f70 | ||
|
|
02f33e2b8e | ||
|
|
52cc2cd3eb | ||
|
|
96cb321eb5 | ||
|
|
fc59294154 | ||
|
|
47141042b6 | ||
|
|
951fc4e89d | ||
|
|
efd86876b4 | ||
|
|
bef53fa263 | ||
|
|
457ecad302 | ||
|
|
64ebcb1b31 | ||
|
|
1a61c028bc | ||
|
|
62e76bbcab | ||
|
|
b0bb36909b | ||
|
|
56277756a6 | ||
|
|
50d1fae85f | ||
|
|
5462ecf6da | ||
|
|
9e74c3c4e8 | ||
|
|
7d0296c409 | ||
|
|
3ce296489b | ||
|
|
9a0e552131 | ||
|
|
994934a42b | ||
|
|
6328f9c879 | ||
|
|
3fb605a743 | ||
|
|
299e72458e | ||
|
|
ab9b3b6851 | ||
|
|
93c21a6d2d | ||
|
|
c5a2cac06a | ||
|
|
32dcfb4842 | ||
|
|
afb9e5f672 | ||
|
|
108afe08fb | ||
|
|
c6440677aa | ||
|
|
92fb48d951 | ||
|
|
c58086ee27 | ||
|
|
6da09235dc | ||
|
|
9584c72026 | ||
|
|
fef5d65c0f | ||
|
|
835b84b12a | ||
|
|
858994a630 | ||
|
|
72871597cd | ||
|
|
8ac71f6d0a | ||
|
|
cbbe01eeb5 | ||
|
|
cf299b39b0 | ||
|
|
c6820ec059 | ||
|
|
e8e4b559e9 | ||
|
|
fdc46ad5df | ||
|
|
dbe580de10 | ||
|
|
25f3384939 | ||
|
|
a15080b563 | ||
|
|
cfcfd5d8fa | ||
|
|
ab529f4641 | ||
|
|
9b70fdbe9d | ||
|
|
dba2df80da | ||
|
|
2c9f4ad5ad | ||
|
|
4f9fcd2b01 | ||
|
|
f806822440 | ||
|
|
44a56c7e33 | ||
|
|
61b7b86af5 | ||
|
|
3287c621ad | ||
|
|
11d1e3cd5f | ||
|
|
1bd2ae034f | ||
|
|
446a24ef3f | ||
|
|
9334e73396 | ||
|
|
4afef16ee6 | ||
|
|
72c1fa81db | ||
|
|
7583c4399a | ||
|
|
a7a6f24ceb | ||
|
|
cd032d5418 | ||
|
|
8613454d1d | ||
|
|
f9aca39caf | ||
|
|
6b9daa4d14 | ||
|
|
df973da748 | ||
|
|
e9cc697ee8 | ||
|
|
bb5a92e2f4 | ||
|
|
461a3cdebc | ||
|
|
d806fafee8 | ||
|
|
e9989d0e46 | ||
|
|
c01d9f05df | ||
|
|
bdd6cea13f | ||
|
|
e777b879a1 | ||
|
|
c7e3e9fa7f | ||
|
|
420888aeae | ||
|
|
594737ff6c | ||
|
|
c1aafb7b71 | ||
|
|
a3b325db5d | ||
|
|
24dd6e01d7 | ||
|
|
22884f18f1 | ||
|
|
984e4e9963 | ||
|
|
f24d401b61 | ||
|
|
9892c60ed0 | ||
|
|
19d457ae5b | ||
|
|
655277171b | ||
|
|
fda3b152bd | ||
|
|
b8bba15ed2 | ||
|
|
c11803ad55 | ||
|
|
5324440f7d | ||
|
|
f6cf27c781 | ||
|
|
d04c01939d | ||
|
|
f2aea11971 | ||
|
|
1f754bdb78 | ||
|
|
46e5cc9317 | ||
|
|
6c6711e638 | ||
|
|
3d52c087cc | ||
|
|
0d72d742b4 | ||
|
|
884e20f637 | ||
|
|
210216a94f | ||
|
|
2af1283c65 | ||
|
|
d2b7e7b2ab | ||
|
|
3fa51f08e1 | ||
|
|
446b1cc883 | ||
|
|
3c7f5f7629 | ||
|
|
dc8ff27b36 | ||
|
|
4d69947eed | ||
|
|
7db5e8061d | ||
|
|
65b921c62c | ||
|
|
c61f341b22 | ||
|
|
e33f873df8 | ||
|
|
46a5013dc1 | ||
|
|
53a6c4eac6 | ||
|
|
2e154ef6d0 | ||
|
|
47346907dd | ||
|
|
0cb2f51549 | ||
|
|
564b88af52 | ||
|
|
d347e7ab8f | ||
|
|
46c7f047d4 | ||
|
|
58729b7fd6 | ||
|
|
4767773d1b | ||
|
|
c9b489437d | ||
|
|
e07059e73d | ||
|
|
0570306bb6 | ||
|
|
0f08da3272 | ||
|
|
d4582fb32e | ||
|
|
3c50baaf5b | ||
|
|
b78b9a441b | ||
|
|
a47b063a24 | ||
|
|
e164dbb953 | ||
|
|
b8e3808c4f | ||
|
|
e1be89b442 | ||
|
|
2ce5a29004 | ||
|
|
39e73e1cb4 | ||
|
|
bc9b5cb5fc | ||
|
|
9990d440e9 | ||
|
|
c6f5214657 | ||
|
|
696469aae7 | ||
|
|
d3fa728894 | ||
|
|
6ca5caef31 | ||
|
|
689b93dc0e | ||
|
|
72cb130e17 | ||
|
|
a999e41677 | ||
|
|
6b1c54162a | ||
|
|
3c291dd23f | ||
|
|
1cfd9555d5 | ||
|
|
064b036000 | ||
|
|
5c37c9d8e9 | ||
|
|
b7975dcd9a | ||
|
|
3beebe5dc8 | ||
|
|
2829245a46 | ||
|
|
b1dcf5fead | ||
|
|
d0599ff1e3 | ||
|
|
a53fd82379 | ||
|
|
86af05ba6f | ||
|
|
c543a10ce7 | ||
|
|
d56170d70e | ||
|
|
d9e3cc0374 | ||
|
|
a5a72a41eb | ||
|
|
2514c96cff | ||
|
|
88bd757024 | ||
|
|
1e6aa4b129 | ||
|
|
daca99687c | ||
|
|
65abeb066d | ||
|
|
13c8a235b6 | ||
|
|
b13226bc2f | ||
|
|
07afd93443 | ||
|
|
dc06d30f52 | ||
|
|
90a31fde9f | ||
|
|
f9cbf6d526 | ||
|
|
b190c3492a | ||
|
|
da5e1b319f | ||
|
|
ba7854d645 | ||
|
|
d844938a92 | ||
|
|
58695dc1bc | ||
|
|
1502ca6460 | ||
|
|
178691e37f | ||
|
|
93d26195f1 | ||
|
|
a584fcb935 | ||
|
|
bf93dfbc3b | ||
|
|
d033f8aab1 | ||
|
|
e34a759889 | ||
|
|
2ef8acdfc8 | ||
|
|
562f5839b7 | ||
|
|
c3a0feef96 | ||
|
|
2fd93a55ac | ||
|
|
783971d2c8 | ||
|
|
f74a1b70ab | ||
|
|
7246ef273f | ||
|
|
e8a5e0d2fe | ||
|
|
a415e49fdb | ||
|
|
655aea1018 | ||
|
|
9707c82285 | ||
|
|
370817eb60 | ||
|
|
97dd082585 | ||
|
|
3196b2cfd5 | ||
|
|
289ef910a0 | ||
|
|
95eaf13b5a | ||
|
|
c6f85886bf | ||
|
|
b6046924b3 | ||
|
|
bc14d0820f | ||
|
|
64e30808f8 | ||
|
|
28420b9eb0 | ||
|
|
b28ed5887c | ||
|
|
827ec75f5f | ||
|
|
c31774b08e | ||
|
|
be9f7b88b2 | ||
|
|
15c4793fe0 | ||
|
|
42cecbd879 | ||
|
|
00e5ace818 | ||
|
|
82b5cb89cd | ||
|
|
b7436cd300 | ||
|
|
715c32ff77 | ||
|
|
44d929c084 | ||
|
|
4b1d6bfcca | ||
|
|
614f45dcfb | ||
|
|
354b5af55a | ||
|
|
fc5120621b | ||
|
|
c4a6b94b9c | ||
|
|
054327b72a | ||
|
|
cb044f83a7 | ||
|
|
f1291f137c | ||
|
|
6bbb8ecafc | ||
|
|
ec08e27af2 | ||
|
|
c5a8b7076c | ||
|
|
4d019f16e4 | ||
|
|
ceea03cd40 | ||
|
|
32065f551e | ||
|
|
7bab281449 | ||
|
|
a8cdb8adc7 | ||
|
|
2be9836196 | ||
|
|
0439e95aa3 | ||
|
|
2e5843a0ee | ||
|
|
751568a4dd | ||
|
|
6dea0a6281 | ||
|
|
a4f3758f4c | ||
|
|
3e143cac4b | ||
|
|
0386cc5d48 | ||
|
|
e02a366419 | ||
|
|
d15ef9ac9b | ||
|
|
70732ac423 | ||
|
|
b18bc90dbc | ||
|
|
8382977e21 | ||
|
|
f4913c19b1 | ||
|
|
253e22d6ea | ||
|
|
a7ed639c21 | ||
|
|
f4adf03ce5 | ||
|
|
c016e34dbc | ||
|
|
21835c785b | ||
|
|
8007c1f9ae | ||
|
|
055795c4cc | ||
|
|
b03c4bc26b | ||
|
|
660ac26dd9 | ||
|
|
65d50c76d6 | ||
|
|
e8d2560581 | ||
|
|
dc7c7608df | ||
|
|
13a5b7f539 | ||
|
|
0c1592f2d3 | ||
|
|
61485beb22 | ||
|
|
01ad4c0514 | ||
|
|
09b9dfc3ce | ||
|
|
c66e594046 | ||
|
|
9ade05b33b | ||
|
|
13ff98416f | ||
|
|
4f675b76ad | ||
|
|
a6658a858f | ||
|
|
bfb5bad124 | ||
|
|
3672053ae9 | ||
|
|
4dfec7b232 | ||
|
|
23c7728edb | ||
|
|
aa278443d3 | ||
|
|
42173e29d6 | ||
|
|
32c159fa3a | ||
|
|
fad250058d | ||
|
|
2304ea0077 | ||
|
|
6df0340136 | ||
|
|
41d370557f | ||
|
|
dfb769c505 | ||
|
|
b916ac83cb | ||
|
|
74f040f9d5 | ||
|
|
fcec665267 | ||
|
|
506624f509 | ||
|
|
1f9ca1958e | ||
|
|
91259c29d4 | ||
|
|
e2278ebe6a | ||
|
|
eeb38fa649 | ||
|
|
ba87cb4fa9 | ||
|
|
65653a1747 | ||
|
|
663b3f4f21 | ||
|
|
d15d9b0fb9 | ||
|
|
86e25e7969 | ||
|
|
2e544e3e6a | ||
|
|
7904f135ff | ||
|
|
89493fe2b8 | ||
|
|
23bf3349d7 | ||
|
|
6166204bac | ||
|
|
97a76a4b9a | ||
|
|
f1948d54f0 | ||
|
|
cd7580e6d8 | ||
|
|
15aa8e5253 | ||
|
|
0c7962ce5f | ||
|
|
694834e8d5 | ||
|
|
47a4128311 | ||
|
|
239e180683 | ||
|
|
25070314ce | ||
|
|
214f46bc88 | ||
|
|
a63ef1dcd5 | ||
|
|
5ed79fa73e | ||
|
|
2e85b42665 | ||
|
|
eb2be69ace | ||
|
|
9cef300535 | ||
|
|
5f28c12f2e | ||
|
|
f850d77f1e | ||
|
|
7c831101f3 | ||
|
|
8b8449faee | ||
|
|
fe92a6e2d4 | ||
|
|
1f9c0f8040 | ||
|
|
7c0b6f41d8 | ||
|
|
bb25eb980d | ||
|
|
afec58f780 | ||
|
|
52da5acc96 | ||
|
|
fd640864cb | ||
|
|
3f151351aa | ||
|
|
844c0a3527 | ||
|
|
83b1009837 | ||
|
|
85e592bbe2 | ||
|
|
e2a6b99144 | ||
|
|
be2a5942fb | ||
|
|
ffa96389bc | ||
|
|
a145819004 | ||
|
|
0e39e760e5 | ||
|
|
721120fc60 | ||
|
|
3634ca50ca | ||
|
|
c965696586 | ||
|
|
53c39b1176 | ||
|
|
7e2d05cfd7 | ||
|
|
f601d1bf6b | ||
|
|
6ce14132cc | ||
|
|
c13ade3fbf | ||
|
|
7d540905ac | ||
|
|
4a8df0c3fa | ||
|
|
2d2ebdcc4b | ||
|
|
f3838a47c7 | ||
|
|
e7f3554c62 | ||
|
|
2609342356 | ||
|
|
9fe3649dd2 | ||
|
|
9b199f0476 | ||
|
|
b6893b0a3f | ||
|
|
69bfe7b7a8 | ||
|
|
e197038b9f | ||
|
|
549afbaa5f | ||
|
|
218f7c2c5d | ||
|
|
375b7a1c4c | ||
|
|
3113b15217 | ||
|
|
34bca28416 | ||
|
|
99972c9e34 | ||
|
|
91a3d1d34a | ||
|
|
71dfc2e338 | ||
|
|
e9fae0425f | ||
|
|
17597fdd8f | ||
|
|
9613acd46b | ||
|
|
4b507f5be1 | ||
|
|
8508cdc00b | ||
|
|
4483d94db3 | ||
|
|
94763c2aaa | ||
|
|
d033042d6b | ||
|
|
54637d5093 | ||
|
|
7d4bc90d42 | ||
|
|
a13690dcf1 | ||
|
|
f0eac01a3c | ||
|
|
ef444676c2 | ||
|
|
853f9da457 | ||
|
|
bb9d2b5af4 | ||
|
|
7aec500384 | ||
|
|
b10b6fdd11 | ||
|
|
2d9123a618 | ||
|
|
96f004032b | ||
|
|
463a647118 | ||
|
|
df66f48f64 | ||
|
|
89ffd368b8 | ||
|
|
44040f0f3f | ||
|
|
1999156d06 | ||
|
|
b4fa099257 | ||
|
|
b7a282decc | ||
|
|
9f807f4aeb | ||
|
|
16dbbadddf | ||
|
|
648f02cbd6 | ||
|
|
880204045b | ||
|
|
9d2208e0e8 | ||
|
|
55061ae6fb | ||
|
|
2b611b3a99 | ||
|
|
de9cef62f7 | ||
|
|
ba56d02a1c | ||
|
|
e7b8511622 | ||
|
|
b1afa2022b | ||
|
|
3737a8f3cc | ||
|
|
7b39c3a907 | ||
|
|
62d20f2191 | ||
|
|
e9664a997e | ||
|
|
6d1bac7f70 | ||
|
|
dc3d17c9ea | ||
|
|
e061a8d163 | ||
|
|
9f34f98368 | ||
|
|
226efe28e5 | ||
|
|
452c85de98 | ||
|
|
09c996d572 | ||
|
|
adee4b2a5e | ||
|
|
322f34c6c6 | ||
|
|
49f8590578 | ||
|
|
016f5e44c0 | ||
|
|
9305947547 | ||
|
|
b92ce76a78 | ||
|
|
379100b470 | ||
|
|
8575f5518c | ||
|
|
707f9e31df | ||
|
|
52d34c8a5e | ||
|
|
68a16afeda | ||
|
|
50146fb9b9 | ||
|
|
c5470ee17e | ||
|
|
00335878ab | ||
|
|
4982de89b2 | ||
|
|
9328d98f84 | ||
|
|
3536ec9f85 | ||
|
|
8191654089 | ||
|
|
e23170d194 | ||
|
|
e7549dbf2c | ||
|
|
65202668af | ||
|
|
51e93feb9a | ||
|
|
c8d985b5c7 | ||
|
|
7ce4e5342b | ||
|
|
f580892e9e | ||
|
|
080a1165ee | ||
|
|
1413d6d4b7 | ||
|
|
9b64dba4a1 | ||
|
|
f9771c67fb | ||
|
|
238174cfca | ||
|
|
f130cd6fca | ||
|
|
336aa95ab5 | ||
|
|
c40c513508 | ||
|
|
bfbdbc04ba | ||
|
|
b242d69805 | ||
|
|
b8853aa4d5 | ||
|
|
fe448e706d | ||
|
|
193630f7b6 | ||
|
|
c597c43724 | ||
|
|
425ad9c5fa | ||
|
|
693bbee953 | ||
|
|
92b765bd21 | ||
|
|
7838752352 | ||
|
|
596b31fb9e | ||
|
|
2219bff1c9 | ||
|
|
5c791cd93b | ||
|
|
ce9146916a | ||
|
|
dff88b63b2 | ||
|
|
a2abeef727 | ||
|
|
dd9682f2be | ||
|
|
a152d98af8 | ||
|
|
27c0ce4a3a | ||
|
|
0c6072a1a0 | ||
|
|
d25e5d1c08 | ||
|
|
e0ade92b29 | ||
|
|
8db9c19e1c | ||
|
|
bc05618fd1 | ||
|
|
444239a643 | ||
|
|
bead8ac38e | ||
|
|
638900f97f | ||
|
|
d8afd71f4c | ||
|
|
869867e92e | ||
|
|
508375a55c | ||
|
|
1f91e7267d | ||
|
|
c8ff58aae1 | ||
|
|
4f33c91f81 | ||
|
|
423ff0631d | ||
|
|
948ee53080 | ||
|
|
4d8327c29a | ||
|
|
cd0cb1407d | ||
|
|
915c5e0fdd | ||
|
|
2a7e4af5ee | ||
|
|
931979809f | ||
|
|
584907269a | ||
|
|
05db5ce426 | ||
|
|
219c695967 | ||
|
|
4544d2118e | ||
|
|
d7c2c073a3 | ||
|
|
6bea9dd178 | ||
|
|
0a169357f7 | ||
|
|
b13a41a44d | ||
|
|
470538b082 | ||
|
|
bac51dd4e3 | ||
|
|
d7b4f92f1f | ||
|
|
87d6daf745 | ||
|
|
49d3bb9497 | ||
|
|
d4f6e1ddb4 | ||
|
|
b63687795d | ||
|
|
96d56ec096 | ||
|
|
6d0b3978b9 | ||
|
|
afe6c51016 | ||
|
|
09be3f0a01 | ||
|
|
6667220a27 | ||
|
|
1af1ceb1e0 | ||
|
|
ae76711ab4 | ||
|
|
fe339d46eb | ||
|
|
91e2530e11 | ||
|
|
f9fc601567 | ||
|
|
2b68ba5f1d | ||
|
|
4b187b85eb | ||
|
|
b8884adaf1 | ||
|
|
b71f069854 | ||
|
|
5a0b9f4197 | ||
|
|
4b1d1b6540 | ||
|
|
15fe726e65 | ||
|
|
17c2c0d1c8 | ||
|
|
2971dd4317 | ||
|
|
6742a74260 | ||
|
|
41af94f1b7 | ||
|
|
6bb67f2fe9 | ||
|
|
961a25298b | ||
|
|
5f1737379a | ||
|
|
c5c0185943 | ||
|
|
8fdb9148e4 | ||
|
|
d3d5f8d7f0 | ||
|
|
99031bae17 | ||
|
|
56373b0d46 | ||
|
|
7921f8d713 | ||
|
|
6d3e59e047 | ||
|
|
63f13977ce | ||
|
|
408183c7a6 | ||
|
|
11b041224e | ||
|
|
36b78b1891 | ||
|
|
a6d061d0f6 | ||
|
|
bf547112de | ||
|
|
5d9c79811f | ||
|
|
28ffa8ca06 | ||
|
|
55240b3e07 | ||
|
|
697a0a3b95 | ||
|
|
26e12e6f6a | ||
|
|
0e3e449bf8 | ||
|
|
f3922e7485 | ||
|
|
fb05bb7f07 | ||
|
|
8246149544 | ||
|
|
d525acdeda | ||
|
|
2f0075752d | ||
|
|
8409e155d4 | ||
|
|
3a3986320c | ||
|
|
498477da04 | ||
|
|
29817b6617 | ||
|
|
7be7a9b5e3 | ||
|
|
a389622ac6 | ||
|
|
72547f9ec3 | ||
|
|
04a866121e | ||
|
|
f4df58ed0f | ||
|
|
bc7eaee6d3 | ||
|
|
ff7bdb5140 | ||
|
|
6184d228c1 | ||
|
|
8ac495723e | ||
|
|
09f9f871a3 | ||
|
|
2a3d930933 | ||
|
|
bd71bf2379 | ||
|
|
6f593d53d0 | ||
|
|
d1e4211f4b | ||
|
|
9745f676ed | ||
|
|
90dd39d581 | ||
|
|
9011e88f9f | ||
|
|
0e20a65a0b | ||
|
|
28c4a2d8fa | ||
|
|
ea810ac806 | ||
|
|
11ed015dca | ||
|
|
029c516cbc | ||
|
|
c6b9e4951f | ||
|
|
ebd6b0da49 | ||
|
|
cceb74a66e | ||
|
|
9f7204ee26 | ||
|
|
0d243bb824 | ||
|
|
e53b0ef068 | ||
|
|
1301fd6ddb | ||
|
|
0101436933 | ||
|
|
0e0ffc9c10 | ||
|
|
a51a62cb42 | ||
|
|
86c204d8a8 | ||
|
|
1182927fe5 | ||
|
|
4d3cd7dcb8 | ||
|
|
8b889139e9 | ||
|
|
1323dbddfe | ||
|
|
c02341c85f | ||
|
|
735c04f999 | ||
|
|
bc6965c86f | ||
|
|
075297d8ad | ||
|
|
8f5847b8e3 | ||
|
|
ab7ee2f8a9 | ||
|
|
18aa97f962 | ||
|
|
2ae0edc4df | ||
|
|
89632416ba | ||
|
|
61fa94617d | ||
|
|
659ceaabdd | ||
|
|
d79ff24014 | ||
|
|
1df7318450 | ||
|
|
60debfb0a6 | ||
|
|
379dd02fb6 | ||
|
|
339391ecfb | ||
|
|
38c404e04e | ||
|
|
f8c3756ac0 | ||
|
|
360194b29b | ||
|
|
af7236f7e7 | ||
|
|
6d78de95a1 | ||
|
|
577476b8fe | ||
|
|
54bf7c99d7 | ||
|
|
e340996919 | ||
|
|
f5401317c9 | ||
|
|
de2637b4fa | ||
|
|
ea726c9f17 | ||
|
|
314dda08e8 | ||
|
|
b010ac21d3 | ||
|
|
7519bdde42 | ||
|
|
09a0d6e607 | ||
|
|
a3e93554e5 | ||
|
|
d2acc78787 | ||
|
|
3ec25cbece | ||
|
|
5caa277261 | ||
|
|
f819e71d12 | ||
|
|
27a9dd3bbb | ||
|
|
5b8f555221 | ||
|
|
fbc05fa5a8 | ||
|
|
95d9084899 | ||
|
|
f31383516e | ||
|
|
82e88a3239 | ||
|
|
3a3270b37c | ||
|
|
290414e935 | ||
|
|
e1122404d1 | ||
|
|
185653f85a | ||
|
|
72a3b41315 | ||
|
|
5bcc6339b4 | ||
|
|
8c8396af59 | ||
|
|
7b8158b1af | ||
|
|
3665f90795 | ||
|
|
f225b7b928 | ||
|
|
4a3ff8ff9e | ||
|
|
378d7a1ad9 | ||
|
|
9a76c648f1 | ||
|
|
6660f81363 | ||
|
|
84c9d1dbb7 | ||
|
|
08aab1c48a | ||
|
|
9149ae2164 | ||
|
|
ec13c5f80d | ||
|
|
4058f5642f | ||
|
|
48bdf79b5b | ||
|
|
bf500711b3 | ||
|
|
f7f5a27ebf | ||
|
|
1f678c17d3 | ||
|
|
5a34e5b2bf | ||
|
|
3577300aee | ||
|
|
258cc0067b | ||
|
|
0b2a02c8ea | ||
|
|
7c442e1a98 | ||
|
|
85e37e4b70 | ||
|
|
de4a0725f3 | ||
|
|
426c2e8c2b | ||
|
|
db1159414f | ||
|
|
6bb8521a55 | ||
|
|
3c9e438a68 | ||
|
|
2f9d19c42c | ||
|
|
ee9df63221 | ||
|
|
2076abf0c1 | ||
|
|
273da38bdd | ||
|
|
d98e989417 | ||
|
|
7f47bf452a | ||
|
|
a3f5d0f590 | ||
|
|
94438bf3cd | ||
|
|
df7f13d069 | ||
|
|
8befc0c1f5 | ||
|
|
dab20efc99 | ||
|
|
0e40a04975 | ||
|
|
c6cd699f0d | ||
|
|
3306bdec29 | ||
|
|
32b7797394 | ||
|
|
b1aa43741a | ||
|
|
c966054bf6 | ||
|
|
105f0fd49a | ||
|
|
fe95d19e29 | ||
|
|
2a294f048a | ||
|
|
bd4322f56f | ||
|
|
a411342f0c | ||
|
|
370ef93db6 | ||
|
|
7d540fc0d8 | ||
|
|
fd1439f284 | ||
|
|
a1e1b03ca4 | ||
|
|
87ce2f774d | ||
|
|
9deda06ec6 | ||
|
|
b0824ada15 | ||
|
|
5487356370 | ||
|
|
97a06444f2 | ||
|
|
809111336a | ||
|
|
18418128c3 | ||
|
|
581ac5b019 | ||
|
|
cde0e58e39 | ||
|
|
842c8ca056 | ||
|
|
fe4298674f | ||
|
|
3e7efad0fd | ||
|
|
9270ac6358 | ||
|
|
d421274dcd | ||
|
|
3c2cd506ec | ||
|
|
1df02d5a93 | ||
|
|
fdd90e036f | ||
|
|
761c9ee2b6 | ||
|
|
c215615da3 | ||
|
|
b7b6252048 | ||
|
|
6d27531663 | ||
|
|
3c44407c57 | ||
|
|
bfa04da572 | ||
|
|
e547710c6d | ||
|
|
5c3055219c | ||
|
|
46619fbb8d | ||
|
|
4d9c90ed4a | ||
|
|
af1743f9f3 | ||
|
|
b5d2f01993 | ||
|
|
af8cc3d29f | ||
|
|
e68f69b63b | ||
|
|
a4cf6fa715 | ||
|
|
656ece06e5 | ||
|
|
1d17d61dbc | ||
|
|
d457b7a5e3 | ||
|
|
398a831701 | ||
|
|
61fa03b1ad | ||
|
|
56980ffc1f | ||
|
|
d1ebf3c769 | ||
|
|
7facdf63c9 | ||
|
|
f4e13ffd80 | ||
|
|
44e34d9606 | ||
|
|
35ccd73a86 | ||
|
|
aece624d1c | ||
|
|
c2355b18f9 | ||
|
|
634467d24b | ||
|
|
0b8a21ee16 | ||
|
|
72e573d98d | ||
|
|
5a98660d1b | ||
|
|
d8d85373f5 | ||
|
|
a16d7f221e | ||
|
|
95f512aa69 | ||
|
|
099c4b5e1d | ||
|
|
9437136f84 | ||
|
|
d2e2322fd2 | ||
|
|
ce27b13076 | ||
|
|
a5c05f87f1 | ||
|
|
7cba0b25fd | ||
|
|
978192233d | ||
|
|
c6a8efff7d | ||
|
|
0f8dadadf5 | ||
|
|
862c5b61a4 | ||
|
|
6fcdf3c7ed | ||
|
|
8eae921cbf | ||
|
|
5a7863d21a | ||
|
|
077bc83f7f | ||
|
|
22742a9ba0 | ||
|
|
3b16faddad | ||
|
|
094ea3fe97 | ||
|
|
6985af5e88 | ||
|
|
6cdbf5216e | ||
|
|
f380d6be43 | ||
|
|
fb492d9acb | ||
|
|
a7ff906e17 | ||
|
|
696a6867dd | ||
|
|
12f6119739 | ||
|
|
885c6c94d3 | ||
|
|
8afceee7a9 | ||
|
|
d6e2c80608 | ||
|
|
2f4582147a | ||
|
|
69e44ebf07 | ||
|
|
f90a387f96 | ||
|
|
5dcf339840 | ||
|
|
774e2ecebf | ||
|
|
af1d45d969 | ||
|
|
79a8ff04fd | ||
|
|
7fbb868513 | ||
|
|
f6ecff0e26 | ||
|
|
5ff42505e8 | ||
|
|
c3d00b0ac6 | ||
|
|
ae7889f830 | ||
|
|
d8d9291402 | ||
|
|
7d02cd6679 | ||
|
|
7d0f279353 | ||
|
|
ad9a5acb7f | ||
|
|
8d25fd39cf | ||
|
|
ee814fb48e | ||
|
|
57234d8ef3 | ||
|
|
47830efbf5 | ||
|
|
dc5d6316c9 | ||
|
|
a650641813 | ||
|
|
8702ff8b7e | ||
|
|
c6b03ce62b | ||
|
|
ea5bb5cdab | ||
|
|
e168f7a917 | ||
|
|
33459f1b36 | ||
|
|
f0f75e2d2c | ||
|
|
a26420f6e8 | ||
|
|
ae905bd056 | ||
|
|
7b8dae92d9 | ||
|
|
c80e8cb7d3 | ||
|
|
a2c66dd102 | ||
|
|
0297be4b9a | ||
|
|
ecc1d94b3a | ||
|
|
553408d573 | ||
|
|
e33cc5ee12 | ||
|
|
32ea060e99 | ||
|
|
ad905fc310 | ||
|
|
5f657b4333 | ||
|
|
704bef5dfc | ||
|
|
f79652c28c | ||
|
|
e575b5fe8a | ||
|
|
da7ecc1527 | ||
|
|
86f9abda0d | ||
|
|
4475b9ac05 | ||
|
|
4100f6eead | ||
|
|
ed2f81da2f | ||
|
|
4cf00b8b42 | ||
|
|
96c5ff7e7f | ||
|
|
8731fe9112 | ||
|
|
84b567c790 | ||
|
|
ba2512655e | ||
|
|
6266bae1d3 | ||
|
|
188d1649d3 | ||
|
|
9ddf7bbd15 | ||
|
|
469666de82 | ||
|
|
fc1ac3e752 | ||
|
|
ab7a66b90d | ||
|
|
2b82e5a118 | ||
|
|
16d2cb6309 | ||
|
|
413643a712 | ||
|
|
843c0719e0 | ||
|
|
3d02dba5dc | ||
|
|
efc8d90bc1 | ||
|
|
1db69acbc0 | ||
|
|
c0f6f834b7 | ||
|
|
8c60069bb8 | ||
|
|
e1da874258 | ||
|
|
616e0e8eb5 | ||
|
|
89f6da14bc | ||
|
|
832c0998e4 | ||
|
|
0d06f8fa2b | ||
|
|
2b6bc7d59a | ||
|
|
0d384050fa | ||
|
|
8141f7b6a6 | ||
|
|
cced3bf9ee | ||
|
|
ea6afe84db | ||
|
|
382dcf9a37 | ||
|
|
8923524f6a | ||
|
|
31a474a1ca | ||
|
|
1afd3a41cb | ||
|
|
5a6195feb6 | ||
|
|
2fd0d430c8 | ||
|
|
f055681972 | ||
|
|
1fefcc2b46 | ||
|
|
c0a039ee11 | ||
|
|
09f1d00733 | ||
|
|
f26385d0c6 | ||
|
|
b097a5fb0c | ||
|
|
af53b72eb8 | ||
|
|
a37c372d06 | ||
|
|
8fe7db107a | ||
|
|
5d34b7d618 | ||
|
|
43b492204c | ||
|
|
ce9cce921d | ||
|
|
5ed57d34f0 | ||
|
|
e65aa4cf17 | ||
|
|
bfbf6a2711 | ||
|
|
6b76371d64 | ||
|
|
cdfa869ea6 | ||
|
|
d4cdc6d334 | ||
|
|
7b3f1c2b85 | ||
|
|
9972f19240 | ||
|
|
f23034305f | ||
|
|
fe40a53e8f | ||
|
|
2663d6c3cb | ||
|
|
8b8d81e767 | ||
|
|
d43bc79050 | ||
|
|
06af2fb52b | ||
|
|
8bb69f1e9c | ||
|
|
b98b2d4310 | ||
|
|
f05b03f02c | ||
|
|
4d87473053 | ||
|
|
660236b224 | ||
|
|
194f56377e | ||
|
|
2023615f55 | ||
|
|
de2cbfa8a9 | ||
|
|
067de4508b | ||
|
|
74bf4c5e71 | ||
|
|
099bb2cbaa | ||
|
|
e395559f75 | ||
|
|
b7b6ab779a | ||
|
|
109b326ae2 | ||
|
|
c7e6c8eacc | ||
|
|
9fbd2a50ff | ||
|
|
ea69386519 | ||
|
|
8124fe98c7 | ||
|
|
16a911bc39 | ||
|
|
c81db5a21c | ||
|
|
dbcba6477e | ||
|
|
36816fb4f3 | ||
|
|
1ec8252412 | ||
|
|
91fae36b86 | ||
|
|
623ffebe62 | ||
|
|
906286fdbe | ||
|
|
92942d44d1 | ||
|
|
9caa6ae69c | ||
|
|
39d9150175 | ||
|
|
5301c416bc | ||
|
|
92395745d3 | ||
|
|
7d9e8f9d92 | ||
|
|
6842c03399 | ||
|
|
2c3d80494f | ||
|
|
2cf770cc91 | ||
|
|
bfdb74bfee | ||
|
|
580a2f4dc6 | ||
|
|
c8fe21c1ef | ||
|
|
59cfabf8a4 | ||
|
|
810feee5a1 | ||
|
|
24fc7d4cbd | ||
|
|
5edfc527b0 | ||
|
|
febc28f83f | ||
|
|
98297cef4d | ||
|
|
0289c39850 | ||
|
|
29e334de54 | ||
|
|
f9723ca3c1 | ||
|
|
c17e8e778d | ||
|
|
b2510e5fc5 | ||
|
|
6c800bd0e3 | ||
|
|
88ac85b6ae | ||
|
|
6bdf9935bf | ||
|
|
29cda82eac | ||
|
|
b05613445e | ||
|
|
defeba5576 | ||
|
|
4a550d12d4 | ||
|
|
70c39fe78c | ||
|
|
6fc8550c19 | ||
|
|
6b9a4c4a34 | ||
|
|
041762a34f | ||
|
|
25c4a1bd8d | ||
|
|
05b459e4c5 | ||
|
|
1665d61c89 | ||
|
|
9a58763a4e | ||
|
|
f9707ba344 | ||
|
|
ae04f3029b | ||
|
|
40872e9d90 | ||
|
|
ee8d8bf5e5 | ||
|
|
b85bf82d00 | ||
|
|
6fb3dafa95 | ||
|
|
f5960df544 | ||
|
|
93227bfd4d | ||
|
|
0832d5a7d5 | ||
|
|
602d2b8ad5 | ||
|
|
0341944350 | ||
|
|
00d1e6b549 | ||
|
|
9c17ac5bde | ||
|
|
90ce1c018e | ||
|
|
618fed75fe | ||
|
|
ef9eea470c | ||
|
|
9d9da1a3e8 | ||
|
|
7c16f2182c | ||
|
|
9dc9bf5eb0 | ||
|
|
035a762358 | ||
|
|
7f98be2920 | ||
|
|
7bdc7aa527 | ||
|
|
5c9c08ef85 | ||
|
|
5e23933757 | ||
|
|
9d15a08d27 | ||
|
|
0c2ec04c09 | ||
|
|
30bda0b4c4 | ||
|
|
710ac9d544 | ||
|
|
bcabe7b3b5 | ||
|
|
4e730b5ec8 | ||
|
|
f0d966a595 | ||
|
|
8cad245f80 | ||
|
|
7cbd4d49c3 | ||
|
|
7a33d5bb34 | ||
|
|
3e767ca5c8 | ||
|
|
c767399fc6 | ||
|
|
3a46c15c4a | ||
|
|
00dcb1bce9 | ||
|
|
420ec18c5b | ||
|
|
d78dd42ed4 | ||
|
|
547c01f5ff | ||
|
|
75eb644108 | ||
|
|
ee5dcbc1d8 | ||
|
|
7f46ad19ac | ||
|
|
6530431995 | ||
|
|
ed1645109a | ||
|
|
277d3e9ab4 | ||
|
|
556f92a823 | ||
|
|
ef32449309 | ||
|
|
e08032da93 | ||
|
|
dc40469cb3 | ||
|
|
abc3e783ff | ||
|
|
6bc56c549a | ||
|
|
580980d149 | ||
|
|
c779e4e8ee | ||
|
|
ee0078f7c1 | ||
|
|
da044d8b00 | ||
|
|
09e92f98ff | ||
|
|
0dbf10ce69 | ||
|
|
e7a68dba58 | ||
|
|
608010c35d | ||
|
|
869d71446d | ||
|
|
268d29222a | ||
|
|
1a10f95973 | ||
|
|
8c86ea6b75 | ||
|
|
dbb421c4f7 | ||
|
|
879aa9512d | ||
|
|
cf4dfa3a05 | ||
|
|
f933e1d2b7 | ||
|
|
8d06cca073 | ||
|
|
7ac5dc55d0 | ||
|
|
68be28ca6d | ||
|
|
70e2170e3e | ||
|
|
a8430088b2 | ||
|
|
925606ff26 | ||
|
|
881e37ec02 | ||
|
|
194c9d6e07 | ||
|
|
2613e837a9 | ||
|
|
51aca86e98 | ||
|
|
b74a3229f8 | ||
|
|
71b3b9075d | ||
|
|
20c57fcd0e | ||
|
|
fbe76d0fa1 | ||
|
|
619ee1e6f9 | ||
|
|
0e88f32d66 | ||
|
|
546614455f | ||
|
|
0b9499a00f | ||
|
|
448ca6e43c | ||
|
|
c9955c0635 | ||
|
|
768d2db114 | ||
|
|
79d94c4771 | ||
|
|
a3e26233b2 | ||
|
|
b7726c4ca8 | ||
|
|
bae3b7d594 | ||
|
|
a36ec27230 | ||
|
|
bc1f18b73a | ||
|
|
cc8a0f8022 | ||
|
|
c3a405eac7 | ||
|
|
e4209d86f6 | ||
|
|
fcb9dea501 | ||
|
|
c810b157cf | ||
|
|
c458f6e826 | ||
|
|
c99e223cb1 | ||
|
|
5c27d6aeee | ||
|
|
4832cad1f1 | ||
|
|
5930bf6d93 | ||
|
|
d37389162e | ||
|
|
1a64caaa4d | ||
|
|
0de3051821 | ||
|
|
0f53eca883 | ||
|
|
4cc1fcb37b | ||
|
|
44af7e43b6 | ||
|
|
673de6aeb6 | ||
|
|
bf959e45fb | ||
|
|
ce247bcab3 | ||
|
|
2a6e05b776 | ||
|
|
fe1ef154cf | ||
|
|
7e3339820f | ||
|
|
6b3ffdbd3d | ||
|
|
0017ea8fd0 | ||
|
|
a5b57068d4 | ||
|
|
921d78f820 | ||
|
|
6b5f8a6b1d | ||
|
|
5932f28519 | ||
|
|
79d2ddf24f | ||
|
|
2cfe22d4e5 | ||
|
|
e3ee4e4718 | ||
|
|
2d16af6ee6 | ||
|
|
4f97d9637e | ||
|
|
c228598098 | ||
|
|
a783bf9b8b | ||
|
|
54fdd6ba5a | ||
|
|
6ddea62d09 | ||
|
|
6855284d88 | ||
|
|
46a5beafe4 | ||
|
|
0f2dcf28b1 | ||
|
|
bc7f20e179 | ||
|
|
1e6a69f8aa | ||
|
|
9bd2537971 | ||
|
|
bf554d0e43 | ||
|
|
810c767200 | ||
|
|
4ba7af6061 | ||
|
|
86cf3c835e | ||
|
|
9e7d6823b1 | ||
|
|
aa7090df49 | ||
|
|
a9d1ca4d83 | ||
|
|
400af0d2fa | ||
|
|
41ab87e904 | ||
|
|
cf71f034dc | ||
|
|
1a7aea1906 | ||
|
|
3207bc4704 | ||
|
|
60e950015c | ||
|
|
08fc0b7aec | ||
|
|
a8fcb86c10 | ||
|
|
48b7945714 | ||
|
|
c507f409a5 | ||
|
|
72537b6614 | ||
|
|
c839c5721c | ||
|
|
04ee53e061 | ||
|
|
f57652524c | ||
|
|
d817dceb05 | ||
|
|
c17f0d7e61 | ||
|
|
3003789288 | ||
|
|
86c222ab58 | ||
|
|
f21ca8591c | ||
|
|
ce6b92484f | ||
|
|
80619fa8a0 | ||
|
|
9a0d5cd739 | ||
|
|
6185e157e9 | ||
|
|
04ad1791b0 | ||
|
|
bb5cc06677 | ||
|
|
706f4f2ef5 | ||
|
|
36b8a017bd | ||
|
|
b8865fb182 | ||
|
|
03c3d8bdb3 | ||
|
|
aa5bd7bc17 | ||
|
|
1c9257d537 | ||
|
|
ea56e56ec1 | ||
|
|
17680fff55 | ||
|
|
d9d644b27f | ||
|
|
5e09581256 | ||
|
|
ed7423b2b5 | ||
|
|
77a956cda4 | ||
|
|
a9253837ac | ||
|
|
63f903a3fb | ||
|
|
f702ce331a | ||
|
|
b1361aaf8b | ||
|
|
8b7e7d438c | ||
|
|
097d82535d | ||
|
|
03cf6cca40 | ||
|
|
20a0f7ac68 | ||
|
|
6cff57ab43 | ||
|
|
e9d25e5919 | ||
|
|
381a6cdfac | ||
|
|
1ebca8f732 | ||
|
|
172204c933 | ||
|
|
77000db747 | ||
|
|
6563a68ae2 | ||
|
|
d9bcdfe61b | ||
|
|
5f08fe7ead | ||
|
|
d3f6657032 | ||
|
|
554570f884 | ||
|
|
231a9e4051 | ||
|
|
9e6f974f3c | ||
|
|
06e3852cef | ||
|
|
5d73943929 | ||
|
|
159ce13f5e | ||
|
|
ed12b83b4e | ||
|
|
6be293e848 | ||
|
|
9cebb09a5f | ||
|
|
f6f3ffc254 | ||
|
|
497bda21b2 | ||
|
|
6164d16f19 | ||
|
|
328cd14897 | ||
|
|
6954e6cb0e | ||
|
|
ad17dc227c | ||
|
|
955b445723 | ||
|
|
b2adc12287 | ||
|
|
0afeed6108 | ||
|
|
b2c2a7b5d0 | ||
|
|
acbb80920b | ||
|
|
9ba87d4613 | ||
|
|
99f466e35e | ||
|
|
ffe3019561 | ||
|
|
47f0ef0eae | ||
|
|
be5bd41640 | ||
|
|
de62012a7f | ||
|
|
a793824d2c | ||
|
|
52cf367a92 | ||
|
|
81ea0ec5f3 | ||
|
|
7d118e1b12 | ||
|
|
fd35438a30 | ||
|
|
8203a5d2c3 | ||
|
|
9c8ced1fc6 | ||
|
|
f97c9e08c0 | ||
|
|
8a59bf7c45 | ||
|
|
5353210814 | ||
|
|
17f0b4a2e1 | ||
|
|
163721651a | ||
|
|
b7e3b4ff77 | ||
|
|
62a9982b76 | ||
|
|
42ef5d3460 | ||
|
|
700a121ccd | ||
|
|
0dc490979f | ||
|
|
0d0fc2d433 | ||
|
|
7af5ab5445 | ||
|
|
510f6bb830 | ||
|
|
e0e4432703 | ||
|
|
48a2161306 | ||
|
|
2c3d473193 | ||
|
|
a50cdda7a5 | ||
|
|
58558f2e1d | ||
|
|
36c722731b | ||
|
|
1cf77d2172 | ||
|
|
5d40607cf9 | ||
|
|
4caecf34ae | ||
|
|
f20b25a123 | ||
|
|
f19148d765 | ||
|
|
6e45d6b68d | ||
|
|
3e06729877 | ||
|
|
b6994b9615 | ||
|
|
4227f2d9dc | ||
|
|
3dbea4b0b7 | ||
|
|
31af5419a2 | ||
|
|
0efcf1b622 | ||
|
|
a1166d6fdb | ||
|
|
ac5fc72347 | ||
|
|
97a17bd587 | ||
|
|
daee5ab1d3 | ||
|
|
645da2b749 | ||
|
|
4926a788c1 | ||
|
|
735c1ecc2a | ||
|
|
8a2a5e7e85 | ||
|
|
6a45211a00 | ||
|
|
f46375a50a | ||
|
|
69332e1189 | ||
|
|
6eb5e24988 | ||
|
|
cb3697cb5a | ||
|
|
5aac474737 | ||
|
|
99b6bb324d | ||
|
|
5d1d7335b0 | ||
|
|
e899da0063 | ||
|
|
0df9b57d48 | ||
|
|
e244f8d3b2 | ||
|
|
c77cd13c97 | ||
|
|
300d401686 | ||
|
|
8a4b6473f4 | ||
|
|
00cc982bcb | ||
|
|
4dea3f41a2 | ||
|
|
1c9b867593 | ||
|
|
920e6f5049 | ||
|
|
00d837d454 | ||
|
|
733f2aa87f | ||
|
|
2ca9e9f937 | ||
|
|
dd3d04fed2 | ||
|
|
4ce21af7de | ||
|
|
db383b6a8b | ||
|
|
b906c492a2 | ||
|
|
8d5a8b0927 | ||
|
|
887bf0511f | ||
|
|
f529f3b14d | ||
|
|
75b842b430 | ||
|
|
1289bca9d8 | ||
|
|
e7271cfd0b | ||
|
|
f4568fc819 | ||
|
|
f062b55cfc | ||
|
|
f7715ab1ba | ||
|
|
84cf7d8c14 | ||
|
|
cd3dbf615f | ||
|
|
7a5f1390d1 | ||
|
|
027b80f5af | ||
|
|
89e413dba7 | ||
|
|
9027161453 | ||
|
|
20b4375f25 | ||
|
|
aa90a8a989 | ||
|
|
eadb49c56d | ||
|
|
9148b0f865 | ||
|
|
3aacb7c377 | ||
|
|
1beb8faa26 | ||
|
|
8708f31c45 | ||
|
|
d867f0c04e | ||
|
|
84bc071179 | ||
|
|
7258ad00f4 | ||
|
|
483a98fc8c | ||
|
|
c3a13240ab | ||
|
|
a223f80992 | ||
|
|
06e5c42541 | ||
|
|
2ed7540dfb | ||
|
|
26ad4dabd1 | ||
|
|
6c14fdaca7 | ||
|
|
91d389330e | ||
|
|
62f1e47bd1 | ||
|
|
2b6c1e0187 | ||
|
|
faeee03dd1 | ||
|
|
7e63197e97 | ||
|
|
65cc1a4c01 | ||
|
|
b6c830c254 | ||
|
|
19ce23e907 | ||
|
|
122926ad49 | ||
|
|
01d6554a00 | ||
|
|
22005d642f | ||
|
|
b601fd12f7 | ||
|
|
740741b129 | ||
|
|
6d0c0b4323 | ||
|
|
1623917bc4 | ||
|
|
9c6b6e61fe | ||
|
|
bcd3e79557 | ||
|
|
fee13a6daf | ||
|
|
619f3fd60b | ||
|
|
4eb2218cf3 | ||
|
|
45f20b8505 | ||
|
|
561b10a62b | ||
|
|
e66d439cb4 | ||
|
|
83313ead4f | ||
|
|
e6bc6aafdf | ||
|
|
c7f95280e4 | ||
|
|
459cd657d3 | ||
|
|
ea6dbc912b | ||
|
|
a8841a8b76 | ||
|
|
167a30fcb9 | ||
|
|
274b07f50a | ||
|
|
e7488209c8 | ||
|
|
11bde71b92 | ||
|
|
cecdb0c896 | ||
|
|
4cd197cb13 | ||
|
|
72426d21fb | ||
|
|
4ac2de1ee5 | ||
|
|
e14b716643 | ||
|
|
f0c636f243 | ||
|
|
8aef427fd8 | ||
|
|
6c4e83f8a2 | ||
|
|
04311d6c1a | ||
|
|
9cb809ac60 | ||
|
|
79b0472924 | ||
|
|
818bdd49b8 | ||
|
|
8ec4eb8030 | ||
|
|
45068f601a | ||
|
|
406bd5da84 | ||
|
|
0b386f21d5 | ||
|
|
8469f67a38 | ||
|
|
e01b887bc8 | ||
|
|
de6d927914 | ||
|
|
e5d6751b09 | ||
|
|
81f8451a23 | ||
|
|
436fe158c9 | ||
|
|
7f3716504b | ||
|
|
035bf8b7db | ||
|
|
af582aff02 | ||
|
|
46beab3cf1 | ||
|
|
0a9af6ad5c | ||
|
|
e3d2d2e7c1 | ||
|
|
903b1ea914 | ||
|
|
b62878c260 | ||
|
|
63bce1a426 | ||
|
|
954ad1f396 | ||
|
|
33e60df301 | ||
|
|
204714a01f | ||
|
|
eec5c23671 | ||
|
|
4595ded0d3 | ||
|
|
36f82ab9fe | ||
|
|
62f63a29b5 | ||
|
|
24730e158b | ||
|
|
6b44e6d0d8 | ||
|
|
79246e6ee9 | ||
|
|
cced69e496 | ||
|
|
da85855a6b | ||
|
|
6c8abeb067 | ||
|
|
b3b89b2072 | ||
|
|
05e5c42f33 | ||
|
|
b47641f1c2 | ||
|
|
22ac7debb9 | ||
|
|
50b9a7f212 | ||
|
|
ea2935e4d7 | ||
|
|
0ec247de8c | ||
|
|
c4347c0485 | ||
|
|
909c12c6b4 | ||
|
|
222d718ccd | ||
|
|
666023f804 | ||
|
|
38132cdb94 | ||
|
|
ba645cfbea | ||
|
|
2b9a6d8574 | ||
|
|
0d908c18b4 | ||
|
|
0487d60d0e | ||
|
|
018406b50c | ||
|
|
e388d96073 | ||
|
|
5fa2c1c410 | ||
|
|
f91364fb3e | ||
|
|
943d9a27ec | ||
|
|
3ff084b720 | ||
|
|
d7631fb997 | ||
|
|
2256a7237c | ||
|
|
b7403fd93c | ||
|
|
3d5f58c8b8 | ||
|
|
f7af27f1d2 | ||
|
|
119defc5e7 | ||
|
|
2a8333e0e4 | ||
|
|
95c3229f89 | ||
|
|
909e0e401f | ||
|
|
b1159b657d | ||
|
|
30a6361a8f | ||
|
|
eb65f1e441 | ||
|
|
a612b77cee | ||
|
|
16149b9198 | ||
|
|
00f137ba3e | ||
|
|
71503cce8b | ||
|
|
1c2af85b20 | ||
|
|
3ff9045178 | ||
|
|
c66dfe1c03 | ||
|
|
19f0aa75eb | ||
|
|
8b0f6c355c | ||
|
|
3cbf5efddd | ||
|
|
fda66f5bd9 | ||
|
|
3f15146c19 | ||
|
|
f11d726ddc | ||
|
|
75ff8d0689 | ||
|
|
e225a644f4 | ||
|
|
4a337785b5 | ||
|
|
1230430c94 | ||
|
|
b0c3963506 | ||
|
|
050a0c1000 | ||
|
|
8588cce4d5 | ||
|
|
fa224271a1 | ||
|
|
7898451236 | ||
|
|
67b1bb6178 | ||
|
|
548ee4a206 | ||
|
|
0c00b8b2ab | ||
|
|
889b440bb1 | ||
|
|
6f298b929e | ||
|
|
1eeeff82d1 | ||
|
|
b476bc86ce | ||
|
|
58923fe2ff | ||
|
|
5cccc81abf | ||
|
|
831cd2e71d | ||
|
|
9f9c30d406 | ||
|
|
1cb087c99e | ||
|
|
ae3fcca543 | ||
|
|
801a4f79b9 | ||
|
|
98bc576888 | ||
|
|
bb758854fb | ||
|
|
f460d24f65 | ||
|
|
b026160c5c | ||
|
|
fe842823a9 | ||
|
|
65dff05008 | ||
|
|
d4f883c1b0 | ||
|
|
e8f037cac8 | ||
|
|
cca568112d | ||
|
|
db19764130 | ||
|
|
2379ff1740 | ||
|
|
f6da7679b8 | ||
|
|
b0d0a7a04a | ||
|
|
f1181ce9c2 | ||
|
|
e9402da131 | ||
|
|
04a945531c | ||
|
|
ebd0e85d65 | ||
|
|
2bfbc6a314 | ||
|
|
0e924edf0e | ||
|
|
448bbf3710 | ||
|
|
1907fe2a91 | ||
|
|
021c0386f8 | ||
|
|
f72616981e | ||
|
|
6eddd62a73 | ||
|
|
306efa66c7 | ||
|
|
0bfaa46ce7 | ||
|
|
91b9cdfae5 | ||
|
|
6f12d797d2 | ||
|
|
86a4d6f607 | ||
|
|
a60a4c507a | ||
|
|
7bbde459f3 | ||
|
|
4a961401fc | ||
|
|
9eab4cfa0d | ||
|
|
92409c321c | ||
|
|
9e348c049b | ||
|
|
c9dbf908b5 | ||
|
|
202cdda358 | ||
|
|
6eae66728b | ||
|
|
e262320348 | ||
|
|
9323fd896a | ||
|
|
f29141b855 | ||
|
|
6f8706818d | ||
|
|
512915b4c9 | ||
|
|
c176f24d05 | ||
|
|
087e60299b | ||
|
|
73c5153ef1 | ||
|
|
2863b5a8c6 | ||
|
|
1b92795d93 | ||
|
|
3cc6fb6c6e | ||
|
|
3ca1593919 | ||
|
|
6f4599be9a | ||
|
|
4b6a677b57 | ||
|
|
6e9dbf4c18 | ||
|
|
3d891e26dd | ||
|
|
139f7f6322 | ||
|
|
a5e4bf63c5 | ||
|
|
2af3fd4a8c | ||
|
|
69ae58f7ba | ||
|
|
7e7b19b904 | ||
|
|
f4e6231358 | ||
|
|
0c909251aa | ||
|
|
2ef46a3165 |
+262
-11
@@ -1,11 +1,13 @@
|
||||
version: 2.1
|
||||
orbs:
|
||||
go: gotest/tools@0.0.13
|
||||
aws-cli: circleci/aws-cli@1.3.2
|
||||
packer: salaxander/packer@0.0.3
|
||||
|
||||
executors:
|
||||
golang:
|
||||
docker:
|
||||
- image: circleci/golang:1.14.6
|
||||
- image: circleci/golang:1.15.5
|
||||
resource_class: 2xlarge
|
||||
ubuntu:
|
||||
docker:
|
||||
@@ -34,7 +36,7 @@ commands:
|
||||
condition: << parameters.linux >>
|
||||
steps:
|
||||
- run: sudo apt-get update
|
||||
- run: sudo apt-get install ocl-icd-opencl-dev
|
||||
- run: sudo apt-get install ocl-icd-opencl-dev libhwloc-dev
|
||||
- run: git submodule sync
|
||||
- run: git submodule update --init
|
||||
download-params:
|
||||
@@ -128,6 +130,9 @@ jobs:
|
||||
winpost-test:
|
||||
type: string
|
||||
default: "0"
|
||||
deadline-test:
|
||||
type: string
|
||||
default: "0"
|
||||
test-suite-name:
|
||||
type: string
|
||||
default: unit
|
||||
@@ -161,6 +166,7 @@ jobs:
|
||||
name: go test
|
||||
environment:
|
||||
LOTUS_TEST_WINDOW_POST: << parameters.winpost-test >>
|
||||
LOTUS_TEST_DEADLINE_TOGGLING: << parameters.deadline-test >>
|
||||
SKIP_CONFORMANCE: "1"
|
||||
command: |
|
||||
mkdir -p /tmp/test-reports/<< parameters.test-suite-name >>
|
||||
@@ -188,10 +194,24 @@ jobs:
|
||||
command: |
|
||||
bash <(curl -s https://codecov.io/bash)
|
||||
|
||||
test-chain:
|
||||
<<: *test
|
||||
test-node:
|
||||
<<: *test
|
||||
test-storage:
|
||||
<<: *test
|
||||
test-cli:
|
||||
<<: *test
|
||||
test-short:
|
||||
<<: *test
|
||||
test-window-post:
|
||||
<<: *test
|
||||
test-window-post-dispute:
|
||||
<<: *test
|
||||
test-deadline-toggling:
|
||||
<<: *test
|
||||
test-terminate:
|
||||
<<: *test
|
||||
test-conformance:
|
||||
description: |
|
||||
Run tests using a corpus of interoperable test vectors for Filecoin
|
||||
@@ -254,24 +274,67 @@ jobs:
|
||||
path: /tmp/test-reports
|
||||
- store_artifacts:
|
||||
path: /tmp/test-artifacts/conformance-coverage.html
|
||||
build-lotus-soup:
|
||||
build-ntwk-calibration:
|
||||
description: |
|
||||
Compile `lotus-soup` Testground test plan using the current version of Lotus.
|
||||
Compile lotus binaries for the calibration network
|
||||
parameters:
|
||||
<<: *test-params
|
||||
executor: << parameters.executor >>
|
||||
steps:
|
||||
- install-deps
|
||||
- prepare
|
||||
- run: make calibnet
|
||||
- run: mkdir linux-calibnet && mv lotus lotus-miner lotus-worker linux-calibnet
|
||||
- persist_to_workspace:
|
||||
root: "."
|
||||
paths:
|
||||
- linux-calibnet
|
||||
build-lotus-soup:
|
||||
description: |
|
||||
Compile `lotus-soup` Testground test plan
|
||||
parameters:
|
||||
<<: *test-params
|
||||
executor: << parameters.executor >>
|
||||
steps:
|
||||
- install-deps
|
||||
- prepare
|
||||
- run: cd extern/oni && git submodule sync
|
||||
- run: cd extern/oni && git submodule update --init
|
||||
- run: cd extern/filecoin-ffi && make
|
||||
- run:
|
||||
name: "replace lotus, filecoin-ffi, blst and fil-blst deps"
|
||||
command: cd extern/oni/lotus-soup && go mod edit -replace github.com/filecoin-project/lotus=../../../ && go mod edit -replace github.com/filecoin-project/filecoin-ffi=../../filecoin-ffi && go mod edit -replace github.com/supranational/blst=../../fil-blst/blst && go mod edit -replace github.com/filecoin-project/fil-blst=../../fil-blst
|
||||
name: "go get lotus@master"
|
||||
command: cd testplans/lotus-soup && go mod edit -replace=github.com/filecoin-project/lotus=../..
|
||||
- run:
|
||||
name: "build lotus-soup testplan"
|
||||
command: pushd extern/oni/lotus-soup && go build -tags=testground .
|
||||
command: pushd testplans/lotus-soup && go build -tags=testground .
|
||||
trigger-testplans:
|
||||
description: |
|
||||
Trigger `lotus-soup` test cases on TaaS
|
||||
parameters:
|
||||
<<: *test-params
|
||||
executor: << parameters.executor >>
|
||||
steps:
|
||||
- install-deps
|
||||
- prepare
|
||||
- run:
|
||||
name: "download testground"
|
||||
command: wget https://gist.github.com/nonsense/5fbf3167cac79945f658771aed32fc44/raw/2e17eb0debf7ec6bdf027c1bdafc2c92dd97273b/testground-d3e9603 -O ~/testground-cli && chmod +x ~/testground-cli
|
||||
- run:
|
||||
name: "prepare .env.toml"
|
||||
command: pushd testplans/lotus-soup && mkdir -p $HOME/testground && cp env-ci.toml $HOME/testground/.env.toml && echo 'endpoint="https://ci.testground.ipfs.team"' >> $HOME/testground/.env.toml && echo 'user="circleci"' >> $HOME/testground/.env.toml
|
||||
- run:
|
||||
name: "prepare testground home dir and link test plans"
|
||||
command: mkdir -p $HOME/testground/plans && ln -s $(pwd)/testplans/lotus-soup $HOME/testground/plans/lotus-soup && ln -s $(pwd)/testplans/graphsync $HOME/testground/plans/graphsync
|
||||
- run:
|
||||
name: "go get lotus@master"
|
||||
command: cd testplans/lotus-soup && go get github.com/filecoin-project/lotus@master
|
||||
- run:
|
||||
name: "trigger deals baseline testplan on taas"
|
||||
command: ~/testground-cli run composition -f $HOME/testground/plans/lotus-soup/_compositions/baseline-k8s-3-1.toml --metadata-commit=$CIRCLE_SHA1 --metadata-repo=filecoin-project/lotus --metadata-branch=$CIRCLE_BRANCH
|
||||
- run:
|
||||
name: "trigger payment channel stress testplan on taas"
|
||||
command: ~/testground-cli run composition -f $HOME/testground/plans/lotus-soup/_compositions/paych-stress-k8s.toml --metadata-commit=$CIRCLE_SHA1 --metadata-repo=filecoin-project/lotus --metadata-branch=$CIRCLE_BRANCH
|
||||
- run:
|
||||
name: "trigger graphsync testplan on taas"
|
||||
command: ~/testground-cli run composition -f $HOME/testground/plans/graphsync/_compositions/stress-k8s.toml --metadata-commit=$CIRCLE_SHA1 --metadata-repo=filecoin-project/lotus --metadata-branch=$CIRCLE_BRANCH
|
||||
|
||||
|
||||
build-macos:
|
||||
@@ -286,8 +349,8 @@ jobs:
|
||||
- run:
|
||||
name: Install go
|
||||
command: |
|
||||
curl -O https://dl.google.com/go/go1.14.2.darwin-amd64.pkg && \
|
||||
sudo installer -pkg go1.14.2.darwin-amd64.pkg -target /
|
||||
curl -O https://dl.google.com/go/go1.15.5.darwin-amd64.pkg && \
|
||||
sudo installer -pkg go1.15.5.darwin-amd64.pkg -target /
|
||||
- run:
|
||||
name: Install pkg-config
|
||||
command: HOMEBREW_NO_AUTO_UPDATE=1 brew install pkg-config
|
||||
@@ -351,6 +414,7 @@ jobs:
|
||||
steps:
|
||||
- install-deps
|
||||
- prepare
|
||||
- run: make deps
|
||||
- run: make docsgen
|
||||
- run: git --no-pager diff
|
||||
- run: git --no-pager diff --quiet
|
||||
@@ -414,6 +478,138 @@ jobs:
|
||||
name: Publish release
|
||||
command: ./scripts/publish-release.sh
|
||||
|
||||
build-and-push-image:
|
||||
description: build and push docker images to public AWS ECR registry
|
||||
executor: aws-cli/default
|
||||
parameters:
|
||||
profile-name:
|
||||
type: string
|
||||
default: "default"
|
||||
description: AWS profile name to be configured.
|
||||
|
||||
aws-access-key-id:
|
||||
type: env_var_name
|
||||
default: AWS_ACCESS_KEY_ID
|
||||
description: >
|
||||
AWS access key id for IAM role. Set this to the name of
|
||||
the environment variable you will set to hold this
|
||||
value, i.e. AWS_ACCESS_KEY.
|
||||
|
||||
aws-secret-access-key:
|
||||
type: env_var_name
|
||||
default: AWS_SECRET_ACCESS_KEY
|
||||
description: >
|
||||
AWS secret key for IAM role. Set this to the name of
|
||||
the environment variable you will set to hold this
|
||||
value, i.e. AWS_SECRET_ACCESS_KEY.
|
||||
|
||||
region:
|
||||
type: env_var_name
|
||||
default: AWS_REGION
|
||||
description: >
|
||||
Name of env var storing your AWS region information,
|
||||
defaults to AWS_REGION
|
||||
|
||||
account-url:
|
||||
type: env_var_name
|
||||
default: AWS_ECR_ACCOUNT_URL
|
||||
description: >
|
||||
Env var storing Amazon ECR account URL that maps to an AWS account,
|
||||
e.g. {awsAccountNum}.dkr.ecr.us-west-2.amazonaws.com
|
||||
defaults to AWS_ECR_ACCOUNT_URL
|
||||
|
||||
dockerfile:
|
||||
type: string
|
||||
default: Dockerfile
|
||||
description: Name of dockerfile to use. Defaults to Dockerfile.
|
||||
|
||||
path:
|
||||
type: string
|
||||
default: .
|
||||
description: Path to the directory containing your Dockerfile and build context. Defaults to . (working directory).
|
||||
|
||||
extra-build-args:
|
||||
type: string
|
||||
default: ""
|
||||
description: >
|
||||
Extra flags to pass to docker build. For examples, see
|
||||
https://docs.docker.com/engine/reference/commandline/build
|
||||
|
||||
repo:
|
||||
type: string
|
||||
description: Name of an Amazon ECR repository
|
||||
|
||||
tag:
|
||||
type: string
|
||||
default: "latest"
|
||||
description: A comma-separated string containing docker image tags to build and push (default = latest)
|
||||
|
||||
steps:
|
||||
- run:
|
||||
name: Confirm that environment variables are set
|
||||
command: |
|
||||
if [ -z "$AWS_ACCESS_KEY_ID" ]; then
|
||||
echo "No AWS_ACCESS_KEY_ID is set. Skipping build-and-push job ..."
|
||||
circleci-agent step halt
|
||||
fi
|
||||
|
||||
- aws-cli/setup:
|
||||
profile-name: <<parameters.profile-name>>
|
||||
aws-access-key-id: <<parameters.aws-access-key-id>>
|
||||
aws-secret-access-key: <<parameters.aws-secret-access-key>>
|
||||
aws-region: <<parameters.region>>
|
||||
|
||||
- run:
|
||||
name: Log into Amazon ECR
|
||||
command: |
|
||||
aws ecr-public get-login-password --region $<<parameters.region>> --profile <<parameters.profile-name>> | docker login --username AWS --password-stdin $<<parameters.account-url>>
|
||||
|
||||
- checkout
|
||||
|
||||
- setup_remote_docker:
|
||||
version: 19.03.13
|
||||
docker_layer_caching: false
|
||||
|
||||
- run:
|
||||
name: Build docker image
|
||||
command: |
|
||||
registry_id=$(echo $<<parameters.account-url>> | sed "s;\..*;;g")
|
||||
|
||||
docker_tag_args=""
|
||||
IFS="," read -ra DOCKER_TAGS \<<< "<< parameters.tag >>"
|
||||
for tag in "${DOCKER_TAGS[@]}"; do
|
||||
docker_tag_args="$docker_tag_args -t $<<parameters.account-url>>/<<parameters.repo>>:$tag"
|
||||
done
|
||||
|
||||
docker build \
|
||||
<<#parameters.extra-build-args>><<parameters.extra-build-args>><</parameters.extra-build-args>> \
|
||||
-f <<parameters.path>>/<<parameters.dockerfile>> \
|
||||
$docker_tag_args \
|
||||
<<parameters.path>>
|
||||
|
||||
- run:
|
||||
name: Push image to Amazon ECR
|
||||
command: |
|
||||
IFS="," read -ra DOCKER_TAGS \<<< "<< parameters.tag >>"
|
||||
for tag in "${DOCKER_TAGS[@]}"; do
|
||||
docker push $<<parameters.account-url>>/<<parameters.repo>>:${tag}
|
||||
done
|
||||
|
||||
publish-packer:
|
||||
description: build and push AWS IAM and DigitalOcean droplet.
|
||||
executor:
|
||||
name: packer/default
|
||||
packer-version: 1.6.6
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: "."
|
||||
- packer/build:
|
||||
template: tools/packer/lotus.pkr.hcl
|
||||
args: "-var ci_workspace_bins=./linux -var lotus_network=mainnet -var git_tag=$CIRCLE_TAG"
|
||||
- packer/build:
|
||||
template: tools/packer/lotus.pkr.hcl
|
||||
args: "-var ci_workspace_bins=./linux-calibnet -var lotus_network=calibrationnet -var git_tag=$CIRCLE_TAG"
|
||||
|
||||
workflows:
|
||||
version: 2.1
|
||||
@@ -428,10 +624,42 @@ workflows:
|
||||
- test:
|
||||
codecov-upload: true
|
||||
test-suite-name: full
|
||||
- test-chain:
|
||||
codecov-upload: true
|
||||
test-suite-name: chain
|
||||
packages: "./chain/..."
|
||||
- test-node:
|
||||
codecov-upload: true
|
||||
test-suite-name: node
|
||||
packages: "./node/..."
|
||||
- test-storage:
|
||||
codecov-upload: true
|
||||
test-suite-name: storage
|
||||
packages: "./storage/... ./extern/..."
|
||||
- test-cli:
|
||||
codecov-upload: true
|
||||
test-suite-name: cli
|
||||
packages: "./cli/... ./cmd/... ./api/..."
|
||||
- test-window-post:
|
||||
codecov-upload: true
|
||||
go-test-flags: "-run=TestWindowedPost"
|
||||
winpost-test: "1"
|
||||
test-suite-name: window-post
|
||||
- test-window-post-dispute:
|
||||
codecov-upload: true
|
||||
go-test-flags: "-run=TestWindowPostDispute"
|
||||
winpost-test: "1"
|
||||
test-suite-name: window-post-dispute
|
||||
- test-terminate:
|
||||
codecov-upload: true
|
||||
go-test-flags: "-run=TestTerminate"
|
||||
winpost-test: "1"
|
||||
test-suite-name: terminate
|
||||
- test-deadline-toggling:
|
||||
codecov-upload: true
|
||||
go-test-flags: "-run=TestDeadlineToggling"
|
||||
deadline-test: "1"
|
||||
test-suite-name: deadline-toggling
|
||||
- test-short:
|
||||
go-test-flags: "--timeout 10m --short"
|
||||
test-suite-name: short
|
||||
@@ -447,7 +675,13 @@ workflows:
|
||||
test-suite-name: conformance-bleeding-edge
|
||||
packages: "./conformance"
|
||||
vectors-branch: master
|
||||
- build-ntwk-calibration
|
||||
- build-lotus-soup
|
||||
- trigger-testplans:
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- build-debug
|
||||
- build-all:
|
||||
requires:
|
||||
@@ -477,3 +711,20 @@ workflows:
|
||||
tags:
|
||||
only:
|
||||
- /^v\d+\.\d+\.\d+$/
|
||||
- build-and-push-image:
|
||||
dockerfile: Dockerfile.lotus
|
||||
path: .
|
||||
repo: lotus-dev
|
||||
tag: '${CIRCLE_SHA1:0:8}'
|
||||
- publish-packer:
|
||||
requires:
|
||||
- build-all
|
||||
- build-ntwk-calibration
|
||||
filters:
|
||||
branches:
|
||||
ignore:
|
||||
- /.*/
|
||||
tags:
|
||||
only:
|
||||
- /^v\d+\.\d+\.\d+$/
|
||||
|
||||
|
||||
@@ -5,5 +5,15 @@ ignore:
|
||||
- "api/test/*"
|
||||
- "gen/**/*"
|
||||
- "gen/*"
|
||||
- "cmd/lotus-shed/*"
|
||||
- "cmd/tvx/*"
|
||||
- "cmd/lotus-pcr/*"
|
||||
- "cmd/tvx/*"
|
||||
- "cmd/lotus-chainwatch/*"
|
||||
- "cmd/lotus-health/*"
|
||||
- "cmd/lotus-fountain/*"
|
||||
- "cmd/lotus-townhall/*"
|
||||
- "cmd/lotus-stats/*"
|
||||
- "cmd/lotus-pcr/*"
|
||||
github_checks:
|
||||
annotations: false
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
---
|
||||
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.
|
||||
@@ -1,27 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**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.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Version (run `lotus version`):**
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
@@ -0,0 +1,49 @@
|
||||
---
|
||||
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,20 @@
|
||||
---
|
||||
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,35 @@
|
||||
---
|
||||
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
|
||||
@@ -0,0 +1,46 @@
|
||||
---
|
||||
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,21 +1,32 @@
|
||||
---
|
||||
name: Sealing Issues
|
||||
about: Create a report for help with sealing (commit) failures.
|
||||
title: ''
|
||||
labels: 'sealing'
|
||||
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.
|
||||
|
||||
A brief description of the problem you encountered while proving (sealing) a sector.
|
||||
**Version**
|
||||
|
||||
Including what commands you ran, and a description of your setup, is very helpful.
|
||||
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**
|
||||
|
||||
@@ -37,7 +48,3 @@ Please collect the following diagnostic information, and share a link here
|
||||
|
||||
If you have modified parts of lotus, please describe which areas were modified,
|
||||
and the scope of those modifications
|
||||
|
||||
**Version**
|
||||
|
||||
The output of `lotus --version`.
|
||||
@@ -13,6 +13,7 @@
|
||||
/lotus-gateway
|
||||
/lotus-pcr
|
||||
/lotus-wallet
|
||||
/lotus-keygen
|
||||
/bench.json
|
||||
/lotuspond/front/node_modules
|
||||
/lotuspond/front/build
|
||||
|
||||
+1
-8
@@ -1,16 +1,9 @@
|
||||
[submodule "extern/filecoin-ffi"]
|
||||
path = extern/filecoin-ffi
|
||||
url = https://github.com/filecoin-project/filecoin-ffi.git
|
||||
branch = master
|
||||
[submodule "extern/serialization-vectors"]
|
||||
path = extern/serialization-vectors
|
||||
url = https://github.com/filecoin-project/serialization-vectors
|
||||
url = https://github.com/filecoin-project/serialization-vectors.git
|
||||
[submodule "extern/test-vectors"]
|
||||
path = extern/test-vectors
|
||||
url = https://github.com/filecoin-project/test-vectors.git
|
||||
[submodule "extern/fil-blst"]
|
||||
path = extern/fil-blst
|
||||
url = https://github.com/filecoin-project/fil-blst.git
|
||||
[submodule "extern/oni"]
|
||||
path = extern/oni
|
||||
url = https://github.com/filecoin-project/oni
|
||||
|
||||
+682
@@ -1,5 +1,687 @@
|
||||
# Lotus changelog
|
||||
|
||||
# 1.8.0 / 2021-04-05
|
||||
|
||||
This is a mandatory release of Lotus that upgrades the network to version 12, which introduces various performance improvements to the cron processing of the power actor. The network will upgrade at height 712320, which is 2021-04-29T06:00:00Z.
|
||||
|
||||
## Changes
|
||||
|
||||
- v4 specs-actors integration, nv12 migration (https://github.com/filecoin-project/lotus/pull/6116)
|
||||
|
||||
# 1.6.0 / 2021-04-05
|
||||
|
||||
This is a mandatory release of Lotus that upgrades the network to version 11, which implements [FIP-0014](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0014.md). The network will upgrade at height 665280, which is 2021-04-12T22:00:00Z.
|
||||
|
||||
## v1 sector extension CLI
|
||||
|
||||
This release also expands the `lotus-miner sectors extend` CLI, with a new option that automatically extends all extensible v1 sectors. The option can be run using `lotus-miner sectors extend --v1-sectors`.
|
||||
|
||||
- The `tolerance` flag can be passed to indicate what durations aren't "worth" extending. It defaults to one week, which means that sectors whose current lifetime's are within one week of the maximum possible lifetime will not be extended.
|
||||
|
||||
- The `expiration-cutoff` flag can be passed to skip sectors whose expiration is past a certain point from the current head. It defaults to infinity (no cutoff), but if, say, 28800 was specified, then only sectors expiring in the next 10 days would be extended (2880 epochs in 1 day).
|
||||
|
||||
## Changes
|
||||
|
||||
- Util for miners to extend all v1 sectors (https://github.com/filecoin-project/lotus/pull/5924)
|
||||
- Upgrade the butterfly network (https://github.com/filecoin-project/lotus/pull/5929)
|
||||
- Introduce the v11 network upgrade (https://github.com/filecoin-project/lotus/pull/5904)
|
||||
- Debug mode: Make upgrade heights controllable by an envvar (https://github.com/filecoin-project/lotus/pull/5919)
|
||||
|
||||
# 1.5.3 / 2021-03-24
|
||||
|
||||
This is a patch release of Lotus that introduces small fixes to the Storage FSM.
|
||||
|
||||
## Changes
|
||||
|
||||
- storagefsm: Fix double unlock with ready WaitDeals sectors (https://github.com/filecoin-project/lotus/pull/5783)
|
||||
- backupds: Allow larger values in write log (https://github.com/filecoin-project/lotus/pull/5776)
|
||||
- storagefsm: Don't log the SectorRestart event (https://github.com/filecoin-project/lotus/pull/5779)
|
||||
|
||||
# 1.5.2 / 2021-03-11
|
||||
|
||||
This is an hotfix release of Lotus that fixes a critical bug introduced in v1.5.1 in the miner windowPoSt logic. This upgrade is only affecting miner nodes.
|
||||
|
||||
## Changes
|
||||
- fix window post rand check (https://github.com/filecoin-project/lotus/pull/5773)
|
||||
- wdpost: Always use head tipset to get randomness (https://github.com/filecoin-project/lotus/pull/5774)
|
||||
|
||||
# 1.5.1 / 2021-03-10
|
||||
|
||||
This is an optional release of Lotus that introduces an important fix to the WindowPoSt computation process. The change is to wait for some confidence before drawing beacon randomness for the proof. Without this, invalid proofs might be generated as the result of a null tipset.
|
||||
|
||||
## Splitstore
|
||||
|
||||
This release also introduces the splitstore, a new optional blockstore that segregates the monolithic blockstore into cold and hot regions. The hot region contains objects from the last 4-5 finalities plus all reachable objects from two finalities away. All other objects are moved to the cold region using a compaction process that executes every finality, once 5 finalities have elapsed.
|
||||
|
||||
The splitstore allows us to separate the two regions quite effectively, using two separate badger blockstores. The separation
|
||||
means that the live working set is much smaller, which results in potentially significant performance improvements. In addition, it means that the coldstore can be moved to a separate (bigger, slower, cheaper) disk without loss of performance.
|
||||
|
||||
The design also allows us to use different implementations for the two blockstores; for example, an append-only blockstore could be used for coldstore and a faster memory mapped blockstore could be used for the hotstore (eg LMDB). We plan to experiment with these options in the future.
|
||||
|
||||
Once the splitstore has been enabled, the existing monolithic blockstore becomes the coldstore. On the first head change notification, the splitstore will warm up the hotstore by copying all reachable objects from the current tipset into the hotstore. All new writes go into the hotstore, with the splitstore tracking the write epoch. Once 5 finalities have elapsed, and every finality thereafter, the splitstore compacts by moving cold objects into the coldstore. There is also experimental support for garbage collection, whereby nunreachable objects are simply discarded.
|
||||
|
||||
To enable the splitstore, add the following to config.toml:
|
||||
|
||||
```
|
||||
[Chainstore]
|
||||
EnableSplitstore = true
|
||||
```
|
||||
|
||||
## Highlights
|
||||
|
||||
Other highlights include:
|
||||
|
||||
- Improved deal data handling - now multiple deals can be adding to sectors in parallel
|
||||
- Rewriten sector pledging - it now actually cares about max sealing sector limits
|
||||
- Better handling for sectors stuck in the RecoverDealIDs state
|
||||
- lotus-miner sectors extend command
|
||||
- Optional configurable storage path size limit
|
||||
- Config to disable owner/worker fallback from control addresses (useful when owner is a key on a hardware wallet)
|
||||
- A write log for node metadata, which can be restored as a backup when the metadata leveldb becomes corrupted (e.g. when you run out of disk space / system crashes in some bad way)
|
||||
|
||||
## Changes
|
||||
|
||||
- avoid use mp.cfg directly to avoid race (https://github.com/filecoin-project/lotus/pull/5350)
|
||||
- Show replacing message CID is state search-msg cli (https://github.com/filecoin-project/lotus/pull/5656)
|
||||
- Fix riceing by importing the main package (https://github.com/filecoin-project/lotus/pull/5675)
|
||||
- Remove sectors with all deals expired in RecoverDealIDs (https://github.com/filecoin-project/lotus/pull/5658)
|
||||
- storagefsm: Rewrite input handling (https://github.com/filecoin-project/lotus/pull/5375)
|
||||
- reintroduce Refactor send command for better testability (https://github.com/filecoin-project/lotus/pull/5668)
|
||||
- Improve error message with importing a chain (https://github.com/filecoin-project/lotus/pull/5669)
|
||||
- storagefsm: Cleanup CC sector creation (https://github.com/filecoin-project/lotus/pull/5612)
|
||||
- chain list --gas-stats display capacity (https://github.com/filecoin-project/lotus/pull/5676)
|
||||
- Correct some logs (https://github.com/filecoin-project/lotus/pull/5694)
|
||||
- refactor blockstores (https://github.com/filecoin-project/lotus/pull/5484)
|
||||
- Add idle to sync stage's String() (https://github.com/filecoin-project/lotus/pull/5702)
|
||||
- packer provisioner (https://github.com/filecoin-project/lotus/pull/5604)
|
||||
- add DeleteMany to Blockstore interface (https://github.com/filecoin-project/lotus/pull/5703)
|
||||
- segregate chain and state blockstores (https://github.com/filecoin-project/lotus/pull/5695)
|
||||
- fix(multisig): The format of the amount is not correct in msigLockApp (https://github.com/filecoin-project/lotus/pull/5718)
|
||||
- Update butterfly network (https://github.com/filecoin-project/lotus/pull/5627)
|
||||
- Collect worker task metrics (https://github.com/filecoin-project/lotus/pull/5648)
|
||||
- Correctly format disputer log (https://github.com/filecoin-project/lotus/pull/5716)
|
||||
- Log block CID in the large delay warning (https://github.com/filecoin-project/lotus/pull/5704)
|
||||
- Move api client builders to a cliutil package (https://github.com/filecoin-project/lotus/pull/5728)
|
||||
- Implement net peers --extended (https://github.com/filecoin-project/lotus/pull/5734)
|
||||
- Command to extend sector expiration (https://github.com/filecoin-project/lotus/pull/5666)
|
||||
- garbage collect hotstore after compaction (https://github.com/filecoin-project/lotus/pull/5744)
|
||||
- tune badger gc to repeatedly gc the value log until there is no rewrite (https://github.com/filecoin-project/lotus/pull/5745)
|
||||
- Add configuration option for pubsub IPColocationWhitelist subnets (https://github.com/filecoin-project/lotus/pull/5735)
|
||||
- hot/cold blockstore segregation (aka. splitstore) (https://github.com/filecoin-project/lotus/pull/4992)
|
||||
- Customize verifreg root key and remainder account when making genesis (https://github.com/filecoin-project/lotus/pull/5730)
|
||||
- chore: update go-graphsync to 0.6.0 (https://github.com/filecoin-project/lotus/pull/5746)
|
||||
- Add connmgr metadata to NetPeerInfo (https://github.com/filecoin-project/lotus/pull/5749)
|
||||
- test: attempt to make the splitstore test deterministic (https://github.com/filecoin-project/lotus/pull/5750)
|
||||
- Feat/api no dep build (https://github.com/filecoin-project/lotus/pull/5729)
|
||||
- Fix bootstrapper profile setting (https://github.com/filecoin-project/lotus/pull/5756)
|
||||
- Check liveness of sectors when processing termination batches (https://github.com/filecoin-project/lotus/pull/5759)
|
||||
- Configurable storage path storage limit (https://github.com/filecoin-project/lotus/pull/5624)
|
||||
- miner: Config to disable owner/worker address fallback (https://github.com/filecoin-project/lotus/pull/5620)
|
||||
- Fix TestUnpadReader on Go 1.16 (https://github.com/filecoin-project/lotus/pull/5761)
|
||||
- Metadata datastore log (https://github.com/filecoin-project/lotus/pull/5755)
|
||||
- Remove the SR2 stats, leave just the network totals (https://github.com/filecoin-project/lotus/pull/5757)
|
||||
- fix: wait a bit before starting to compute window post proofs (https://github.com/filecoin-project/lotus/pull/5764)
|
||||
- fix: retry proof when randomness changes (https://github.com/filecoin-project/lotus/pull/5768)
|
||||
|
||||
|
||||
# 1.5.0 / 2021-02-23
|
||||
|
||||
This is a mandatory release of Lotus that introduces the fifth upgrade to the Filecoin network. The network upgrade occurs at height 550321, before which time all nodes must have updated to this release (or later). At this height, [v3 specs-actors](https://github.com/filecoin-project/specs-actors/releases/tag/v3.0.0) will take effect, which in turn implements the following two FIPs:
|
||||
|
||||
- [FIP-0007 h/amt-v3](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0007.md) which improves the performance of the Filecoin HAMT and AMT.
|
||||
- [FIP-0010 off-chain Window PoSt Verification](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0010.md) which reduces the gas consumption of `SubmitWindowedPoSt` messages significantly by optimistically accepting Window PoSt proofs without verification, and allowing them to be disputed later by off-chain verifiers.
|
||||
|
||||
Note that the integration of v3 actors was already completed in 1.4.2, this upgrade simply sets the epoch for the upgrade to occur.
|
||||
|
||||
## Disputer
|
||||
|
||||
FIP-0010 introduces the ability to dispute bad Window PoSts. Node operators are encouraged to run the new Lotus disputer alongside their Lotus daemons. For more information, see the announcement [here](https://github.com/filecoin-project/lotus/discussions/5617#discussioncomment-387333).
|
||||
|
||||
## Changes
|
||||
|
||||
- [#5341](https://github.com/filecoin-project/lotus/pull/5341) Add a `LOTUS_DISABLE_V3_ACTOR_MIGRATION` envvar
|
||||
- Setting this envvar to 1 disables the v3 actor migration, should only be used in the event of a failed migration
|
||||
|
||||
# 1.4.2 / 2021-02-17
|
||||
|
||||
This is a large, and highly recommended, optional release with new features and improvements for lotus miner and deal-making UX. The release also integrates [v3 specs-actors](https://github.com/filecoin-project/specs-actors/releases/tag/v3.0.0), which implements two FIPs:
|
||||
|
||||
- [FIP-0007 h/amt-v3](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0007.md) which improves the performance of the Filecoin HAMT and AMT.
|
||||
- [FIP-0010 off-chain Window PoSt Verification](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0010.md) which reduces the gas consumption of `SubmitWindowedPoSt` messages significantly by optimistically accepting Window PoSt proofs without verification, and allowing them to be disputed later by off-chain verifiers.
|
||||
|
||||
Note that this release does NOT set an upgrade epoch for v3 actors to take effect. That will be done in the upcoming 1.5.0 release.
|
||||
|
||||
## New Features
|
||||
|
||||
- [#5341](https://github.com/filecoin-project/lotus/pull/5341) Added sector termination API and CLI
|
||||
- Run `lotus-miner sectors terminate`
|
||||
- [#5342](https://github.com/filecoin-project/lotus/pull/5342) Added CLI for using a multisig wallet as miner's owner address
|
||||
- See how to set it up [here](https://github.com/filecoin-project/lotus/pull/5342#issue-554009129)
|
||||
- [#5363](https://github.com/filecoin-project/lotus/pull/5363), [#5418](https://github.com/filecoin-project/lotus/pull/), [#5476](https://github.com/filecoin-project/lotus/pull/5476), [#5459](https://github.com/filecoin-project/lotus/pull/5459) Integrated [spec-actor v3](https://github.com/filecoin-pro5418ject/specs-actors/releases/tag/v3.0.0)
|
||||
- [#5472](https://github.com/filecoin-project/lotus/pull/5472) Generate actor v3 methods for pond
|
||||
- [#5379](https://github.com/filecoin-project/lotus/pull/5379) Added WindowPoSt disputer
|
||||
- This is to support [FIP-0010 off-chian Window PoSt verification](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0010.md)
|
||||
- See how to run a disputer [here](https://github.com/filecoin-project/lotus/pull/5379#issuecomment-776482445)
|
||||
- [#5309](https://github.com/filecoin-project/lotus/pull/5309) Batch multiple deals in one `PublishStorageMessages`
|
||||
- [#5411](https://github.com/filecoin-project/lotus/pull/5411) Handle batch `PublishStorageDeals` message in sealing recovery
|
||||
- [#5505](https://github.com/filecoin-project/lotus/pull/5505) Exclude expired deals from batching in `PublishStorageDeals` messages
|
||||
- Added `PublishMsgPeriod` and `MaxDealsPerPublishMsg` to miner `Dealmaking` [configuration](https://docs.filecoin.io/mine/lotus/miner-configuration/#dealmaking-section). See how they work [here](https://docs.filecoin.io/mine/lotus/miner-configuration/#publishing-several-deals-in-one-message).
|
||||
- [#5538](https://github.com/filecoin-project/lotus/pull/5538), [#5549](https://github.com/filecoin-project/lotus/pull/5549) Added a command to list pending deals and force publish messages.
|
||||
- Run `lotus-miner market pending-publish`
|
||||
- [#5428](https://github.com/filecoin-project/lotus/pull/5428) Moved waiting for `PublishStorageDeals` messages' receipt from markets to lotus
|
||||
- [#5510](https://github.com/filecoin-project/lotus/pull/5510) Added `nerpanet` build option
|
||||
- To build `nerpanet`, run `make nerpanet`
|
||||
- [#5433](https://github.com/filecoin-project/lotus/pull/5433) Added `AlwaysKeepUnsealedCopy` option to the miner configuration
|
||||
- [#5520](https://github.com/filecoin-project/lotus/pull/5520) Added `MsigGetPending` to get pending transactions for multisig wallets
|
||||
- [#5219](https://github.com/filecoin-project/lotus/pull/5219) Added interactive mode for lotus-wallet
|
||||
- [5529](https://github.com/filecoin-project/lotus/pull/5529) Added support for minder nodes in `lotus-shed rpc` util
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- [#5210](https://github.com/filecoin-project/lotus/pull/5210) Miner should not dial client on restart
|
||||
- [#5403](https://github.com/filecoin-project/lotus/pull/5403) When estimating GasLimit only apply prior messages up to the nonce
|
||||
- [#5410](https://github.com/filecoin-project/lotus/pull/510) Fix the calibnet build option
|
||||
- [#5492](https://github.com/filecoin-project/lotus/pull/5492) Fixed `has` for ipfsbstore for non-existing blocks
|
||||
- [#5361](https://github.com/filecoin-project/lotus/pull/5361) Fixed retrieval hangs when using `IpfsOnlineMode=true`
|
||||
- [#5493](https://github.com/filecoin-project/lotus/pull/5493) Fixed retrieval failure when price-per-byte is zero
|
||||
- [#5506](https://github.com/filecoin-project/lotus/pull/5506) Fixed contexts in the storage adpater
|
||||
- [#5515](https://github.com/filecoin-project/lotus/pull/5515) Properly wire up `StateReadState` on gateway API
|
||||
- [#5582](https://github.com/filecoin-project/lotus/pull/5582) Fixed error logging format strings
|
||||
- [#5614](https://github.com/filecoin-project/lotus/pull/5614) Fixed websocket reconnecting handling
|
||||
|
||||
|
||||
## Improvements
|
||||
|
||||
- [#5389](https://github.com/filecoin-project/lotus/pull/5389) Show verified indicator for `./lotus-miner storage-deals list`
|
||||
- [#5229](https://github.com/filecoin-project/lotus/pull/5220) Show power for verified deals in `./lotus-miner setocr list`
|
||||
- [#5407](https://github.com/filecoin-project/lotus/pull/5407) Added explicit check of the miner address protocol
|
||||
- [#5399](https://github.com/filecoin-project/lotus/pull/5399) watchdog: increase heapprof capture threshold to 90%
|
||||
- [#5398](https://github.com/filecoin-project/lotus/pull/5398) storageadapter: Look at precommits on-chain since deal publish msg
|
||||
- [#5470](https://github.com/filecoin-project/lotus/pull/5470) Added `--no-timing` option for `./lotus state compute-state --html`
|
||||
- [#5417](https://github.com/filecoin-project/lotus/pull/5417) Storage Manager: Always unseal full sectors
|
||||
- [#5393](https://github.com/filecoin-project/lotus/pull/5393) Switched to [filecoin-ffi bls api ](https://github.com/filecoin-project/filecoin-ffi/pull/159)for bls signatures
|
||||
- [#5380](https://github.com/filecoin-project/lotus/pull/5210) Refactor deals API tests
|
||||
- [#5397](https://github.com/filecoin-project/lotus/pull/5397) Fixed a flake in the sync manager edge case test
|
||||
- [#5406](https://github.com/filecoin-project/lotus/pull/5406) Added a test to ensure a correct window post cannot be disputed
|
||||
- [#5294](https://github.com/filecoin-project/lotus/pull/5394) Added jobs to build Lotus docker image and push it to AWS ECR
|
||||
- [#5387](https://github.com/filecoin-project/lotus/pull/5387) Added network info(mainnet|calibnet) in version
|
||||
- [#5497](https://github.com/filecoin-project/lotus/pull/5497) Export metric for lotus-gateaway
|
||||
- [#4950](https://github.com/filecoin-project/lotus/pull/4950) Removed bench policy
|
||||
- [#5047](https://github.com/filecoin-project/lotus/pull/5047) Improved the UX for `./lotus-shed bitfield enc`
|
||||
- [#5282](https://github.com/filecoin-project/lotus/pull/5282) Snake a context through the chian blockstore creation
|
||||
- [#5350](https://github.com/filecoin-project/lotus/pull/5350) Avoid using `mp.cfg` directrly to prevent race condition
|
||||
- [#5449](https://github.com/filecoin-project/lotus/pull/5449) Documented the block-header better
|
||||
- [#5404](https://github.com/filecoin-project/lotus/pull/5404) Added retrying proofs if an incorrect one is generated
|
||||
- [#4545](https://github.com/filecoin-project/lotus/pull/4545) Made state tipset usage consistent in the API
|
||||
- [#5540](https://github.com/filecoin-project/lotus/pull/5540) Removed unnecessary database reads in validation check
|
||||
- [#5554](https://github.com/filecoin-project/lotus/pull/5554) Fixed `build lotus-soup` CI job
|
||||
- [#5552](https://github.com/filecoin-project/lotus/pull/5552) Updated CircleCI to halt gracefully
|
||||
- [#5555](https://github.com/filecoin-project/lotus/pull/5555) Cleanup and add docstrings of node builder
|
||||
- [#5564](https://github.com/filecoin-project/lotus/pull/5564) Stopped depending on gocheck with gomod
|
||||
- [#5574](https://github.com/filecoin-project/lotus/pull/5574) Updated CLI UI
|
||||
- [#5570](https://github.com/filecoin-project/lotus/pull/5570) Added code CID to `StateReadState` return object
|
||||
- [#5565](https://github.com/filecoin-project/lotus/pull/5565) Added storageadapter.PublishMsgConfig to miner in testkit for lotus-soup testplan
|
||||
- [#5571](https://github.com/filecoin-project/lotus/pull/5571) Added `lotus-seed gensis car` to generate lotus block for devnets
|
||||
- [#5613](https://github.com/filecoin-project/lotus/pull/5613) Check format in client commP util
|
||||
- [#5507](https://github.com/filecoin-project/lotus/pull/5507) Refactored coalescing logic into its own function and take both cancellation sets into account
|
||||
- [#5592](https://github.com/filecoin-project/lotus/pull/5592) Verify FFI version before building
|
||||
|
||||
## Dependency Updates
|
||||
- [#5296](https://github.com/filecoin-project/lotus/pull/5396) Upgraded to [raulk/go-watchdog@v1.0.1](https://github.com/raulk/go-watchdog/releases/tag/v1.0.1)
|
||||
- [#5450](https://github.com/filecoin-project/lotus/pull/5450) Dependency updates
|
||||
- [#5425](https://github.com/filecoin-project/lotus/pull/5425) Fixed stale imports in testplans/lotus-soup
|
||||
- [#5535](https://github.com/filecoin-project/lotus/pull/5535) Updated to [go-fil-markets@v1.1.7](https://github.com/filecoin-project/go-fil-markets/releases/tag/v1.1.7)
|
||||
- [#5616](https://github.com/filecoin-project/lotus/pull/5600) Updated to [filecoin-ffi@b6e0b35fb49ed0fe](https://github.com/filecoin-project/filecoin-ffi/releases/tag/b6e0b35fb49ed0fe)
|
||||
- [#5599](https://github.com/filecoin-project/lotus/pull/5599) Updated to [go-bitfield@v0.2.4](https://github.com/filecoin-project/go-bitfield/releases/tag/v0.2.4)
|
||||
- [#5614](https://github.com/filecoin-project/lotus/pull/5614), , [#5621](https://github.com/filecoin-project/lotus/pull/5621) Updated to [go-jsonrpc@v0.1.3](https://github.com/filecoin-project/go-jsonrpc/releases/tag/v0.1.3)
|
||||
- [#5459](https://github.com/filecoin-project/lotus/pull/5459) Updated to [spec-actors@v3.0.1](https://github.com/filecoin-project/specs-actors/releases/tag/v3.0.1)
|
||||
|
||||
|
||||
## Network Version v10 Upgrade
|
||||
- [#5473](https://github.com/filecoin-project/lotus/pull/5473) Merged staging branch for v1.5.0
|
||||
- [#5603](https://github.com/filecoin-project/lotus/pull/5603) Set nerpanet's upgrade epochs up to v3 actors
|
||||
- [#5471](https://github.com/filecoin-project/lotus/pull/5471), [#5456](https://github.com/filecoin-project/lotus/pull/5456) Set calibration net actor v3 migration epochs for testing
|
||||
- [#5434](https://github.com/filecoin-project/lotus/pull/5434) Implemented pre-migration framework
|
||||
- [#5476](https://github.com/filecoin-project/lotus/pull/5477) Tune migration
|
||||
|
||||
# 1.4.1 / 2021-01-20
|
||||
|
||||
This is an optional Lotus release that introduces various improvements to the sealing, mining, and deal-making processes. In particular, [#5341](https://github.com/filecoin-project/lotus/pull/5341) introduces the ability for Lotus miners to terminate sectors.
|
||||
|
||||
## Changes
|
||||
|
||||
#### Core Lotus
|
||||
|
||||
- fix(sync): enforce ForkLengthThreshold for synced chain (https://github.com/filecoin-project/lotus/pull/5182)
|
||||
- introduce memory watchdog; LOTUS_MAX_HEAP (https://github.com/filecoin-project/lotus/pull/5101)
|
||||
- Skip bootstrapping if no peers specified (https://github.com/filecoin-project/lotus/pull/5301)
|
||||
- Chainxchg write response timeout (https://github.com/filecoin-project/lotus/pull/5254)
|
||||
- update NewestNetworkVersion (https://github.com/filecoin-project/lotus/pull/5277)
|
||||
- fix(sync): remove checks bypass when we submit the block (https://github.com/filecoin-project/lotus/pull/4192)
|
||||
- chore: export vm.ShouldBurn (https://github.com/filecoin-project/lotus/pull/5355)
|
||||
- fix(sync): enforce fork len when changing head (https://github.com/filecoin-project/lotus/pull/5244)
|
||||
- Use 55th percentile instead of median for gas-price (https://github.com/filecoin-project/lotus/pull/5369)
|
||||
- update go-libp2p-pubsub to v0.4.1 (https://github.com/filecoin-project/lotus/pull/5329)
|
||||
|
||||
#### Sealing
|
||||
|
||||
- Sector termination support (https://github.com/filecoin-project/lotus/pull/5341)
|
||||
- update weight canSeal and canStore when attach (https://github.com/filecoin-project/lotus/pull/5242/files)
|
||||
- sector-storage/mock: improve mocked readpiece (https://github.com/filecoin-project/lotus/pull/5208)
|
||||
- Fix deadlock in runWorker in sched_worker.go (https://github.com/filecoin-project/lotus/pull/5251)
|
||||
- Skip checking terminated sectors provable (https://github.com/filecoin-project/lotus/pull/5217)
|
||||
- storagefsm: Fix unsealedInfoMap.lk init race (https://github.com/filecoin-project/lotus/pull/5319)
|
||||
- Multicore AddPiece CommP (https://github.com/filecoin-project/lotus/pull/5320)
|
||||
- storagefsm: Send correct event on ErrExpiredTicket in CommitFailed (https://github.com/filecoin-project/lotus/pull/5366)
|
||||
- expose StateSearchMessage on gateway (https://github.com/filecoin-project/lotus/pull/5382)
|
||||
- fix FileSize to return correct disk usage recursively (https://github.com/filecoin-project/lotus/pull/5384)
|
||||
|
||||
#### Dealmaking
|
||||
|
||||
- Better error message when withdrawing funds (https://github.com/filecoin-project/lotus/pull/5293)
|
||||
- add verbose for list transfers (https://github.com/filecoin-project/lotus/pull/5259)
|
||||
- cli - rename `client info` to `client balances` (https://github.com/filecoin-project/lotus/pull/5304)
|
||||
- Better CLI for wallet market withdraw and client info (https://github.com/filecoin-project/lotus/pull/5303)
|
||||
|
||||
#### UX
|
||||
|
||||
- correct flag usages for replace cmd (https://github.com/filecoin-project/lotus/pull/5255)
|
||||
- lotus state call will panic (https://github.com/filecoin-project/lotus/pull/5275)
|
||||
- fix get sector bug (https://github.com/filecoin-project/lotus/pull/4976)
|
||||
- feat: lotus wallet market add (adds funds to storage market actor) (https://github.com/filecoin-project/lotus/pull/5300)
|
||||
- Fix client flag parsing in client balances cli (https://github.com/filecoin-project/lotus/pull/5312)
|
||||
- delete slash-consensus miner (https://github.com/filecoin-project/lotus/pull/4577)
|
||||
- add fund sufficient check in send (https://github.com/filecoin-project/lotus/pull/5252)
|
||||
- enable parse and shorten negative FIL values (https://github.com/filecoin-project/lotus/pull/5315)
|
||||
- add limit and rate for chain noise (https://github.com/filecoin-project/lotus/pull/5223)
|
||||
- add bench env print (https://github.com/filecoin-project/lotus/pull/5222)
|
||||
- Implement full-node restore option (https://github.com/filecoin-project/lotus/pull/5362)
|
||||
- add color for token amount (https://github.com/filecoin-project/lotus/pull/5352)
|
||||
- correct log in maybeUseAddress (https://github.com/filecoin-project/lotus/pull/5359)
|
||||
- add slash-consensus from flag (https://github.com/filecoin-project/lotus/pull/5378)
|
||||
|
||||
#### Testing
|
||||
|
||||
- tvx extract: more tipset extraction goodness (https://github.com/filecoin-project/lotus/pull/5258)
|
||||
- Fix race in blockstore test suite (https://github.com/filecoin-project/lotus/pull/5297)
|
||||
|
||||
|
||||
#### Build & Networks
|
||||
|
||||
- Remove LOTUS_DISABLE_V2_ACTOR_MIGRATION envvar (https://github.com/filecoin-project/lotus/pull/5289)
|
||||
- Create a calibnet build option (https://github.com/filecoin-project/lotus/pull/5288)
|
||||
- Calibnet: Set Orange epoch (https://github.com/filecoin-project/lotus/pull/5325)
|
||||
|
||||
#### Management
|
||||
|
||||
- Update SECURITY.md (https://github.com/filecoin-project/lotus/pull/5246)
|
||||
- README: Contribute section (https://github.com/filecoin-project/lotus/pull/5330)
|
||||
- README: refine Contribute section (https://github.com/filecoin-project/lotus/pull/5331)
|
||||
- Add misc tooling to codecov ignore list (https://github.com/filecoin-project/lotus/pull/5347)
|
||||
|
||||
# 1.4.0 / 2020-12-19
|
||||
|
||||
This is a MANDATORY hotfix release of Lotus that resolves a chain halt at height 336,459 caused by nondeterminism in specs-actors. The fix is to update actors to 2.3.3 in order to incorporate this fix https://github.com/filecoin-project/specs-actors/pull/1334.
|
||||
|
||||
# 1.3.0 / 2020-12-16
|
||||
|
||||
This is a mandatory release of Lotus that introduces the third post-liftoff upgrade to the Filecoin network. The network upgrade occurs at height 343200, before which time all nodes must have updated to this release (or later). The change that breaks consensus is an implementation of FIP-0009(https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0009.md).
|
||||
|
||||
## Changes
|
||||
|
||||
- Disable gas burning for window post messages (https://github.com/filecoin-project/lotus/pull/5200)
|
||||
- fix lock propose (https://github.com/filecoin-project/lotus/pull/5197)
|
||||
|
||||
# 1.2.3 / 2020-12-15
|
||||
|
||||
This is an optional Lotus release that introduces many performance improvements, bugfixes, and UX improvements.
|
||||
|
||||
## Changes
|
||||
|
||||
- When waiting for deal commit messages, ignore unsuccessful messages (https://github.com/filecoin-project/lotus/pull/5189)
|
||||
- Bigger copy buffer size for stores (https://github.com/filecoin-project/lotus/pull/5177)
|
||||
- Print MinPieceSize when querying ask (https://github.com/filecoin-project/lotus/pull/5178)
|
||||
- Optimize miner info & sectors list loading (https://github.com/filecoin-project/lotus/pull/5176)
|
||||
- Allow miners to filter (un)verified deals (https://github.com/filecoin-project/lotus/pull/5094)
|
||||
- Fix curSealing out of MaxSealingSectors limit (https://github.com/filecoin-project/lotus/pull/5166)
|
||||
- Add mpool pending from / to filter (https://github.com/filecoin-project/lotus/pull/5169)
|
||||
- Add metrics for delayed blocks (https://github.com/filecoin-project/lotus/pull/5171)
|
||||
- Fix PushUntrusted publishing -- the message is local (https://github.com/filecoin-project/lotus/pull/5173)
|
||||
- Avoid potential hang in events API when starting event listener (https://github.com/filecoin-project/lotus/pull/5159)
|
||||
- Show data transfer ID in list-deals (https://github.com/filecoin-project/lotus/pull/5150)
|
||||
- Fix events API mutex locking (https://github.com/filecoin-project/lotus/pull/5160)
|
||||
- Message pool refactors (https://github.com/filecoin-project/lotus/pull/5162)
|
||||
- Fix lotus-shed cid output (https://github.com/filecoin-project/lotus/pull/5072)
|
||||
- Use FundManager to withdraw funds, add MarketWithdraw API (https://github.com/filecoin-project/lotus/pull/5112)
|
||||
- Add keygen outfile (https://github.com/filecoin-project/lotus/pull/5118)
|
||||
- Update sr2 stat aggregation (https://github.com/filecoin-project/lotus/pull/5114)
|
||||
- Fix miner control address lookup (https://github.com/filecoin-project/lotus/pull/5119)
|
||||
- Fix send with declared nonce 0 (https://github.com/filecoin-project/lotus/pull/5111)
|
||||
- Introduce memory watchdog; LOTUS_MAX_HEAP (https://github.com/filecoin-project/lotus/pull/5101)
|
||||
- Miner control address config for (pre)commits (https://github.com/filecoin-project/lotus/pull/5103)
|
||||
- Delete repeated call func (https://github.com/filecoin-project/lotus/pull/5099)
|
||||
- lotus-shed ledger show command (https://github.com/filecoin-project/lotus/pull/5098)
|
||||
- Log a message when there aren't enough peers for sync (https://github.com/filecoin-project/lotus/pull/5105)
|
||||
- Miner code cleanup (https://github.com/filecoin-project/lotus/pull/5107)
|
||||
|
||||
# 1.2.2 / 2020-12-03
|
||||
|
||||
This is an optional Lotus release that introduces various improvements to the mining logic and deal-making workflow, as well as several new UX features.
|
||||
|
||||
## Changes
|
||||
|
||||
- Set lower feecap on PoSt messages with low balance (https://github.com/filecoin-project/lotus/pull/4217)
|
||||
- Add options to set BlockProfileRate and MutexProfileFraction (https://github.com/filecoin-project/lotus/pull/4140)
|
||||
- Shed/post find (https://github.com/filecoin-project/lotus/pull/4355)
|
||||
- tvx extract: make it work with secp messages.(https://github.com/filecoin-project/lotus/pull/4583)
|
||||
- update go from 1.14 to 1.15 (https://github.com/filecoin-project/lotus/pull/4909)
|
||||
- print multiple blocks from miner cid (https://github.com/filecoin-project/lotus/pull/4767)
|
||||
- Connection Gater support (https://github.com/filecoin-project/lotus/pull/4849)
|
||||
- just return storedask.NewStoredAsk to reduce unuseful code (https://github.com/filecoin-project/lotus/pull/4902)
|
||||
- add go main version (https://github.com/filecoin-project/lotus/pull/4910)
|
||||
- Use version0 when pre-sealing (https://github.com/filecoin-project/lotus/pull/4911)
|
||||
- optimize code UpgradeTapeHeight and go fmt (https://github.com/filecoin-project/lotus/pull/4913)
|
||||
- CLI to get network version (https://github.com/filecoin-project/lotus/pull/4914)
|
||||
- Improve error for ActorsVersionPredicate (https://github.com/filecoin-project/lotus/pull/4915)
|
||||
- upgrade to go-fil-markets 1.0.5 (https://github.com/filecoin-project/lotus/pull/4916)
|
||||
- bug:replace with func recordFailure (https://github.com/filecoin-project/lotus/pull/4919)
|
||||
- Remove unused key (https://github.com/filecoin-project/lotus/pull/4924)
|
||||
- change typeV7 make len (https://github.com/filecoin-project/lotus/pull/4943)
|
||||
- emit events for peer disconnections and act upon them in the blocksync tracker (https://github.com/filecoin-project/lotus/pull/4754)
|
||||
- Fix lotus bench error (https://github.com/filecoin-project/lotus/pull/4305)
|
||||
- Reduce badger ValueTreshold to 128 (https://github.com/filecoin-project/lotus/pull/4629)
|
||||
- Downgrade duplicate nonce logs to debug (https://github.com/filecoin-project/lotus/pull/4933)
|
||||
- readme update golang version from 1.14.7 to 1.15.5 (https://github.com/filecoin-project/lotus/pull/4974)
|
||||
- add data transfer logging (https://github.com/filecoin-project/lotus/pull/4975)
|
||||
- Remove all temp file generation for deals (https://github.com/filecoin-project/lotus/pull/4929)
|
||||
- fix get sector bug (https://github.com/filecoin-project/lotus/pull/4976)
|
||||
- fix nil pointer in StateSectorPreCommitInfo (https://github.com/filecoin-project/lotus/pull/4082)
|
||||
- Add logging on data-transfer to miner (https://github.com/filecoin-project/lotus/pull/4980)
|
||||
- bugfix: fixup devnet script (https://github.com/filecoin-project/lotus/pull/4956)
|
||||
- modify for unsafe (https://github.com/filecoin-project/lotus/pull/4024)
|
||||
- move testground/lotus-soup testplan from oni to lotus (https://github.com/filecoin-project/lotus/pull/4727)
|
||||
- Setup remainder msig signers when parsing genesis template (https://github.com/filecoin-project/lotus/pull/4904)
|
||||
- Update JSON RPC server to enforce a maximum request size (https://github.com/filecoin-project/lotus/pull/4923)
|
||||
- New SR-specific lotus-shed cmd (https://github.com/filecoin-project/lotus/pull/4971)
|
||||
- update index to sectorNumber (https://github.com/filecoin-project/lotus/pull/4987)
|
||||
- storagefsm: Fix expired ticket retry loop (https://github.com/filecoin-project/lotus/pull/4876)
|
||||
- add .sec scale to measurements; humanize for metric tags (https://github.com/filecoin-project/lotus/pull/4989)
|
||||
- Support seal proof type switching (https://github.com/filecoin-project/lotus/pull/4873)
|
||||
- fix log format (https://github.com/filecoin-project/lotus/pull/4984)
|
||||
- Format workerID as string (https://github.com/filecoin-project/lotus/pull/4973)
|
||||
- miner: Winning PoSt Warmup (https://github.com/filecoin-project/lotus/pull/4824)
|
||||
- Default StartDealParams's fast retrieval field to true over JSON (https://github.com/filecoin-project/lotus/pull/4998)
|
||||
- Fix actor not found in chain inspect-usage (https://github.com/filecoin-project/lotus/pull/5010)
|
||||
- storagefsm: Improve new deal sector logic (https://github.com/filecoin-project/lotus/pull/5007)
|
||||
- Configure simultaneous requests (https://github.com/filecoin-project/lotus/pull/4996)
|
||||
- miner: log winningPoSt duration separately (https://github.com/filecoin-project/lotus/pull/5005)
|
||||
- fix wallet dead lock (https://github.com/filecoin-project/lotus/pull/5002)
|
||||
- Update go-jsonrpc to v0.1.2 (https://github.com/filecoin-project/lotus/pull/5015)
|
||||
- markets - separate watching for pre-commit from prove-commit (https://github.com/filecoin-project/lotus/pull/4945)
|
||||
- storagefsm: Add missing planners (https://github.com/filecoin-project/lotus/pull/5016)
|
||||
- fix wallet delete address where address is default (https://github.com/filecoin-project/lotus/pull/5019)
|
||||
- worker: More robust remote checks (https://github.com/filecoin-project/lotus/pull/5008)
|
||||
- Add new booststrappers (https://github.com/filecoin-project/lotus/pull/4007)
|
||||
- add a tooling to make filecoin accounting a little easier (https://github.com/filecoin-project/lotus/pull/5025)
|
||||
- fix: start a new line in print miner-info to avoid ambiguous display (https://github.com/filecoin-project/lotus/pull/5029)
|
||||
- Print gas limit sum in mpool stat (https://github.com/filecoin-project/lotus/pull/5035)
|
||||
- Fix chainstore tipset leak (https://github.com/filecoin-project/lotus/pull/5037)
|
||||
- shed rpc: Allow calling with args (https://github.com/filecoin-project/lotus/pull/5036)
|
||||
- Make --gas-limit optional in mpool replace cli (https://github.com/filecoin-project/lotus/pull/5059)
|
||||
- client list-asks --by-ping (https://github.com/filecoin-project/lotus/pull/5060)
|
||||
- Ledger signature verification (https://github.com/filecoin-project/lotus/pull/5068)
|
||||
- Fix helptext for verified-deal default in client deal (https://github.com/filecoin-project/lotus/pull/5074)
|
||||
- worker: Support setting task types at runtime (https://github.com/filecoin-project/lotus/pull/5023)
|
||||
- Enable Callers tracing when GasTracing is enabled (https://github.com/filecoin-project/lotus/pull/5080)
|
||||
- Cancel transfer cancels storage deal (https://github.com/filecoin-project/lotus/pull/5032)
|
||||
- Sector check command (https://github.com/filecoin-project/lotus/pull/5041)
|
||||
- add commp-to-cid base64 decode (https://github.com/filecoin-project/lotus/pull/5079)
|
||||
- miner info cli improvements (https://github.com/filecoin-project/lotus/pull/5083)
|
||||
- miner: Add slow mode to proving check (https://github.com/filecoin-project/lotus/pull/5086)
|
||||
- Error out deals that are not activated by proposed deal start epoch (https://github.com/filecoin-project/lotus/pull/5061)
|
||||
|
||||
# 1.2.1 / 2020-11-20
|
||||
|
||||
This is a very small release of Lotus that fixes an issue users are experiencing when importing snapshots. There is no need to upgrade unless you experience an issue with creating a new datastore directory in the Lotus repo.
|
||||
|
||||
## Changes
|
||||
|
||||
- fix blockstore directory not created automatically (https://github.com/filecoin-project/lotus/pull/4922)
|
||||
- WindowPoStScheduler.checkSectors() delete useless judgment (https://github.com/filecoin-project/lotus/pull/4918)
|
||||
|
||||
|
||||
# 1.2.0 / 2020-11-18
|
||||
|
||||
This is a mandatory release of Lotus that introduces the second post-liftoff upgrade to the Filecoin network. The network upgrade occurs at height 265200, before which time all nodes must have updated to this release (or later). This release also bumps the required version of Go to 1.15.
|
||||
|
||||
The changes that break consensus are:
|
||||
|
||||
- Upgrading to sepcs-actors 2.3.2 (https://github.com/filecoin-project/specs-actors/releases/tag/v2.3.2)
|
||||
- Introducing proofs v5.4.0 (https://github.com/filecoin-project/rust-fil-proofs/releases/tag/storage-proofs-v5.4.0), and switching between the proof types (https://github.com/filecoin-project/lotus/pull/4873)
|
||||
- Don't use terminated sectors for winning PoSt (https://github.com/filecoin-project/lotus/pull/4770)
|
||||
- Various small VM-level edge-case handling (https://github.com/filecoin-project/lotus/pull/4783)
|
||||
- Correction of the VM circulating supply calculation (https://github.com/filecoin-project/lotus/pull/4862)
|
||||
- Retuning gas costs (https://github.com/filecoin-project/lotus/pull/4830)
|
||||
- Avoid sending messages to the zero BLS address (https://github.com/filecoin-project/lotus/pull/4888)
|
||||
|
||||
## Other Changes
|
||||
|
||||
- delayed pubsub subscribe for messages topic (https://github.com/filecoin-project/lotus/pull/3646)
|
||||
- add chain base64 decode params (https://github.com/filecoin-project/lotus/pull/4748)
|
||||
- chore(dep): update bitswap to fix an initialization race that could panic (https://github.com/filecoin-project/lotus/pull/4855)
|
||||
- Chore/blockstore nits (https://github.com/filecoin-project/lotus/pull/4813)
|
||||
- Print Consensus Faults in miner info (https://github.com/filecoin-project/lotus/pull/4853)
|
||||
- Truncate genesis file before generating (https://github.com/filecoin-project/lotus/pull/4851)
|
||||
- miner: Winning PoSt Warmup (https://github.com/filecoin-project/lotus/pull/4824)
|
||||
- Fix init actor address map diffing (https://github.com/filecoin-project/lotus/pull/4875)
|
||||
- Bump API versions to 1.0.0 (https://github.com/filecoin-project/lotus/pull/4884)
|
||||
- Fix cid recording issue (https://github.com/filecoin-project/lotus/pull/4874)
|
||||
- Speed up worker key retrieval (https://github.com/filecoin-project/lotus/pull/4885)
|
||||
- Add error codes to worker return (https://github.com/filecoin-project/lotus/pull/4890)
|
||||
- Update go to 1.15.5 (https://github.com/filecoin-project/lotus/pull/4896)
|
||||
- Fix MaxSealingSectrosForDeals getting reset to 0 (https://github.com/filecoin-project/lotus/pull/4879)
|
||||
- add sanity check for maximum block size (https://github.com/filecoin-project/lotus/pull/3171)
|
||||
- Check (pre)commit receipt before other checks in failed states (https://github.com/filecoin-project/lotus/pull/4712)
|
||||
- fix badger double open on daemon --import-snapshot; chainstore lifecycle (https://github.com/filecoin-project/lotus/pull/4872)
|
||||
- Update to ipfs-blockstore 1.0.3 (https://github.com/filecoin-project/lotus/pull/4897)
|
||||
- break loop when found warm up sector (https://github.com/filecoin-project/lotus/pull/4869)
|
||||
- Tweak handling of bad beneficaries in DeleteActor (https://github.com/filecoin-project/lotus/pull/4903)
|
||||
- cap maximum number of messages per block in selection (https://github.com/filecoin-project/lotus/pull/4905)
|
||||
- Set Calico epoch (https://github.com/filecoin-project/lotus/pull/4889)
|
||||
|
||||
# 1.1.3 / 2020-11-13
|
||||
|
||||
This is an optional release of Lotus that upgrades Lotus dependencies, and includes many performance enhancements, bugfixes, and UX improvements.
|
||||
|
||||
## Highlights
|
||||
|
||||
- Refactored much of the miner code (https://github.com/filecoin-project/lotus/pull/3618), improving its recovery from restarts and overall sector success rate
|
||||
- Updated [proofs](https://github.com/filecoin-project/rust-fil-proofs) to v5.3.0, which brings significant performance improvements
|
||||
- Updated [markets](https://github.com/filecoin-project/go-fil-markets/releases/tag/v1.0.4) to v1.0.4, which reduces failures due to reorgs (https://github.com/filecoin-project/lotus/pull/4730) and uses the newly refactored fund manager (https://github.com/filecoin-project/lotus/pull/4736)
|
||||
|
||||
## Changes
|
||||
|
||||
#### Core Lotus
|
||||
|
||||
- polish: add Equals method to MinerInfo shim (https://github.com/filecoin-project/lotus/pull/4604)
|
||||
- Fix messagepool accounting (https://github.com/filecoin-project/lotus/pull/4668)
|
||||
- Prep for gas balancing (https://github.com/filecoin-project/lotus/pull/4651)
|
||||
- Reduce badger ValueThreshold to 128 (https://github.com/filecoin-project/lotus/pull/4629)
|
||||
- Config for default max gas fee (https://github.com/filecoin-project/lotus/pull/4652)
|
||||
- bootstrap: don't return early when one drand resolution fails (https://github.com/filecoin-project/lotus/pull/4626)
|
||||
- polish: add ClaimsChanged and DiffClaims method to power shim (https://github.com/filecoin-project/lotus/pull/4628)
|
||||
- Simplify chain event Called API (https://github.com/filecoin-project/lotus/pull/4664)
|
||||
- Cache deal states for most recent old/new tipset (https://github.com/filecoin-project/lotus/pull/4623)
|
||||
- Add miner available balance and power info to state miner info (https://github.com/filecoin-project/lotus/pull/4618)
|
||||
- Call GetHeaviestTipSet() only once when syncing (https://github.com/filecoin-project/lotus/pull/4696)
|
||||
- modify runtime gasUsed printf (https://github.com/filecoin-project/lotus/pull/4704)
|
||||
- Rename builtin actor generators (https://github.com/filecoin-project/lotus/pull/4697)
|
||||
- Move gas multiplier as property of pricelist (https://github.com/filecoin-project/lotus/pull/4728)
|
||||
- polish: add msig pendingtxn diffing and comp (https://github.com/filecoin-project/lotus/pull/4719)
|
||||
- Optional chain Bitswap (https://github.com/filecoin-project/lotus/pull/4717)
|
||||
- rewrite sync manager (https://github.com/filecoin-project/lotus/pull/4599)
|
||||
- async connect to bootstrappers (https://github.com/filecoin-project/lotus/pull/4785)
|
||||
- head change coalescer (https://github.com/filecoin-project/lotus/pull/4688)
|
||||
- move to native badger blockstore; leverage zero-copy View() to deserialize in-place (https://github.com/filecoin-project/lotus/pull/4681)
|
||||
- badger blockstore: minor improvements (https://github.com/filecoin-project/lotus/pull/4811)
|
||||
- Do not fail wallet delete because of pre-existing trashed key (https://github.com/filecoin-project/lotus/pull/4589)
|
||||
- Correctly delete the default wallet address (https://github.com/filecoin-project/lotus/pull/4705)
|
||||
- Reduce badger ValueTreshold to 128 (https://github.com/filecoin-project/lotus/pull/4629)
|
||||
- predicates: Fast StateGetActor wrapper (https://github.com/filecoin-project/lotus/pull/4835)
|
||||
|
||||
#### Mining
|
||||
|
||||
- worker key should change when set sender found key not equal with the value on chain (https://github.com/filecoin-project/lotus/pull/4595)
|
||||
- extern/sector-storage: fix GPU usage overwrite bug (https://github.com/filecoin-project/lotus/pull/4627)
|
||||
- sectorstorage: Fix manager restart edge-case (https://github.com/filecoin-project/lotus/pull/4645)
|
||||
- storagefsm: Fix GetTicket loop when the sector is already precommitted (https://github.com/filecoin-project/lotus/pull/4643)
|
||||
- Debug flag to force running sealing scheduler (https://github.com/filecoin-project/lotus/pull/4662)
|
||||
- Fix worker reenabling, handle multiple restarts in worker (https://github.com/filecoin-project/lotus/pull/4666)
|
||||
- keep retrying the proof until we run out of sectors to skip (https://github.com/filecoin-project/lotus/pull/4633)
|
||||
- worker: Commands to pause/resume task processing (https://github.com/filecoin-project/lotus/pull/4615)
|
||||
- struct name incorrect (https://github.com/filecoin-project/lotus/pull/4699)
|
||||
- optimize code replace strings with constants (https://github.com/filecoin-project/lotus/pull/4769)
|
||||
- optimize pledge sector (https://github.com/filecoin-project/lotus/pull/4765)
|
||||
- Track sealing processes across lotus-miner restarts (https://github.com/filecoin-project/lotus/pull/3618)
|
||||
- Fix scheduler lockups after storage is freed (https://github.com/filecoin-project/lotus/pull/4778)
|
||||
- storage: Track worker hostnames with work (https://github.com/filecoin-project/lotus/pull/4779)
|
||||
- Expand sched-diag; Command to abort sealing calls (https://github.com/filecoin-project/lotus/pull/4804)
|
||||
- miner: Winning PoSt Warmup (https://github.com/filecoin-project/lotus/pull/4824)
|
||||
- docsgen: Support miner/worker (https://github.com/filecoin-project/lotus/pull/4817)
|
||||
- miner: Basic storage cleanup command (https://github.com/filecoin-project/lotus/pull/4834)
|
||||
|
||||
#### Markets and Data Transfer
|
||||
|
||||
- Flesh out data transfer features (https://github.com/filecoin-project/lotus/pull/4572)
|
||||
- Fix memory leaks in data transfer (https://github.com/filecoin-project/lotus/pull/4619)
|
||||
- Handle deal id changes in OnDealSectorCommitted (https://github.com/filecoin-project/lotus/pull/4730)
|
||||
- Refactor FundManager (https://github.com/filecoin-project/lotus/pull/4736)
|
||||
- refactor: integrate new FundManager (https://github.com/filecoin-project/lotus/pull/4787)
|
||||
- Fix race in paych manager when req context is cancelled (https://github.com/filecoin-project/lotus/pull/4803)
|
||||
- fix race in paych manager add funds (https://github.com/filecoin-project/lotus/pull/4597)
|
||||
- Fix panic in FundManager (https://github.com/filecoin-project/lotus/pull/4808)
|
||||
- Fix: dont crash on startup if funds migration fails (https://github.com/filecoin-project/lotus/pull/4827)
|
||||
|
||||
#### UX
|
||||
|
||||
- Make EarlyExpiration in sectors list less scary (https://github.com/filecoin-project/lotus/pull/4600)
|
||||
- Add commands to change the worker key (https://github.com/filecoin-project/lotus/pull/4513)
|
||||
- Expose ClientDealSize via CLI (https://github.com/filecoin-project/lotus/pull/4569)
|
||||
- client deal: Cache CommD when creating multiple deals (https://github.com/filecoin-project/lotus/pull/4535)
|
||||
- miner sectors list: flags for events/seal time (https://github.com/filecoin-project/lotus/pull/4649)
|
||||
- make IPFS online mode configurable (https://github.com/filecoin-project/lotus/pull/4650)
|
||||
- Add sync status to miner info command (https://github.com/filecoin-project/lotus/pull/4669)
|
||||
- Add a StateDecodeParams method (https://github.com/filecoin-project/lotus/pull/4105)
|
||||
- sched: Interactive RPC Shell (https://github.com/filecoin-project/lotus/pull/4692)
|
||||
- Add api for getting status given a code (https://github.com/filecoin-project/lotus/pull/4210)
|
||||
- Update lotus-stats with a richer cli (https://github.com/filecoin-project/lotus/pull/4718)
|
||||
- Use TSK passed to GasEstimateGasLimit (https://github.com/filecoin-project/lotus/pull/4739)
|
||||
- match data type for reward state api (https://github.com/filecoin-project/lotus/pull/4745)
|
||||
- Add `termination-estimate` to get an estimation for how much a termination penalty will be (https://github.com/filecoin-project/lotus/pull/4617)
|
||||
- Restrict `ParseFIL` input length (https://github.com/filecoin-project/lotus/pull/4780)
|
||||
- cmd sectors commitIDs len debug (https://github.com/filecoin-project/lotus/pull/4786)
|
||||
- Add client deal-stats CLI (https://github.com/filecoin-project/lotus/pull/4788)
|
||||
- Modify printf format (https://github.com/filecoin-project/lotus/pull/4795)
|
||||
- Updated msig inspect (https://github.com/filecoin-project/lotus/pull/4533)
|
||||
- Delete the duplicate output (https://github.com/filecoin-project/lotus/pull/4819)
|
||||
- miner: Storage list sectors command (https://github.com/filecoin-project/lotus/pull/4831)
|
||||
- drop a few logs down to debug (https://github.com/filecoin-project/lotus/pull/4832)
|
||||
|
||||
#### Testing and Tooling
|
||||
|
||||
- refactor: share code between CLI tests (https://github.com/filecoin-project/lotus/pull/4598)
|
||||
- Fix flaky TestCLIDealFlow (https://github.com/filecoin-project/lotus/pull/4608)
|
||||
- Fix flaky testMiningReal (https://github.com/filecoin-project/lotus/pull/4609)
|
||||
- Add election run-dummy command (https://github.com/filecoin-project/lotus/pull/4498)
|
||||
- Fix .gitmodules (https://github.com/filecoin-project/lotus/pull/4713)
|
||||
- fix metrics wiring.(https://github.com/filecoin-project/lotus/pull/4691)
|
||||
- shed: Util for creating ID CIDs (https://github.com/filecoin-project/lotus/pull/4726)
|
||||
- Run kumquat upgrade on devnets (https://github.com/filecoin-project/lotus/pull/4734)
|
||||
- Make pond work again (https://github.com/filecoin-project/lotus/pull/4775)
|
||||
- lotus-stats: fix influx flags (https://github.com/filecoin-project/lotus/pull/4810)
|
||||
- 2k sync BootstrapPeerThreshold (https://github.com/filecoin-project/lotus/pull/4797)
|
||||
- test for FundManager panic to ensure it is fixed (https://github.com/filecoin-project/lotus/pull/4825)
|
||||
- Stop mining at the end of tests (https://github.com/filecoin-project/lotus/pull/4826)
|
||||
- Make some logs quieter (https://github.com/filecoin-project/lotus/pull/4709)
|
||||
|
||||
#### Dependencies
|
||||
|
||||
- update filecoin-ffi in go mod (https://github.com/filecoin-project/lotus/pull/4584)
|
||||
- Update FFI (https://github.com/filecoin-project/lotus/pull/4613)
|
||||
- feat: integrate new optional blst backend and verification optimizations from proofs (https://github.com/filecoin-project/lotus/pull/4630)
|
||||
- Use https for blst submodule (https://github.com/filecoin-project/lotus/pull/4710)
|
||||
- Update go-bitfield (https://github.com/filecoin-project/lotus/pull/4756)
|
||||
- Update Yamux (https://github.com/filecoin-project/lotus/pull/4758)
|
||||
- Update to latest go-bitfield (https://github.com/filecoin-project/lotus/pull/4793)
|
||||
- Update to latest go-address (https://github.com/filecoin-project/lotus/pull/4798)
|
||||
- update libp2p for stream interface changes (https://github.com/filecoin-project/lotus/pull/4814)
|
||||
|
||||
# 1.1.2 / 2020-10-24
|
||||
|
||||
This is a patch release of Lotus that builds on the fixes involving worker keys that was introduced in v1.1.1. Miners and node operators should update to this release as soon as possible in order to ensure their blocks are propagated and validated.
|
||||
|
||||
## Changes
|
||||
|
||||
- Handle worker key changes correctly in runtime (https://github.com/filecoin-project/lotus/pull/4579)
|
||||
|
||||
# 1.1.1 / 2020-10-24
|
||||
|
||||
This is a patch release of Lotus that addresses some issues caused by when miners change their worker keys. Miners and node operators should update to this release as soon as possible, especially any miner who has changed their worker key recently.
|
||||
|
||||
## Changes
|
||||
|
||||
- Miner finder for interactive client deal CLI (https://github.com/filecoin-project/lotus/pull/4504)
|
||||
- Disable blockstore bloom filter (https://github.com/filecoin-project/lotus/pull/4512)
|
||||
- Add api for getting status given a code (https://github.com/filecoin-project/lotus/pull/4210)
|
||||
- add batch api for push messages (https://github.com/filecoin-project/lotus/pull/4236)
|
||||
- add measure datastore wrapper around bench chain datastore (https://github.com/filecoin-project/lotus/pull/4302)
|
||||
- Look at block base fee for PCR (https://github.com/filecoin-project/lotus/pull/4313)
|
||||
- Add a shed util to determine % of power that has won a block (https://github.com/filecoin-project/lotus/pull/4318)
|
||||
- Shed/borked cmd (https://github.com/filecoin-project/lotus/pull/4339)
|
||||
- optimize mining code (https://github.com/filecoin-project/lotus/pull/4379)
|
||||
- heaviestTipSet reurning nil is a ok (https://github.com/filecoin-project/lotus/pull/4523)
|
||||
- Remove most v0 actor imports (https://github.com/filecoin-project/lotus/pull/4383)
|
||||
- Small chain export optimization (https://github.com/filecoin-project/lotus/pull/4536)
|
||||
- Add block list to pcr (https://github.com/filecoin-project/lotus/pull/4314)
|
||||
- Fix circ supply default in conformance (https://github.com/filecoin-project/lotus/pull/4449)
|
||||
- miner: fix init --create-worker-key (https://github.com/filecoin-project/lotus/pull/4475)
|
||||
- make push and addLocal atomic (https://github.com/filecoin-project/lotus/pull/4500)
|
||||
- add some methods that oni needs (https://github.com/filecoin-project/lotus/pull/4501)
|
||||
- MinerGetBaseInfo: if miner is not found in lookback, check current (https://github.com/filecoin-project/lotus/pull/4508)
|
||||
- Delete wallet from local wallet cache (https://github.com/filecoin-project/lotus/pull/4526)
|
||||
- Fix lotus-shed ledger list (https://github.com/filecoin-project/lotus/pull/4521)
|
||||
- Manage sectors by size instead of proof type (https://github.com/filecoin-project/lotus/pull/4511)
|
||||
- Feat/api request metrics wrapper (https://github.com/filecoin-project/lotus/pull/4516)
|
||||
- Fix chain sync stopping to sync (https://github.com/filecoin-project/lotus/pull/4541)
|
||||
- Use the correct lookback for the worker key when creating blocks (https://github.com/filecoin-project/lotus/pull/4539)
|
||||
- Cleanup test initialization and always validate VRFs in tests (https://github.com/filecoin-project/lotus/pull/4538)
|
||||
- Add a market WithdrawBalance CLI (https://github.com/filecoin-project/lotus/pull/4524)
|
||||
- wallet list: Add market balance and ID address flags (https://github.com/filecoin-project/lotus/pull/4555)
|
||||
- tvx simulate command; tvx extract --ignore-sanity-checks (https://github.com/filecoin-project/lotus/pull/4554)
|
||||
- lotus-lite: CLI tests for `lotus client` commands (https://github.com/filecoin-project/lotus/pull/4497)
|
||||
- lite-mode - market storage and retrieval clients (https://github.com/filecoin-project/lotus/pull/4263)
|
||||
- Chore: update drand to v1.2.0 (https://github.com/filecoin-project/lotus/pull/4420)
|
||||
- Fix random test failures (https://github.com/filecoin-project/lotus/pull/4559)
|
||||
- Fix flaky TestTimedBSSimple (https://github.com/filecoin-project/lotus/pull/4561)
|
||||
- Make wallet market withdraw usable with miner addresses (https://github.com/filecoin-project/lotus/pull/4556)
|
||||
- Fix flaky TestChainExportImportFull (https://github.com/filecoin-project/lotus/pull/4564)
|
||||
- Use older randomness for the PoSt commit on specs-actors version 2 (https://github.com/filecoin-project/lotus/pull/4563)
|
||||
- shed: Commad to decode messages (https://github.com/filecoin-project/lotus/pull/4565)
|
||||
- Fetch worker key from correct block on sync (https://github.com/filecoin-project/lotus/pull/4573)
|
||||
|
||||
# 1.1.0 / 2020-10-20
|
||||
|
||||
This is a mandatory release that introduces the first post-liftoff upgrade to the Filecoin network. The changes that break consensus are an upgrade to specs-actors v2.2.0 at epoch 170000.
|
||||
|
||||
## Changes
|
||||
|
||||
- Introduce Network version 6 (https://github.com/filecoin-project/lotus/pull/4506)
|
||||
- Update markets v1.0.0 (https://github.com/filecoin-project/lotus/pull/4505)
|
||||
- Add some extra logging to try and debug sync issues (https://github.com/filecoin-project/lotus/pull/4486)
|
||||
- Circle: Run tests for some subsystems separately (https://github.com/filecoin-project/lotus/pull/4496)
|
||||
- Add a terminate sectors command to lotus-shed (https://github.com/filecoin-project/lotus/pull/4507)
|
||||
- Add a comment to BlockMessages to address #4446 (https://github.com/filecoin-project/lotus/pull/4491)
|
||||
|
||||
# 1.0.0 / 2020-10-19
|
||||
|
||||
It's 1.0.0! This is an optional release of Lotus that introduces some UX improvements to the 0.10 series.
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
FROM golang:1.15.6 AS builder-deps
|
||||
MAINTAINER Lotus Development Team
|
||||
|
||||
RUN apt-get update && apt-get install -y ca-certificates build-essential clang ocl-icd-opencl-dev ocl-icd-libopencl1 jq libhwloc-dev
|
||||
|
||||
ARG RUST_VERSION=nightly
|
||||
ENV XDG_CACHE_HOME="/tmp"
|
||||
|
||||
ENV RUSTUP_HOME=/usr/local/rustup \
|
||||
CARGO_HOME=/usr/local/cargo \
|
||||
PATH=/usr/local/cargo/bin:$PATH
|
||||
|
||||
RUN wget "https://static.rust-lang.org/rustup/dist/x86_64-unknown-linux-gnu/rustup-init"; \
|
||||
chmod +x rustup-init; \
|
||||
./rustup-init -y --no-modify-path --profile minimal --default-toolchain $RUST_VERSION; \
|
||||
rm rustup-init; \
|
||||
chmod -R a+w $RUSTUP_HOME $CARGO_HOME; \
|
||||
rustup --version; \
|
||||
cargo --version; \
|
||||
rustc --version;
|
||||
|
||||
|
||||
FROM builder-deps AS builder-local
|
||||
MAINTAINER Lotus Development Team
|
||||
|
||||
COPY ./ /opt/filecoin
|
||||
WORKDIR /opt/filecoin
|
||||
RUN make clean deps
|
||||
|
||||
|
||||
FROM builder-local AS builder
|
||||
MAINTAINER Lotus Development Team
|
||||
|
||||
WORKDIR /opt/filecoin
|
||||
|
||||
ARG RUSTFLAGS=""
|
||||
ARG GOFLAGS=""
|
||||
|
||||
RUN make deps lotus lotus-miner lotus-worker lotus-shed lotus-chainwatch lotus-stats
|
||||
|
||||
|
||||
FROM ubuntu:20.04 AS base
|
||||
MAINTAINER Lotus Development Team
|
||||
|
||||
# Base resources
|
||||
COPY --from=builder /etc/ssl/certs /etc/ssl/certs
|
||||
COPY --from=builder /lib/x86_64-linux-gnu/libdl.so.2 /lib/
|
||||
COPY --from=builder /lib/x86_64-linux-gnu/librt.so.1 /lib/
|
||||
COPY --from=builder /lib/x86_64-linux-gnu/libgcc_s.so.1 /lib/
|
||||
COPY --from=builder /lib/x86_64-linux-gnu/libutil.so.1 /lib/
|
||||
COPY --from=builder /usr/lib/x86_64-linux-gnu/libltdl.so.7 /lib/
|
||||
COPY --from=builder /usr/lib/x86_64-linux-gnu/libnuma.so.1 /lib/
|
||||
COPY --from=builder /usr/lib/x86_64-linux-gnu/libhwloc.so.5 /lib/
|
||||
COPY --from=builder /usr/lib/x86_64-linux-gnu/libOpenCL.so.1 /lib/
|
||||
|
||||
RUN useradd -r -u 532 -U fc
|
||||
|
||||
|
||||
FROM base AS lotus
|
||||
MAINTAINER Lotus Development Team
|
||||
|
||||
COPY --from=builder /opt/filecoin/lotus /usr/local/bin/
|
||||
COPY --from=builder /opt/filecoin/lotus-shed /usr/local/bin/
|
||||
|
||||
ENV FILECOIN_PARAMETER_CACHE /var/tmp/filecoin-proof-parameters
|
||||
ENV LOTUS_PATH /var/lib/lotus
|
||||
|
||||
RUN mkdir /var/lib/lotus /var/tmp/filecoin-proof-parameters && chown fc /var/lib/lotus /var/tmp/filecoin-proof-parameters
|
||||
|
||||
USER fc
|
||||
|
||||
ENTRYPOINT ["/usr/local/bin/lotus"]
|
||||
|
||||
CMD ["-help"]
|
||||
@@ -5,10 +5,10 @@ all: build
|
||||
|
||||
unexport GOFLAGS
|
||||
|
||||
GOVERSION:=$(shell go version | cut -d' ' -f 3 | cut -d. -f 2)
|
||||
ifeq ($(shell expr $(GOVERSION) \< 14), 1)
|
||||
$(warning Your Golang version is go 1.$(GOVERSION))
|
||||
$(error Update Golang to version $(shell grep '^go' go.mod))
|
||||
GOVERSION:=$(shell go version | cut -d' ' -f 3 | sed 's/^go//' | awk -F. '{printf "%d%03d%03d", $$1, $$2, $$3}')
|
||||
ifeq ($(shell expr $(GOVERSION) \< 1015005), 1)
|
||||
$(warning Your Golang version is go$(shell expr $(GOVERSION) / 1000000).$(shell expr $(GOVERSION) % 1000000 / 1000).$(shell expr $(GOVERSION) % 1000))
|
||||
$(error Update Golang to version to at least 1.15.5)
|
||||
endif
|
||||
|
||||
# git modules that need to be loaded
|
||||
@@ -41,8 +41,14 @@ MODULES+=$(FFI_PATH)
|
||||
BUILD_DEPS+=build/.filecoin-install
|
||||
CLEAN+=build/.filecoin-install
|
||||
|
||||
$(MODULES): build/.update-modules ;
|
||||
ffi-version-check:
|
||||
@[[ "$$(awk '/const Version/{print $$5}' extern/filecoin-ffi/version.go)" -eq 2 ]] || (echo "FFI version mismatch, update submodules"; exit 1)
|
||||
BUILD_DEPS+=ffi-version-check
|
||||
|
||||
.PHONY: ffi-version-check
|
||||
|
||||
|
||||
$(MODULES): build/.update-modules ;
|
||||
# dummy file that marks the last time modules were updated
|
||||
build/.update-modules:
|
||||
git submodule update --init --recursive
|
||||
@@ -57,11 +63,23 @@ CLEAN+=build/.update-modules
|
||||
deps: $(BUILD_DEPS)
|
||||
.PHONY: deps
|
||||
|
||||
build-devnets: build lotus-seed lotus-shed lotus-wallet lotus-gateway
|
||||
.PHONY: build-devnets
|
||||
|
||||
debug: GOFLAGS+=-tags=debug
|
||||
debug: lotus lotus-miner lotus-worker lotus-seed
|
||||
debug: build-devnets
|
||||
|
||||
2k: GOFLAGS+=-tags=2k
|
||||
2k: lotus lotus-miner lotus-worker lotus-seed
|
||||
2k: build-devnets
|
||||
|
||||
calibnet: GOFLAGS+=-tags=calibnet
|
||||
calibnet: build-devnets
|
||||
|
||||
nerpanet: GOFLAGS+=-tags=nerpanet
|
||||
nerpanet: build-devnets
|
||||
|
||||
butterflynet: GOFLAGS+=-tags=butterflynet
|
||||
butterflynet: build-devnets
|
||||
|
||||
lotus: $(BUILD_DEPS)
|
||||
rm -f lotus
|
||||
@@ -133,18 +151,30 @@ benchmarks:
|
||||
|
||||
lotus-pond: 2k
|
||||
go build -o lotus-pond ./lotuspond
|
||||
(cd lotuspond/front && npm i && CI=false npm run build)
|
||||
.PHONY: lotus-pond
|
||||
BINS+=lotus-pond
|
||||
|
||||
lotus-pond-front:
|
||||
(cd lotuspond/front && npm i && CI=false npm run build)
|
||||
.PHONY: lotus-pond-front
|
||||
|
||||
lotus-pond-app: lotus-pond-front lotus-pond
|
||||
.PHONY: lotus-pond-app
|
||||
|
||||
lotus-townhall:
|
||||
rm -f lotus-townhall
|
||||
go build -o lotus-townhall ./cmd/lotus-townhall
|
||||
(cd ./cmd/lotus-townhall/townhall && npm i && npm run build)
|
||||
go run github.com/GeertJohan/go.rice/rice append --exec lotus-townhall -i ./cmd/lotus-townhall -i ./build
|
||||
.PHONY: lotus-townhall
|
||||
BINS+=lotus-townhall
|
||||
|
||||
lotus-townhall-front:
|
||||
(cd ./cmd/lotus-townhall/townhall && npm i && npm run build)
|
||||
.PHONY: lotus-townhall-front
|
||||
|
||||
lotus-townhall-app: lotus-touch lotus-townhall-front
|
||||
go run github.com/GeertJohan/go.rice/rice append --exec lotus-townhall -i ./cmd/lotus-townhall -i ./build
|
||||
.PHONY: lotus-townhall-app
|
||||
|
||||
lotus-fountain:
|
||||
rm -f lotus-fountain
|
||||
go build -o lotus-fountain ./cmd/lotus-fountain
|
||||
@@ -167,7 +197,7 @@ BINS+=lotus-bench
|
||||
|
||||
lotus-stats:
|
||||
rm -f lotus-stats
|
||||
go build -o lotus-stats ./cmd/lotus-stats
|
||||
go build $(GOFLAGS) -o lotus-stats ./cmd/lotus-stats
|
||||
go run github.com/GeertJohan/go.rice/rice append --exec lotus-stats -i ./build
|
||||
.PHONY: lotus-stats
|
||||
BINS+=lotus-stats
|
||||
@@ -192,6 +222,12 @@ lotus-wallet:
|
||||
.PHONY: lotus-wallet
|
||||
BINS+=lotus-wallet
|
||||
|
||||
lotus-keygen:
|
||||
rm -f lotus-keygen
|
||||
go build -o lotus-keygen ./cmd/lotus-keygen
|
||||
.PHONY: lotus-keygen
|
||||
BINS+=lotus-keygen
|
||||
|
||||
testground:
|
||||
go build -tags testground -o /dev/null ./cmd/lotus
|
||||
.PHONY: testground
|
||||
@@ -292,7 +328,9 @@ method-gen:
|
||||
gen: type-gen method-gen
|
||||
|
||||
docsgen:
|
||||
go run ./api/docgen > documentation/en/api-methods.md
|
||||
go run ./api/docgen "api/api_full.go" "FullNode" > documentation/en/api-methods.md
|
||||
go run ./api/docgen "api/api_storage.go" "StorageMiner" > documentation/en/api-methods-miner.md
|
||||
go run ./api/docgen "api/api_worker.go" "WorkerAPI" > documentation/en/api-methods-worker.md
|
||||
|
||||
print-%:
|
||||
@echo $*=$($*)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<a href="https://circleci.com/gh/filecoin-project/lotus"><img src="https://circleci.com/gh/filecoin-project/lotus.svg?style=svg"></a>
|
||||
<a href="https://codecov.io/gh/filecoin-project/lotus"><img src="https://codecov.io/gh/filecoin-project/lotus/branch/master/graph/badge.svg"></a>
|
||||
<a href="https://goreportcard.com/report/github.com/filecoin-project/lotus"><img src="https://goreportcard.com/badge/github.com/filecoin-project/lotus" /></a>
|
||||
<a href=""><img src="https://img.shields.io/badge/golang-%3E%3D1.14.7-blue.svg" /></a>
|
||||
<a href=""><img src="https://img.shields.io/badge/golang-%3E%3D1.15.5-blue.svg" /></a>
|
||||
<br>
|
||||
</p>
|
||||
|
||||
@@ -24,24 +24,31 @@ For instructions on how to build, install and setup lotus, please visit [https:/
|
||||
|
||||
Please send an email to security@filecoin.org. See our [security policy](SECURITY.md) for more details.
|
||||
|
||||
## Development
|
||||
## Related packages
|
||||
|
||||
The main branches under development at the moment are:
|
||||
* [`master`](https://github.com/filecoin-project/lotus): current testnet.
|
||||
* [`next`](https://github.com/filecoin-project/lotus/tree/next): working branch with chain-breaking changes.
|
||||
* [`ntwk-calibration`](https://github.com/filecoin-project/lotus/tree/ntwk-calibration): devnet running one of `next` commits.
|
||||
These repos are independent and reusable modules, but are tightly integrated into Lotus to make up a fully featured Filecoin implementation:
|
||||
|
||||
### Tracker
|
||||
|
||||
All work is tracked via issues. An attempt at keeping an up-to-date view on remaining work towards Mainnet launch can be seen at the [lotus github project board](https://github.com/orgs/filecoin-project/projects/8). The issues labeled with `incentives` are there to identify the issues needed for Space Race launch.
|
||||
|
||||
### Packages
|
||||
|
||||
The lotus Filecoin implementation unfolds into the following packages:
|
||||
|
||||
- [This repo](https://github.com/filecoin-project/lotus)
|
||||
- [go-fil-markets](https://github.com/filecoin-project/go-fil-markets) which has its own [kanban work tracker available here](https://app.zenhub.com/workspaces/markets-shared-components-5daa144a7046a60001c6e253/board)
|
||||
- [spec-actors](https://github.com/filecoin-project/specs-actors) which has its own [kanban work tracker available here](https://app.zenhub.com/workspaces/actors-5ee6f3aa87591f0016c05685/board)
|
||||
- [specs-actors](https://github.com/filecoin-project/specs-actors) which has its own [kanban work tracker available here](https://app.zenhub.com/workspaces/actors-5ee6f3aa87591f0016c05685/board)
|
||||
|
||||
## Contribute
|
||||
|
||||
Lotus is a universally open project and welcomes contributions of all kinds: code, docs, and more. However, before making a contribution, we ask you to heed these recommendations:
|
||||
|
||||
1. If the proposal entails a protocol change, please first submit a [Filecoin Improvement Proposal](https://github.com/filecoin-project/FIPs).
|
||||
2. If the change is complex and requires prior discussion, [open an issue](github.com/filecoin-project/lotus/issues) or a [discussion](https://github.com/filecoin-project/lotus/discussions) to request feedback before you start working on a pull request. This is to avoid disappointment and sunk costs, in case the change is not actually needed or accepted.
|
||||
3. Please refrain from submitting PRs to adapt existing code to subjective preferences. The changeset should contain functional or technical improvements/enhancements, bug fixes, new features, or some other clear material contribution. Simple stylistic changes are likely to be rejected in order to reduce code churn.
|
||||
|
||||
When implementing a change:
|
||||
|
||||
1. Adhere to the standard Go formatting guidelines, e.g. [Effective Go](https://golang.org/doc/effective_go.html). Run `go fmt`.
|
||||
2. Stick to the idioms and patterns used in the codebase. Familiar-looking code has a higher chance of being accepted than eerie code. Pay attention to commonly used variable and parameter names, avoidance of naked returns, error handling patterns, etc.
|
||||
3. Comments: follow the advice on the [Commentary](https://golang.org/doc/effective_go.html#commentary) section of Effective Go.
|
||||
4. Minimize code churn. Modify only what is strictly necessary. Well-encapsulated changesets will get a quicker response from maintainers.
|
||||
5. Lint your code with [`golangci-lint`](https://golangci-lint.run) (CI will reject your PR if unlinted).
|
||||
6. Add tests.
|
||||
7. Title the PR in a meaningful way and describe the rationale and the thought process in the PR description.
|
||||
8. Write clean, thoughtful, and detailed [commit messages](https://chris.beams.io/posts/git-commit/). This is even more important than the PR description, because commit messages are stored _inside_ the Git history. One good rule is: if you are happy posting the commit message as the PR description, then it's a good commit message.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
+4
-4
@@ -2,11 +2,11 @@
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
For *critical* bugs, please consult our Security Policy and Responsible Disclosure Program information at https://github.com/filecoin-project/community/blob/master/SECURITY.md
|
||||
For reporting security vulnerabilities/bugs, please consult our Security Policy and Responsible Disclosure Program information at https://github.com/filecoin-project/community/blob/master/SECURITY.md. Security vulnerabilities should be reported via our [Vulnerability Reporting channels](https://github.com/filecoin-project/community/blob/master/SECURITY.md#vulnerability-reporting) and will be eligible for a [Bug Bounty](https://security.filecoin.io/bug-bounty/).
|
||||
|
||||
Please try to provide a clear description of any bugs reported, along with how to reproduce the bug if possible. More detailed bug reports (especially those with a PoC included) will help us move forward much faster. Additionally, please avoid reporting bugs that already have open issues. Take a moment to search the issue list of the related GitHub repositories before writing up a new report.
|
||||
|
||||
Here are some examples of bugs we would consider 'critical':
|
||||
Here are some examples of bugs we would consider to be security vulnerabilities:
|
||||
|
||||
* If you can spend from a `multisig` wallet you do not control the keys for.
|
||||
* If you can cause a miner to be slashed without them actually misbehaving.
|
||||
@@ -16,8 +16,8 @@ Here are some examples of bugs we would consider 'critical':
|
||||
* If you can craft a message that causes a persistent fork in the network.
|
||||
* If you can cause the total amount of Filecoin in the network to no longer be 2 billion.
|
||||
|
||||
This is not an exhaustive list, but should provide some idea of what we consider 'critical'.
|
||||
This is not an exhaustive list, but should provide some idea of what we consider as a security vulnerability, .
|
||||
|
||||
## Reporting a non security bug
|
||||
|
||||
For non-critical bugs, please simply file a GitHub [issue](https://github.com/filecoin-project/lotus/issues/new?template=bug_report.md).
|
||||
For non-security bugs, please simply file a GitHub [issue](https://github.com/filecoin-project/lotus/issues/new?template=bug_report.md).
|
||||
|
||||
+16
-7
@@ -4,13 +4,13 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/uuid"
|
||||
|
||||
"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"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
)
|
||||
|
||||
type Common interface {
|
||||
@@ -31,6 +31,7 @@ type Common interface {
|
||||
NetPubsubScores(context.Context) ([]PubsubScore, error)
|
||||
NetAutoNatStatus(context.Context) (NatInfo, error)
|
||||
NetAgentVersion(ctx context.Context, p peer.ID) (string, error)
|
||||
NetPeerInfo(context.Context, peer.ID) (*ExtendedPeerInfo, error)
|
||||
|
||||
// NetBandwidthStats returns statistics about the nodes total bandwidth
|
||||
// usage and current rate across all peers and protocols.
|
||||
@@ -44,13 +45,18 @@ type Common interface {
|
||||
// usage and current rate per protocol
|
||||
NetBandwidthStatsByProtocol(ctx context.Context) (map[protocol.ID]metrics.Stats, error)
|
||||
|
||||
// ConnectionGater API
|
||||
NetBlockAdd(ctx context.Context, acl NetBlockList) error
|
||||
NetBlockRemove(ctx context.Context, acl NetBlockList) error
|
||||
NetBlockList(ctx context.Context) (NetBlockList, error)
|
||||
|
||||
// MethodGroup: Common
|
||||
|
||||
// ID returns peerID of libp2p node backing this API
|
||||
ID(context.Context) (peer.ID, error)
|
||||
|
||||
// Version provides information about API provider
|
||||
Version(context.Context) (Version, error)
|
||||
Version(context.Context) (APIVersion, error)
|
||||
|
||||
LogList(context.Context) ([]string, error)
|
||||
LogSetLevel(context.Context, string, string) error
|
||||
@@ -58,18 +64,21 @@ type Common interface {
|
||||
// trigger graceful shutdown
|
||||
Shutdown(context.Context) error
|
||||
|
||||
// Session returns a random UUID of api provider session
|
||||
Session(context.Context) (uuid.UUID, error)
|
||||
|
||||
Closing(context.Context) (<-chan struct{}, error)
|
||||
}
|
||||
|
||||
// Version provides various build-time information
|
||||
type Version struct {
|
||||
// APIVersion provides various build-time information
|
||||
type APIVersion struct {
|
||||
Version string
|
||||
|
||||
// APIVersion is a binary encoded semver version of the remote implementing
|
||||
// this api
|
||||
//
|
||||
// See APIVersion in build/version.go
|
||||
APIVersion build.Version
|
||||
APIVersion Version
|
||||
|
||||
// TODO: git commit / os / genesis cid?
|
||||
|
||||
@@ -77,7 +86,7 @@ type Version struct {
|
||||
BlockDelay uint64
|
||||
}
|
||||
|
||||
func (v Version) String() string {
|
||||
func (v APIVersion) String() string {
|
||||
return fmt.Sprintf("%s+api%s", v.Version, v.APIVersion.String())
|
||||
}
|
||||
|
||||
|
||||
+96
-6
@@ -2,6 +2,7 @@ package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
@@ -31,6 +32,14 @@ import (
|
||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||
)
|
||||
|
||||
//go:generate go run github.com/golang/mock/mockgen -destination=mocks/mock_full.go -package=mocks . FullNode
|
||||
|
||||
// ChainIO abstracts operations for accessing raw IPLD objects.
|
||||
type ChainIO interface {
|
||||
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
|
||||
ChainHasObj(context.Context, cid.Cid) (bool, error)
|
||||
}
|
||||
|
||||
// FullNode API is a low-level interface to the Filecoin network full node
|
||||
type FullNode interface {
|
||||
Common
|
||||
@@ -207,6 +216,15 @@ type FullNode interface {
|
||||
// based on current chain conditions
|
||||
MpoolPushMessage(ctx context.Context, msg *types.Message, spec *MessageSendSpec) (*types.SignedMessage, error)
|
||||
|
||||
// MpoolBatchPush batch pushes a signed message to mempool.
|
||||
MpoolBatchPush(context.Context, []*types.SignedMessage) ([]cid.Cid, error)
|
||||
|
||||
// MpoolBatchPushUntrusted batch pushes a signed message to mempool from untrusted sources.
|
||||
MpoolBatchPushUntrusted(context.Context, []*types.SignedMessage) ([]cid.Cid, error)
|
||||
|
||||
// MpoolBatchPushMessage batch pushes a unsigned message to mempool.
|
||||
MpoolBatchPushMessage(context.Context, []*types.Message, *MessageSendSpec) ([]*types.SignedMessage, error)
|
||||
|
||||
// MpoolGetNonce gets next nonce for the specified sender.
|
||||
// Note that this method may not be atomic. Use MpoolPushMessage instead.
|
||||
MpoolGetNonce(context.Context, address.Address) (uint64, error)
|
||||
@@ -277,6 +295,8 @@ type FullNode interface {
|
||||
ClientListDeals(ctx context.Context) ([]DealInfo, error)
|
||||
// ClientGetDealUpdates returns the status of updated deals
|
||||
ClientGetDealUpdates(ctx context.Context) (<-chan DealInfo, error)
|
||||
// ClientGetDealStatus returns status given a code
|
||||
ClientGetDealStatus(ctx context.Context, statusCode uint64) (string, error)
|
||||
// ClientHasLocal indicates whether a certain CID is locally stored.
|
||||
ClientHasLocal(ctx context.Context, root cid.Cid) (bool, error)
|
||||
// ClientFindData identifies peers that have a certain file, and returns QueryOffers (one per peer).
|
||||
@@ -290,6 +310,8 @@ type FullNode interface {
|
||||
ClientRetrieveWithEvents(ctx context.Context, order RetrievalOrder, ref *FileRef) (<-chan marketevents.RetrievalEvent, error)
|
||||
// ClientQueryAsk returns a signed StorageAsk from the specified miner.
|
||||
ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.StorageAsk, error)
|
||||
// ClientCalcCommP calculates the CommP and data size of the specified CID
|
||||
ClientDealPieceCID(ctx context.Context, root cid.Cid) (DataCIDSize, error)
|
||||
// ClientCalcCommP calculates the CommP for a specified file
|
||||
ClientCalcCommP(ctx context.Context, inpath string) (*CommPRet, error)
|
||||
// ClientGenCar generates a CAR file for the specified file.
|
||||
@@ -301,6 +323,8 @@ type FullNode interface {
|
||||
ClientDataTransferUpdates(ctx context.Context) (<-chan DataTransferChannel, error)
|
||||
// ClientRestartDataTransfer attempts to restart a data transfer with the given transfer ID and other peer
|
||||
ClientRestartDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error
|
||||
// ClientCancelDataTransfer cancels a data transfer with the given transfer ID and other peer
|
||||
ClientCancelDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error
|
||||
// ClientRetrieveTryRestartInsufficientFunds attempts to restart stalled retrievals on a given payment channel
|
||||
// which are stuck due to insufficient funds
|
||||
ClientRetrieveTryRestartInsufficientFunds(ctx context.Context, paymentChannel address.Address) error
|
||||
@@ -315,10 +339,14 @@ type FullNode interface {
|
||||
|
||||
// MethodGroup: State
|
||||
// The State methods are used to query, inspect, and interact with chain state.
|
||||
// Most methods take a TipSetKey as a parameter. The state looked up is the state at that tipset.
|
||||
// Most methods take a TipSetKey as a parameter. The state looked up is the parent state of the tipset.
|
||||
// A nil TipSetKey can be provided as a param, this will cause the heaviest tipset in the chain to be used.
|
||||
|
||||
// StateCall runs the given message and returns its result without any persisted changes.
|
||||
//
|
||||
// StateCall applies the message to the tipset's parent state. The
|
||||
// message is not applied on-top-of the messages in the passed-in
|
||||
// tipset.
|
||||
StateCall(context.Context, *types.Message, types.TipSetKey) (*InvocResult, error)
|
||||
// StateReplay replays a given message, assuming it was included in a block in the specified tipset.
|
||||
// If no tipset key is provided, the appropriate tipset is looked up.
|
||||
@@ -329,6 +357,8 @@ type FullNode interface {
|
||||
StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*ActorState, error)
|
||||
// StateListMessages looks back and returns all messages with a matching to or from address, stopping at the given height.
|
||||
StateListMessages(ctx context.Context, match *MessageMatch, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error)
|
||||
// StateDecodeParams attempts to decode the provided params, based on the recipient actor address and method number.
|
||||
StateDecodeParams(ctx context.Context, toAddr address.Address, method abi.MethodNum, params []byte, tsk types.TipSetKey) (interface{}, error)
|
||||
|
||||
// StateNetworkName returns the name of the network the node is synced to
|
||||
StateNetworkName(context.Context) (dtypes.NetworkName, error)
|
||||
@@ -359,6 +389,8 @@ type FullNode interface {
|
||||
StateMinerInitialPledgeCollateral(context.Context, address.Address, miner.SectorPreCommitInfo, types.TipSetKey) (types.BigInt, error)
|
||||
// StateMinerAvailableBalance returns the portion of a miner's balance that can be withdrawn or spent
|
||||
StateMinerAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error)
|
||||
// StateMinerSectorAllocated checks if a sector is allocated
|
||||
StateMinerSectorAllocated(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (bool, error)
|
||||
// StateSectorPreCommitInfo returns the PreCommit info for the specified miner's sector
|
||||
StateSectorPreCommitInfo(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error)
|
||||
// StateSectorGetInfo returns the on-chain info for the specified miner's sector. Returns null in case the sector info isn't found
|
||||
@@ -371,6 +403,8 @@ type FullNode interface {
|
||||
StateSectorPartition(ctx context.Context, maddr address.Address, sectorNumber abi.SectorNumber, tok types.TipSetKey) (*miner.SectorLocation, error)
|
||||
// StateSearchMsg searches for a message in the chain, and returns its receipt and the tipset where it was executed
|
||||
StateSearchMsg(context.Context, cid.Cid) (*MsgLookup, error)
|
||||
// StateSearchMsgLimited looks back up to limit epochs in the chain for a message, and returns its receipt and the tipset where it was executed
|
||||
StateSearchMsgLimited(ctx context.Context, msg cid.Cid, limit abi.ChainEpoch) (*MsgLookup, error)
|
||||
// StateWaitMsg looks back in the chain for a message. If not found, it blocks until the
|
||||
// message arrives on chain, and gets to the indicated confidence depth.
|
||||
StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64) (*MsgLookup, error)
|
||||
@@ -438,6 +472,12 @@ type FullNode interface {
|
||||
// MsigGetVested returns the amount of FIL that vested in a multisig in a certain period.
|
||||
// It takes the following params: <multisig address>, <start epoch>, <end epoch>
|
||||
MsigGetVested(context.Context, address.Address, types.TipSetKey, types.TipSetKey) (types.BigInt, error)
|
||||
|
||||
//MsigGetPending returns pending transactions for the given multisig
|
||||
//wallet. Once pending transactions are fully approved, they will no longer
|
||||
//appear here.
|
||||
MsigGetPending(context.Context, address.Address, types.TipSetKey) ([]*MsigTransaction, error)
|
||||
|
||||
// MsigCreate creates a multisig wallet
|
||||
// It takes the following params: <required number of senders>, <approving addresses>, <unlock duration>
|
||||
//<initial balance>, <sender address of the create msg>, <gas price>
|
||||
@@ -495,8 +535,16 @@ type FullNode interface {
|
||||
// along with the address removal.
|
||||
MsigRemoveSigner(ctx context.Context, msig address.Address, proposer address.Address, toRemove address.Address, decrease bool) (cid.Cid, error)
|
||||
|
||||
MarketEnsureAvailable(context.Context, address.Address, address.Address, types.BigInt) (cid.Cid, error)
|
||||
// MarketFreeBalance
|
||||
// MarketAddBalance adds funds to the market actor
|
||||
MarketAddBalance(ctx context.Context, wallet, addr address.Address, amt types.BigInt) (cid.Cid, error)
|
||||
// MarketGetReserved gets the amount of funds that are currently reserved for the address
|
||||
MarketGetReserved(ctx context.Context, addr address.Address) (types.BigInt, error)
|
||||
// MarketReserveFunds reserves funds for a deal
|
||||
MarketReserveFunds(ctx context.Context, wallet address.Address, addr address.Address, amt types.BigInt) (cid.Cid, error)
|
||||
// MarketReleaseFunds releases funds reserved by MarketReserveFunds
|
||||
MarketReleaseFunds(ctx context.Context, addr address.Address, amt types.BigInt) error
|
||||
// MarketWithdraw withdraws unlocked funds from the market actor
|
||||
MarketWithdraw(ctx context.Context, wallet, addr address.Address, amt types.BigInt) (cid.Cid, error)
|
||||
|
||||
// MethodGroup: Paych
|
||||
// The Paych methods are for interacting with and managing payment channels
|
||||
@@ -570,6 +618,9 @@ type DealInfo struct {
|
||||
|
||||
CreationTime time.Time
|
||||
Verified bool
|
||||
|
||||
TransferChannelID *datatransfer.ChannelID
|
||||
DataTransfer *DataTransferChannel
|
||||
}
|
||||
|
||||
type MsgLookup struct {
|
||||
@@ -591,6 +642,8 @@ type MsgGasCost struct {
|
||||
TotalCost abi.TokenAmount
|
||||
}
|
||||
|
||||
// BlsMessages[x].cid = Cids[x]
|
||||
// SecpkMessages[y].cid = Cids[BlsMessages.length + y]
|
||||
type BlockMessages struct {
|
||||
BlsMessages []*types.Message
|
||||
SecpkMessages []*types.SignedMessage
|
||||
@@ -605,6 +658,7 @@ type Message struct {
|
||||
|
||||
type ActorState struct {
|
||||
Balance types.BigInt
|
||||
Code cid.Cid
|
||||
State interface{}
|
||||
}
|
||||
|
||||
@@ -762,14 +816,31 @@ type StartDealParams struct {
|
||||
VerifiedDeal bool
|
||||
}
|
||||
|
||||
func (s *StartDealParams) UnmarshalJSON(raw []byte) (err error) {
|
||||
type sdpAlias StartDealParams
|
||||
|
||||
sdp := sdpAlias{
|
||||
FastRetrieval: true,
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(raw, &sdp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*s = StartDealParams(sdp)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type IpldObject struct {
|
||||
Cid cid.Cid
|
||||
Obj interface{}
|
||||
}
|
||||
|
||||
type ActiveSync struct {
|
||||
Base *types.TipSet
|
||||
Target *types.TipSet
|
||||
WorkerID uint64
|
||||
Base *types.TipSet
|
||||
Target *types.TipSet
|
||||
|
||||
Stage SyncStateStage
|
||||
Height abi.ChainEpoch
|
||||
@@ -799,6 +870,8 @@ const (
|
||||
|
||||
func (v SyncStateStage) String() string {
|
||||
switch v {
|
||||
case StageIdle:
|
||||
return "idle"
|
||||
case StageHeaders:
|
||||
return "header sync"
|
||||
case StagePersistHeaders:
|
||||
@@ -874,6 +947,12 @@ type DataSize struct {
|
||||
PieceSize abi.PaddedPieceSize
|
||||
}
|
||||
|
||||
type DataCIDSize struct {
|
||||
PayloadSize int64
|
||||
PieceSize abi.PaddedPieceSize
|
||||
PieceCID cid.Cid
|
||||
}
|
||||
|
||||
type CommPRet struct {
|
||||
Root cid.Cid
|
||||
Size abi.UnpaddedPieceSize
|
||||
@@ -891,7 +970,8 @@ const (
|
||||
)
|
||||
|
||||
type Deadline struct {
|
||||
PostSubmissions bitfield.BitField
|
||||
PostSubmissions bitfield.BitField
|
||||
DisputableProofCount uint64
|
||||
}
|
||||
|
||||
type Partition struct {
|
||||
@@ -923,3 +1003,13 @@ type MessageMatch struct {
|
||||
To address.Address
|
||||
From address.Address
|
||||
}
|
||||
|
||||
type MsigTransaction struct {
|
||||
ID int64
|
||||
To address.Address
|
||||
Value abi.TokenAmount
|
||||
Method abi.MethodNum
|
||||
Params []byte
|
||||
|
||||
Approved []address.Address
|
||||
}
|
||||
|
||||
+22
-1
@@ -3,24 +3,45 @@ package api
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/dline"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/ipfs/go-cid"
|
||||
)
|
||||
|
||||
type GatewayAPI interface {
|
||||
ChainHasObj(context.Context, cid.Cid) (bool, error)
|
||||
ChainHead(ctx context.Context) (*types.TipSet, error)
|
||||
ChainGetBlockMessages(context.Context, cid.Cid) (*BlockMessages, error)
|
||||
ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error)
|
||||
ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
|
||||
ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
|
||||
ChainNotify(context.Context) (<-chan []*HeadChange, error)
|
||||
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
|
||||
GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
|
||||
MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
|
||||
MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
|
||||
MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error)
|
||||
MsigGetPending(context.Context, address.Address, types.TipSetKey) ([]*MsigTransaction, 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)
|
||||
StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
|
||||
StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error)
|
||||
StateListMiners(ctx context.Context, 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)
|
||||
StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*MarketDeal, error)
|
||||
StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error)
|
||||
StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error)
|
||||
StateMinerPower(context.Context, address.Address, types.TipSetKey) (*MinerPower, error)
|
||||
StateNetworkVersion(context.Context, types.TipSetKey) (network.Version, error)
|
||||
StateSearchMsg(ctx context.Context, msg cid.Cid) (*MsgLookup, error)
|
||||
StateSectorGetInfo(ctx context.Context, maddr address.Address, n abi.SectorNumber, tsk types.TipSetKey) (*miner.SectorOnChainInfo, error)
|
||||
StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error)
|
||||
StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*MsgLookup, error)
|
||||
}
|
||||
|
||||
+68
-4
@@ -5,13 +5,19 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
datatransfer "github.com/filecoin-project/go-data-transfer"
|
||||
"github.com/filecoin-project/go-fil-markets/piecestore"
|
||||
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
||||
"github.com/filecoin-project/go-fil-markets/storagemarket"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/specs-actors/v2/actors/builtin/market"
|
||||
"github.com/filecoin-project/specs-storage/storage"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/fsutil"
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/stores"
|
||||
@@ -25,11 +31,12 @@ type StorageMiner interface {
|
||||
ActorAddress(context.Context) (address.Address, error)
|
||||
|
||||
ActorSectorSize(context.Context, address.Address) (abi.SectorSize, error)
|
||||
ActorAddressConfig(ctx context.Context) (AddressConfig, error)
|
||||
|
||||
MiningBase(context.Context) (*types.TipSet, error)
|
||||
|
||||
// Temp api for testing
|
||||
PledgeSector(context.Context) error
|
||||
PledgeSector(context.Context) (abi.SectorID, error)
|
||||
|
||||
// Get the status of a given sector by ID
|
||||
SectorsStatus(ctx context.Context, sid abi.SectorNumber, showOnChainInfo bool) (SectorInfo, error)
|
||||
@@ -37,6 +44,12 @@ type StorageMiner interface {
|
||||
// List all staged sectors
|
||||
SectorsList(context.Context) ([]abi.SectorNumber, error)
|
||||
|
||||
// Get summary info of sectors
|
||||
SectorsSummary(ctx context.Context) (map[SectorState]int, error)
|
||||
|
||||
// List sectors in particular states
|
||||
SectorsListInStates(context.Context, []SectorState) ([]abi.SectorNumber, error)
|
||||
|
||||
SectorsRefs(context.Context) (map[string][]SealedRef, error)
|
||||
|
||||
// SectorStartSealing can be called on sectors in Empty or WaitDeals states
|
||||
@@ -53,7 +66,17 @@ type StorageMiner interface {
|
||||
// SectorGetExpectedSealDuration gets the expected time for a sector to seal
|
||||
SectorGetExpectedSealDuration(context.Context) (time.Duration, error)
|
||||
SectorsUpdate(context.Context, abi.SectorNumber, SectorState) error
|
||||
// SectorRemove removes the sector from storage. It doesn't terminate it on-chain, which can
|
||||
// be done with SectorTerminate. Removing and not terminating live sectors will cause additional penalties.
|
||||
SectorRemove(context.Context, abi.SectorNumber) error
|
||||
// SectorTerminate terminates the sector on-chain (adding it to a termination batch first), then
|
||||
// automatically removes it from storage
|
||||
SectorTerminate(context.Context, abi.SectorNumber) error
|
||||
// SectorTerminateFlush immediately sends a terminate message with sectors batched for termination.
|
||||
// Returns null if message wasn't sent
|
||||
SectorTerminateFlush(ctx context.Context) (*cid.Cid, error)
|
||||
// SectorTerminatePending returns a list of pending sector terminations to be sent in the next batch message
|
||||
SectorTerminatePending(ctx context.Context) ([]abi.SectorID, error)
|
||||
SectorMarkForUpgrade(ctx context.Context, id abi.SectorNumber) error
|
||||
|
||||
StorageList(ctx context.Context) (map[stores.ID][]stores.Decl, error)
|
||||
@@ -62,11 +85,13 @@ type StorageMiner interface {
|
||||
|
||||
// WorkerConnect tells the node to connect to workers RPC
|
||||
WorkerConnect(context.Context, string) error
|
||||
WorkerStats(context.Context) (map[uint64]storiface.WorkerStats, error)
|
||||
WorkerJobs(context.Context) (map[uint64][]storiface.WorkerJob, error)
|
||||
WorkerStats(context.Context) (map[uuid.UUID]storiface.WorkerStats, error)
|
||||
WorkerJobs(context.Context) (map[uuid.UUID][]storiface.WorkerJob, error)
|
||||
storiface.WorkerReturn
|
||||
|
||||
// SealingSchedDiag dumps internal sealing scheduler state
|
||||
SealingSchedDiag(context.Context) (interface{}, error)
|
||||
SealingSchedDiag(ctx context.Context, doSched bool) (interface{}, error)
|
||||
SealingAbort(ctx context.Context, call storiface.CallID) error
|
||||
|
||||
stores.SectorIndex
|
||||
|
||||
@@ -81,6 +106,12 @@ type StorageMiner interface {
|
||||
MarketGetRetrievalAsk(ctx context.Context) (*retrievalmarket.Ask, error)
|
||||
MarketListDataTransfers(ctx context.Context) ([]DataTransferChannel, error)
|
||||
MarketDataTransferUpdates(ctx context.Context) (<-chan DataTransferChannel, error)
|
||||
// MarketRestartDataTransfer attempts to restart a data transfer with the given transfer ID and other peer
|
||||
MarketRestartDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error
|
||||
// MarketCancelDataTransfer cancels a data transfer with the given transfer ID and other peer
|
||||
MarketCancelDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error
|
||||
MarketPendingDeals(ctx context.Context) (PendingDealInfo, error)
|
||||
MarketPublishPendingDeals(ctx context.Context) error
|
||||
|
||||
DealsImportData(ctx context.Context, dealPropCid cid.Cid, file string) error
|
||||
DealsList(ctx context.Context) ([]MarketDeal, error)
|
||||
@@ -94,6 +125,10 @@ type StorageMiner interface {
|
||||
DealsSetConsiderOfflineStorageDeals(context.Context, bool) error
|
||||
DealsConsiderOfflineRetrievalDeals(context.Context) (bool, error)
|
||||
DealsSetConsiderOfflineRetrievalDeals(context.Context, bool) error
|
||||
DealsConsiderVerifiedStorageDeals(context.Context) (bool, error)
|
||||
DealsSetConsiderVerifiedStorageDeals(context.Context, bool) error
|
||||
DealsConsiderUnverifiedStorageDeals(context.Context) (bool, error)
|
||||
DealsSetConsiderUnverifiedStorageDeals(context.Context, bool) error
|
||||
|
||||
StorageAddLocal(ctx context.Context, path string) error
|
||||
|
||||
@@ -107,6 +142,8 @@ type StorageMiner interface {
|
||||
// LOTUS_BACKUP_BASE_PATH environment variable set to some path, and that
|
||||
// the path specified when calling CreateBackup is within the base path
|
||||
CreateBackup(ctx context.Context, fpath string) error
|
||||
|
||||
CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, sectors []storage.SectorRef, expensive bool) (map[abi.SectorNumber]string, error)
|
||||
}
|
||||
|
||||
type SealRes struct {
|
||||
@@ -186,3 +223,30 @@ func (st *SealSeed) Equals(ost *SealSeed) bool {
|
||||
}
|
||||
|
||||
type SectorState string
|
||||
|
||||
type AddrUse int
|
||||
|
||||
const (
|
||||
PreCommitAddr AddrUse = iota
|
||||
CommitAddr
|
||||
PoStAddr
|
||||
|
||||
TerminateSectorsAddr
|
||||
)
|
||||
|
||||
type AddressConfig struct {
|
||||
PreCommitControl []address.Address
|
||||
CommitControl []address.Address
|
||||
TerminateControl []address.Address
|
||||
|
||||
DisableOwnerFallback bool
|
||||
DisableWorkerFallback bool
|
||||
}
|
||||
|
||||
// PendingDealInfo has info about pending deals and when they are due to be
|
||||
// published
|
||||
type PendingDealInfo struct {
|
||||
Deals []market.ClientDealProposal
|
||||
PublishPeriodStart time.Time
|
||||
PublishPeriod time.Duration
|
||||
}
|
||||
|
||||
+21
-14
@@ -2,39 +2,46 @@ package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/google/uuid"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/sealtasks"
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/stores"
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/storiface"
|
||||
"github.com/filecoin-project/specs-storage/storage"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
)
|
||||
|
||||
type WorkerAPI interface {
|
||||
Version(context.Context) (build.Version, error)
|
||||
Version(context.Context) (Version, error)
|
||||
// TODO: Info() (name, ...) ?
|
||||
|
||||
TaskTypes(context.Context) (map[sealtasks.TaskType]struct{}, error) // TaskType -> Weight
|
||||
Paths(context.Context) ([]stores.StoragePath, error)
|
||||
Info(context.Context) (storiface.WorkerInfo, error)
|
||||
|
||||
AddPiece(ctx context.Context, sector abi.SectorID, pieceSizes []abi.UnpaddedPieceSize, newPieceSize abi.UnpaddedPieceSize, pieceData storage.Data) (abi.PieceInfo, error)
|
||||
storiface.WorkerCalls
|
||||
|
||||
storage.Sealer
|
||||
TaskDisable(ctx context.Context, tt sealtasks.TaskType) error
|
||||
TaskEnable(ctx context.Context, tt sealtasks.TaskType) error
|
||||
|
||||
MoveStorage(ctx context.Context, sector abi.SectorID, types stores.SectorFileType) error
|
||||
|
||||
UnsealPiece(context.Context, abi.SectorID, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize, abi.SealRandomness, cid.Cid) error
|
||||
ReadPiece(context.Context, io.Writer, abi.SectorID, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize) (bool, error)
|
||||
// Storage / Other
|
||||
Remove(ctx context.Context, sector abi.SectorID) error
|
||||
|
||||
StorageAddLocal(ctx context.Context, path string) error
|
||||
|
||||
Fetch(context.Context, abi.SectorID, stores.SectorFileType, stores.PathType, stores.AcquireMode) error
|
||||
// SetEnabled marks the worker as enabled/disabled. Not that this setting
|
||||
// may take a few seconds to propagate to task scheduler
|
||||
SetEnabled(ctx context.Context, enabled bool) error
|
||||
|
||||
Closing(context.Context) (<-chan struct{}, error)
|
||||
Enabled(ctx context.Context) (bool, error)
|
||||
|
||||
// WaitQuiet blocks until there are no tasks running
|
||||
WaitQuiet(ctx context.Context) error
|
||||
|
||||
// returns a random UUID of worker session, generated randomly when worker
|
||||
// process starts
|
||||
ProcessSession(context.Context) (uuid.UUID, error)
|
||||
|
||||
// Like ProcessSession, but returns an error when worker is disabled
|
||||
Session(context.Context) (uuid.UUID, error)
|
||||
}
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
package apibstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
blocks "github.com/ipfs/go-block-format"
|
||||
"github.com/ipfs/go-cid"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/lib/blockstore"
|
||||
)
|
||||
|
||||
type ChainIO interface {
|
||||
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
|
||||
ChainHasObj(context.Context, cid.Cid) (bool, error)
|
||||
}
|
||||
|
||||
type apiBStore struct {
|
||||
api ChainIO
|
||||
}
|
||||
|
||||
func NewAPIBlockstore(cio ChainIO) blockstore.Blockstore {
|
||||
return &apiBStore{
|
||||
api: cio,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *apiBStore) DeleteBlock(cid.Cid) error {
|
||||
return xerrors.New("not supported")
|
||||
}
|
||||
|
||||
func (a *apiBStore) Has(c cid.Cid) (bool, error) {
|
||||
return a.api.ChainHasObj(context.TODO(), c)
|
||||
}
|
||||
|
||||
func (a *apiBStore) Get(c cid.Cid) (blocks.Block, error) {
|
||||
bb, err := a.api.ChainReadObj(context.TODO(), c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return blocks.NewBlockWithCid(bb, c)
|
||||
}
|
||||
|
||||
func (a *apiBStore) GetSize(c cid.Cid) (int, error) {
|
||||
bb, err := a.api.ChainReadObj(context.TODO(), c)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return len(bb), nil
|
||||
}
|
||||
|
||||
func (a *apiBStore) Put(blocks.Block) error {
|
||||
return xerrors.New("not supported")
|
||||
}
|
||||
|
||||
func (a *apiBStore) PutMany([]blocks.Block) error {
|
||||
return xerrors.New("not supported")
|
||||
}
|
||||
|
||||
func (a *apiBStore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
|
||||
return nil, xerrors.New("not supported")
|
||||
}
|
||||
|
||||
func (a *apiBStore) HashOnRead(enabled bool) {
|
||||
return
|
||||
}
|
||||
|
||||
var _ blockstore.Blockstore = &apiBStore{}
|
||||
+458
-109
@@ -5,8 +5,7 @@ import (
|
||||
"io"
|
||||
"time"
|
||||
|
||||
stnetwork "github.com/filecoin-project/go-state-types/network"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/ipfs/go-cid"
|
||||
metrics "github.com/libp2p/go-libp2p-core/metrics"
|
||||
"github.com/libp2p/go-libp2p-core/network"
|
||||
@@ -25,6 +24,7 @@ import (
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
"github.com/filecoin-project/go-state-types/dline"
|
||||
stnetwork "github.com/filecoin-project/go-state-types/network"
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/fsutil"
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/sealtasks"
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/stores"
|
||||
@@ -33,7 +33,6 @@ import (
|
||||
"github.com/filecoin-project/specs-storage/storage"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
@@ -60,14 +59,19 @@ type CommonStruct struct {
|
||||
NetBandwidthStatsByPeer func(ctx context.Context) (map[string]metrics.Stats, error) `perm:"read"`
|
||||
NetBandwidthStatsByProtocol func(ctx context.Context) (map[protocol.ID]metrics.Stats, error) `perm:"read"`
|
||||
NetAgentVersion func(ctx context.Context, p peer.ID) (string, error) `perm:"read"`
|
||||
NetPeerInfo func(context.Context, peer.ID) (*api.ExtendedPeerInfo, error) `perm:"read"`
|
||||
NetBlockAdd func(ctx context.Context, acl api.NetBlockList) error `perm:"admin"`
|
||||
NetBlockRemove func(ctx context.Context, acl api.NetBlockList) error `perm:"admin"`
|
||||
NetBlockList func(ctx context.Context) (api.NetBlockList, error) `perm:"read"`
|
||||
|
||||
ID func(context.Context) (peer.ID, error) `perm:"read"`
|
||||
Version func(context.Context) (api.Version, error) `perm:"read"`
|
||||
ID func(context.Context) (peer.ID, error) `perm:"read"`
|
||||
Version func(context.Context) (api.APIVersion, error) `perm:"read"`
|
||||
|
||||
LogList func(context.Context) ([]string, error) `perm:"write"`
|
||||
LogSetLevel func(context.Context, string, string) error `perm:"write"`
|
||||
|
||||
Shutdown func(context.Context) error `perm:"admin"`
|
||||
Session func(context.Context) (uuid.UUID, error) `perm:"read"`
|
||||
Closing func(context.Context) (<-chan struct{}, error) `perm:"read"`
|
||||
}
|
||||
}
|
||||
@@ -131,6 +135,10 @@ type FullNodeStruct struct {
|
||||
MpoolGetNonce func(context.Context, address.Address) (uint64, error) `perm:"read"`
|
||||
MpoolSub func(context.Context) (<-chan api.MpoolUpdate, error) `perm:"read"`
|
||||
|
||||
MpoolBatchPush func(ctx context.Context, smsgs []*types.SignedMessage) ([]cid.Cid, error) `perm:"write"`
|
||||
MpoolBatchPushUntrusted func(ctx context.Context, smsgs []*types.SignedMessage) ([]cid.Cid, error) `perm:"write"`
|
||||
MpoolBatchPushMessage func(ctx context.Context, msgs []*types.Message, spec *api.MessageSendSpec) ([]*types.SignedMessage, error) `perm:"sign"`
|
||||
|
||||
MinerGetBaseInfo func(context.Context, address.Address, abi.ChainEpoch, types.TipSetKey) (*api.MiningBaseInfo, error) `perm:"read"`
|
||||
MinerCreateBlock func(context.Context, *api.BlockTemplate) (*types.BlockMsg, error) `perm:"write"`
|
||||
|
||||
@@ -156,17 +164,20 @@ type FullNodeStruct struct {
|
||||
ClientMinerQueryOffer func(ctx context.Context, miner address.Address, root cid.Cid, piece *cid.Cid) (api.QueryOffer, error) `perm:"read"`
|
||||
ClientStartDeal func(ctx context.Context, params *api.StartDealParams) (*cid.Cid, error) `perm:"admin"`
|
||||
ClientGetDealInfo func(context.Context, cid.Cid) (*api.DealInfo, error) `perm:"read"`
|
||||
ClientGetDealStatus func(context.Context, uint64) (string, error) `perm:"read"`
|
||||
ClientListDeals func(ctx context.Context) ([]api.DealInfo, error) `perm:"write"`
|
||||
ClientGetDealUpdates func(ctx context.Context) (<-chan api.DealInfo, error) `perm:"read"`
|
||||
ClientRetrieve func(ctx context.Context, order api.RetrievalOrder, ref *api.FileRef) error `perm:"admin"`
|
||||
ClientRetrieveWithEvents func(ctx context.Context, order api.RetrievalOrder, ref *api.FileRef) (<-chan marketevents.RetrievalEvent, error) `perm:"admin"`
|
||||
ClientQueryAsk func(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.StorageAsk, error) `perm:"read"`
|
||||
ClientDealPieceCID func(ctx context.Context, root cid.Cid) (api.DataCIDSize, error) `perm:"read"`
|
||||
ClientCalcCommP func(ctx context.Context, inpath string) (*api.CommPRet, error) `perm:"read"`
|
||||
ClientGenCar func(ctx context.Context, ref api.FileRef, outpath string) error `perm:"write"`
|
||||
ClientDealSize func(ctx context.Context, root cid.Cid) (api.DataSize, error) `perm:"read"`
|
||||
ClientListDataTransfers func(ctx context.Context) ([]api.DataTransferChannel, error) `perm:"write"`
|
||||
ClientDataTransferUpdates func(ctx context.Context) (<-chan api.DataTransferChannel, error) `perm:"write"`
|
||||
ClientRestartDataTransfer func(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error `perm:"write"`
|
||||
ClientCancelDataTransfer func(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error `perm:"write"`
|
||||
ClientRetrieveTryRestartInsufficientFunds func(ctx context.Context, paymentChannel address.Address) error `perm:"write"`
|
||||
|
||||
StateNetworkName func(context.Context) (dtypes.NetworkName, error) `perm:"read"`
|
||||
@@ -183,6 +194,7 @@ type FullNodeStruct struct {
|
||||
StateMinerPreCommitDepositForPower func(context.Context, address.Address, miner.SectorPreCommitInfo, types.TipSetKey) (types.BigInt, error) `perm:"read"`
|
||||
StateMinerInitialPledgeCollateral func(context.Context, address.Address, miner.SectorPreCommitInfo, types.TipSetKey) (types.BigInt, error) `perm:"read"`
|
||||
StateMinerAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"`
|
||||
StateMinerSectorAllocated func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (bool, error) `perm:"read"`
|
||||
StateSectorPreCommitInfo func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error) `perm:"read"`
|
||||
StateSectorGetInfo func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorOnChainInfo, error) `perm:"read"`
|
||||
StateSectorExpiration func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorExpiration, error) `perm:"read"`
|
||||
@@ -194,6 +206,7 @@ type FullNodeStruct struct {
|
||||
StateWaitMsg func(ctx context.Context, cid cid.Cid, confidence uint64) (*api.MsgLookup, error) `perm:"read"`
|
||||
StateWaitMsgLimited func(context.Context, cid.Cid, uint64, abi.ChainEpoch) (*api.MsgLookup, error) `perm:"read"`
|
||||
StateSearchMsg func(context.Context, cid.Cid) (*api.MsgLookup, error) `perm:"read"`
|
||||
StateSearchMsgLimited func(context.Context, cid.Cid, abi.ChainEpoch) (*api.MsgLookup, error) `perm:"read"`
|
||||
StateListMiners func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"`
|
||||
StateListActors func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"`
|
||||
StateMarketBalance func(context.Context, address.Address, types.TipSetKey) (api.MarketBalance, error) `perm:"read"`
|
||||
@@ -206,6 +219,7 @@ type FullNodeStruct struct {
|
||||
StateGetReceipt func(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error) `perm:"read"`
|
||||
StateMinerSectorCount func(context.Context, address.Address, types.TipSetKey) (api.MinerSectors, error) `perm:"read"`
|
||||
StateListMessages func(ctx context.Context, match *api.MessageMatch, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) `perm:"read"`
|
||||
StateDecodeParams func(context.Context, address.Address, abi.MethodNum, []byte, types.TipSetKey) (interface{}, error) `perm:"read"`
|
||||
StateCompute func(context.Context, abi.ChainEpoch, []*types.Message, types.TipSetKey) (*api.ComputeStateOutput, error) `perm:"read"`
|
||||
StateVerifierStatus func(context.Context, address.Address, types.TipSetKey) (*abi.StoragePower, error) `perm:"read"`
|
||||
StateVerifiedClientStatus func(context.Context, address.Address, types.TipSetKey) (*abi.StoragePower, error) `perm:"read"`
|
||||
@@ -218,6 +232,7 @@ type FullNodeStruct struct {
|
||||
MsigGetAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"`
|
||||
MsigGetVestingSchedule func(context.Context, address.Address, types.TipSetKey) (api.MsigVesting, error) `perm:"read"`
|
||||
MsigGetVested func(context.Context, address.Address, types.TipSetKey, types.TipSetKey) (types.BigInt, error) `perm:"read"`
|
||||
MsigGetPending func(context.Context, address.Address, types.TipSetKey) ([]*api.MsigTransaction, error) `perm:"read"`
|
||||
MsigCreate func(context.Context, uint64, []address.Address, abi.ChainEpoch, types.BigInt, address.Address, types.BigInt) (cid.Cid, error) `perm:"sign"`
|
||||
MsigPropose func(context.Context, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) `perm:"sign"`
|
||||
MsigApprove func(context.Context, address.Address, uint64, address.Address) (cid.Cid, error) `perm:"sign"`
|
||||
@@ -231,7 +246,11 @@ type FullNodeStruct struct {
|
||||
MsigSwapCancel func(context.Context, address.Address, address.Address, uint64, address.Address, address.Address) (cid.Cid, error) `perm:"sign"`
|
||||
MsigRemoveSigner func(ctx context.Context, msig address.Address, proposer address.Address, toRemove address.Address, decrease bool) (cid.Cid, error) `perm:"sign"`
|
||||
|
||||
MarketEnsureAvailable func(context.Context, address.Address, address.Address, types.BigInt) (cid.Cid, error) `perm:"sign"`
|
||||
MarketAddBalance func(ctx context.Context, wallet, addr address.Address, amt types.BigInt) (cid.Cid, error) `perm:"sign"`
|
||||
MarketGetReserved func(ctx context.Context, addr address.Address) (types.BigInt, error) `perm:"sign"`
|
||||
MarketReserveFunds func(ctx context.Context, wallet address.Address, addr address.Address, amt types.BigInt) (cid.Cid, error) `perm:"sign"`
|
||||
MarketReleaseFunds func(ctx context.Context, addr address.Address, amt types.BigInt) error `perm:"sign"`
|
||||
MarketWithdraw func(ctx context.Context, wallet, addr address.Address, amt types.BigInt) (cid.Cid, error) `perm:"sign"`
|
||||
|
||||
PaychGet func(ctx context.Context, from, to address.Address, amt types.BigInt) (*api.ChannelInfo, error) `perm:"sign"`
|
||||
PaychGetWaitReady func(context.Context, cid.Cid) (address.Address, error) `perm:"sign"`
|
||||
@@ -263,8 +282,9 @@ type StorageMinerStruct struct {
|
||||
CommonStruct
|
||||
|
||||
Internal struct {
|
||||
ActorAddress func(context.Context) (address.Address, error) `perm:"read"`
|
||||
ActorSectorSize func(context.Context, address.Address) (abi.SectorSize, error) `perm:"read"`
|
||||
ActorAddress func(context.Context) (address.Address, error) `perm:"read"`
|
||||
ActorSectorSize func(context.Context, address.Address) (abi.SectorSize, error) `perm:"read"`
|
||||
ActorAddressConfig func(ctx context.Context) (api.AddressConfig, error) `perm:"read"`
|
||||
|
||||
MiningBase func(context.Context) (*types.TipSet, error) `perm:"read"`
|
||||
|
||||
@@ -279,11 +299,17 @@ type StorageMinerStruct struct {
|
||||
MarketGetRetrievalAsk func(ctx context.Context) (*retrievalmarket.Ask, error) `perm:"read"`
|
||||
MarketListDataTransfers func(ctx context.Context) ([]api.DataTransferChannel, error) `perm:"write"`
|
||||
MarketDataTransferUpdates func(ctx context.Context) (<-chan api.DataTransferChannel, error) `perm:"write"`
|
||||
MarketRestartDataTransfer func(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error `perm:"write"`
|
||||
MarketCancelDataTransfer func(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error `perm:"write"`
|
||||
MarketPendingDeals func(ctx context.Context) (api.PendingDealInfo, error) `perm:"write"`
|
||||
MarketPublishPendingDeals func(ctx context.Context) error `perm:"admin"`
|
||||
|
||||
PledgeSector func(context.Context) error `perm:"write"`
|
||||
PledgeSector func(context.Context) (abi.SectorID, error) `perm:"write"`
|
||||
|
||||
SectorsStatus func(ctx context.Context, sid abi.SectorNumber, showOnChainInfo bool) (api.SectorInfo, error) `perm:"read"`
|
||||
SectorsList func(context.Context) ([]abi.SectorNumber, error) `perm:"read"`
|
||||
SectorsListInStates func(context.Context, []api.SectorState) ([]abi.SectorNumber, error) `perm:"read"`
|
||||
SectorsSummary func(ctx context.Context) (map[api.SectorState]int, error) `perm:"read"`
|
||||
SectorsRefs func(context.Context) (map[string][]api.SealedRef, error) `perm:"read"`
|
||||
SectorStartSealing func(context.Context, abi.SectorNumber) error `perm:"write"`
|
||||
SectorSetSealDelay func(context.Context, time.Duration) error `perm:"write"`
|
||||
@@ -292,39 +318,59 @@ type StorageMinerStruct struct {
|
||||
SectorGetExpectedSealDuration func(context.Context) (time.Duration, error) `perm:"read"`
|
||||
SectorsUpdate func(context.Context, abi.SectorNumber, api.SectorState) error `perm:"admin"`
|
||||
SectorRemove func(context.Context, abi.SectorNumber) error `perm:"admin"`
|
||||
SectorTerminate func(context.Context, abi.SectorNumber) error `perm:"admin"`
|
||||
SectorTerminateFlush func(ctx context.Context) (*cid.Cid, error) `perm:"admin"`
|
||||
SectorTerminatePending func(ctx context.Context) ([]abi.SectorID, error) `perm:"admin"`
|
||||
SectorMarkForUpgrade func(ctx context.Context, id abi.SectorNumber) error `perm:"admin"`
|
||||
|
||||
WorkerConnect func(context.Context, string) error `perm:"admin"` // TODO: worker perm
|
||||
WorkerStats func(context.Context) (map[uint64]storiface.WorkerStats, error) `perm:"admin"`
|
||||
WorkerJobs func(context.Context) (map[uint64][]storiface.WorkerJob, error) `perm:"admin"`
|
||||
WorkerConnect func(context.Context, string) error `perm:"admin" retry:"true"` // TODO: worker perm
|
||||
WorkerStats func(context.Context) (map[uuid.UUID]storiface.WorkerStats, error) `perm:"admin"`
|
||||
WorkerJobs func(context.Context) (map[uuid.UUID][]storiface.WorkerJob, error) `perm:"admin"`
|
||||
|
||||
SealingSchedDiag func(context.Context) (interface{}, error) `perm:"admin"`
|
||||
ReturnAddPiece func(ctx context.Context, callID storiface.CallID, pi abi.PieceInfo, err *storiface.CallError) error `perm:"admin" retry:"true"`
|
||||
ReturnSealPreCommit1 func(ctx context.Context, callID storiface.CallID, p1o storage.PreCommit1Out, err *storiface.CallError) error `perm:"admin" retry:"true"`
|
||||
ReturnSealPreCommit2 func(ctx context.Context, callID storiface.CallID, sealed storage.SectorCids, err *storiface.CallError) error `perm:"admin" retry:"true"`
|
||||
ReturnSealCommit1 func(ctx context.Context, callID storiface.CallID, out storage.Commit1Out, err *storiface.CallError) error `perm:"admin" retry:"true"`
|
||||
ReturnSealCommit2 func(ctx context.Context, callID storiface.CallID, proof storage.Proof, err *storiface.CallError) error `perm:"admin" retry:"true"`
|
||||
ReturnFinalizeSector func(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error `perm:"admin" retry:"true"`
|
||||
ReturnReleaseUnsealed func(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error `perm:"admin" retry:"true"`
|
||||
ReturnMoveStorage func(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error `perm:"admin" retry:"true"`
|
||||
ReturnUnsealPiece func(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error `perm:"admin" retry:"true"`
|
||||
ReturnReadPiece func(ctx context.Context, callID storiface.CallID, ok bool, err *storiface.CallError) error `perm:"admin" retry:"true"`
|
||||
ReturnFetch func(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error `perm:"admin" retry:"true"`
|
||||
|
||||
StorageList func(context.Context) (map[stores.ID][]stores.Decl, error) `perm:"admin"`
|
||||
StorageLocal func(context.Context) (map[stores.ID]string, error) `perm:"admin"`
|
||||
StorageStat func(context.Context, stores.ID) (fsutil.FsStat, error) `perm:"admin"`
|
||||
StorageAttach func(context.Context, stores.StorageInfo, fsutil.FsStat) error `perm:"admin"`
|
||||
StorageDeclareSector func(context.Context, stores.ID, abi.SectorID, stores.SectorFileType, bool) error `perm:"admin"`
|
||||
StorageDropSector func(context.Context, stores.ID, abi.SectorID, stores.SectorFileType) error `perm:"admin"`
|
||||
StorageFindSector func(context.Context, abi.SectorID, stores.SectorFileType, abi.RegisteredSealProof, bool) ([]stores.SectorStorageInfo, error) `perm:"admin"`
|
||||
StorageInfo func(context.Context, stores.ID) (stores.StorageInfo, error) `perm:"admin"`
|
||||
StorageBestAlloc func(ctx context.Context, allocate stores.SectorFileType, spt abi.RegisteredSealProof, sealing stores.PathType) ([]stores.StorageInfo, error) `perm:"admin"`
|
||||
StorageReportHealth func(ctx context.Context, id stores.ID, report stores.HealthReport) error `perm:"admin"`
|
||||
StorageLock func(ctx context.Context, sector abi.SectorID, read stores.SectorFileType, write stores.SectorFileType) error `perm:"admin"`
|
||||
StorageTryLock func(ctx context.Context, sector abi.SectorID, read stores.SectorFileType, write stores.SectorFileType) (bool, error) `perm:"admin"`
|
||||
SealingSchedDiag func(context.Context, bool) (interface{}, error) `perm:"admin"`
|
||||
SealingAbort func(ctx context.Context, call storiface.CallID) error `perm:"admin"`
|
||||
|
||||
DealsImportData func(ctx context.Context, dealPropCid cid.Cid, file string) error `perm:"write"`
|
||||
DealsList func(ctx context.Context) ([]api.MarketDeal, error) `perm:"read"`
|
||||
DealsConsiderOnlineStorageDeals func(context.Context) (bool, error) `perm:"read"`
|
||||
DealsSetConsiderOnlineStorageDeals func(context.Context, bool) error `perm:"admin"`
|
||||
DealsConsiderOnlineRetrievalDeals func(context.Context) (bool, error) `perm:"read"`
|
||||
DealsSetConsiderOnlineRetrievalDeals func(context.Context, bool) error `perm:"admin"`
|
||||
DealsConsiderOfflineStorageDeals func(context.Context) (bool, error) `perm:"read"`
|
||||
DealsSetConsiderOfflineStorageDeals func(context.Context, bool) error `perm:"admin"`
|
||||
DealsConsiderOfflineRetrievalDeals func(context.Context) (bool, error) `perm:"read"`
|
||||
DealsSetConsiderOfflineRetrievalDeals func(context.Context, bool) error `perm:"admin"`
|
||||
DealsPieceCidBlocklist func(context.Context) ([]cid.Cid, error) `perm:"read"`
|
||||
DealsSetPieceCidBlocklist func(context.Context, []cid.Cid) error `perm:"admin"`
|
||||
StorageList func(context.Context) (map[stores.ID][]stores.Decl, error) `perm:"admin"`
|
||||
StorageLocal func(context.Context) (map[stores.ID]string, error) `perm:"admin"`
|
||||
StorageStat func(context.Context, stores.ID) (fsutil.FsStat, error) `perm:"admin"`
|
||||
StorageAttach func(context.Context, stores.StorageInfo, fsutil.FsStat) error `perm:"admin"`
|
||||
StorageDeclareSector func(context.Context, stores.ID, abi.SectorID, storiface.SectorFileType, bool) error `perm:"admin"`
|
||||
StorageDropSector func(context.Context, stores.ID, abi.SectorID, storiface.SectorFileType) error `perm:"admin"`
|
||||
StorageFindSector func(context.Context, abi.SectorID, storiface.SectorFileType, abi.SectorSize, bool) ([]stores.SectorStorageInfo, error) `perm:"admin"`
|
||||
StorageInfo func(context.Context, stores.ID) (stores.StorageInfo, error) `perm:"admin"`
|
||||
StorageBestAlloc func(ctx context.Context, allocate storiface.SectorFileType, ssize abi.SectorSize, sealing storiface.PathType) ([]stores.StorageInfo, error) `perm:"admin"`
|
||||
StorageReportHealth func(ctx context.Context, id stores.ID, report stores.HealthReport) error `perm:"admin"`
|
||||
StorageLock func(ctx context.Context, sector abi.SectorID, read storiface.SectorFileType, write storiface.SectorFileType) error `perm:"admin"`
|
||||
StorageTryLock func(ctx context.Context, sector abi.SectorID, read storiface.SectorFileType, write storiface.SectorFileType) (bool, error) `perm:"admin"`
|
||||
|
||||
DealsImportData func(ctx context.Context, dealPropCid cid.Cid, file string) error `perm:"write"`
|
||||
DealsList func(ctx context.Context) ([]api.MarketDeal, error) `perm:"read"`
|
||||
DealsConsiderOnlineStorageDeals func(context.Context) (bool, error) `perm:"read"`
|
||||
DealsSetConsiderOnlineStorageDeals func(context.Context, bool) error `perm:"admin"`
|
||||
DealsConsiderOnlineRetrievalDeals func(context.Context) (bool, error) `perm:"read"`
|
||||
DealsSetConsiderOnlineRetrievalDeals func(context.Context, bool) error `perm:"admin"`
|
||||
DealsConsiderOfflineStorageDeals func(context.Context) (bool, error) `perm:"read"`
|
||||
DealsSetConsiderOfflineStorageDeals func(context.Context, bool) error `perm:"admin"`
|
||||
DealsConsiderOfflineRetrievalDeals func(context.Context) (bool, error) `perm:"read"`
|
||||
DealsSetConsiderOfflineRetrievalDeals func(context.Context, bool) error `perm:"admin"`
|
||||
DealsConsiderVerifiedStorageDeals func(context.Context) (bool, error) `perm:"read"`
|
||||
DealsSetConsiderVerifiedStorageDeals func(context.Context, bool) error `perm:"admin"`
|
||||
DealsConsiderUnverifiedStorageDeals func(context.Context) (bool, error) `perm:"read"`
|
||||
DealsSetConsiderUnverifiedStorageDeals func(context.Context, bool) error `perm:"admin"`
|
||||
DealsPieceCidBlocklist func(context.Context) ([]cid.Cid, error) `perm:"read"`
|
||||
DealsSetPieceCidBlocklist func(context.Context, []cid.Cid) error `perm:"admin"`
|
||||
|
||||
StorageAddLocal func(ctx context.Context, path string) error `perm:"admin"`
|
||||
|
||||
@@ -334,6 +380,8 @@ type StorageMinerStruct struct {
|
||||
PiecesGetCIDInfo func(ctx context.Context, payloadCid cid.Cid) (*piecestore.CIDInfo, error) `perm:"read"`
|
||||
|
||||
CreateBackup func(ctx context.Context, fpath string) error `perm:"admin"`
|
||||
|
||||
CheckProvable func(ctx context.Context, pp abi.RegisteredPoStProof, sectors []storage.SectorRef, expensive bool) (map[abi.SectorNumber]string, error) `perm:"admin"`
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,48 +389,72 @@ type WorkerStruct struct {
|
||||
Internal struct {
|
||||
// TODO: lower perms
|
||||
|
||||
Version func(context.Context) (build.Version, error) `perm:"admin"`
|
||||
Version func(context.Context) (api.Version, error) `perm:"admin"`
|
||||
|
||||
TaskTypes func(context.Context) (map[sealtasks.TaskType]struct{}, error) `perm:"admin"`
|
||||
Paths func(context.Context) ([]stores.StoragePath, error) `perm:"admin"`
|
||||
Info func(context.Context) (storiface.WorkerInfo, error) `perm:"admin"`
|
||||
|
||||
AddPiece func(ctx context.Context, sector abi.SectorID, pieceSizes []abi.UnpaddedPieceSize, newPieceSize abi.UnpaddedPieceSize, pieceData storage.Data) (abi.PieceInfo, error) `perm:"admin"`
|
||||
SealPreCommit1 func(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storage.PreCommit1Out, error) `perm:"admin"`
|
||||
SealPreCommit2 func(context.Context, abi.SectorID, storage.PreCommit1Out) (cids storage.SectorCids, err error) `perm:"admin"`
|
||||
SealCommit1 func(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (storage.Commit1Out, error) `perm:"admin"`
|
||||
SealCommit2 func(context.Context, abi.SectorID, storage.Commit1Out) (storage.Proof, error) `perm:"admin"`
|
||||
FinalizeSector func(context.Context, abi.SectorID, []storage.Range) error `perm:"admin"`
|
||||
ReleaseUnsealed func(ctx context.Context, sector abi.SectorID, safeToFree []storage.Range) error `perm:"admin"`
|
||||
Remove func(ctx context.Context, sector abi.SectorID) error `perm:"admin"`
|
||||
MoveStorage func(ctx context.Context, sector abi.SectorID, types stores.SectorFileType) error `perm:"admin"`
|
||||
StorageAddLocal func(ctx context.Context, path string) error `perm:"admin"`
|
||||
AddPiece func(ctx context.Context, sector storage.SectorRef, pieceSizes []abi.UnpaddedPieceSize, newPieceSize abi.UnpaddedPieceSize, pieceData storage.Data) (storiface.CallID, error) `perm:"admin"`
|
||||
SealPreCommit1 func(ctx context.Context, sector storage.SectorRef, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storiface.CallID, error) `perm:"admin"`
|
||||
SealPreCommit2 func(ctx context.Context, sector storage.SectorRef, pc1o storage.PreCommit1Out) (storiface.CallID, error) `perm:"admin"`
|
||||
SealCommit1 func(ctx context.Context, sector storage.SectorRef, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (storiface.CallID, error) `perm:"admin"`
|
||||
SealCommit2 func(ctx context.Context, sector storage.SectorRef, c1o storage.Commit1Out) (storiface.CallID, error) `perm:"admin"`
|
||||
FinalizeSector func(ctx context.Context, sector storage.SectorRef, keepUnsealed []storage.Range) (storiface.CallID, error) `perm:"admin"`
|
||||
ReleaseUnsealed func(ctx context.Context, sector storage.SectorRef, safeToFree []storage.Range) (storiface.CallID, error) `perm:"admin"`
|
||||
MoveStorage func(ctx context.Context, sector storage.SectorRef, types storiface.SectorFileType) (storiface.CallID, error) `perm:"admin"`
|
||||
UnsealPiece func(context.Context, storage.SectorRef, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize, abi.SealRandomness, cid.Cid) (storiface.CallID, error) `perm:"admin"`
|
||||
ReadPiece func(context.Context, io.Writer, storage.SectorRef, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize) (storiface.CallID, error) `perm:"admin"`
|
||||
Fetch func(context.Context, storage.SectorRef, storiface.SectorFileType, storiface.PathType, storiface.AcquireMode) (storiface.CallID, error) `perm:"admin"`
|
||||
|
||||
UnsealPiece func(context.Context, abi.SectorID, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize, abi.SealRandomness, cid.Cid) error `perm:"admin"`
|
||||
ReadPiece func(context.Context, io.Writer, abi.SectorID, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize) (bool, error) `perm:"admin"`
|
||||
TaskDisable func(ctx context.Context, tt sealtasks.TaskType) error `perm:"admin"`
|
||||
TaskEnable func(ctx context.Context, tt sealtasks.TaskType) error `perm:"admin"`
|
||||
|
||||
Fetch func(context.Context, abi.SectorID, stores.SectorFileType, stores.PathType, stores.AcquireMode) error `perm:"admin"`
|
||||
Remove func(ctx context.Context, sector abi.SectorID) error `perm:"admin"`
|
||||
StorageAddLocal func(ctx context.Context, path string) error `perm:"admin"`
|
||||
|
||||
Closing func(context.Context) (<-chan struct{}, error) `perm:"admin"`
|
||||
SetEnabled func(ctx context.Context, enabled bool) error `perm:"admin"`
|
||||
Enabled func(ctx context.Context) (bool, error) `perm:"admin"`
|
||||
|
||||
WaitQuiet func(ctx context.Context) error `perm:"admin"`
|
||||
|
||||
ProcessSession func(context.Context) (uuid.UUID, error) `perm:"admin"`
|
||||
Session func(context.Context) (uuid.UUID, error) `perm:"admin"`
|
||||
}
|
||||
}
|
||||
|
||||
type GatewayStruct struct {
|
||||
Internal struct {
|
||||
// TODO: does the gateway need perms?
|
||||
ChainHasObj func(context.Context, cid.Cid) (bool, error)
|
||||
ChainGetTipSet func(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
|
||||
ChainGetTipSetByHeight func(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
|
||||
ChainHead func(ctx context.Context) (*types.TipSet, error)
|
||||
ChainReadObj func(context.Context, cid.Cid) ([]byte, error)
|
||||
GasEstimateMessageGas func(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
|
||||
MpoolPush func(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
|
||||
MsigGetAvailableBalance func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
|
||||
MsigGetVested func(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error)
|
||||
StateAccountKey func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
||||
StateGetActor func(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
|
||||
StateLookupID func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
||||
StateWaitMsg func(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error)
|
||||
ChainGetBlockMessages func(ctx context.Context, c cid.Cid) (*api.BlockMessages, error)
|
||||
ChainGetMessage func(ctx context.Context, mc cid.Cid) (*types.Message, error)
|
||||
ChainGetTipSet func(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
|
||||
ChainGetTipSetByHeight func(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
|
||||
ChainHasObj func(context.Context, cid.Cid) (bool, error)
|
||||
ChainHead func(ctx context.Context) (*types.TipSet, error)
|
||||
ChainNotify func(ctx context.Context) (<-chan []*api.HeadChange, error)
|
||||
ChainReadObj func(context.Context, cid.Cid) ([]byte, error)
|
||||
GasEstimateMessageGas func(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
|
||||
MpoolPush func(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
|
||||
MsigGetAvailableBalance func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
|
||||
MsigGetVested func(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error)
|
||||
MsigGetPending func(context.Context, address.Address, types.TipSetKey) ([]*api.MsigTransaction, error)
|
||||
StateAccountKey func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
||||
StateDealProviderCollateralBounds func(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error)
|
||||
StateGetActor func(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
|
||||
StateGetReceipt func(ctx context.Context, c cid.Cid, tsk types.TipSetKey) (*types.MessageReceipt, error)
|
||||
StateLookupID func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
||||
StateListMiners func(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error)
|
||||
StateMinerInfo func(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error)
|
||||
StateMinerProvingDeadline func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error)
|
||||
StateMinerPower func(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error)
|
||||
StateMarketBalance func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error)
|
||||
StateMarketStorageDeal func(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error)
|
||||
StateReadState func(context.Context, address.Address, types.TipSetKey) (*api.ActorState, error)
|
||||
StateNetworkVersion func(ctx context.Context, tsk types.TipSetKey) (stnetwork.Version, error)
|
||||
StateSearchMsg func(ctx context.Context, msg cid.Cid) (*api.MsgLookup, error)
|
||||
StateSectorGetInfo func(ctx context.Context, maddr address.Address, n abi.SectorNumber, tsk types.TipSetKey) (*miner.SectorOnChainInfo, error)
|
||||
StateVerifiedClientStatus func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error)
|
||||
StateWaitMsg func(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -452,17 +524,33 @@ func (c *CommonStruct) NetBandwidthStatsByProtocol(ctx context.Context) (map[pro
|
||||
return c.Internal.NetBandwidthStatsByProtocol(ctx)
|
||||
}
|
||||
|
||||
func (c *CommonStruct) NetBlockAdd(ctx context.Context, acl api.NetBlockList) error {
|
||||
return c.Internal.NetBlockAdd(ctx, acl)
|
||||
}
|
||||
|
||||
func (c *CommonStruct) NetBlockRemove(ctx context.Context, acl api.NetBlockList) error {
|
||||
return c.Internal.NetBlockRemove(ctx, acl)
|
||||
}
|
||||
|
||||
func (c *CommonStruct) NetBlockList(ctx context.Context) (api.NetBlockList, error) {
|
||||
return c.Internal.NetBlockList(ctx)
|
||||
}
|
||||
|
||||
func (c *CommonStruct) NetAgentVersion(ctx context.Context, p peer.ID) (string, error) {
|
||||
return c.Internal.NetAgentVersion(ctx, p)
|
||||
}
|
||||
|
||||
func (c *CommonStruct) NetPeerInfo(ctx context.Context, p peer.ID) (*api.ExtendedPeerInfo, error) {
|
||||
return c.Internal.NetPeerInfo(ctx, p)
|
||||
}
|
||||
|
||||
// ID implements API.ID
|
||||
func (c *CommonStruct) ID(ctx context.Context) (peer.ID, error) {
|
||||
return c.Internal.ID(ctx)
|
||||
}
|
||||
|
||||
// Version implements API.Version
|
||||
func (c *CommonStruct) Version(ctx context.Context) (api.Version, error) {
|
||||
func (c *CommonStruct) Version(ctx context.Context) (api.APIVersion, error) {
|
||||
return c.Internal.Version(ctx)
|
||||
}
|
||||
|
||||
@@ -478,6 +566,10 @@ func (c *CommonStruct) Shutdown(ctx context.Context) error {
|
||||
return c.Internal.Shutdown(ctx)
|
||||
}
|
||||
|
||||
func (c *CommonStruct) Session(ctx context.Context) (uuid.UUID, error) {
|
||||
return c.Internal.Session(ctx)
|
||||
}
|
||||
|
||||
func (c *CommonStruct) Closing(ctx context.Context) (<-chan struct{}, error) {
|
||||
return c.Internal.Closing(ctx)
|
||||
}
|
||||
@@ -516,6 +608,10 @@ func (c *FullNodeStruct) ClientGetDealInfo(ctx context.Context, deal cid.Cid) (*
|
||||
return c.Internal.ClientGetDealInfo(ctx, deal)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) ClientGetDealStatus(ctx context.Context, statusCode uint64) (string, error) {
|
||||
return c.Internal.ClientGetDealStatus(ctx, statusCode)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) ClientListDeals(ctx context.Context) ([]api.DealInfo, error) {
|
||||
return c.Internal.ClientListDeals(ctx)
|
||||
}
|
||||
@@ -535,6 +631,11 @@ func (c *FullNodeStruct) ClientRetrieveWithEvents(ctx context.Context, order api
|
||||
func (c *FullNodeStruct) ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.StorageAsk, error) {
|
||||
return c.Internal.ClientQueryAsk(ctx, p, miner)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) ClientDealPieceCID(ctx context.Context, root cid.Cid) (api.DataCIDSize, error) {
|
||||
return c.Internal.ClientDealPieceCID(ctx, root)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) ClientCalcCommP(ctx context.Context, inpath string) (*api.CommPRet, error) {
|
||||
return c.Internal.ClientCalcCommP(ctx, inpath)
|
||||
}
|
||||
@@ -559,6 +660,10 @@ func (c *FullNodeStruct) ClientRestartDataTransfer(ctx context.Context, transfer
|
||||
return c.Internal.ClientRestartDataTransfer(ctx, transferID, otherPeer, isInitiator)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) ClientCancelDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error {
|
||||
return c.Internal.ClientCancelDataTransfer(ctx, transferID, otherPeer, isInitiator)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) ClientRetrieveTryRestartInsufficientFunds(ctx context.Context, paymentChannel address.Address) error {
|
||||
return c.Internal.ClientRetrieveTryRestartInsufficientFunds(ctx, paymentChannel)
|
||||
}
|
||||
@@ -611,6 +716,18 @@ func (c *FullNodeStruct) MpoolPushMessage(ctx context.Context, msg *types.Messag
|
||||
return c.Internal.MpoolPushMessage(ctx, msg, spec)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) MpoolBatchPush(ctx context.Context, smsgs []*types.SignedMessage) ([]cid.Cid, error) {
|
||||
return c.Internal.MpoolBatchPush(ctx, smsgs)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) MpoolBatchPushUntrusted(ctx context.Context, smsgs []*types.SignedMessage) ([]cid.Cid, error) {
|
||||
return c.Internal.MpoolBatchPushUntrusted(ctx, smsgs)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) MpoolBatchPushMessage(ctx context.Context, msgs []*types.Message, spec *api.MessageSendSpec) ([]*types.SignedMessage, error) {
|
||||
return c.Internal.MpoolBatchPushMessage(ctx, msgs, spec)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) MpoolSub(ctx context.Context) (<-chan api.MpoolUpdate, error) {
|
||||
return c.Internal.MpoolSub(ctx)
|
||||
}
|
||||
@@ -859,6 +976,10 @@ func (c *FullNodeStruct) StateMinerAvailableBalance(ctx context.Context, maddr a
|
||||
return c.Internal.StateMinerAvailableBalance(ctx, maddr, tsk)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) StateMinerSectorAllocated(ctx context.Context, maddr address.Address, s abi.SectorNumber, tsk types.TipSetKey) (bool, error) {
|
||||
return c.Internal.StateMinerSectorAllocated(ctx, maddr, s, tsk)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) StateSectorPreCommitInfo(ctx context.Context, maddr address.Address, n abi.SectorNumber, tsk types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error) {
|
||||
return c.Internal.StateSectorPreCommitInfo(ctx, maddr, n, tsk)
|
||||
}
|
||||
@@ -903,6 +1024,10 @@ func (c *FullNodeStruct) StateSearchMsg(ctx context.Context, msgc cid.Cid) (*api
|
||||
return c.Internal.StateSearchMsg(ctx, msgc)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) StateSearchMsgLimited(ctx context.Context, msgc cid.Cid, limit abi.ChainEpoch) (*api.MsgLookup, error) {
|
||||
return c.Internal.StateSearchMsgLimited(ctx, msgc, limit)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) {
|
||||
return c.Internal.StateListMiners(ctx, tsk)
|
||||
}
|
||||
@@ -947,6 +1072,10 @@ func (c *FullNodeStruct) StateListMessages(ctx context.Context, match *api.Messa
|
||||
return c.Internal.StateListMessages(ctx, match, tsk, toht)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) StateDecodeParams(ctx context.Context, toAddr address.Address, method abi.MethodNum, params []byte, tsk types.TipSetKey) (interface{}, error) {
|
||||
return c.Internal.StateDecodeParams(ctx, toAddr, method, params, tsk)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) StateCompute(ctx context.Context, height abi.ChainEpoch, msgs []*types.Message, tsk types.TipSetKey) (*api.ComputeStateOutput, error) {
|
||||
return c.Internal.StateCompute(ctx, height, msgs, tsk)
|
||||
}
|
||||
@@ -991,6 +1120,10 @@ func (c *FullNodeStruct) MsigGetVested(ctx context.Context, a address.Address, s
|
||||
return c.Internal.MsigGetVested(ctx, a, sTsk, eTsk)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) MsigGetPending(ctx context.Context, a address.Address, tsk types.TipSetKey) ([]*api.MsigTransaction, error) {
|
||||
return c.Internal.MsigGetPending(ctx, a, tsk)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) MsigCreate(ctx context.Context, req uint64, addrs []address.Address, duration abi.ChainEpoch, val types.BigInt, src address.Address, gp types.BigInt) (cid.Cid, error) {
|
||||
return c.Internal.MsigCreate(ctx, req, addrs, duration, val, src, gp)
|
||||
}
|
||||
@@ -1039,8 +1172,24 @@ func (c *FullNodeStruct) MsigRemoveSigner(ctx context.Context, msig address.Addr
|
||||
return c.Internal.MsigRemoveSigner(ctx, msig, proposer, toRemove, decrease)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) MarketEnsureAvailable(ctx context.Context, addr, wallet address.Address, amt types.BigInt) (cid.Cid, error) {
|
||||
return c.Internal.MarketEnsureAvailable(ctx, addr, wallet, amt)
|
||||
func (c *FullNodeStruct) MarketAddBalance(ctx context.Context, wallet address.Address, addr address.Address, amt types.BigInt) (cid.Cid, error) {
|
||||
return c.Internal.MarketAddBalance(ctx, wallet, addr, amt)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) MarketGetReserved(ctx context.Context, addr address.Address) (types.BigInt, error) {
|
||||
return c.Internal.MarketGetReserved(ctx, addr)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) MarketReserveFunds(ctx context.Context, wallet address.Address, addr address.Address, amt types.BigInt) (cid.Cid, error) {
|
||||
return c.Internal.MarketReserveFunds(ctx, wallet, addr, amt)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) MarketReleaseFunds(ctx context.Context, addr address.Address, amt types.BigInt) error {
|
||||
return c.Internal.MarketReleaseFunds(ctx, addr, amt)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) MarketWithdraw(ctx context.Context, wallet, addr address.Address, amt types.BigInt) (cid.Cid, error) {
|
||||
return c.Internal.MarketWithdraw(ctx, wallet, addr, amt)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) PaychGet(ctx context.Context, from, to address.Address, amt types.BigInt) (*api.ChannelInfo, error) {
|
||||
@@ -1125,7 +1274,11 @@ func (c *StorageMinerStruct) ActorSectorSize(ctx context.Context, addr address.A
|
||||
return c.Internal.ActorSectorSize(ctx, addr)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) PledgeSector(ctx context.Context) error {
|
||||
func (c *StorageMinerStruct) ActorAddressConfig(ctx context.Context) (api.AddressConfig, error) {
|
||||
return c.Internal.ActorAddressConfig(ctx)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) PledgeSector(ctx context.Context) (abi.SectorID, error) {
|
||||
return c.Internal.PledgeSector(ctx)
|
||||
}
|
||||
|
||||
@@ -1139,6 +1292,14 @@ func (c *StorageMinerStruct) SectorsList(ctx context.Context) ([]abi.SectorNumbe
|
||||
return c.Internal.SectorsList(ctx)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) SectorsListInStates(ctx context.Context, states []api.SectorState) ([]abi.SectorNumber, error) {
|
||||
return c.Internal.SectorsListInStates(ctx, states)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) SectorsSummary(ctx context.Context) (map[api.SectorState]int, error) {
|
||||
return c.Internal.SectorsSummary(ctx)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) SectorsRefs(ctx context.Context) (map[string][]api.SealedRef, error) {
|
||||
return c.Internal.SectorsRefs(ctx)
|
||||
}
|
||||
@@ -1171,6 +1332,18 @@ func (c *StorageMinerStruct) SectorRemove(ctx context.Context, number abi.Sector
|
||||
return c.Internal.SectorRemove(ctx, number)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) SectorTerminate(ctx context.Context, number abi.SectorNumber) error {
|
||||
return c.Internal.SectorTerminate(ctx, number)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) SectorTerminateFlush(ctx context.Context) (*cid.Cid, error) {
|
||||
return c.Internal.SectorTerminateFlush(ctx)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) SectorTerminatePending(ctx context.Context) ([]abi.SectorID, error) {
|
||||
return c.Internal.SectorTerminatePending(ctx)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) SectorMarkForUpgrade(ctx context.Context, number abi.SectorNumber) error {
|
||||
return c.Internal.SectorMarkForUpgrade(ctx, number)
|
||||
}
|
||||
@@ -1179,32 +1352,80 @@ func (c *StorageMinerStruct) WorkerConnect(ctx context.Context, url string) erro
|
||||
return c.Internal.WorkerConnect(ctx, url)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) WorkerStats(ctx context.Context) (map[uint64]storiface.WorkerStats, error) {
|
||||
func (c *StorageMinerStruct) WorkerStats(ctx context.Context) (map[uuid.UUID]storiface.WorkerStats, error) {
|
||||
return c.Internal.WorkerStats(ctx)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) WorkerJobs(ctx context.Context) (map[uint64][]storiface.WorkerJob, error) {
|
||||
func (c *StorageMinerStruct) WorkerJobs(ctx context.Context) (map[uuid.UUID][]storiface.WorkerJob, error) {
|
||||
return c.Internal.WorkerJobs(ctx)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) SealingSchedDiag(ctx context.Context) (interface{}, error) {
|
||||
return c.Internal.SealingSchedDiag(ctx)
|
||||
func (c *StorageMinerStruct) ReturnAddPiece(ctx context.Context, callID storiface.CallID, pi abi.PieceInfo, err *storiface.CallError) error {
|
||||
return c.Internal.ReturnAddPiece(ctx, callID, pi, err)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) ReturnSealPreCommit1(ctx context.Context, callID storiface.CallID, p1o storage.PreCommit1Out, err *storiface.CallError) error {
|
||||
return c.Internal.ReturnSealPreCommit1(ctx, callID, p1o, err)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) ReturnSealPreCommit2(ctx context.Context, callID storiface.CallID, sealed storage.SectorCids, err *storiface.CallError) error {
|
||||
return c.Internal.ReturnSealPreCommit2(ctx, callID, sealed, err)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) ReturnSealCommit1(ctx context.Context, callID storiface.CallID, out storage.Commit1Out, err *storiface.CallError) error {
|
||||
return c.Internal.ReturnSealCommit1(ctx, callID, out, err)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) ReturnSealCommit2(ctx context.Context, callID storiface.CallID, proof storage.Proof, err *storiface.CallError) error {
|
||||
return c.Internal.ReturnSealCommit2(ctx, callID, proof, err)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) ReturnFinalizeSector(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error {
|
||||
return c.Internal.ReturnFinalizeSector(ctx, callID, err)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) ReturnReleaseUnsealed(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error {
|
||||
return c.Internal.ReturnReleaseUnsealed(ctx, callID, err)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) ReturnMoveStorage(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error {
|
||||
return c.Internal.ReturnMoveStorage(ctx, callID, err)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) ReturnUnsealPiece(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error {
|
||||
return c.Internal.ReturnUnsealPiece(ctx, callID, err)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) ReturnReadPiece(ctx context.Context, callID storiface.CallID, ok bool, err *storiface.CallError) error {
|
||||
return c.Internal.ReturnReadPiece(ctx, callID, ok, err)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) ReturnFetch(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error {
|
||||
return c.Internal.ReturnFetch(ctx, callID, err)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) SealingSchedDiag(ctx context.Context, doSched bool) (interface{}, error) {
|
||||
return c.Internal.SealingSchedDiag(ctx, doSched)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) SealingAbort(ctx context.Context, call storiface.CallID) error {
|
||||
return c.Internal.SealingAbort(ctx, call)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) StorageAttach(ctx context.Context, si stores.StorageInfo, st fsutil.FsStat) error {
|
||||
return c.Internal.StorageAttach(ctx, si, st)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) StorageDeclareSector(ctx context.Context, storageId stores.ID, s abi.SectorID, ft stores.SectorFileType, primary bool) error {
|
||||
func (c *StorageMinerStruct) StorageDeclareSector(ctx context.Context, storageId stores.ID, s abi.SectorID, ft storiface.SectorFileType, primary bool) error {
|
||||
return c.Internal.StorageDeclareSector(ctx, storageId, s, ft, primary)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) StorageDropSector(ctx context.Context, storageId stores.ID, s abi.SectorID, ft stores.SectorFileType) error {
|
||||
func (c *StorageMinerStruct) StorageDropSector(ctx context.Context, storageId stores.ID, s abi.SectorID, ft storiface.SectorFileType) error {
|
||||
return c.Internal.StorageDropSector(ctx, storageId, s, ft)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) StorageFindSector(ctx context.Context, si abi.SectorID, types stores.SectorFileType, spt abi.RegisteredSealProof, allowFetch bool) ([]stores.SectorStorageInfo, error) {
|
||||
return c.Internal.StorageFindSector(ctx, si, types, spt, allowFetch)
|
||||
func (c *StorageMinerStruct) StorageFindSector(ctx context.Context, si abi.SectorID, types storiface.SectorFileType, ssize abi.SectorSize, allowFetch bool) ([]stores.SectorStorageInfo, error) {
|
||||
return c.Internal.StorageFindSector(ctx, si, types, ssize, allowFetch)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) StorageList(ctx context.Context) (map[stores.ID][]stores.Decl, error) {
|
||||
@@ -1223,19 +1444,19 @@ func (c *StorageMinerStruct) StorageInfo(ctx context.Context, id stores.ID) (sto
|
||||
return c.Internal.StorageInfo(ctx, id)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) StorageBestAlloc(ctx context.Context, allocate stores.SectorFileType, spt abi.RegisteredSealProof, pt stores.PathType) ([]stores.StorageInfo, error) {
|
||||
return c.Internal.StorageBestAlloc(ctx, allocate, spt, pt)
|
||||
func (c *StorageMinerStruct) StorageBestAlloc(ctx context.Context, allocate storiface.SectorFileType, ssize abi.SectorSize, pt storiface.PathType) ([]stores.StorageInfo, error) {
|
||||
return c.Internal.StorageBestAlloc(ctx, allocate, ssize, pt)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) StorageReportHealth(ctx context.Context, id stores.ID, report stores.HealthReport) error {
|
||||
return c.Internal.StorageReportHealth(ctx, id, report)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) StorageLock(ctx context.Context, sector abi.SectorID, read stores.SectorFileType, write stores.SectorFileType) error {
|
||||
func (c *StorageMinerStruct) StorageLock(ctx context.Context, sector abi.SectorID, read storiface.SectorFileType, write storiface.SectorFileType) error {
|
||||
return c.Internal.StorageLock(ctx, sector, read, write)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) StorageTryLock(ctx context.Context, sector abi.SectorID, read stores.SectorFileType, write stores.SectorFileType) (bool, error) {
|
||||
func (c *StorageMinerStruct) StorageTryLock(ctx context.Context, sector abi.SectorID, read storiface.SectorFileType, write storiface.SectorFileType) (bool, error) {
|
||||
return c.Internal.StorageTryLock(ctx, sector, read, write)
|
||||
}
|
||||
|
||||
@@ -1283,6 +1504,22 @@ func (c *StorageMinerStruct) MarketDataTransferUpdates(ctx context.Context) (<-c
|
||||
return c.Internal.MarketDataTransferUpdates(ctx)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) MarketRestartDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error {
|
||||
return c.Internal.MarketRestartDataTransfer(ctx, transferID, otherPeer, isInitiator)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) MarketCancelDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error {
|
||||
return c.Internal.MarketCancelDataTransfer(ctx, transferID, otherPeer, isInitiator)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) MarketPendingDeals(ctx context.Context) (api.PendingDealInfo, error) {
|
||||
return c.Internal.MarketPendingDeals(ctx)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) MarketPublishPendingDeals(ctx context.Context) error {
|
||||
return c.Internal.MarketPublishPendingDeals(ctx)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) DealsImportData(ctx context.Context, dealPropCid cid.Cid, file string) error {
|
||||
return c.Internal.DealsImportData(ctx, dealPropCid, file)
|
||||
}
|
||||
@@ -1331,6 +1568,22 @@ func (c *StorageMinerStruct) DealsSetConsiderOfflineRetrievalDeals(ctx context.C
|
||||
return c.Internal.DealsSetConsiderOfflineRetrievalDeals(ctx, b)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) DealsConsiderVerifiedStorageDeals(ctx context.Context) (bool, error) {
|
||||
return c.Internal.DealsConsiderVerifiedStorageDeals(ctx)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) DealsSetConsiderVerifiedStorageDeals(ctx context.Context, b bool) error {
|
||||
return c.Internal.DealsSetConsiderVerifiedStorageDeals(ctx, b)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) DealsConsiderUnverifiedStorageDeals(ctx context.Context) (bool, error) {
|
||||
return c.Internal.DealsConsiderUnverifiedStorageDeals(ctx)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) DealsSetConsiderUnverifiedStorageDeals(ctx context.Context, b bool) error {
|
||||
return c.Internal.DealsSetConsiderUnverifiedStorageDeals(ctx, b)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) StorageAddLocal(ctx context.Context, path string) error {
|
||||
return c.Internal.StorageAddLocal(ctx, path)
|
||||
}
|
||||
@@ -1355,9 +1608,13 @@ func (c *StorageMinerStruct) CreateBackup(ctx context.Context, fpath string) err
|
||||
return c.Internal.CreateBackup(ctx, fpath)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, sectors []storage.SectorRef, expensive bool) (map[abi.SectorNumber]string, error) {
|
||||
return c.Internal.CheckProvable(ctx, pp, sectors, expensive)
|
||||
}
|
||||
|
||||
// WorkerStruct
|
||||
|
||||
func (w *WorkerStruct) Version(ctx context.Context) (build.Version, error) {
|
||||
func (w *WorkerStruct) Version(ctx context.Context) (api.Version, error) {
|
||||
return w.Internal.Version(ctx)
|
||||
}
|
||||
|
||||
@@ -1373,60 +1630,100 @@ func (w *WorkerStruct) Info(ctx context.Context) (storiface.WorkerInfo, error) {
|
||||
return w.Internal.Info(ctx)
|
||||
}
|
||||
|
||||
func (w *WorkerStruct) AddPiece(ctx context.Context, sector abi.SectorID, pieceSizes []abi.UnpaddedPieceSize, newPieceSize abi.UnpaddedPieceSize, pieceData storage.Data) (abi.PieceInfo, error) {
|
||||
func (w *WorkerStruct) AddPiece(ctx context.Context, sector storage.SectorRef, pieceSizes []abi.UnpaddedPieceSize, newPieceSize abi.UnpaddedPieceSize, pieceData storage.Data) (storiface.CallID, error) {
|
||||
return w.Internal.AddPiece(ctx, sector, pieceSizes, newPieceSize, pieceData)
|
||||
}
|
||||
|
||||
func (w *WorkerStruct) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storage.PreCommit1Out, error) {
|
||||
func (w *WorkerStruct) SealPreCommit1(ctx context.Context, sector storage.SectorRef, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storiface.CallID, error) {
|
||||
return w.Internal.SealPreCommit1(ctx, sector, ticket, pieces)
|
||||
}
|
||||
|
||||
func (w *WorkerStruct) SealPreCommit2(ctx context.Context, sector abi.SectorID, p1o storage.PreCommit1Out) (storage.SectorCids, error) {
|
||||
return w.Internal.SealPreCommit2(ctx, sector, p1o)
|
||||
func (w *WorkerStruct) SealPreCommit2(ctx context.Context, sector storage.SectorRef, pc1o storage.PreCommit1Out) (storiface.CallID, error) {
|
||||
return w.Internal.SealPreCommit2(ctx, sector, pc1o)
|
||||
}
|
||||
|
||||
func (w *WorkerStruct) SealCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (storage.Commit1Out, error) {
|
||||
func (w *WorkerStruct) SealCommit1(ctx context.Context, sector storage.SectorRef, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (storiface.CallID, error) {
|
||||
return w.Internal.SealCommit1(ctx, sector, ticket, seed, pieces, cids)
|
||||
}
|
||||
|
||||
func (w *WorkerStruct) SealCommit2(ctx context.Context, sector abi.SectorID, c1o storage.Commit1Out) (storage.Proof, error) {
|
||||
func (w *WorkerStruct) SealCommit2(ctx context.Context, sector storage.SectorRef, c1o storage.Commit1Out) (storiface.CallID, error) {
|
||||
return w.Internal.SealCommit2(ctx, sector, c1o)
|
||||
}
|
||||
|
||||
func (w *WorkerStruct) FinalizeSector(ctx context.Context, sector abi.SectorID, keepUnsealed []storage.Range) error {
|
||||
func (w *WorkerStruct) FinalizeSector(ctx context.Context, sector storage.SectorRef, keepUnsealed []storage.Range) (storiface.CallID, error) {
|
||||
return w.Internal.FinalizeSector(ctx, sector, keepUnsealed)
|
||||
}
|
||||
|
||||
func (w *WorkerStruct) ReleaseUnsealed(ctx context.Context, sector abi.SectorID, safeToFree []storage.Range) error {
|
||||
func (w *WorkerStruct) ReleaseUnsealed(ctx context.Context, sector storage.SectorRef, safeToFree []storage.Range) (storiface.CallID, error) {
|
||||
return w.Internal.ReleaseUnsealed(ctx, sector, safeToFree)
|
||||
}
|
||||
|
||||
func (w *WorkerStruct) MoveStorage(ctx context.Context, sector storage.SectorRef, types storiface.SectorFileType) (storiface.CallID, error) {
|
||||
return w.Internal.MoveStorage(ctx, sector, types)
|
||||
}
|
||||
|
||||
func (w *WorkerStruct) UnsealPiece(ctx context.Context, sector storage.SectorRef, offset storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, ticket abi.SealRandomness, c cid.Cid) (storiface.CallID, error) {
|
||||
return w.Internal.UnsealPiece(ctx, sector, offset, size, ticket, c)
|
||||
}
|
||||
|
||||
func (w *WorkerStruct) ReadPiece(ctx context.Context, sink io.Writer, sector storage.SectorRef, offset storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize) (storiface.CallID, error) {
|
||||
return w.Internal.ReadPiece(ctx, sink, sector, offset, size)
|
||||
}
|
||||
|
||||
func (w *WorkerStruct) Fetch(ctx context.Context, id storage.SectorRef, fileType storiface.SectorFileType, ptype storiface.PathType, am storiface.AcquireMode) (storiface.CallID, error) {
|
||||
return w.Internal.Fetch(ctx, id, fileType, ptype, am)
|
||||
}
|
||||
|
||||
func (w *WorkerStruct) TaskDisable(ctx context.Context, tt sealtasks.TaskType) error {
|
||||
return w.Internal.TaskDisable(ctx, tt)
|
||||
}
|
||||
|
||||
func (w *WorkerStruct) TaskEnable(ctx context.Context, tt sealtasks.TaskType) error {
|
||||
return w.Internal.TaskEnable(ctx, tt)
|
||||
}
|
||||
|
||||
func (w *WorkerStruct) Remove(ctx context.Context, sector abi.SectorID) error {
|
||||
return w.Internal.Remove(ctx, sector)
|
||||
}
|
||||
|
||||
func (w *WorkerStruct) MoveStorage(ctx context.Context, sector abi.SectorID, types stores.SectorFileType) error {
|
||||
return w.Internal.MoveStorage(ctx, sector, types)
|
||||
}
|
||||
|
||||
func (w *WorkerStruct) StorageAddLocal(ctx context.Context, path string) error {
|
||||
return w.Internal.StorageAddLocal(ctx, path)
|
||||
}
|
||||
|
||||
func (w *WorkerStruct) UnsealPiece(ctx context.Context, id abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, randomness abi.SealRandomness, c cid.Cid) error {
|
||||
return w.Internal.UnsealPiece(ctx, id, index, size, randomness, c)
|
||||
func (w *WorkerStruct) SetEnabled(ctx context.Context, enabled bool) error {
|
||||
return w.Internal.SetEnabled(ctx, enabled)
|
||||
}
|
||||
|
||||
func (w *WorkerStruct) ReadPiece(ctx context.Context, writer io.Writer, id abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize) (bool, error) {
|
||||
return w.Internal.ReadPiece(ctx, writer, id, index, size)
|
||||
func (w *WorkerStruct) Enabled(ctx context.Context) (bool, error) {
|
||||
return w.Internal.Enabled(ctx)
|
||||
}
|
||||
|
||||
func (w *WorkerStruct) Fetch(ctx context.Context, id abi.SectorID, fileType stores.SectorFileType, ptype stores.PathType, am stores.AcquireMode) error {
|
||||
return w.Internal.Fetch(ctx, id, fileType, ptype, am)
|
||||
func (w *WorkerStruct) WaitQuiet(ctx context.Context) error {
|
||||
return w.Internal.WaitQuiet(ctx)
|
||||
}
|
||||
|
||||
func (w *WorkerStruct) Closing(ctx context.Context) (<-chan struct{}, error) {
|
||||
return w.Internal.Closing(ctx)
|
||||
func (w *WorkerStruct) ProcessSession(ctx context.Context) (uuid.UUID, error) {
|
||||
return w.Internal.ProcessSession(ctx)
|
||||
}
|
||||
|
||||
func (w *WorkerStruct) Session(ctx context.Context) (uuid.UUID, error) {
|
||||
return w.Internal.Session(ctx)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) ChainGetBlockMessages(ctx context.Context, c cid.Cid) (*api.BlockMessages, error) {
|
||||
return g.Internal.ChainGetBlockMessages(ctx, c)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) {
|
||||
return g.Internal.ChainGetMessage(ctx, mc)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) {
|
||||
return g.Internal.ChainGetTipSet(ctx, tsk)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) {
|
||||
return g.Internal.ChainGetTipSetByHeight(ctx, h, tsk)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) ChainHasObj(ctx context.Context, c cid.Cid) (bool, error) {
|
||||
@@ -1437,12 +1734,8 @@ func (g GatewayStruct) ChainHead(ctx context.Context) (*types.TipSet, error) {
|
||||
return g.Internal.ChainHead(ctx)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) {
|
||||
return g.Internal.ChainGetTipSet(ctx, tsk)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) {
|
||||
return g.Internal.ChainGetTipSetByHeight(ctx, h, tsk)
|
||||
func (g GatewayStruct) ChainNotify(ctx context.Context) (<-chan []*api.HeadChange, error) {
|
||||
return g.Internal.ChainNotify(ctx)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error) {
|
||||
@@ -1465,22 +1758,78 @@ func (g GatewayStruct) MsigGetVested(ctx context.Context, addr address.Address,
|
||||
return g.Internal.MsigGetVested(ctx, addr, start, end)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) MsigGetPending(ctx context.Context, addr address.Address, tsk types.TipSetKey) ([]*api.MsigTransaction, error) {
|
||||
return g.Internal.MsigGetPending(ctx, addr, tsk)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
|
||||
return g.Internal.StateAccountKey(ctx, addr, tsk)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error) {
|
||||
return g.Internal.StateDealProviderCollateralBounds(ctx, size, verified, tsk)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error) {
|
||||
return g.Internal.StateGetActor(ctx, actor, ts)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) StateGetReceipt(ctx context.Context, c cid.Cid, tsk types.TipSetKey) (*types.MessageReceipt, error) {
|
||||
return g.Internal.StateGetReceipt(ctx, c, tsk)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
|
||||
return g.Internal.StateLookupID(ctx, addr, tsk)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) {
|
||||
return g.Internal.StateListMiners(ctx, tsk)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) {
|
||||
return g.Internal.StateMarketBalance(ctx, addr, tsk)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) {
|
||||
return g.Internal.StateMarketStorageDeal(ctx, dealId, tsk)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) {
|
||||
return g.Internal.StateMinerInfo(ctx, actor, tsk)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error) {
|
||||
return g.Internal.StateMinerProvingDeadline(ctx, addr, tsk)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) StateMinerPower(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*api.MinerPower, error) {
|
||||
return g.Internal.StateMinerPower(ctx, addr, tsk)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (stnetwork.Version, error) {
|
||||
return g.Internal.StateNetworkVersion(ctx, tsk)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) StateSearchMsg(ctx context.Context, msg cid.Cid) (*api.MsgLookup, error) {
|
||||
return g.Internal.StateSearchMsg(ctx, msg)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) StateSectorGetInfo(ctx context.Context, maddr address.Address, n abi.SectorNumber, tsk types.TipSetKey) (*miner.SectorOnChainInfo, error) {
|
||||
return g.Internal.StateSectorGetInfo(ctx, maddr, n, tsk)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) {
|
||||
return g.Internal.StateVerifiedClientStatus(ctx, addr, tsk)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error) {
|
||||
return g.Internal.StateWaitMsg(ctx, msg, confidence)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) StateReadState(ctx context.Context, addr address.Address, ts types.TipSetKey) (*api.ActorState, error) {
|
||||
return g.Internal.StateReadState(ctx, addr, ts)
|
||||
}
|
||||
|
||||
func (c *WalletStruct) WalletNew(ctx context.Context, typ types.KeyType) (address.Address, error) {
|
||||
return c.Internal.WalletNew(ctx, typ)
|
||||
}
|
||||
|
||||
+14
-5
@@ -5,14 +5,18 @@ package api
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
|
||||
abi "github.com/filecoin-project/go-state-types/abi"
|
||||
paych "github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
||||
cid "github.com/ipfs/go-cid"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
xerrors "golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
var _ = xerrors.Errorf
|
||||
var _ = cid.Undef
|
||||
var _ = sort.Sort
|
||||
|
||||
func (t *PaymentInfo) MarshalCBOR(w io.Writer) error {
|
||||
if t == nil {
|
||||
@@ -171,7 +175,8 @@ func (t *PaymentInfo) UnmarshalCBOR(r io.Reader) error {
|
||||
}
|
||||
|
||||
default:
|
||||
return fmt.Errorf("unknown struct field %d: '%s'", i, name)
|
||||
// Field doesn't exist on this type, so ignore it
|
||||
cbg.ScanForLinks(r, func(cid.Cid) {})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -319,7 +324,8 @@ func (t *SealedRef) UnmarshalCBOR(r io.Reader) error {
|
||||
}
|
||||
|
||||
default:
|
||||
return fmt.Errorf("unknown struct field %d: '%s'", i, name)
|
||||
// Field doesn't exist on this type, so ignore it
|
||||
cbg.ScanForLinks(r, func(cid.Cid) {})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -427,7 +433,8 @@ func (t *SealedRefs) UnmarshalCBOR(r io.Reader) error {
|
||||
}
|
||||
|
||||
default:
|
||||
return fmt.Errorf("unknown struct field %d: '%s'", i, name)
|
||||
// Field doesn't exist on this type, so ignore it
|
||||
cbg.ScanForLinks(r, func(cid.Cid) {})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -575,7 +582,8 @@ func (t *SealTicket) UnmarshalCBOR(r io.Reader) error {
|
||||
}
|
||||
|
||||
default:
|
||||
return fmt.Errorf("unknown struct field %d: '%s'", i, name)
|
||||
// Field doesn't exist on this type, so ignore it
|
||||
cbg.ScanForLinks(r, func(cid.Cid) {})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -723,7 +731,8 @@ func (t *SealSeed) UnmarshalCBOR(r io.Reader) error {
|
||||
}
|
||||
|
||||
default:
|
||||
return fmt.Errorf("unknown struct field %d: '%s'", i, name)
|
||||
// Field doesn't exist on this type, so ignore it
|
||||
cbg.ScanForLinks(r, func(cid.Cid) {})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+133
-29
@@ -6,12 +6,14 @@ import (
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"os"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/ipfs/go-filestore"
|
||||
metrics "github.com/libp2p/go-libp2p-core/metrics"
|
||||
@@ -24,6 +26,7 @@ import (
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-bitfield"
|
||||
datatransfer "github.com/filecoin-project/go-data-transfer"
|
||||
filestore2 "github.com/filecoin-project/go-fil-markets/filestore"
|
||||
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
||||
"github.com/filecoin-project/go-jsonrpc/auth"
|
||||
"github.com/filecoin-project/go-multistore"
|
||||
@@ -36,6 +39,10 @@ import (
|
||||
"github.com/filecoin-project/lotus/api/apistruct"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/sealtasks"
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/stores"
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/storiface"
|
||||
sealing "github.com/filecoin-project/lotus/extern/storage-sealing"
|
||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||
)
|
||||
|
||||
@@ -83,7 +90,7 @@ func init() {
|
||||
addExample(&pid)
|
||||
|
||||
addExample(bitfield.NewFromSet([]uint64{5}))
|
||||
addExample(abi.RegisteredSealProof_StackedDrg32GiBV1)
|
||||
addExample(abi.RegisteredSealProof_StackedDrg32GiBV1_1)
|
||||
addExample(abi.RegisteredPoStProof_StackedDrgWindow32GiBV1)
|
||||
addExample(abi.ChainEpoch(10101))
|
||||
addExample(crypto.SigTypeBLS)
|
||||
@@ -106,7 +113,7 @@ func init() {
|
||||
addExample(network.Connected)
|
||||
addExample(dtypes.NetworkName("lotus"))
|
||||
addExample(api.SyncStateStage(1))
|
||||
addExample(build.FullAPIVersion)
|
||||
addExample(api.FullAPIVersion)
|
||||
addExample(api.PCHInbound)
|
||||
addExample(time.Minute)
|
||||
addExample(datatransfer.TransferID(3))
|
||||
@@ -116,18 +123,20 @@ func init() {
|
||||
addExample(retrievalmarket.DealStatusNew)
|
||||
addExample(network.ReachabilityPublic)
|
||||
addExample(build.NewestNetworkVersion)
|
||||
addExample(map[string]int{"name": 42})
|
||||
addExample(map[string]time.Time{"name": time.Unix(1615243938, 0).UTC()})
|
||||
addExample(&types.ExecutionTrace{
|
||||
Msg: exampleValue(reflect.TypeOf(&types.Message{}), nil).(*types.Message),
|
||||
MsgRct: exampleValue(reflect.TypeOf(&types.MessageReceipt{}), nil).(*types.MessageReceipt),
|
||||
Msg: exampleValue("init", reflect.TypeOf(&types.Message{}), nil).(*types.Message),
|
||||
MsgRct: exampleValue("init", reflect.TypeOf(&types.MessageReceipt{}), nil).(*types.MessageReceipt),
|
||||
})
|
||||
addExample(map[string]types.Actor{
|
||||
"t01236": exampleValue(reflect.TypeOf(types.Actor{}), nil).(types.Actor),
|
||||
"t01236": exampleValue("init", reflect.TypeOf(types.Actor{}), nil).(types.Actor),
|
||||
})
|
||||
addExample(map[string]api.MarketDeal{
|
||||
"t026363": exampleValue(reflect.TypeOf(api.MarketDeal{}), nil).(api.MarketDeal),
|
||||
"t026363": exampleValue("init", reflect.TypeOf(api.MarketDeal{}), nil).(api.MarketDeal),
|
||||
})
|
||||
addExample(map[string]api.MarketBalance{
|
||||
"t026363": exampleValue(reflect.TypeOf(api.MarketBalance{}), nil).(api.MarketBalance),
|
||||
"t026363": exampleValue("init", reflect.TypeOf(api.MarketBalance{}), nil).(api.MarketBalance),
|
||||
})
|
||||
addExample(map[string]*pubsub.TopicScoreSnapshot{
|
||||
"/blocks": {
|
||||
@@ -162,9 +171,89 @@ func init() {
|
||||
// because reflect.TypeOf(maddr) returns the concrete type...
|
||||
ExampleValues[reflect.TypeOf(struct{ A multiaddr.Multiaddr }{}).Field(0).Type] = maddr
|
||||
|
||||
// miner specific
|
||||
addExample(filestore2.Path(".lotusminer/fstmp123"))
|
||||
si := multistore.StoreID(12)
|
||||
addExample(&si)
|
||||
addExample(retrievalmarket.DealID(5))
|
||||
addExample(abi.ActorID(1000))
|
||||
addExample(map[string][]api.SealedRef{
|
||||
"98000": {
|
||||
api.SealedRef{
|
||||
SectorID: 100,
|
||||
Offset: 10 << 20,
|
||||
Size: 1 << 20,
|
||||
},
|
||||
},
|
||||
})
|
||||
addExample(api.SectorState(sealing.Proving))
|
||||
addExample(stores.ID("76f1988b-ef30-4d7e-b3ec-9a627f4ba5a8"))
|
||||
addExample(storiface.FTUnsealed)
|
||||
addExample(storiface.PathSealing)
|
||||
addExample(map[stores.ID][]stores.Decl{
|
||||
"76f1988b-ef30-4d7e-b3ec-9a627f4ba5a8": {
|
||||
{
|
||||
SectorID: abi.SectorID{Miner: 1000, Number: 100},
|
||||
SectorFileType: storiface.FTSealed,
|
||||
},
|
||||
},
|
||||
})
|
||||
addExample(map[stores.ID]string{
|
||||
"76f1988b-ef30-4d7e-b3ec-9a627f4ba5a8": "/data/path",
|
||||
})
|
||||
addExample(map[uuid.UUID][]storiface.WorkerJob{
|
||||
uuid.MustParse("ef8d99a2-6865-4189-8ffa-9fef0f806eee"): {
|
||||
{
|
||||
ID: storiface.CallID{
|
||||
Sector: abi.SectorID{Miner: 1000, Number: 100},
|
||||
ID: uuid.MustParse("76081ba0-61bd-45a5-bc08-af05f1c26e5d"),
|
||||
},
|
||||
Sector: abi.SectorID{Miner: 1000, Number: 100},
|
||||
Task: sealtasks.TTPreCommit2,
|
||||
RunWait: 0,
|
||||
Start: time.Unix(1605172927, 0).UTC(),
|
||||
Hostname: "host",
|
||||
},
|
||||
},
|
||||
})
|
||||
addExample(map[uuid.UUID]storiface.WorkerStats{
|
||||
uuid.MustParse("ef8d99a2-6865-4189-8ffa-9fef0f806eee"): {
|
||||
Info: storiface.WorkerInfo{
|
||||
Hostname: "host",
|
||||
Resources: storiface.WorkerResources{
|
||||
MemPhysical: 256 << 30,
|
||||
MemSwap: 120 << 30,
|
||||
MemReserved: 2 << 30,
|
||||
CPUs: 64,
|
||||
GPUs: []string{"aGPU 1337"},
|
||||
},
|
||||
},
|
||||
Enabled: true,
|
||||
MemUsedMin: 0,
|
||||
MemUsedMax: 0,
|
||||
GpuUsed: false,
|
||||
CpuUse: 0,
|
||||
},
|
||||
})
|
||||
addExample(storiface.ErrorCode(0))
|
||||
addExample(map[abi.SectorNumber]string{
|
||||
123: "can't acquire read lock",
|
||||
})
|
||||
addExample(map[api.SectorState]int{
|
||||
api.SectorState(sealing.Proving): 120,
|
||||
})
|
||||
addExample([]abi.SectorNumber{123, 124})
|
||||
|
||||
// worker specific
|
||||
addExample(storiface.AcquireMove)
|
||||
addExample(storiface.UnpaddedByteIndex(abi.PaddedPieceSize(1 << 20).Unpadded()))
|
||||
addExample(map[sealtasks.TaskType]struct{}{
|
||||
sealtasks.TTPreCommit2: {},
|
||||
})
|
||||
addExample(sealtasks.TTCommit2)
|
||||
}
|
||||
|
||||
func exampleValue(t, parent reflect.Type) interface{} {
|
||||
func exampleValue(method string, t, parent reflect.Type) interface{} {
|
||||
v, ok := ExampleValues[t]
|
||||
if ok {
|
||||
return v
|
||||
@@ -173,25 +262,25 @@ func exampleValue(t, parent reflect.Type) interface{} {
|
||||
switch t.Kind() {
|
||||
case reflect.Slice:
|
||||
out := reflect.New(t).Elem()
|
||||
reflect.Append(out, reflect.ValueOf(exampleValue(t.Elem(), t)))
|
||||
reflect.Append(out, reflect.ValueOf(exampleValue(method, t.Elem(), t)))
|
||||
return out.Interface()
|
||||
case reflect.Chan:
|
||||
return exampleValue(t.Elem(), nil)
|
||||
return exampleValue(method, t.Elem(), nil)
|
||||
case reflect.Struct:
|
||||
es := exampleStruct(t, parent)
|
||||
es := exampleStruct(method, t, parent)
|
||||
v := reflect.ValueOf(es).Elem().Interface()
|
||||
ExampleValues[t] = v
|
||||
return v
|
||||
case reflect.Array:
|
||||
out := reflect.New(t).Elem()
|
||||
for i := 0; i < t.Len(); i++ {
|
||||
out.Index(i).Set(reflect.ValueOf(exampleValue(t.Elem(), t)))
|
||||
out.Index(i).Set(reflect.ValueOf(exampleValue(method, t.Elem(), t)))
|
||||
}
|
||||
return out.Interface()
|
||||
|
||||
case reflect.Ptr:
|
||||
if t.Elem().Kind() == reflect.Struct {
|
||||
es := exampleStruct(t.Elem(), t)
|
||||
es := exampleStruct(method, t.Elem(), t)
|
||||
//ExampleValues[t] = es
|
||||
return es
|
||||
}
|
||||
@@ -199,10 +288,10 @@ func exampleValue(t, parent reflect.Type) interface{} {
|
||||
return struct{}{}
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("No example value for type: %s", t))
|
||||
panic(fmt.Sprintf("No example value for type: %s (method '%s')", t, method))
|
||||
}
|
||||
|
||||
func exampleStruct(t, parent reflect.Type) interface{} {
|
||||
func exampleStruct(method string, t, parent reflect.Type) interface{} {
|
||||
ns := reflect.New(t)
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
f := t.Field(i)
|
||||
@@ -210,7 +299,7 @@ func exampleStruct(t, parent reflect.Type) interface{} {
|
||||
continue
|
||||
}
|
||||
if strings.Title(f.Name) == f.Name {
|
||||
ns.Elem().Field(i).Set(reflect.ValueOf(exampleValue(f.Type, t)))
|
||||
ns.Elem().Field(i).Set(reflect.ValueOf(exampleValue(method, f.Type, t)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,6 +307,7 @@ func exampleStruct(t, parent reflect.Type) interface{} {
|
||||
}
|
||||
|
||||
type Visitor struct {
|
||||
Root string
|
||||
Methods map[string]ast.Node
|
||||
}
|
||||
|
||||
@@ -227,7 +317,7 @@ func (v *Visitor) Visit(node ast.Node) ast.Visitor {
|
||||
return v
|
||||
}
|
||||
|
||||
if st.Name.Name != "FullNode" {
|
||||
if st.Name.Name != v.Root {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -243,7 +333,7 @@ func (v *Visitor) Visit(node ast.Node) ast.Visitor {
|
||||
|
||||
const noComment = "There are not yet any comments for this method."
|
||||
|
||||
func parseApiASTInfo() (map[string]string, map[string]string) { //nolint:golint
|
||||
func parseApiASTInfo(apiFile, iface string) (map[string]string, map[string]string) { //nolint:golint
|
||||
fset := token.NewFileSet()
|
||||
pkgs, err := parser.ParseDir(fset, "./api", nil, parser.AllErrors|parser.ParseComments)
|
||||
if err != nil {
|
||||
@@ -252,11 +342,11 @@ func parseApiASTInfo() (map[string]string, map[string]string) { //nolint:golint
|
||||
|
||||
ap := pkgs["api"]
|
||||
|
||||
f := ap.Files["api/api_full.go"]
|
||||
f := ap.Files[apiFile]
|
||||
|
||||
cmap := ast.NewCommentMap(fset, f, f.Comments)
|
||||
|
||||
v := &Visitor{make(map[string]ast.Node)}
|
||||
v := &Visitor{iface, make(map[string]ast.Node)}
|
||||
ast.Walk(v, pkgs["api"])
|
||||
|
||||
groupDocs := make(map[string]string)
|
||||
@@ -312,13 +402,30 @@ func methodGroupFromName(mn string) string {
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
comments, groupComments := parseApiASTInfo()
|
||||
comments, groupComments := parseApiASTInfo(os.Args[1], os.Args[2])
|
||||
|
||||
groups := make(map[string]*MethodGroup)
|
||||
|
||||
var api struct{ api.FullNode }
|
||||
t := reflect.TypeOf(api)
|
||||
var t reflect.Type
|
||||
var permStruct, commonPermStruct reflect.Type
|
||||
|
||||
switch os.Args[2] {
|
||||
case "FullNode":
|
||||
t = reflect.TypeOf(new(struct{ api.FullNode })).Elem()
|
||||
permStruct = reflect.TypeOf(apistruct.FullNodeStruct{}.Internal)
|
||||
commonPermStruct = reflect.TypeOf(apistruct.CommonStruct{}.Internal)
|
||||
case "StorageMiner":
|
||||
t = reflect.TypeOf(new(struct{ api.StorageMiner })).Elem()
|
||||
permStruct = reflect.TypeOf(apistruct.StorageMinerStruct{}.Internal)
|
||||
commonPermStruct = reflect.TypeOf(apistruct.CommonStruct{}.Internal)
|
||||
case "WorkerAPI":
|
||||
t = reflect.TypeOf(new(struct{ api.WorkerAPI })).Elem()
|
||||
permStruct = reflect.TypeOf(apistruct.WorkerStruct{}.Internal)
|
||||
commonPermStruct = reflect.TypeOf(apistruct.WorkerStruct{}.Internal)
|
||||
default:
|
||||
panic("unknown type")
|
||||
}
|
||||
|
||||
for i := 0; i < t.NumMethod(); i++ {
|
||||
m := t.Method(i)
|
||||
|
||||
@@ -336,7 +443,7 @@ func main() {
|
||||
ft := m.Func.Type()
|
||||
for j := 2; j < ft.NumIn(); j++ {
|
||||
inp := ft.In(j)
|
||||
args = append(args, exampleValue(inp, nil))
|
||||
args = append(args, exampleValue(m.Name, inp, nil))
|
||||
}
|
||||
|
||||
v, err := json.MarshalIndent(args, "", " ")
|
||||
@@ -344,7 +451,7 @@ func main() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
outv := exampleValue(ft.Out(0), nil)
|
||||
outv := exampleValue(m.Name, ft.Out(0), nil)
|
||||
|
||||
ov, err := json.MarshalIndent(outv, "", " ")
|
||||
if err != nil {
|
||||
@@ -377,9 +484,6 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
permStruct := reflect.TypeOf(apistruct.FullNodeStruct{}.Internal)
|
||||
commonPermStruct := reflect.TypeOf(apistruct.CommonStruct{}.Internal)
|
||||
|
||||
for _, g := range groupslice {
|
||||
g := g
|
||||
fmt.Printf("## %s\n", g.GroupName)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -37,7 +37,12 @@ func (bm *BlockMiner) MineBlocks() {
|
||||
go func() {
|
||||
defer close(bm.done)
|
||||
for atomic.LoadInt64(&bm.mine) == 1 {
|
||||
time.Sleep(bm.blocktime)
|
||||
select {
|
||||
case <-bm.ctx.Done():
|
||||
return
|
||||
case <-time.After(bm.blocktime):
|
||||
}
|
||||
|
||||
nulls := atomic.SwapInt64(&bm.nulls, 0)
|
||||
if err := bm.miner.MineOne(bm.ctx, miner.MineReq{
|
||||
InjectNulls: abi.ChainEpoch(nulls),
|
||||
|
||||
@@ -3,7 +3,6 @@ package test
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -17,12 +16,10 @@ import (
|
||||
)
|
||||
|
||||
func TestCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
||||
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
||||
|
||||
for _, height := range []abi.ChainEpoch{
|
||||
1, // before
|
||||
-1, // before
|
||||
162, // while sealing
|
||||
520, // after upgrade deal
|
||||
530, // after upgrade deal
|
||||
5000, // after
|
||||
} {
|
||||
height := height // make linters happy by copying
|
||||
@@ -34,7 +31,7 @@ func TestCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
||||
|
||||
func testCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration, upgradeHeight abi.ChainEpoch) {
|
||||
ctx := context.Background()
|
||||
n, sn := b(t, []FullNodeOpts{FullNodeWithUpgradeAt(upgradeHeight)}, OneMiner)
|
||||
n, sn := b(t, []FullNodeOpts{FullNodeWithActorsV4At(upgradeHeight)}, OneMiner)
|
||||
client := n[0].FullNode.(*impl.FullNodeAPI)
|
||||
miner := sn[0]
|
||||
|
||||
@@ -92,7 +89,7 @@ func testCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration, upgradeH
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
makeDeal(t, ctx, 6, client, miner, false, false)
|
||||
MakeDeal(t, ctx, 6, client, miner, false, false, 0)
|
||||
|
||||
// Validate upgrade
|
||||
|
||||
|
||||
@@ -0,0 +1,350 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-bitfield"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"github.com/filecoin-project/go-state-types/exitcode"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner"
|
||||
"github.com/ipfs/go-cid"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
|
||||
"github.com/filecoin-project/lotus/blockstore"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/mock"
|
||||
"github.com/filecoin-project/lotus/node/impl"
|
||||
)
|
||||
|
||||
// TestDeadlineToggling:
|
||||
// * spins up a v3 network (miner A)
|
||||
// * creates an inactive miner (miner B)
|
||||
// * creates another miner, pledges a sector, waits for power (miner C)
|
||||
//
|
||||
// * goes through v4 upgrade
|
||||
// * goes through PP
|
||||
// * creates minerD, minerE
|
||||
// * makes sure that miner B/D are inactive, A/C still are
|
||||
// * pledges sectors on miner B/D
|
||||
// * precommits a sector on minerE
|
||||
// * disables post on miner C
|
||||
// * goes through PP 0.5PP
|
||||
// * asserts that minerE is active
|
||||
// * goes through rest of PP (1.5)
|
||||
// * asserts that miner C loses power
|
||||
// * asserts that miner B/D is active and has power
|
||||
// * asserts that minerE is inactive
|
||||
// * disables post on miner B
|
||||
// * terminates sectors on miner D
|
||||
// * goes through another PP
|
||||
// * asserts that miner B loses power
|
||||
// * asserts that miner D loses power, is inactive
|
||||
func TestDeadlineToggling(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
||||
var upgradeH abi.ChainEpoch = 4000
|
||||
var provingPeriod abi.ChainEpoch = 2880
|
||||
|
||||
const sectorsC, sectorsD, sectersB = 10, 9, 8
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
n, sn := b(t, []FullNodeOpts{FullNodeWithActorsV4At(upgradeH)}, OneMiner)
|
||||
|
||||
client := n[0].FullNode.(*impl.FullNodeAPI)
|
||||
minerA := sn[0]
|
||||
|
||||
{
|
||||
addrinfo, err := client.NetAddrsListen(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := minerA.NetConnect(ctx, addrinfo); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
defaultFrom, err := client.WalletDefaultAddress(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
maddrA, err := minerA.ActorAddress(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
build.Clock.Sleep(time.Second)
|
||||
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
for ctx.Err() == nil {
|
||||
build.Clock.Sleep(blocktime)
|
||||
if err := minerA.MineOne(ctx, MineNext); err != nil {
|
||||
if ctx.Err() != nil {
|
||||
// context was canceled, ignore the error.
|
||||
return
|
||||
}
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
defer func() {
|
||||
cancel()
|
||||
<-done
|
||||
}()
|
||||
|
||||
minerB := n[0].Stb(ctx, t, TestSpt, defaultFrom)
|
||||
minerC := n[0].Stb(ctx, t, TestSpt, defaultFrom)
|
||||
|
||||
maddrB, err := minerB.ActorAddress(ctx)
|
||||
require.NoError(t, err)
|
||||
maddrC, err := minerC.ActorAddress(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
ssz, err := minerC.ActorSectorSize(ctx, maddrC)
|
||||
require.NoError(t, err)
|
||||
|
||||
// pledge sectors on C, go through a PP, check for power
|
||||
{
|
||||
pledgeSectors(t, ctx, minerC, sectorsC, 0, nil)
|
||||
|
||||
di, err := client.StateMinerProvingDeadline(ctx, maddrC, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
|
||||
fmt.Printf("Running one proving period (miner C)\n")
|
||||
fmt.Printf("End for head.Height > %d\n", di.PeriodStart+di.WPoStProvingPeriod*2)
|
||||
|
||||
for {
|
||||
head, err := client.ChainHead(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
if head.Height() > di.PeriodStart+provingPeriod*2 {
|
||||
fmt.Printf("Now head.Height = %d\n", head.Height())
|
||||
break
|
||||
}
|
||||
build.Clock.Sleep(blocktime)
|
||||
}
|
||||
|
||||
expectedPower := types.NewInt(uint64(ssz) * sectorsC)
|
||||
|
||||
p, err := client.StateMinerPower(ctx, maddrC, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
|
||||
// make sure it has gained power.
|
||||
require.Equal(t, p.MinerPower.RawBytePower, expectedPower)
|
||||
}
|
||||
|
||||
// go through upgrade + PP
|
||||
for {
|
||||
head, err := client.ChainHead(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
if head.Height() > upgradeH+provingPeriod {
|
||||
fmt.Printf("Now head.Height = %d\n", head.Height())
|
||||
break
|
||||
}
|
||||
build.Clock.Sleep(blocktime)
|
||||
}
|
||||
|
||||
checkMiner := func(ma address.Address, power abi.StoragePower, active bool, tsk types.TipSetKey) {
|
||||
p, err := client.StateMinerPower(ctx, ma, tsk)
|
||||
require.NoError(t, err)
|
||||
|
||||
// make sure it has the expected power.
|
||||
require.Equal(t, p.MinerPower.RawBytePower, power)
|
||||
|
||||
mact, err := client.StateGetActor(ctx, ma, tsk)
|
||||
require.NoError(t, err)
|
||||
|
||||
mst, err := miner.Load(adt.WrapStore(ctx, cbor.NewCborStore(blockstore.NewAPIBlockstore(client))), mact)
|
||||
require.NoError(t, err)
|
||||
|
||||
act, err := mst.DeadlineCronActive()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, active, act)
|
||||
}
|
||||
|
||||
// check that just after the upgrade minerB was still active
|
||||
{
|
||||
uts, err := client.ChainGetTipSetByHeight(ctx, upgradeH+2, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
checkMiner(maddrB, types.NewInt(0), true, uts.Key())
|
||||
}
|
||||
|
||||
nv, err := client.StateNetworkVersion(ctx, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
require.GreaterOrEqual(t, nv, network.Version12)
|
||||
|
||||
minerD := n[0].Stb(ctx, t, TestSpt, defaultFrom)
|
||||
minerE := n[0].Stb(ctx, t, TestSpt, defaultFrom)
|
||||
|
||||
maddrD, err := minerD.ActorAddress(ctx)
|
||||
require.NoError(t, err)
|
||||
maddrE, err := minerE.ActorAddress(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
// first round of miner checks
|
||||
checkMiner(maddrA, types.NewInt(uint64(ssz)*GenesisPreseals), true, types.EmptyTSK)
|
||||
checkMiner(maddrC, types.NewInt(uint64(ssz)*sectorsC), true, types.EmptyTSK)
|
||||
|
||||
checkMiner(maddrB, types.NewInt(0), false, types.EmptyTSK)
|
||||
checkMiner(maddrD, types.NewInt(0), false, types.EmptyTSK)
|
||||
checkMiner(maddrE, types.NewInt(0), false, types.EmptyTSK)
|
||||
|
||||
// pledge sectors on minerB/minerD, stop post on minerC
|
||||
pledgeSectors(t, ctx, minerB, sectersB, 0, nil)
|
||||
checkMiner(maddrB, types.NewInt(0), true, types.EmptyTSK)
|
||||
|
||||
pledgeSectors(t, ctx, minerD, sectorsD, 0, nil)
|
||||
checkMiner(maddrD, types.NewInt(0), true, types.EmptyTSK)
|
||||
|
||||
minerC.StorageMiner.(*impl.StorageMinerAPI).IStorageMgr.(*mock.SectorMgr).Fail()
|
||||
|
||||
// precommit a sector on minerE
|
||||
{
|
||||
head, err := client.ChainHead(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
cr, err := cid.Parse("bagboea4b5abcatlxechwbp7kjpjguna6r6q7ejrhe6mdp3lf34pmswn27pkkiekz")
|
||||
require.NoError(t, err)
|
||||
|
||||
params := &miner.SectorPreCommitInfo{
|
||||
Expiration: 2880 * 300,
|
||||
SectorNumber: 22,
|
||||
SealProof: TestSpt,
|
||||
|
||||
SealedCID: cr,
|
||||
SealRandEpoch: head.Height() - 200,
|
||||
}
|
||||
|
||||
enc := new(bytes.Buffer)
|
||||
require.NoError(t, params.MarshalCBOR(enc))
|
||||
|
||||
m, err := client.MpoolPushMessage(ctx, &types.Message{
|
||||
To: maddrE,
|
||||
From: defaultFrom,
|
||||
Value: types.FromFil(1),
|
||||
Method: miner.Methods.PreCommitSector,
|
||||
Params: enc.Bytes(),
|
||||
}, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
r, err := client.StateWaitMsg(ctx, m.Cid(), 2)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, exitcode.Ok, r.Receipt.ExitCode)
|
||||
}
|
||||
|
||||
// go through 0.5 PP
|
||||
for {
|
||||
head, err := client.ChainHead(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
if head.Height() > upgradeH+provingPeriod+(provingPeriod/2) {
|
||||
fmt.Printf("Now head.Height = %d\n", head.Height())
|
||||
break
|
||||
}
|
||||
build.Clock.Sleep(blocktime)
|
||||
}
|
||||
|
||||
checkMiner(maddrE, types.NewInt(0), true, types.EmptyTSK)
|
||||
|
||||
// go through rest of the PP
|
||||
for {
|
||||
head, err := client.ChainHead(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
if head.Height() > upgradeH+(provingPeriod*3) {
|
||||
fmt.Printf("Now head.Height = %d\n", head.Height())
|
||||
break
|
||||
}
|
||||
build.Clock.Sleep(blocktime)
|
||||
}
|
||||
|
||||
// second round of miner checks
|
||||
checkMiner(maddrA, types.NewInt(uint64(ssz)*GenesisPreseals), true, types.EmptyTSK)
|
||||
checkMiner(maddrC, types.NewInt(0), true, types.EmptyTSK)
|
||||
checkMiner(maddrB, types.NewInt(uint64(ssz)*sectersB), true, types.EmptyTSK)
|
||||
checkMiner(maddrD, types.NewInt(uint64(ssz)*sectorsD), true, types.EmptyTSK)
|
||||
checkMiner(maddrE, types.NewInt(0), false, types.EmptyTSK)
|
||||
|
||||
// disable post on minerB
|
||||
minerB.StorageMiner.(*impl.StorageMinerAPI).IStorageMgr.(*mock.SectorMgr).Fail()
|
||||
|
||||
// terminate sectors on minerD
|
||||
{
|
||||
var terminationDeclarationParams []miner2.TerminationDeclaration
|
||||
secs, err := minerD.SectorsList(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, secs, sectorsD)
|
||||
|
||||
for _, sectorNum := range secs {
|
||||
sectorbit := bitfield.New()
|
||||
sectorbit.Set(uint64(sectorNum))
|
||||
|
||||
loca, err := client.StateSectorPartition(ctx, maddrD, sectorNum, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
|
||||
para := miner2.TerminationDeclaration{
|
||||
Deadline: loca.Deadline,
|
||||
Partition: loca.Partition,
|
||||
Sectors: sectorbit,
|
||||
}
|
||||
|
||||
terminationDeclarationParams = append(terminationDeclarationParams, para)
|
||||
}
|
||||
|
||||
terminateSectorParams := &miner2.TerminateSectorsParams{
|
||||
Terminations: terminationDeclarationParams,
|
||||
}
|
||||
|
||||
sp, aerr := actors.SerializeParams(terminateSectorParams)
|
||||
require.NoError(t, aerr)
|
||||
|
||||
smsg, err := client.MpoolPushMessage(ctx, &types.Message{
|
||||
From: defaultFrom,
|
||||
To: maddrD,
|
||||
Method: miner.Methods.TerminateSectors,
|
||||
|
||||
Value: big.Zero(),
|
||||
Params: sp,
|
||||
}, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
fmt.Println("sent termination message:", smsg.Cid())
|
||||
|
||||
r, err := client.StateWaitMsg(ctx, smsg.Cid(), 2)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, exitcode.Ok, r.Receipt.ExitCode)
|
||||
|
||||
checkMiner(maddrD, types.NewInt(0), true, r.TipSet)
|
||||
}
|
||||
|
||||
// go through another PP
|
||||
for {
|
||||
head, err := client.ChainHead(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
if head.Height() > upgradeH+(provingPeriod*5) {
|
||||
fmt.Printf("Now head.Height = %d\n", head.Height())
|
||||
break
|
||||
}
|
||||
build.Clock.Sleep(blocktime)
|
||||
}
|
||||
|
||||
// third round of miner checks
|
||||
checkMiner(maddrA, types.NewInt(uint64(ssz)*GenesisPreseals), true, types.EmptyTSK)
|
||||
checkMiner(maddrC, types.NewInt(0), true, types.EmptyTSK)
|
||||
checkMiner(maddrB, types.NewInt(0), true, types.EmptyTSK)
|
||||
checkMiner(maddrD, types.NewInt(0), false, types.EmptyTSK)
|
||||
}
|
||||
+206
-175
@@ -8,131 +8,56 @@ import (
|
||||
"math/rand"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
files "github.com/ipfs/go-ipfs-files"
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
"github.com/ipld/go-car"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/filecoin-project/go-fil-markets/storagemarket"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
sealing "github.com/filecoin-project/lotus/extern/storage-sealing"
|
||||
"github.com/filecoin-project/lotus/miner"
|
||||
"github.com/filecoin-project/lotus/markets/storageadapter"
|
||||
"github.com/filecoin-project/lotus/node"
|
||||
"github.com/filecoin-project/lotus/node/impl"
|
||||
market2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/market"
|
||||
ipld "github.com/ipfs/go-ipld-format"
|
||||
dag "github.com/ipfs/go-merkledag"
|
||||
dstest "github.com/ipfs/go-merkledag/test"
|
||||
unixfile "github.com/ipfs/go-unixfs/file"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/node/impl"
|
||||
ipld "github.com/ipfs/go-ipld-format"
|
||||
)
|
||||
|
||||
var MineNext = miner.MineReq{
|
||||
InjectNulls: 0,
|
||||
Done: func(bool, abi.ChainEpoch, error) {},
|
||||
func TestDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration, carExport, fastRet bool, startEpoch abi.ChainEpoch) {
|
||||
s := setupOneClientOneMiner(t, b, blocktime)
|
||||
defer s.blockMiner.Stop()
|
||||
|
||||
MakeDeal(t, s.ctx, 6, s.client, s.miner, carExport, fastRet, startEpoch)
|
||||
}
|
||||
|
||||
func init() {
|
||||
logging.SetAllLoggers(logging.LevelInfo)
|
||||
build.InsecurePoStValidation = true
|
||||
func TestDoubleDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration, startEpoch abi.ChainEpoch) {
|
||||
s := setupOneClientOneMiner(t, b, blocktime)
|
||||
defer s.blockMiner.Stop()
|
||||
|
||||
MakeDeal(t, s.ctx, 6, s.client, s.miner, false, false, startEpoch)
|
||||
MakeDeal(t, s.ctx, 7, s.client, s.miner, false, false, startEpoch)
|
||||
}
|
||||
|
||||
func TestDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration, carExport, fastRet bool) {
|
||||
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
||||
|
||||
ctx := context.Background()
|
||||
n, sn := b(t, OneFull, OneMiner)
|
||||
client := n[0].FullNode.(*impl.FullNodeAPI)
|
||||
miner := sn[0]
|
||||
|
||||
addrinfo, err := client.NetAddrsListen(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := miner.NetConnect(ctx, addrinfo); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
|
||||
mine := int64(1)
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
for atomic.LoadInt64(&mine) == 1 {
|
||||
time.Sleep(blocktime)
|
||||
if err := sn[0].MineOne(ctx, MineNext); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
makeDeal(t, ctx, 6, client, miner, carExport, fastRet)
|
||||
|
||||
atomic.AddInt64(&mine, -1)
|
||||
fmt.Println("shutting down mining")
|
||||
<-done
|
||||
}
|
||||
|
||||
func TestDoubleDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
||||
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
||||
|
||||
ctx := context.Background()
|
||||
n, sn := b(t, OneFull, OneMiner)
|
||||
client := n[0].FullNode.(*impl.FullNodeAPI)
|
||||
miner := sn[0]
|
||||
|
||||
addrinfo, err := client.NetAddrsListen(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := miner.NetConnect(ctx, addrinfo); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
|
||||
mine := int64(1)
|
||||
done := make(chan struct{})
|
||||
|
||||
go func() {
|
||||
defer close(done)
|
||||
for atomic.LoadInt64(&mine) == 1 {
|
||||
time.Sleep(blocktime)
|
||||
if err := sn[0].MineOne(ctx, MineNext); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
makeDeal(t, ctx, 6, client, miner, false, false)
|
||||
makeDeal(t, ctx, 7, client, miner, false, false)
|
||||
|
||||
atomic.AddInt64(&mine, -1)
|
||||
fmt.Println("shutting down mining")
|
||||
<-done
|
||||
}
|
||||
|
||||
func makeDeal(t *testing.T, ctx context.Context, rseed int, client *impl.FullNodeAPI, miner TestStorageNode, carExport, fastRet bool) {
|
||||
data := make([]byte, 1600)
|
||||
rand.New(rand.NewSource(int64(rseed))).Read(data)
|
||||
|
||||
r := bytes.NewReader(data)
|
||||
fcid, err := client.ClientImportLocal(ctx, r)
|
||||
func MakeDeal(t *testing.T, ctx context.Context, rseed int, client api.FullNode, miner TestStorageNode, carExport, fastRet bool, startEpoch abi.ChainEpoch) {
|
||||
res, data, err := CreateClientFile(ctx, client, rseed)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
fcid := res.Root
|
||||
fmt.Println("FILE CID: ", fcid)
|
||||
|
||||
deal := startDeal(t, ctx, miner, client, fcid, fastRet)
|
||||
deal := startDeal(t, ctx, miner, client, fcid, fastRet, startEpoch)
|
||||
|
||||
// TODO: this sleep is only necessary because deals don't immediately get logged in the dealstore, we should fix this
|
||||
time.Sleep(time.Second)
|
||||
@@ -145,98 +70,155 @@ func makeDeal(t *testing.T, ctx context.Context, rseed int, client *impl.FullNod
|
||||
testRetrieval(t, ctx, client, fcid, &info.PieceCID, carExport, data)
|
||||
}
|
||||
|
||||
func TestFastRetrievalDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
||||
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
||||
func CreateClientFile(ctx context.Context, client api.FullNode, rseed int) (*api.ImportRes, []byte, error) {
|
||||
data := make([]byte, 1600)
|
||||
rand.New(rand.NewSource(int64(rseed))).Read(data)
|
||||
|
||||
ctx := context.Background()
|
||||
n, sn := b(t, OneFull, OneMiner)
|
||||
dir, err := ioutil.TempDir(os.TempDir(), "test-make-deal-")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
path := filepath.Join(dir, "sourcefile.dat")
|
||||
err = ioutil.WriteFile(path, data, 0644)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
res, err := client.ClientImport(ctx, api.FileRef{Path: path})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return res, data, nil
|
||||
}
|
||||
|
||||
func TestPublishDealsBatching(t *testing.T, b APIBuilder, blocktime time.Duration, startEpoch abi.ChainEpoch) {
|
||||
publishPeriod := 10 * time.Second
|
||||
maxDealsPerMsg := uint64(2)
|
||||
|
||||
// Set max deals per publish deals message to 2
|
||||
minerDef := []StorageMiner{{
|
||||
Full: 0,
|
||||
Opts: node.Override(
|
||||
new(*storageadapter.DealPublisher),
|
||||
storageadapter.NewDealPublisher(nil, storageadapter.PublishMsgConfig{
|
||||
Period: publishPeriod,
|
||||
MaxDealsPerMsg: maxDealsPerMsg,
|
||||
})),
|
||||
Preseal: PresealGenesis,
|
||||
}}
|
||||
|
||||
// Create a connect client and miner node
|
||||
n, sn := b(t, OneFull, minerDef)
|
||||
client := n[0].FullNode.(*impl.FullNodeAPI)
|
||||
miner := sn[0]
|
||||
s := connectAndStartMining(t, b, blocktime, client, miner)
|
||||
defer s.blockMiner.Stop()
|
||||
|
||||
addrinfo, err := client.NetAddrsListen(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Starts a deal and waits until it's published
|
||||
runDealTillPublish := func(rseed int) {
|
||||
res, _, err := CreateClientFile(s.ctx, s.client, rseed)
|
||||
require.NoError(t, err)
|
||||
|
||||
if err := miner.NetConnect(ctx, addrinfo); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
upds, err := client.ClientGetDealUpdates(s.ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
mine := int64(1)
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
for atomic.LoadInt64(&mine) == 1 {
|
||||
time.Sleep(blocktime)
|
||||
if err := sn[0].MineOne(ctx, MineNext); err != nil {
|
||||
t.Error(err)
|
||||
startDeal(t, s.ctx, s.miner, s.client, res.Root, false, startEpoch)
|
||||
|
||||
// TODO: this sleep is only necessary because deals don't immediately get logged in the dealstore, we should fix this
|
||||
time.Sleep(time.Second)
|
||||
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
for upd := range upds {
|
||||
if upd.DataRef.Root == res.Root && upd.State == storagemarket.StorageDealAwaitingPreCommit {
|
||||
done <- struct{}{}
|
||||
}
|
||||
}
|
||||
}()
|
||||
<-done
|
||||
}
|
||||
|
||||
// Run three deals in parallel
|
||||
done := make(chan struct{}, maxDealsPerMsg+1)
|
||||
for rseed := 1; rseed <= 3; rseed++ {
|
||||
rseed := rseed
|
||||
go func() {
|
||||
runDealTillPublish(rseed)
|
||||
done <- struct{}{}
|
||||
}()
|
||||
}
|
||||
|
||||
// Wait for two of the deals to be published
|
||||
for i := 0; i < int(maxDealsPerMsg); i++ {
|
||||
<-done
|
||||
}
|
||||
|
||||
// Expect a single PublishStorageDeals message that includes the first two deals
|
||||
msgCids, err := s.client.StateListMessages(s.ctx, &api.MessageMatch{To: market.Address}, types.EmptyTSK, 1)
|
||||
require.NoError(t, err)
|
||||
count := 0
|
||||
for _, msgCid := range msgCids {
|
||||
msg, err := s.client.ChainGetMessage(s.ctx, msgCid)
|
||||
require.NoError(t, err)
|
||||
|
||||
if msg.Method == market.Methods.PublishStorageDeals {
|
||||
count++
|
||||
var pubDealsParams market2.PublishStorageDealsParams
|
||||
err = pubDealsParams.UnmarshalCBOR(bytes.NewReader(msg.Params))
|
||||
require.NoError(t, err)
|
||||
require.Len(t, pubDealsParams.Deals, int(maxDealsPerMsg))
|
||||
}
|
||||
}()
|
||||
}
|
||||
require.Equal(t, 1, count)
|
||||
|
||||
// The third deal should be published once the publish period expires.
|
||||
// Allow a little padding as it takes a moment for the state change to
|
||||
// be noticed by the client.
|
||||
padding := 10 * time.Second
|
||||
select {
|
||||
case <-time.After(publishPeriod + padding):
|
||||
require.Fail(t, "Expected 3rd deal to be published once publish period elapsed")
|
||||
case <-done: // Success
|
||||
}
|
||||
}
|
||||
|
||||
func TestFastRetrievalDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration, startEpoch abi.ChainEpoch) {
|
||||
s := setupOneClientOneMiner(t, b, blocktime)
|
||||
defer s.blockMiner.Stop()
|
||||
|
||||
data := make([]byte, 1600)
|
||||
rand.New(rand.NewSource(int64(8))).Read(data)
|
||||
|
||||
r := bytes.NewReader(data)
|
||||
fcid, err := client.ClientImportLocal(ctx, r)
|
||||
fcid, err := s.client.ClientImportLocal(s.ctx, r)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println("FILE CID: ", fcid)
|
||||
|
||||
deal := startDeal(t, ctx, miner, client, fcid, true)
|
||||
deal := startDeal(t, s.ctx, s.miner, s.client, fcid, true, startEpoch)
|
||||
|
||||
waitDealPublished(t, ctx, miner, deal)
|
||||
waitDealPublished(t, s.ctx, s.miner, deal)
|
||||
fmt.Println("deal published, retrieving")
|
||||
// Retrieval
|
||||
info, err := client.ClientGetDealInfo(ctx, *deal)
|
||||
info, err := s.client.ClientGetDealInfo(s.ctx, *deal)
|
||||
require.NoError(t, err)
|
||||
|
||||
testRetrieval(t, ctx, client, fcid, &info.PieceCID, false, data)
|
||||
atomic.AddInt64(&mine, -1)
|
||||
fmt.Println("shutting down mining")
|
||||
<-done
|
||||
testRetrieval(t, s.ctx, s.client, fcid, &info.PieceCID, false, data)
|
||||
}
|
||||
|
||||
func TestSenondDealRetrieval(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
||||
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
||||
|
||||
ctx := context.Background()
|
||||
n, sn := b(t, OneFull, OneMiner)
|
||||
client := n[0].FullNode.(*impl.FullNodeAPI)
|
||||
miner := sn[0]
|
||||
|
||||
addrinfo, err := client.NetAddrsListen(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := miner.NetConnect(ctx, addrinfo); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
|
||||
mine := int64(1)
|
||||
done := make(chan struct{})
|
||||
|
||||
go func() {
|
||||
defer close(done)
|
||||
for atomic.LoadInt64(&mine) == 1 {
|
||||
time.Sleep(blocktime)
|
||||
if err := sn[0].MineOne(ctx, MineNext); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
func TestSecondDealRetrieval(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
||||
s := setupOneClientOneMiner(t, b, blocktime)
|
||||
defer s.blockMiner.Stop()
|
||||
|
||||
{
|
||||
data1 := make([]byte, 800)
|
||||
rand.New(rand.NewSource(int64(3))).Read(data1)
|
||||
r := bytes.NewReader(data1)
|
||||
|
||||
fcid1, err := client.ClientImportLocal(ctx, r)
|
||||
fcid1, err := s.client.ClientImportLocal(s.ctx, r)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -245,38 +227,49 @@ func TestSenondDealRetrieval(t *testing.T, b APIBuilder, blocktime time.Duration
|
||||
rand.New(rand.NewSource(int64(9))).Read(data2)
|
||||
r2 := bytes.NewReader(data2)
|
||||
|
||||
fcid2, err := client.ClientImportLocal(ctx, r2)
|
||||
fcid2, err := s.client.ClientImportLocal(s.ctx, r2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
deal1 := startDeal(t, ctx, miner, client, fcid1, true)
|
||||
deal1 := startDeal(t, s.ctx, s.miner, s.client, fcid1, true, 0)
|
||||
|
||||
// TODO: this sleep is only necessary because deals don't immediately get logged in the dealstore, we should fix this
|
||||
time.Sleep(time.Second)
|
||||
waitDealSealed(t, ctx, miner, client, deal1, true)
|
||||
waitDealSealed(t, s.ctx, s.miner, s.client, deal1, true)
|
||||
|
||||
deal2 := startDeal(t, ctx, miner, client, fcid2, true)
|
||||
deal2 := startDeal(t, s.ctx, s.miner, s.client, fcid2, true, 0)
|
||||
|
||||
time.Sleep(time.Second)
|
||||
waitDealSealed(t, ctx, miner, client, deal2, false)
|
||||
waitDealSealed(t, s.ctx, s.miner, s.client, deal2, false)
|
||||
|
||||
// Retrieval
|
||||
info, err := client.ClientGetDealInfo(ctx, *deal2)
|
||||
info, err := s.client.ClientGetDealInfo(s.ctx, *deal2)
|
||||
require.NoError(t, err)
|
||||
|
||||
rf, _ := miner.SectorsRefs(ctx)
|
||||
rf, _ := s.miner.SectorsRefs(s.ctx)
|
||||
fmt.Printf("refs: %+v\n", rf)
|
||||
|
||||
testRetrieval(t, ctx, client, fcid2, &info.PieceCID, false, data2)
|
||||
testRetrieval(t, s.ctx, s.client, fcid2, &info.PieceCID, false, data2)
|
||||
}
|
||||
|
||||
atomic.AddInt64(&mine, -1)
|
||||
fmt.Println("shutting down mining")
|
||||
<-done
|
||||
}
|
||||
|
||||
func startDeal(t *testing.T, ctx context.Context, miner TestStorageNode, client *impl.FullNodeAPI, fcid cid.Cid, fastRet bool) *cid.Cid {
|
||||
func TestZeroPricePerByteRetrievalDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration, startEpoch abi.ChainEpoch) {
|
||||
s := setupOneClientOneMiner(t, b, blocktime)
|
||||
defer s.blockMiner.Stop()
|
||||
|
||||
// Set price-per-byte to zero
|
||||
ask, err := s.miner.MarketGetRetrievalAsk(s.ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
ask.PricePerByte = abi.NewTokenAmount(0)
|
||||
err = s.miner.MarketSetRetrievalAsk(s.ctx, ask)
|
||||
require.NoError(t, err)
|
||||
|
||||
MakeDeal(t, s.ctx, 6, s.client, s.miner, false, false, startEpoch)
|
||||
}
|
||||
|
||||
func startDeal(t *testing.T, ctx context.Context, miner TestStorageNode, client api.FullNode, fcid cid.Cid, fastRet bool, startEpoch abi.ChainEpoch) *cid.Cid {
|
||||
maddr, err := miner.ActorAddress(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -294,6 +287,7 @@ func startDeal(t *testing.T, ctx context.Context, miner TestStorageNode, client
|
||||
Wallet: addr,
|
||||
Miner: maddr,
|
||||
EpochPrice: types.NewInt(1000000),
|
||||
DealStartEpoch: startEpoch,
|
||||
MinBlocksDuration: uint64(build.MinDealDuration),
|
||||
FastRetrieval: fastRet,
|
||||
})
|
||||
@@ -303,7 +297,7 @@ func startDeal(t *testing.T, ctx context.Context, miner TestStorageNode, client
|
||||
return deal
|
||||
}
|
||||
|
||||
func waitDealSealed(t *testing.T, ctx context.Context, miner TestStorageNode, client *impl.FullNodeAPI, deal *cid.Cid, noseal bool) {
|
||||
func waitDealSealed(t *testing.T, ctx context.Context, miner TestStorageNode, client api.FullNode, deal *cid.Cid, noseal bool) {
|
||||
loop:
|
||||
for {
|
||||
di, err := client.ClientGetDealInfo(ctx, *deal)
|
||||
@@ -311,7 +305,7 @@ loop:
|
||||
t.Fatal(err)
|
||||
}
|
||||
switch di.State {
|
||||
case storagemarket.StorageDealSealing:
|
||||
case storagemarket.StorageDealAwaitingPreCommit, storagemarket.StorageDealSealing:
|
||||
if noseal {
|
||||
return
|
||||
}
|
||||
@@ -351,7 +345,7 @@ func waitDealPublished(t *testing.T, ctx context.Context, miner TestStorageNode,
|
||||
t.Fatal("deal failed")
|
||||
case storagemarket.StorageDealError:
|
||||
t.Fatal("deal errored", di.Message)
|
||||
case storagemarket.StorageDealFinalizing, storagemarket.StorageDealSealing, storagemarket.StorageDealActive:
|
||||
case storagemarket.StorageDealFinalizing, storagemarket.StorageDealAwaitingPreCommit, storagemarket.StorageDealSealing, storagemarket.StorageDealActive:
|
||||
fmt.Println("COMPLETE", di)
|
||||
return
|
||||
}
|
||||
@@ -376,7 +370,7 @@ func startSealingWaiting(t *testing.T, ctx context.Context, miner TestStorageNod
|
||||
}
|
||||
}
|
||||
|
||||
func testRetrieval(t *testing.T, ctx context.Context, client *impl.FullNodeAPI, fcid cid.Cid, piece *cid.Cid, carExport bool, data []byte) {
|
||||
func testRetrieval(t *testing.T, ctx context.Context, client api.FullNode, fcid cid.Cid, piece *cid.Cid, carExport bool, data []byte) {
|
||||
offers, err := client.ClientFindData(ctx, fcid, piece)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -454,3 +448,40 @@ func extractCarData(t *testing.T, ctx context.Context, rdata []byte, rpath strin
|
||||
}
|
||||
return rdata
|
||||
}
|
||||
|
||||
type dealsScaffold struct {
|
||||
ctx context.Context
|
||||
client *impl.FullNodeAPI
|
||||
miner TestStorageNode
|
||||
blockMiner *BlockMiner
|
||||
}
|
||||
|
||||
func setupOneClientOneMiner(t *testing.T, b APIBuilder, blocktime time.Duration) *dealsScaffold {
|
||||
n, sn := b(t, OneFull, OneMiner)
|
||||
client := n[0].FullNode.(*impl.FullNodeAPI)
|
||||
miner := sn[0]
|
||||
return connectAndStartMining(t, b, blocktime, client, miner)
|
||||
}
|
||||
|
||||
func connectAndStartMining(t *testing.T, b APIBuilder, blocktime time.Duration, client *impl.FullNodeAPI, miner TestStorageNode) *dealsScaffold {
|
||||
ctx := context.Background()
|
||||
addrinfo, err := client.NetAddrsListen(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := miner.NetConnect(ctx, addrinfo); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
|
||||
blockMiner := NewBlockMiner(ctx, t, miner, blocktime)
|
||||
blockMiner.MineBlocks()
|
||||
|
||||
return &dealsScaffold{
|
||||
ctx: ctx,
|
||||
client: client,
|
||||
miner: miner,
|
||||
blockMiner: blockMiner,
|
||||
}
|
||||
}
|
||||
|
||||
+46
-13
@@ -5,17 +5,19 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/miner"
|
||||
"github.com/filecoin-project/lotus/node/impl"
|
||||
)
|
||||
@@ -59,14 +61,11 @@ func (ts *testSuite) testMiningReal(t *testing.T) {
|
||||
|
||||
newHeads, err := api.ChainNotify(ctx)
|
||||
require.NoError(t, err)
|
||||
initHead := (<-newHeads)[0]
|
||||
if initHead.Val.Height() != 2 {
|
||||
<-newHeads
|
||||
}
|
||||
at := (<-newHeads)[0].Val.Height()
|
||||
|
||||
h1, err := api.ChainHead(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, abi.ChainEpoch(2), h1.Height())
|
||||
require.Equal(t, int64(at), int64(h1.Height()))
|
||||
|
||||
MineUntilBlock(ctx, t, apis[0], sn[0], nil)
|
||||
require.NoError(t, err)
|
||||
@@ -75,21 +74,19 @@ func (ts *testSuite) testMiningReal(t *testing.T) {
|
||||
|
||||
h2, err := api.ChainHead(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, abi.ChainEpoch(3), h2.Height())
|
||||
require.Greater(t, int64(h2.Height()), int64(h1.Height()))
|
||||
|
||||
MineUntilBlock(ctx, t, apis[0], sn[0], nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
<-newHeads
|
||||
|
||||
h2, err = api.ChainHead(ctx)
|
||||
h3, err := api.ChainHead(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, abi.ChainEpoch(4), h2.Height())
|
||||
require.Greater(t, int64(h3.Height()), int64(h2.Height()))
|
||||
}
|
||||
|
||||
func TestDealMining(t *testing.T, b APIBuilder, blocktime time.Duration, carExport bool) {
|
||||
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
||||
|
||||
// test making a deal with a fresh miner, and see if it starts to mine
|
||||
|
||||
ctx := context.Background()
|
||||
@@ -192,7 +189,7 @@ func TestDealMining(t *testing.T, b APIBuilder, blocktime time.Duration, carExpo
|
||||
}
|
||||
}()
|
||||
|
||||
deal := startDeal(t, ctx, provider, client, fcid, false)
|
||||
deal := startDeal(t, ctx, provider, client, fcid, false, 0)
|
||||
|
||||
// TODO: this sleep is only necessary because deals don't immediately get logged in the dealstore, we should fix this
|
||||
time.Sleep(time.Second)
|
||||
@@ -205,3 +202,39 @@ func TestDealMining(t *testing.T, b APIBuilder, blocktime time.Duration, carExpo
|
||||
fmt.Println("shutting down mining")
|
||||
<-done
|
||||
}
|
||||
|
||||
func (ts *testSuite) testNonGenesisMiner(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
n, sn := ts.makeNodes(t, []FullNodeOpts{
|
||||
FullNodeWithActorsV4At(-1),
|
||||
}, []StorageMiner{
|
||||
{Full: 0, Preseal: PresealGenesis},
|
||||
})
|
||||
|
||||
full, ok := n[0].FullNode.(*impl.FullNodeAPI)
|
||||
if !ok {
|
||||
t.Skip("not testing with a full node")
|
||||
return
|
||||
}
|
||||
genesisMiner := sn[0]
|
||||
|
||||
bm := NewBlockMiner(ctx, t, genesisMiner, 4*time.Millisecond)
|
||||
bm.MineBlocks()
|
||||
t.Cleanup(bm.Stop)
|
||||
|
||||
gaa, err := genesisMiner.ActorAddress(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
gmi, err := full.StateMinerInfo(ctx, gaa, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
|
||||
testm := n[0].Stb(ctx, t, TestSpt, gmi.Owner)
|
||||
|
||||
ta, err := testm.ActorAddress(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
tid, err := address.IDFromAddress(ta)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, uint64(1001), tid)
|
||||
}
|
||||
|
||||
+6
-10
@@ -3,14 +3,10 @@ package test
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
paych0 "github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"github.com/ipfs/go-cid"
|
||||
@@ -19,18 +15,18 @@ import (
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/api/apibstore"
|
||||
"github.com/filecoin-project/lotus/blockstore"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
|
||||
"github.com/filecoin-project/lotus/chain/actors/policy"
|
||||
"github.com/filecoin-project/lotus/chain/events"
|
||||
"github.com/filecoin-project/lotus/chain/events/state"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
func TestPaymentChannels(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
||||
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
||||
|
||||
ctx := context.Background()
|
||||
n, sn := b(t, TwoFull, OneMiner)
|
||||
|
||||
@@ -136,7 +132,7 @@ func TestPaymentChannels(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
||||
t.Fatal("Unable to settle payment channel")
|
||||
}
|
||||
|
||||
creatorStore := adt.WrapStore(ctx, cbor.NewCborStore(apibstore.NewAPIBlockstore(paymentCreator)))
|
||||
creatorStore := adt.WrapStore(ctx, cbor.NewCborStore(blockstore.NewAPIBlockstore(paymentCreator)))
|
||||
|
||||
// wait for the receiver to submit their vouchers
|
||||
ev := events.NewEvents(ctx, paymentCreator)
|
||||
@@ -227,7 +223,7 @@ func TestPaymentChannels(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
||||
}
|
||||
|
||||
// wait for the settlement period to pass before collecting
|
||||
waitForBlocks(ctx, t, bm, paymentReceiver, receiverAddr, paych0.SettleDelay)
|
||||
waitForBlocks(ctx, t, bm, paymentReceiver, receiverAddr, policy.PaychSettleDelay)
|
||||
|
||||
creatorPreCollectBalance, err := paymentCreator.WalletBalance(ctx, createrAddr)
|
||||
if err != nil {
|
||||
@@ -283,7 +279,7 @@ func waitForBlocks(ctx context.Context, t *testing.T, bm *BlockMiner, paymentRec
|
||||
|
||||
// Add a real block
|
||||
m, err := paymentReceiver.MpoolPushMessage(ctx, &types.Message{
|
||||
To: builtin0.BurntFundsActorAddr,
|
||||
To: builtin.BurntFundsActorAddr,
|
||||
From: receiverAddr,
|
||||
Value: types.NewInt(0),
|
||||
}, nil)
|
||||
|
||||
+5
-18
@@ -6,7 +6,6 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
@@ -18,7 +17,9 @@ import (
|
||||
)
|
||||
|
||||
func TestTapeFix(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
||||
t.Run("before", func(t *testing.T) { testTapeFix(t, b, blocktime, false) })
|
||||
// The "before" case is disabled, because we need the builder to mock 32 GiB sectors to accurately repro this case
|
||||
// TODO: Make the mock sector size configurable and reenable this
|
||||
//t.Run("before", func(t *testing.T) { testTapeFix(t, b, blocktime, false) })
|
||||
t.Run("after", func(t *testing.T) { testTapeFix(t, b, blocktime, true) })
|
||||
}
|
||||
func testTapeFix(t *testing.T, b APIBuilder, blocktime time.Duration, after bool) {
|
||||
@@ -73,23 +74,9 @@ func testTapeFix(t *testing.T, b APIBuilder, blocktime time.Duration, after bool
|
||||
<-done
|
||||
}()
|
||||
|
||||
err = miner.PledgeSector(ctx)
|
||||
sid, err := miner.PledgeSector(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Wait till done.
|
||||
var sectorNo abi.SectorNumber
|
||||
for {
|
||||
s, err := miner.SectorsList(ctx) // Note - the test builder doesn't import genesis sectors into FSM
|
||||
require.NoError(t, err)
|
||||
fmt.Printf("Sectors: %d\n", len(s))
|
||||
if len(s) == 1 {
|
||||
sectorNo = s[0]
|
||||
break
|
||||
}
|
||||
|
||||
build.Clock.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
|
||||
fmt.Printf("All sectors is fsm\n")
|
||||
|
||||
// If before, we expect the precommit to fail
|
||||
@@ -101,7 +88,7 @@ func testTapeFix(t *testing.T, b APIBuilder, blocktime time.Duration, after bool
|
||||
}
|
||||
|
||||
for {
|
||||
st, err := miner.SectorsStatus(ctx, sectorNo, false)
|
||||
st, err := miner.SectorsStatus(ctx, sid.Number, false)
|
||||
require.NoError(t, err)
|
||||
if st.State == successState {
|
||||
break
|
||||
|
||||
+77
-11
@@ -2,31 +2,49 @@ package test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
"github.com/multiformats/go-multiaddr"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/miner"
|
||||
"github.com/filecoin-project/lotus/node"
|
||||
)
|
||||
|
||||
func init() {
|
||||
logging.SetAllLoggers(logging.LevelInfo)
|
||||
err := os.Setenv("BELLMAN_NO_GPU", "1")
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to set BELLMAN_NO_GPU env variable: %s", err))
|
||||
}
|
||||
build.InsecurePoStValidation = true
|
||||
}
|
||||
|
||||
type StorageBuilder func(context.Context, *testing.T, abi.RegisteredSealProof, address.Address) TestStorageNode
|
||||
|
||||
type TestNode struct {
|
||||
api.FullNode
|
||||
// ListenAddr is the address on which an API server is listening, if an
|
||||
// API server is created for this Node
|
||||
ListenAddr multiaddr.Multiaddr
|
||||
|
||||
Stb StorageBuilder
|
||||
}
|
||||
|
||||
type TestStorageNode struct {
|
||||
@@ -36,15 +54,19 @@ type TestStorageNode struct {
|
||||
ListenAddr multiaddr.Multiaddr
|
||||
|
||||
MineOne func(context.Context, miner.MineReq) error
|
||||
Stop func(context.Context) error
|
||||
}
|
||||
|
||||
var PresealGenesis = -1
|
||||
|
||||
const GenesisPreseals = 2
|
||||
|
||||
const TestSpt = abi.RegisteredSealProof_StackedDrg2KiBV1_1
|
||||
|
||||
// Options for setting up a mock storage miner
|
||||
type StorageMiner struct {
|
||||
Full int
|
||||
Opts node.Option
|
||||
Preseal int
|
||||
}
|
||||
|
||||
@@ -79,6 +101,7 @@ func TestApis(t *testing.T, b APIBuilder) {
|
||||
t.Run("testMining", ts.testMining)
|
||||
t.Run("testMiningReal", ts.testMiningReal)
|
||||
t.Run("testSearchMsg", ts.testSearchMsg)
|
||||
t.Run("testNonGenesisMiner", ts.testNonGenesisMiner)
|
||||
}
|
||||
|
||||
func DefaultFullOpts(nFull int) []FullNodeOpts {
|
||||
@@ -97,31 +120,74 @@ var OneMiner = []StorageMiner{{Full: 0, Preseal: PresealGenesis}}
|
||||
var OneFull = DefaultFullOpts(1)
|
||||
var TwoFull = DefaultFullOpts(2)
|
||||
|
||||
var FullNodeWithUpgradeAt = func(upgradeHeight abi.ChainEpoch) FullNodeOpts {
|
||||
var FullNodeWithActorsV4At = func(upgradeHeight abi.ChainEpoch) FullNodeOpts {
|
||||
if upgradeHeight == -1 {
|
||||
upgradeHeight = 3
|
||||
}
|
||||
|
||||
return FullNodeOpts{
|
||||
Opts: func(nodes []TestNode) node.Option {
|
||||
return node.Override(new(stmgr.UpgradeSchedule), stmgr.UpgradeSchedule{{
|
||||
// Skip directly to tape height so precommits work.
|
||||
Network: network.Version5,
|
||||
Height: upgradeHeight,
|
||||
// prepare for upgrade.
|
||||
Network: network.Version9,
|
||||
Height: 1,
|
||||
Migration: stmgr.UpgradeActorsV2,
|
||||
}, {
|
||||
Network: network.Version10,
|
||||
Height: 2,
|
||||
Migration: stmgr.UpgradeActorsV3,
|
||||
}, {
|
||||
Network: network.Version12,
|
||||
Height: upgradeHeight,
|
||||
Migration: stmgr.UpgradeActorsV4,
|
||||
}})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
var FullNodeWithSDRAt = func(calico, persian abi.ChainEpoch) FullNodeOpts {
|
||||
return FullNodeOpts{
|
||||
Opts: func(nodes []TestNode) node.Option {
|
||||
return node.Override(new(stmgr.UpgradeSchedule), stmgr.UpgradeSchedule{{
|
||||
Network: network.Version6,
|
||||
Height: 1,
|
||||
Migration: stmgr.UpgradeActorsV2,
|
||||
}, {
|
||||
Network: network.Version7,
|
||||
Height: calico,
|
||||
Migration: stmgr.UpgradeCalico,
|
||||
}, {
|
||||
Network: network.Version8,
|
||||
Height: persian,
|
||||
}})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
var MineNext = miner.MineReq{
|
||||
InjectNulls: 0,
|
||||
Done: func(bool, abi.ChainEpoch, error) {},
|
||||
}
|
||||
|
||||
func (ts *testSuite) testVersion(t *testing.T) {
|
||||
build.RunningNodeType = build.NodeFull
|
||||
api.RunningNodeType = api.NodeFull
|
||||
t.Cleanup(func() {
|
||||
api.RunningNodeType = api.NodeUnknown
|
||||
})
|
||||
|
||||
ctx := context.Background()
|
||||
apis, _ := ts.makeNodes(t, OneFull, OneMiner)
|
||||
api := apis[0]
|
||||
napi := apis[0]
|
||||
|
||||
v, err := api.Version(ctx)
|
||||
v, err := napi.Version(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.Equal(t, v.Version, build.BuildVersion)
|
||||
versions := strings.Split(v.Version, "+")
|
||||
if len(versions) <= 0 {
|
||||
t.Fatal("empty version")
|
||||
}
|
||||
require.Equal(t, versions[0], build.BuildVersion)
|
||||
}
|
||||
|
||||
func (ts *testSuite) testSearchMsg(t *testing.T) {
|
||||
|
||||
+697
-15
@@ -3,32 +3,118 @@ package test
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"sync/atomic"
|
||||
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-bitfield"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
"github.com/filecoin-project/go-state-types/dline"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/mock"
|
||||
sealing "github.com/filecoin-project/lotus/extern/storage-sealing"
|
||||
proof3 "github.com/filecoin-project/specs-actors/v3/actors/runtime/proof"
|
||||
"github.com/filecoin-project/specs-storage/storage"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
minerActor "github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
bminer "github.com/filecoin-project/lotus/miner"
|
||||
"github.com/filecoin-project/lotus/node/impl"
|
||||
)
|
||||
|
||||
func init() {
|
||||
err := os.Setenv("BELLMAN_NO_GPU", "1")
|
||||
func TestSDRUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
n, sn := b(t, []FullNodeOpts{FullNodeWithSDRAt(500, 1000)}, OneMiner)
|
||||
client := n[0].FullNode.(*impl.FullNodeAPI)
|
||||
miner := sn[0]
|
||||
|
||||
addrinfo, err := client.NetAddrsListen(ctx)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to set BELLMAN_NO_GPU env variable: %s", err))
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := miner.NetConnect(ctx, addrinfo); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
build.Clock.Sleep(time.Second)
|
||||
|
||||
pledge := make(chan struct{})
|
||||
mine := int64(1)
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
round := 0
|
||||
for atomic.LoadInt64(&mine) != 0 {
|
||||
build.Clock.Sleep(blocktime)
|
||||
if err := sn[0].MineOne(ctx, bminer.MineReq{Done: func(bool, abi.ChainEpoch, error) {
|
||||
|
||||
}}); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// 3 sealing rounds: before, during after.
|
||||
if round >= 3 {
|
||||
continue
|
||||
}
|
||||
|
||||
head, err := client.ChainHead(ctx)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// rounds happen every 100 blocks, with a 50 block offset.
|
||||
if head.Height() >= abi.ChainEpoch(round*500+50) {
|
||||
round++
|
||||
pledge <- struct{}{}
|
||||
|
||||
ver, err := client.StateNetworkVersion(ctx, head.Key())
|
||||
assert.NoError(t, err)
|
||||
switch round {
|
||||
case 1:
|
||||
assert.Equal(t, network.Version6, ver)
|
||||
case 2:
|
||||
assert.Equal(t, network.Version7, ver)
|
||||
case 3:
|
||||
assert.Equal(t, network.Version8, ver)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}()
|
||||
|
||||
// before.
|
||||
pledgeSectors(t, ctx, miner, 9, 0, pledge)
|
||||
|
||||
s, err := miner.SectorsList(ctx)
|
||||
require.NoError(t, err)
|
||||
sort.Slice(s, func(i, j int) bool {
|
||||
return s[i] < s[j]
|
||||
})
|
||||
|
||||
for i, id := range s {
|
||||
info, err := miner.SectorsStatus(ctx, id, true)
|
||||
require.NoError(t, err)
|
||||
expectProof := abi.RegisteredSealProof_StackedDrg2KiBV1
|
||||
if i >= 3 {
|
||||
// after
|
||||
expectProof = abi.RegisteredSealProof_StackedDrg2KiBV1_1
|
||||
}
|
||||
assert.Equal(t, expectProof, info.SealProof, "sector %d, id %d", i, id)
|
||||
}
|
||||
|
||||
atomic.StoreInt64(&mine, 0)
|
||||
<-done
|
||||
}
|
||||
|
||||
func TestPledgeSector(t *testing.T, b APIBuilder, blocktime time.Duration, nSectors int) {
|
||||
@@ -71,11 +157,13 @@ func TestPledgeSector(t *testing.T, b APIBuilder, blocktime time.Duration, nSect
|
||||
|
||||
func pledgeSectors(t *testing.T, ctx context.Context, miner TestStorageNode, n, existing int, blockNotif <-chan struct{}) {
|
||||
for i := 0; i < n; i++ {
|
||||
err := miner.PledgeSector(ctx)
|
||||
require.NoError(t, err)
|
||||
if i%3 == 0 && blockNotif != nil {
|
||||
<-blockNotif
|
||||
log.Errorf("WAIT")
|
||||
}
|
||||
log.Errorf("PLEDGING %d", i)
|
||||
_, err := miner.PledgeSector(ctx)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
for {
|
||||
@@ -118,7 +206,7 @@ func pledgeSectors(t *testing.T, ctx context.Context, miner TestStorageNode, n,
|
||||
|
||||
func TestWindowPost(t *testing.T, b APIBuilder, blocktime time.Duration, nSectors int) {
|
||||
for _, height := range []abi.ChainEpoch{
|
||||
1, // before
|
||||
-1, // before
|
||||
162, // while sealing
|
||||
5000, // while proving
|
||||
} {
|
||||
@@ -129,12 +217,13 @@ func TestWindowPost(t *testing.T, b APIBuilder, blocktime time.Duration, nSector
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func testWindowPostUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration, nSectors int,
|
||||
upgradeHeight abi.ChainEpoch) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
n, sn := b(t, []FullNodeOpts{FullNodeWithUpgradeAt(upgradeHeight)}, OneMiner)
|
||||
n, sn := b(t, []FullNodeOpts{FullNodeWithActorsV4At(upgradeHeight)}, OneMiner)
|
||||
|
||||
client := n[0].FullNode.(*impl.FullNodeAPI)
|
||||
miner := sn[0]
|
||||
@@ -217,15 +306,17 @@ func testWindowPostUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration,
|
||||
|
||||
// Drop the partition
|
||||
err = secs.ForEach(func(sid uint64) error {
|
||||
return miner.StorageMiner.(*impl.StorageMinerAPI).IStorageMgr.(*mock.SectorMgr).MarkCorrupted(abi.SectorID{
|
||||
Miner: abi.ActorID(mid),
|
||||
Number: abi.SectorNumber(sid),
|
||||
return miner.StorageMiner.(*impl.StorageMinerAPI).IStorageMgr.(*mock.SectorMgr).MarkCorrupted(storage.SectorRef{
|
||||
ID: abi.SectorID{
|
||||
Miner: abi.ActorID(mid),
|
||||
Number: abi.SectorNumber(sid),
|
||||
},
|
||||
}, true)
|
||||
})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
var s abi.SectorID
|
||||
var s storage.SectorRef
|
||||
|
||||
// Drop 1 sectors from deadline 3 partition 0
|
||||
{
|
||||
@@ -246,9 +337,11 @@ func testWindowPostUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration,
|
||||
require.NoError(t, err)
|
||||
fmt.Println("the sectors", all)
|
||||
|
||||
s = abi.SectorID{
|
||||
Miner: abi.ActorID(mid),
|
||||
Number: abi.SectorNumber(sn),
|
||||
s = storage.SectorRef{
|
||||
ID: abi.SectorID{
|
||||
Miner: abi.ActorID(mid),
|
||||
Number: abi.SectorNumber(sn),
|
||||
},
|
||||
}
|
||||
|
||||
err = miner.StorageMiner.(*impl.StorageMinerAPI).IStorageMgr.(*mock.SectorMgr).MarkFailed(s, true)
|
||||
@@ -342,3 +435,592 @@ func testWindowPostUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration,
|
||||
sectors = p.MinerPower.RawBytePower.Uint64() / uint64(ssz)
|
||||
require.Equal(t, nSectors+GenesisPreseals-2+1, int(sectors)) // -2 not recovered sectors + 1 just pledged
|
||||
}
|
||||
|
||||
func TestTerminate(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
nSectors := uint64(2)
|
||||
|
||||
n, sn := b(t, []FullNodeOpts{FullNodeWithActorsV4At(-1)}, []StorageMiner{{Full: 0, Preseal: int(nSectors)}})
|
||||
|
||||
client := n[0].FullNode.(*impl.FullNodeAPI)
|
||||
miner := sn[0]
|
||||
|
||||
addrinfo, err := client.NetAddrsListen(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := miner.NetConnect(ctx, addrinfo); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
build.Clock.Sleep(time.Second)
|
||||
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
for ctx.Err() == nil {
|
||||
build.Clock.Sleep(blocktime)
|
||||
if err := sn[0].MineOne(ctx, MineNext); err != nil {
|
||||
if ctx.Err() != nil {
|
||||
// context was canceled, ignore the error.
|
||||
return
|
||||
}
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
defer func() {
|
||||
cancel()
|
||||
<-done
|
||||
}()
|
||||
|
||||
maddr, err := miner.ActorAddress(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
ssz, err := miner.ActorSectorSize(ctx, maddr)
|
||||
require.NoError(t, err)
|
||||
|
||||
p, err := client.StateMinerPower(ctx, maddr, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, p.MinerPower, p.TotalPower)
|
||||
require.Equal(t, p.MinerPower.RawBytePower, types.NewInt(uint64(ssz)*nSectors))
|
||||
|
||||
fmt.Printf("Seal a sector\n")
|
||||
|
||||
pledgeSectors(t, ctx, miner, 1, 0, nil)
|
||||
|
||||
fmt.Printf("wait for power\n")
|
||||
|
||||
{
|
||||
// Wait until proven.
|
||||
di, err := client.StateMinerProvingDeadline(ctx, maddr, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
|
||||
waitUntil := di.PeriodStart + di.WPoStProvingPeriod + 2
|
||||
fmt.Printf("End for head.Height > %d\n", waitUntil)
|
||||
|
||||
for {
|
||||
head, err := client.ChainHead(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
if head.Height() > waitUntil {
|
||||
fmt.Printf("Now head.Height = %d\n", head.Height())
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nSectors++
|
||||
|
||||
p, err = client.StateMinerPower(ctx, maddr, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, p.MinerPower, p.TotalPower)
|
||||
require.Equal(t, p.MinerPower.RawBytePower, types.NewInt(uint64(ssz)*nSectors))
|
||||
|
||||
fmt.Println("Terminate a sector")
|
||||
|
||||
toTerminate := abi.SectorNumber(3)
|
||||
|
||||
err = miner.SectorTerminate(ctx, toTerminate)
|
||||
require.NoError(t, err)
|
||||
|
||||
msgTriggerred := false
|
||||
loop:
|
||||
for {
|
||||
si, err := miner.SectorsStatus(ctx, toTerminate, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
fmt.Println("state: ", si.State, msgTriggerred)
|
||||
|
||||
switch sealing.SectorState(si.State) {
|
||||
case sealing.Terminating:
|
||||
if !msgTriggerred {
|
||||
{
|
||||
p, err := miner.SectorTerminatePending(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, p, 1)
|
||||
require.Equal(t, abi.SectorNumber(3), p[0].Number)
|
||||
}
|
||||
|
||||
c, err := miner.SectorTerminateFlush(ctx)
|
||||
require.NoError(t, err)
|
||||
if c != nil {
|
||||
msgTriggerred = true
|
||||
fmt.Println("terminate message:", c)
|
||||
|
||||
{
|
||||
p, err := miner.SectorTerminatePending(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, p, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
case sealing.TerminateWait, sealing.TerminateFinality, sealing.Removed:
|
||||
break loop
|
||||
}
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
|
||||
// check power decreased
|
||||
p, err = client.StateMinerPower(ctx, maddr, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, p.MinerPower, p.TotalPower)
|
||||
require.Equal(t, p.MinerPower.RawBytePower, types.NewInt(uint64(ssz)*(nSectors-1)))
|
||||
|
||||
// check in terminated set
|
||||
{
|
||||
parts, err := client.StateMinerPartitions(ctx, maddr, 1, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
require.Greater(t, len(parts), 0)
|
||||
|
||||
bflen := func(b bitfield.BitField) uint64 {
|
||||
l, err := b.Count()
|
||||
require.NoError(t, err)
|
||||
return l
|
||||
}
|
||||
|
||||
require.Equal(t, uint64(1), bflen(parts[0].AllSectors))
|
||||
require.Equal(t, uint64(0), bflen(parts[0].LiveSectors))
|
||||
}
|
||||
|
||||
di, err := client.StateMinerProvingDeadline(ctx, maddr, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
for {
|
||||
head, err := client.ChainHead(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
if head.Height() > di.PeriodStart+di.WPoStProvingPeriod+2 {
|
||||
fmt.Printf("Now head.Height = %d\n", head.Height())
|
||||
break
|
||||
}
|
||||
build.Clock.Sleep(blocktime)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
fmt.Printf("End for head.Height > %d\n", di.PeriodStart+di.WPoStProvingPeriod+2)
|
||||
|
||||
p, err = client.StateMinerPower(ctx, maddr, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, p.MinerPower, p.TotalPower)
|
||||
require.Equal(t, p.MinerPower.RawBytePower, types.NewInt(uint64(ssz)*(nSectors-1)))
|
||||
}
|
||||
|
||||
func TestWindowPostDispute(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
// First, we configure two miners. After sealing, we're going to turn off the first miner so
|
||||
// it doesn't submit proofs.
|
||||
///
|
||||
// Then we're going to manually submit bad proofs.
|
||||
n, sn := b(t, []FullNodeOpts{
|
||||
FullNodeWithActorsV4At(-1),
|
||||
}, []StorageMiner{
|
||||
{Full: 0, Preseal: PresealGenesis},
|
||||
{Full: 0},
|
||||
})
|
||||
|
||||
client := n[0].FullNode.(*impl.FullNodeAPI)
|
||||
chainMiner := sn[0]
|
||||
evilMiner := sn[1]
|
||||
|
||||
{
|
||||
addrinfo, err := client.NetAddrsListen(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := chainMiner.NetConnect(ctx, addrinfo); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := evilMiner.NetConnect(ctx, addrinfo); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
defaultFrom, err := client.WalletDefaultAddress(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
build.Clock.Sleep(time.Second)
|
||||
|
||||
// Mine with the _second_ node (the good one).
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
for ctx.Err() == nil {
|
||||
build.Clock.Sleep(blocktime)
|
||||
if err := chainMiner.MineOne(ctx, MineNext); err != nil {
|
||||
if ctx.Err() != nil {
|
||||
// context was canceled, ignore the error.
|
||||
return
|
||||
}
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
defer func() {
|
||||
cancel()
|
||||
<-done
|
||||
}()
|
||||
|
||||
// Give the chain miner enough sectors to win every block.
|
||||
pledgeSectors(t, ctx, chainMiner, 10, 0, nil)
|
||||
// And the evil one 1 sector. No cookie for you.
|
||||
pledgeSectors(t, ctx, evilMiner, 1, 0, nil)
|
||||
|
||||
// Let the evil miner's sectors gain power.
|
||||
evilMinerAddr, err := evilMiner.ActorAddress(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
di, err := client.StateMinerProvingDeadline(ctx, evilMinerAddr, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
|
||||
fmt.Printf("Running one proving period\n")
|
||||
fmt.Printf("End for head.Height > %d\n", di.PeriodStart+di.WPoStProvingPeriod*2)
|
||||
|
||||
for {
|
||||
head, err := client.ChainHead(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
if head.Height() > di.PeriodStart+di.WPoStProvingPeriod*2 {
|
||||
fmt.Printf("Now head.Height = %d\n", head.Height())
|
||||
break
|
||||
}
|
||||
build.Clock.Sleep(blocktime)
|
||||
}
|
||||
|
||||
p, err := client.StateMinerPower(ctx, evilMinerAddr, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
|
||||
ssz, err := evilMiner.ActorSectorSize(ctx, evilMinerAddr)
|
||||
require.NoError(t, err)
|
||||
|
||||
// make sure it has gained power.
|
||||
require.Equal(t, p.MinerPower.RawBytePower, types.NewInt(uint64(ssz)))
|
||||
|
||||
evilSectors, err := evilMiner.SectorsList(ctx)
|
||||
require.NoError(t, err)
|
||||
evilSectorNo := evilSectors[0] // only one.
|
||||
evilSectorLoc, err := client.StateSectorPartition(ctx, evilMinerAddr, evilSectorNo, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
|
||||
fmt.Println("evil miner stopping")
|
||||
|
||||
// Now stop the evil miner, and start manually submitting bad proofs.
|
||||
require.NoError(t, evilMiner.Stop(ctx))
|
||||
|
||||
fmt.Println("evil miner stopped")
|
||||
|
||||
// Wait until we need to prove our sector.
|
||||
for {
|
||||
di, err = client.StateMinerProvingDeadline(ctx, evilMinerAddr, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
if di.Index == evilSectorLoc.Deadline {
|
||||
break
|
||||
}
|
||||
build.Clock.Sleep(blocktime)
|
||||
}
|
||||
|
||||
err = submitBadProof(ctx, client, evilMinerAddr, di, evilSectorLoc.Deadline, evilSectorLoc.Partition)
|
||||
require.NoError(t, err, "evil proof not accepted")
|
||||
|
||||
// Wait until after the proving period.
|
||||
for {
|
||||
di, err = client.StateMinerProvingDeadline(ctx, evilMinerAddr, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
if di.Index != evilSectorLoc.Deadline {
|
||||
break
|
||||
}
|
||||
build.Clock.Sleep(blocktime)
|
||||
}
|
||||
|
||||
fmt.Println("accepted evil proof")
|
||||
|
||||
// Make sure the evil node didn't lose any power.
|
||||
p, err = client.StateMinerPower(ctx, evilMinerAddr, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, p.MinerPower.RawBytePower, types.NewInt(uint64(ssz)))
|
||||
|
||||
// OBJECTION! The good miner files a DISPUTE!!!!
|
||||
{
|
||||
params := &minerActor.DisputeWindowedPoStParams{
|
||||
Deadline: evilSectorLoc.Deadline,
|
||||
PoStIndex: 0,
|
||||
}
|
||||
|
||||
enc, aerr := actors.SerializeParams(params)
|
||||
require.NoError(t, aerr)
|
||||
|
||||
msg := &types.Message{
|
||||
To: evilMinerAddr,
|
||||
Method: minerActor.Methods.DisputeWindowedPoSt,
|
||||
Params: enc,
|
||||
Value: types.NewInt(0),
|
||||
From: defaultFrom,
|
||||
}
|
||||
sm, err := client.MpoolPushMessage(ctx, msg, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
fmt.Println("waiting dispute")
|
||||
rec, err := client.StateWaitMsg(ctx, sm.Cid(), build.MessageConfidence)
|
||||
require.NoError(t, err)
|
||||
require.Zero(t, rec.Receipt.ExitCode, "dispute not accepted: %s", rec.Receipt.ExitCode.Error())
|
||||
}
|
||||
|
||||
// Objection SUSTAINED!
|
||||
// Make sure the evil node lost power.
|
||||
p, err = client.StateMinerPower(ctx, evilMinerAddr, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
require.True(t, p.MinerPower.RawBytePower.IsZero())
|
||||
|
||||
// Now we begin the redemption arc.
|
||||
require.True(t, p.MinerPower.RawBytePower.IsZero())
|
||||
|
||||
// First, recover the sector.
|
||||
|
||||
{
|
||||
minerInfo, err := client.StateMinerInfo(ctx, evilMinerAddr, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
|
||||
params := &minerActor.DeclareFaultsRecoveredParams{
|
||||
Recoveries: []minerActor.RecoveryDeclaration{{
|
||||
Deadline: evilSectorLoc.Deadline,
|
||||
Partition: evilSectorLoc.Partition,
|
||||
Sectors: bitfield.NewFromSet([]uint64{uint64(evilSectorNo)}),
|
||||
}},
|
||||
}
|
||||
|
||||
enc, aerr := actors.SerializeParams(params)
|
||||
require.NoError(t, aerr)
|
||||
|
||||
msg := &types.Message{
|
||||
To: evilMinerAddr,
|
||||
Method: minerActor.Methods.DeclareFaultsRecovered,
|
||||
Params: enc,
|
||||
Value: types.FromFil(30), // repay debt.
|
||||
From: minerInfo.Owner,
|
||||
}
|
||||
sm, err := client.MpoolPushMessage(ctx, msg, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
rec, err := client.StateWaitMsg(ctx, sm.Cid(), build.MessageConfidence)
|
||||
require.NoError(t, err)
|
||||
require.Zero(t, rec.Receipt.ExitCode, "recovery not accepted: %s", rec.Receipt.ExitCode.Error())
|
||||
}
|
||||
|
||||
// Then wait for the deadline.
|
||||
for {
|
||||
di, err = client.StateMinerProvingDeadline(ctx, evilMinerAddr, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
if di.Index == evilSectorLoc.Deadline {
|
||||
break
|
||||
}
|
||||
build.Clock.Sleep(blocktime)
|
||||
}
|
||||
|
||||
// Now try to be evil again
|
||||
err = submitBadProof(ctx, client, evilMinerAddr, di, evilSectorLoc.Deadline, evilSectorLoc.Partition)
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), "message execution failed: exit 16, reason: window post failed: invalid PoSt")
|
||||
|
||||
// It didn't work because we're recovering.
|
||||
}
|
||||
|
||||
func submitBadProof(
|
||||
ctx context.Context,
|
||||
client api.FullNode, maddr address.Address,
|
||||
di *dline.Info, dlIdx, partIdx uint64,
|
||||
) error {
|
||||
head, err := client.ChainHead(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
from, err := client.WalletDefaultAddress(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
minerInfo, err := client.StateMinerInfo(ctx, maddr, head.Key())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
commEpoch := di.Open
|
||||
commRand, err := client.ChainGetRandomnessFromTickets(
|
||||
ctx, head.Key(), crypto.DomainSeparationTag_PoStChainCommit,
|
||||
commEpoch, nil,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
params := &minerActor.SubmitWindowedPoStParams{
|
||||
ChainCommitEpoch: commEpoch,
|
||||
ChainCommitRand: commRand,
|
||||
Deadline: dlIdx,
|
||||
Partitions: []minerActor.PoStPartition{{Index: partIdx}},
|
||||
Proofs: []proof3.PoStProof{{
|
||||
PoStProof: minerInfo.WindowPoStProofType,
|
||||
ProofBytes: []byte("I'm soooo very evil."),
|
||||
}},
|
||||
}
|
||||
|
||||
enc, aerr := actors.SerializeParams(params)
|
||||
if aerr != nil {
|
||||
return aerr
|
||||
}
|
||||
|
||||
msg := &types.Message{
|
||||
To: maddr,
|
||||
Method: minerActor.Methods.SubmitWindowedPoSt,
|
||||
Params: enc,
|
||||
Value: types.NewInt(0),
|
||||
From: from,
|
||||
}
|
||||
sm, err := client.MpoolPushMessage(ctx, msg, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rec, err := client.StateWaitMsg(ctx, sm.Cid(), build.MessageConfidence)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if rec.Receipt.ExitCode.IsError() {
|
||||
return rec.Receipt.ExitCode
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestWindowPostDisputeFails(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
n, sn := b(t, []FullNodeOpts{FullNodeWithActorsV4At(-1)}, OneMiner)
|
||||
|
||||
client := n[0].FullNode.(*impl.FullNodeAPI)
|
||||
miner := sn[0]
|
||||
|
||||
{
|
||||
addrinfo, err := client.NetAddrsListen(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := miner.NetConnect(ctx, addrinfo); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
defaultFrom, err := client.WalletDefaultAddress(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
maddr, err := miner.ActorAddress(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
build.Clock.Sleep(time.Second)
|
||||
|
||||
// Mine with the _second_ node (the good one).
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
for ctx.Err() == nil {
|
||||
build.Clock.Sleep(blocktime)
|
||||
if err := miner.MineOne(ctx, MineNext); err != nil {
|
||||
if ctx.Err() != nil {
|
||||
// context was canceled, ignore the error.
|
||||
return
|
||||
}
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
defer func() {
|
||||
cancel()
|
||||
<-done
|
||||
}()
|
||||
|
||||
pledgeSectors(t, ctx, miner, 10, 0, nil)
|
||||
|
||||
di, err := client.StateMinerProvingDeadline(ctx, maddr, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
|
||||
fmt.Printf("Running one proving period\n")
|
||||
fmt.Printf("End for head.Height > %d\n", di.PeriodStart+di.WPoStProvingPeriod*2)
|
||||
|
||||
for {
|
||||
head, err := client.ChainHead(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
if head.Height() > di.PeriodStart+di.WPoStProvingPeriod*2 {
|
||||
fmt.Printf("Now head.Height = %d\n", head.Height())
|
||||
break
|
||||
}
|
||||
build.Clock.Sleep(blocktime)
|
||||
}
|
||||
|
||||
ssz, err := miner.ActorSectorSize(ctx, maddr)
|
||||
require.NoError(t, err)
|
||||
expectedPower := types.NewInt(uint64(ssz) * (GenesisPreseals + 10))
|
||||
|
||||
p, err := client.StateMinerPower(ctx, maddr, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
|
||||
// make sure it has gained power.
|
||||
require.Equal(t, p.MinerPower.RawBytePower, expectedPower)
|
||||
|
||||
// Wait until a proof has been submitted.
|
||||
var targetDeadline uint64
|
||||
waitForProof:
|
||||
for {
|
||||
deadlines, err := client.StateMinerDeadlines(ctx, maddr, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
for dlIdx, dl := range deadlines {
|
||||
nonEmpty, err := dl.PostSubmissions.IsEmpty()
|
||||
require.NoError(t, err)
|
||||
if nonEmpty {
|
||||
targetDeadline = uint64(dlIdx)
|
||||
break waitForProof
|
||||
}
|
||||
}
|
||||
|
||||
build.Clock.Sleep(blocktime)
|
||||
}
|
||||
|
||||
for {
|
||||
di, err := client.StateMinerProvingDeadline(ctx, maddr, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
// wait until the deadline finishes.
|
||||
if di.Index == ((targetDeadline + 1) % di.WPoStPeriodDeadlines) {
|
||||
break
|
||||
}
|
||||
|
||||
build.Clock.Sleep(blocktime)
|
||||
}
|
||||
|
||||
// Try to object to the proof. This should fail.
|
||||
{
|
||||
params := &minerActor.DisputeWindowedPoStParams{
|
||||
Deadline: targetDeadline,
|
||||
PoStIndex: 0,
|
||||
}
|
||||
|
||||
enc, aerr := actors.SerializeParams(params)
|
||||
require.NoError(t, aerr)
|
||||
|
||||
msg := &types.Message{
|
||||
To: maddr,
|
||||
Method: minerActor.Methods.DisputeWindowedPoSt,
|
||||
Params: enc,
|
||||
Value: types.NewInt(0),
|
||||
From: defaultFrom,
|
||||
}
|
||||
_, err := client.MpoolPushMessage(ctx, msg, nil)
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), "failed to dispute valid post (RetCode=16)")
|
||||
}
|
||||
}
|
||||
|
||||
+22
-14
@@ -3,10 +3,10 @@ package api
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
datatransfer "github.com/filecoin-project/go-data-transfer"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/ipfs/go-cid"
|
||||
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
@@ -51,19 +51,6 @@ type MessageSendSpec struct {
|
||||
MaxFee abi.TokenAmount
|
||||
}
|
||||
|
||||
var DefaultMessageSendSpec = MessageSendSpec{
|
||||
// MaxFee of 0.1FIL
|
||||
MaxFee: abi.NewTokenAmount(int64(build.FilecoinPrecision) / 10),
|
||||
}
|
||||
|
||||
func (ms *MessageSendSpec) Get() MessageSendSpec {
|
||||
if ms == nil {
|
||||
return DefaultMessageSendSpec
|
||||
}
|
||||
|
||||
return *ms
|
||||
}
|
||||
|
||||
type DataTransferChannel struct {
|
||||
TransferID datatransfer.TransferID
|
||||
Status datatransfer.Status
|
||||
@@ -107,3 +94,24 @@ func NewDataTransferChannel(hostID peer.ID, channelState datatransfer.ChannelSta
|
||||
}
|
||||
return channel
|
||||
}
|
||||
|
||||
type NetBlockList struct {
|
||||
Peers []peer.ID
|
||||
IPAddrs []string
|
||||
IPSubnets []string
|
||||
}
|
||||
|
||||
type ExtendedPeerInfo struct {
|
||||
ID peer.ID
|
||||
Agent string
|
||||
Addrs []string
|
||||
Protocols []string
|
||||
ConnMgrMeta *ConnMgrInfo
|
||||
}
|
||||
|
||||
type ConnMgrInfo struct {
|
||||
FirstSeen time.Time
|
||||
Value int
|
||||
Tags map[string]int
|
||||
Conns map[string]time.Time
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
xerrors "golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
type Version uint32
|
||||
|
||||
func newVer(major, minor, patch uint8) Version {
|
||||
return Version(uint32(major)<<16 | uint32(minor)<<8 | uint32(patch))
|
||||
}
|
||||
|
||||
// Ints returns (major, minor, patch) versions
|
||||
func (ve Version) Ints() (uint32, uint32, uint32) {
|
||||
v := uint32(ve)
|
||||
return (v & majorOnlyMask) >> 16, (v & minorOnlyMask) >> 8, v & patchOnlyMask
|
||||
}
|
||||
|
||||
func (ve Version) String() string {
|
||||
vmj, vmi, vp := ve.Ints()
|
||||
return fmt.Sprintf("%d.%d.%d", vmj, vmi, vp)
|
||||
}
|
||||
|
||||
func (ve Version) EqMajorMinor(v2 Version) bool {
|
||||
return ve&minorMask == v2&minorMask
|
||||
}
|
||||
|
||||
type NodeType int
|
||||
|
||||
const (
|
||||
NodeUnknown NodeType = iota
|
||||
|
||||
NodeFull
|
||||
NodeMiner
|
||||
NodeWorker
|
||||
)
|
||||
|
||||
var RunningNodeType NodeType
|
||||
|
||||
func VersionForType(nodeType NodeType) (Version, error) {
|
||||
switch nodeType {
|
||||
case NodeFull:
|
||||
return FullAPIVersion, nil
|
||||
case NodeMiner:
|
||||
return MinerAPIVersion, nil
|
||||
case NodeWorker:
|
||||
return WorkerAPIVersion, nil
|
||||
default:
|
||||
return Version(0), xerrors.Errorf("unknown node type %d", nodeType)
|
||||
}
|
||||
}
|
||||
|
||||
// semver versions of the rpc api exposed
|
||||
var (
|
||||
FullAPIVersion = newVer(1, 2, 0)
|
||||
MinerAPIVersion = newVer(1, 0, 1)
|
||||
WorkerAPIVersion = newVer(1, 0, 0)
|
||||
)
|
||||
|
||||
//nolint:varcheck,deadcode
|
||||
const (
|
||||
majorMask = 0xff0000
|
||||
minorMask = 0xffff00
|
||||
patchMask = 0xffffff
|
||||
|
||||
majorOnlyMask = 0xff0000
|
||||
minorOnlyMask = 0x00ff00
|
||||
patchOnlyMask = 0x0000ff
|
||||
)
|
||||
@@ -0,0 +1,66 @@
|
||||
package blockstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
blocks "github.com/ipfs/go-block-format"
|
||||
"github.com/ipfs/go-cid"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
type ChainIO interface {
|
||||
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
|
||||
ChainHasObj(context.Context, cid.Cid) (bool, error)
|
||||
}
|
||||
|
||||
type apiBlockstore struct {
|
||||
api ChainIO
|
||||
}
|
||||
|
||||
// This blockstore is adapted in the constructor.
|
||||
var _ BasicBlockstore = (*apiBlockstore)(nil)
|
||||
|
||||
func NewAPIBlockstore(cio ChainIO) Blockstore {
|
||||
bs := &apiBlockstore{api: cio}
|
||||
return Adapt(bs) // return an adapted blockstore.
|
||||
}
|
||||
|
||||
func (a *apiBlockstore) DeleteBlock(cid.Cid) error {
|
||||
return xerrors.New("not supported")
|
||||
}
|
||||
|
||||
func (a *apiBlockstore) Has(c cid.Cid) (bool, error) {
|
||||
return a.api.ChainHasObj(context.TODO(), c)
|
||||
}
|
||||
|
||||
func (a *apiBlockstore) Get(c cid.Cid) (blocks.Block, error) {
|
||||
bb, err := a.api.ChainReadObj(context.TODO(), c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return blocks.NewBlockWithCid(bb, c)
|
||||
}
|
||||
|
||||
func (a *apiBlockstore) GetSize(c cid.Cid) (int, error) {
|
||||
bb, err := a.api.ChainReadObj(context.TODO(), c)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return len(bb), nil
|
||||
}
|
||||
|
||||
func (a *apiBlockstore) Put(blocks.Block) error {
|
||||
return xerrors.New("not supported")
|
||||
}
|
||||
|
||||
func (a *apiBlockstore) PutMany([]blocks.Block) error {
|
||||
return xerrors.New("not supported")
|
||||
}
|
||||
|
||||
func (a *apiBlockstore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
|
||||
return nil, xerrors.New("not supported")
|
||||
}
|
||||
|
||||
func (a *apiBlockstore) HashOnRead(enabled bool) {
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,481 @@
|
||||
package badgerbs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/dgraph-io/badger/v2"
|
||||
"github.com/dgraph-io/badger/v2/options"
|
||||
"github.com/multiformats/go-base32"
|
||||
"go.uber.org/zap"
|
||||
|
||||
blocks "github.com/ipfs/go-block-format"
|
||||
"github.com/ipfs/go-cid"
|
||||
logger "github.com/ipfs/go-log/v2"
|
||||
pool "github.com/libp2p/go-buffer-pool"
|
||||
|
||||
"github.com/filecoin-project/lotus/blockstore"
|
||||
)
|
||||
|
||||
var (
|
||||
// KeyPool is the buffer pool we use to compute storage keys.
|
||||
KeyPool *pool.BufferPool = pool.GlobalPool
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrBlockstoreClosed is returned from blockstore operations after
|
||||
// the blockstore has been closed.
|
||||
ErrBlockstoreClosed = fmt.Errorf("badger blockstore closed")
|
||||
|
||||
log = logger.Logger("badgerbs")
|
||||
)
|
||||
|
||||
// aliases to mask badger dependencies.
|
||||
const (
|
||||
// FileIO is equivalent to badger/options.FileIO.
|
||||
FileIO = options.FileIO
|
||||
// MemoryMap is equivalent to badger/options.MemoryMap.
|
||||
MemoryMap = options.MemoryMap
|
||||
// LoadToRAM is equivalent to badger/options.LoadToRAM.
|
||||
LoadToRAM = options.LoadToRAM
|
||||
)
|
||||
|
||||
// Options embeds the badger options themselves, and augments them with
|
||||
// blockstore-specific options.
|
||||
type Options struct {
|
||||
badger.Options
|
||||
|
||||
// Prefix is an optional prefix to prepend to keys. Default: "".
|
||||
Prefix string
|
||||
}
|
||||
|
||||
func DefaultOptions(path string) Options {
|
||||
return Options{
|
||||
Options: badger.DefaultOptions(path),
|
||||
Prefix: "",
|
||||
}
|
||||
}
|
||||
|
||||
// badgerLogger is a local wrapper for go-log to make the interface
|
||||
// compatible with badger.Logger (namely, aliasing Warnf to Warningf)
|
||||
type badgerLogger struct {
|
||||
*zap.SugaredLogger // skips 1 caller to get useful line info, skipping over badger.Options.
|
||||
|
||||
skip2 *zap.SugaredLogger // skips 2 callers, just like above + this logger.
|
||||
}
|
||||
|
||||
// Warningf is required by the badger logger APIs.
|
||||
func (b *badgerLogger) Warningf(format string, args ...interface{}) {
|
||||
b.skip2.Warnf(format, args...)
|
||||
}
|
||||
|
||||
const (
|
||||
stateOpen int64 = iota
|
||||
stateClosing
|
||||
stateClosed
|
||||
)
|
||||
|
||||
// Blockstore is a badger-backed IPLD blockstore.
|
||||
//
|
||||
// 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 {
|
||||
DB *badger.DB
|
||||
|
||||
// state is guarded by atomic.
|
||||
state int64
|
||||
|
||||
prefixing bool
|
||||
prefix []byte
|
||||
prefixLen int
|
||||
}
|
||||
|
||||
var _ blockstore.Blockstore = (*Blockstore)(nil)
|
||||
var _ blockstore.Viewer = (*Blockstore)(nil)
|
||||
var _ io.Closer = (*Blockstore)(nil)
|
||||
|
||||
// Open creates a new badger-backed blockstore, with the supplied options.
|
||||
func Open(opts Options) (*Blockstore, error) {
|
||||
opts.Logger = &badgerLogger{
|
||||
SugaredLogger: log.Desugar().WithOptions(zap.AddCallerSkip(1)).Sugar(),
|
||||
skip2: log.Desugar().WithOptions(zap.AddCallerSkip(2)).Sugar(),
|
||||
}
|
||||
|
||||
db, err := badger.Open(opts.Options)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open badger blockstore: %w", err)
|
||||
}
|
||||
|
||||
bs := &Blockstore{DB: db}
|
||||
if p := opts.Prefix; p != "" {
|
||||
bs.prefixing = true
|
||||
bs.prefix = []byte(p)
|
||||
bs.prefixLen = len(bs.prefix)
|
||||
}
|
||||
|
||||
return bs, nil
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (b *Blockstore) Close() error {
|
||||
if !atomic.CompareAndSwapInt64(&b.state, stateOpen, stateClosing) {
|
||||
return nil
|
||||
}
|
||||
|
||||
defer atomic.StoreInt64(&b.state, stateClosed)
|
||||
return b.DB.Close()
|
||||
}
|
||||
|
||||
// CollectGarbage runs garbage collection on the value log
|
||||
func (b *Blockstore) CollectGarbage() error {
|
||||
if atomic.LoadInt64(&b.state) != stateOpen {
|
||||
return ErrBlockstoreClosed
|
||||
}
|
||||
|
||||
var err error
|
||||
for err == nil {
|
||||
err = b.DB.RunValueLogGC(0.125)
|
||||
}
|
||||
|
||||
if err == badger.ErrNoRewrite {
|
||||
// not really an error in this case
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// View implements blockstore.Viewer, which leverages zero-copy read-only
|
||||
// access to values.
|
||||
func (b *Blockstore) View(cid cid.Cid, fn func([]byte) error) error {
|
||||
if atomic.LoadInt64(&b.state) != stateOpen {
|
||||
return ErrBlockstoreClosed
|
||||
}
|
||||
|
||||
k, pooled := b.PooledStorageKey(cid)
|
||||
if pooled {
|
||||
defer KeyPool.Put(k)
|
||||
}
|
||||
|
||||
return b.DB.View(func(txn *badger.Txn) error {
|
||||
switch item, err := txn.Get(k); err {
|
||||
case nil:
|
||||
return item.Value(fn)
|
||||
case badger.ErrKeyNotFound:
|
||||
return blockstore.ErrNotFound
|
||||
default:
|
||||
return fmt.Errorf("failed to view block from badger blockstore: %w", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Has implements Blockstore.Has.
|
||||
func (b *Blockstore) Has(cid cid.Cid) (bool, error) {
|
||||
if atomic.LoadInt64(&b.state) != stateOpen {
|
||||
return false, ErrBlockstoreClosed
|
||||
}
|
||||
|
||||
k, pooled := b.PooledStorageKey(cid)
|
||||
if pooled {
|
||||
defer KeyPool.Put(k)
|
||||
}
|
||||
|
||||
err := b.DB.View(func(txn *badger.Txn) error {
|
||||
_, err := txn.Get(k)
|
||||
return err
|
||||
})
|
||||
|
||||
switch err {
|
||||
case badger.ErrKeyNotFound:
|
||||
return false, nil
|
||||
case nil:
|
||||
return true, nil
|
||||
default:
|
||||
return false, fmt.Errorf("failed to check if block exists in badger blockstore: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Get implements Blockstore.Get.
|
||||
func (b *Blockstore) Get(cid cid.Cid) (blocks.Block, error) {
|
||||
if !cid.Defined() {
|
||||
return nil, blockstore.ErrNotFound
|
||||
}
|
||||
|
||||
if atomic.LoadInt64(&b.state) != stateOpen {
|
||||
return nil, ErrBlockstoreClosed
|
||||
}
|
||||
|
||||
k, pooled := b.PooledStorageKey(cid)
|
||||
if pooled {
|
||||
defer KeyPool.Put(k)
|
||||
}
|
||||
|
||||
var val []byte
|
||||
err := b.DB.View(func(txn *badger.Txn) error {
|
||||
switch item, err := txn.Get(k); err {
|
||||
case nil:
|
||||
val, err = item.ValueCopy(nil)
|
||||
return err
|
||||
case badger.ErrKeyNotFound:
|
||||
return blockstore.ErrNotFound
|
||||
default:
|
||||
return fmt.Errorf("failed to get block from badger blockstore: %w", err)
|
||||
}
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return blocks.NewBlockWithCid(val, cid)
|
||||
}
|
||||
|
||||
// GetSize implements Blockstore.GetSize.
|
||||
func (b *Blockstore) GetSize(cid cid.Cid) (int, error) {
|
||||
if atomic.LoadInt64(&b.state) != stateOpen {
|
||||
return -1, ErrBlockstoreClosed
|
||||
}
|
||||
|
||||
k, pooled := b.PooledStorageKey(cid)
|
||||
if pooled {
|
||||
defer KeyPool.Put(k)
|
||||
}
|
||||
|
||||
var size int
|
||||
err := b.DB.View(func(txn *badger.Txn) error {
|
||||
switch item, err := txn.Get(k); err {
|
||||
case nil:
|
||||
size = int(item.ValueSize())
|
||||
case badger.ErrKeyNotFound:
|
||||
return blockstore.ErrNotFound
|
||||
default:
|
||||
return fmt.Errorf("failed to get block size from badger blockstore: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
size = -1
|
||||
}
|
||||
return size, err
|
||||
}
|
||||
|
||||
// Put implements Blockstore.Put.
|
||||
func (b *Blockstore) Put(block blocks.Block) error {
|
||||
if atomic.LoadInt64(&b.state) != stateOpen {
|
||||
return ErrBlockstoreClosed
|
||||
}
|
||||
|
||||
k, pooled := b.PooledStorageKey(block.Cid())
|
||||
if pooled {
|
||||
defer KeyPool.Put(k)
|
||||
}
|
||||
|
||||
err := b.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)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// PutMany implements Blockstore.PutMany.
|
||||
func (b *Blockstore) PutMany(blocks []blocks.Block) error {
|
||||
if atomic.LoadInt64(&b.state) != stateOpen {
|
||||
return ErrBlockstoreClosed
|
||||
}
|
||||
|
||||
batch := b.DB.NewWriteBatch()
|
||||
defer batch.Cancel()
|
||||
|
||||
// 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
|
||||
// badger holds on to the slice.
|
||||
var toReturn [][]byte
|
||||
if b.prefixing {
|
||||
toReturn = make([][]byte, 0, len(blocks))
|
||||
defer func() {
|
||||
for _, b := range toReturn {
|
||||
KeyPool.Put(b)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
for _, block := range blocks {
|
||||
k, pooled := b.PooledStorageKey(block.Cid())
|
||||
if pooled {
|
||||
toReturn = append(toReturn, k)
|
||||
}
|
||||
if err := batch.Set(k, block.RawData()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err := batch.Flush()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to put blocks in badger blockstore: %w", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteBlock implements Blockstore.DeleteBlock.
|
||||
func (b *Blockstore) DeleteBlock(cid cid.Cid) error {
|
||||
if atomic.LoadInt64(&b.state) != stateOpen {
|
||||
return ErrBlockstoreClosed
|
||||
}
|
||||
|
||||
k, pooled := b.PooledStorageKey(cid)
|
||||
if pooled {
|
||||
defer KeyPool.Put(k)
|
||||
}
|
||||
|
||||
return b.DB.Update(func(txn *badger.Txn) error {
|
||||
return txn.Delete(k)
|
||||
})
|
||||
}
|
||||
|
||||
func (b *Blockstore) DeleteMany(cids []cid.Cid) error {
|
||||
if atomic.LoadInt64(&b.state) != stateOpen {
|
||||
return ErrBlockstoreClosed
|
||||
}
|
||||
|
||||
batch := b.DB.NewWriteBatch()
|
||||
defer batch.Cancel()
|
||||
|
||||
// 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
|
||||
// badger holds on to the slice.
|
||||
var toReturn [][]byte
|
||||
if b.prefixing {
|
||||
toReturn = make([][]byte, 0, len(cids))
|
||||
defer func() {
|
||||
for _, b := range toReturn {
|
||||
KeyPool.Put(b)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
for _, cid := range cids {
|
||||
k, pooled := b.PooledStorageKey(cid)
|
||||
if pooled {
|
||||
toReturn = append(toReturn, k)
|
||||
}
|
||||
if err := batch.Delete(k); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err := batch.Flush()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to delete blocks from badger blockstore: %w", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// AllKeysChan implements Blockstore.AllKeysChan.
|
||||
func (b *Blockstore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
|
||||
if atomic.LoadInt64(&b.state) != stateOpen {
|
||||
return nil, ErrBlockstoreClosed
|
||||
}
|
||||
|
||||
txn := b.DB.NewTransaction(false)
|
||||
opts := badger.IteratorOptions{PrefetchSize: 100}
|
||||
if b.prefixing {
|
||||
opts.Prefix = b.prefix
|
||||
}
|
||||
iter := txn.NewIterator(opts)
|
||||
|
||||
ch := make(chan cid.Cid)
|
||||
go func() {
|
||||
defer close(ch)
|
||||
defer iter.Close()
|
||||
|
||||
// NewCidV1 makes a copy of the multihash buffer, so we can reuse it to
|
||||
// contain allocs.
|
||||
var buf []byte
|
||||
for iter.Rewind(); iter.Valid(); iter.Next() {
|
||||
if ctx.Err() != nil {
|
||||
return // context has fired.
|
||||
}
|
||||
if atomic.LoadInt64(&b.state) != stateOpen {
|
||||
// open iterators will run even after the database is closed...
|
||||
return // closing, yield.
|
||||
}
|
||||
k := iter.Item().Key()
|
||||
if b.prefixing {
|
||||
k = k[b.prefixLen:]
|
||||
}
|
||||
|
||||
if reqlen := base32.RawStdEncoding.DecodedLen(len(k)); len(buf) < reqlen {
|
||||
buf = make([]byte, reqlen)
|
||||
}
|
||||
if n, err := base32.RawStdEncoding.Decode(buf, k); err == nil {
|
||||
select {
|
||||
case ch <- cid.NewCidV1(cid.Raw, buf[:n]):
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
} else {
|
||||
log.Warnf("failed to decode key %s in badger AllKeysChan; err: %s", k, err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return ch, nil
|
||||
}
|
||||
|
||||
// HashOnRead implements Blockstore.HashOnRead. It is not supported by this
|
||||
// blockstore.
|
||||
func (b *Blockstore) HashOnRead(_ bool) {
|
||||
log.Warnf("called HashOnRead on badger blockstore; function not supported; ignoring")
|
||||
}
|
||||
|
||||
// PooledStorageKey returns the storage key under which this CID is stored.
|
||||
//
|
||||
// The key is: prefix + base32_no_padding(cid.Hash)
|
||||
//
|
||||
// This method may return pooled byte slice, which MUST be returned to the
|
||||
// KeyPool if pooled=true, or a leak will occur.
|
||||
func (b *Blockstore) PooledStorageKey(cid cid.Cid) (key []byte, pooled bool) {
|
||||
h := cid.Hash()
|
||||
size := base32.RawStdEncoding.EncodedLen(len(h))
|
||||
if !b.prefixing { // optimize for branch prediction.
|
||||
k := pool.Get(size)
|
||||
base32.RawStdEncoding.Encode(k, h)
|
||||
return k, true // slicing upto length unnecessary; the pool has already done this.
|
||||
}
|
||||
|
||||
size += b.prefixLen
|
||||
k := pool.Get(size)
|
||||
copy(k, b.prefix)
|
||||
base32.RawStdEncoding.Encode(k[b.prefixLen:], h)
|
||||
return k, true // slicing upto length unnecessary; the pool has already done this.
|
||||
}
|
||||
|
||||
// Storage acts like PooledStorageKey, but attempts to write the storage key
|
||||
// into the provided slice. If the slice capacity is insufficient, it allocates
|
||||
// a new byte slice with enough capacity to accommodate the result. This method
|
||||
// returns the resulting slice.
|
||||
func (b *Blockstore) StorageKey(dst []byte, cid cid.Cid) []byte {
|
||||
h := cid.Hash()
|
||||
reqsize := base32.RawStdEncoding.EncodedLen(len(h)) + b.prefixLen
|
||||
if reqsize > cap(dst) {
|
||||
// passed slice is smaller than required size; create new.
|
||||
dst = make([]byte, reqsize)
|
||||
} else if reqsize > len(dst) {
|
||||
// passed slice has enough capacity, but its length is
|
||||
// restricted, expand.
|
||||
dst = dst[:cap(dst)]
|
||||
}
|
||||
|
||||
if b.prefixing { // optimize for branch prediction.
|
||||
copy(dst, b.prefix)
|
||||
base32.RawStdEncoding.Encode(dst[b.prefixLen:], h)
|
||||
} else {
|
||||
base32.RawStdEncoding.Encode(dst, h)
|
||||
}
|
||||
return dst[:reqsize]
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package badgerbs
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
blocks "github.com/ipfs/go-block-format"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/filecoin-project/lotus/blockstore"
|
||||
)
|
||||
|
||||
func TestBadgerBlockstore(t *testing.T) {
|
||||
(&Suite{
|
||||
NewBlockstore: newBlockstore(DefaultOptions),
|
||||
OpenBlockstore: openBlockstore(DefaultOptions),
|
||||
}).RunTests(t, "non_prefixed")
|
||||
|
||||
prefixed := func(path string) Options {
|
||||
opts := DefaultOptions(path)
|
||||
opts.Prefix = "/prefixed/"
|
||||
return opts
|
||||
}
|
||||
|
||||
(&Suite{
|
||||
NewBlockstore: newBlockstore(prefixed),
|
||||
OpenBlockstore: openBlockstore(prefixed),
|
||||
}).RunTests(t, "prefixed")
|
||||
}
|
||||
|
||||
func TestStorageKey(t *testing.T) {
|
||||
bs, _ := newBlockstore(DefaultOptions)(t)
|
||||
bbs := bs.(*Blockstore)
|
||||
defer bbs.Close() //nolint:errcheck
|
||||
|
||||
cid1 := blocks.NewBlock([]byte("some data")).Cid()
|
||||
cid2 := blocks.NewBlock([]byte("more data")).Cid()
|
||||
cid3 := blocks.NewBlock([]byte("a little more data")).Cid()
|
||||
require.NotEqual(t, cid1, cid2) // sanity check
|
||||
require.NotEqual(t, cid2, cid3) // sanity check
|
||||
|
||||
// nil slice; let StorageKey allocate for us.
|
||||
k1 := bbs.StorageKey(nil, cid1)
|
||||
require.Len(t, k1, 55)
|
||||
require.True(t, cap(k1) == len(k1))
|
||||
|
||||
// k1's backing array is reused.
|
||||
k2 := bbs.StorageKey(k1, cid2)
|
||||
require.Len(t, k2, 55)
|
||||
require.True(t, cap(k2) == len(k1))
|
||||
|
||||
// bring k2 to len=0, and verify that its backing array gets reused
|
||||
// (i.e. k1 and k2 are overwritten)
|
||||
k3 := bbs.StorageKey(k2[:0], cid3)
|
||||
require.Len(t, k3, 55)
|
||||
require.True(t, cap(k3) == len(k3))
|
||||
|
||||
// backing array of k1 and k2 has been modified, i.e. memory is shared.
|
||||
require.Equal(t, k3, k1)
|
||||
require.Equal(t, k3, k2)
|
||||
}
|
||||
|
||||
func newBlockstore(optsSupplier func(path string) Options) func(tb testing.TB) (bs blockstore.BasicBlockstore, path string) {
|
||||
return func(tb testing.TB) (bs blockstore.BasicBlockstore, path string) {
|
||||
tb.Helper()
|
||||
|
||||
path, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
tb.Fatal(err)
|
||||
}
|
||||
|
||||
db, err := Open(optsSupplier(path))
|
||||
if err != nil {
|
||||
tb.Fatal(err)
|
||||
}
|
||||
|
||||
tb.Cleanup(func() {
|
||||
_ = os.RemoveAll(path)
|
||||
})
|
||||
|
||||
return db, path
|
||||
}
|
||||
}
|
||||
|
||||
func openBlockstore(optsSupplier func(path string) Options) func(tb testing.TB, path string) (bs blockstore.BasicBlockstore, err error) {
|
||||
return func(tb testing.TB, path string) (bs blockstore.BasicBlockstore, err error) {
|
||||
tb.Helper()
|
||||
return Open(optsSupplier(path))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,313 @@
|
||||
package badgerbs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
blocks "github.com/ipfs/go-block-format"
|
||||
"github.com/ipfs/go-cid"
|
||||
u "github.com/ipfs/go-ipfs-util"
|
||||
|
||||
"github.com/filecoin-project/lotus/blockstore"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// TODO: move this to go-ipfs-blockstore.
|
||||
type Suite struct {
|
||||
NewBlockstore func(tb testing.TB) (bs blockstore.BasicBlockstore, path string)
|
||||
OpenBlockstore func(tb testing.TB, path string) (bs blockstore.BasicBlockstore, err error)
|
||||
}
|
||||
|
||||
func (s *Suite) RunTests(t *testing.T, prefix string) {
|
||||
v := reflect.TypeOf(s)
|
||||
f := func(t *testing.T) {
|
||||
for i := 0; i < v.NumMethod(); i++ {
|
||||
if m := v.Method(i); strings.HasPrefix(m.Name, "Test") {
|
||||
f := m.Func.Interface().(func(*Suite, *testing.T))
|
||||
t.Run(m.Name, func(t *testing.T) {
|
||||
f(s, t)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if prefix == "" {
|
||||
f(t)
|
||||
} else {
|
||||
t.Run(prefix, f)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Suite) TestGetWhenKeyNotPresent(t *testing.T) {
|
||||
bs, _ := s.NewBlockstore(t)
|
||||
if c, ok := bs.(io.Closer); ok {
|
||||
defer func() { require.NoError(t, c.Close()) }()
|
||||
}
|
||||
|
||||
c := cid.NewCidV0(u.Hash([]byte("stuff")))
|
||||
bl, err := bs.Get(c)
|
||||
require.Nil(t, bl)
|
||||
require.Equal(t, blockstore.ErrNotFound, err)
|
||||
}
|
||||
|
||||
func (s *Suite) TestGetWhenKeyIsNil(t *testing.T) {
|
||||
bs, _ := s.NewBlockstore(t)
|
||||
if c, ok := bs.(io.Closer); ok {
|
||||
defer func() { require.NoError(t, c.Close()) }()
|
||||
}
|
||||
|
||||
_, err := bs.Get(cid.Undef)
|
||||
require.Equal(t, blockstore.ErrNotFound, err)
|
||||
}
|
||||
|
||||
func (s *Suite) TestPutThenGetBlock(t *testing.T) {
|
||||
bs, _ := s.NewBlockstore(t)
|
||||
if c, ok := bs.(io.Closer); ok {
|
||||
defer func() { require.NoError(t, c.Close()) }()
|
||||
}
|
||||
|
||||
orig := blocks.NewBlock([]byte("some data"))
|
||||
|
||||
err := bs.Put(orig)
|
||||
require.NoError(t, err)
|
||||
|
||||
fetched, err := bs.Get(orig.Cid())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, orig.RawData(), fetched.RawData())
|
||||
}
|
||||
|
||||
func (s *Suite) TestHas(t *testing.T) {
|
||||
bs, _ := s.NewBlockstore(t)
|
||||
if c, ok := bs.(io.Closer); ok {
|
||||
defer func() { require.NoError(t, c.Close()) }()
|
||||
}
|
||||
|
||||
orig := blocks.NewBlock([]byte("some data"))
|
||||
|
||||
err := bs.Put(orig)
|
||||
require.NoError(t, err)
|
||||
|
||||
ok, err := bs.Has(orig.Cid())
|
||||
require.NoError(t, err)
|
||||
require.True(t, ok)
|
||||
|
||||
ok, err = bs.Has(blocks.NewBlock([]byte("another thing")).Cid())
|
||||
require.NoError(t, err)
|
||||
require.False(t, ok)
|
||||
}
|
||||
|
||||
func (s *Suite) TestCidv0v1(t *testing.T) {
|
||||
bs, _ := s.NewBlockstore(t)
|
||||
if c, ok := bs.(io.Closer); ok {
|
||||
defer func() { require.NoError(t, c.Close()) }()
|
||||
}
|
||||
|
||||
orig := blocks.NewBlock([]byte("some data"))
|
||||
|
||||
err := bs.Put(orig)
|
||||
require.NoError(t, err)
|
||||
|
||||
fetched, err := bs.Get(cid.NewCidV1(cid.DagProtobuf, orig.Cid().Hash()))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, orig.RawData(), fetched.RawData())
|
||||
}
|
||||
|
||||
func (s *Suite) TestPutThenGetSizeBlock(t *testing.T) {
|
||||
bs, _ := s.NewBlockstore(t)
|
||||
if c, ok := bs.(io.Closer); ok {
|
||||
defer func() { require.NoError(t, c.Close()) }()
|
||||
}
|
||||
|
||||
block := blocks.NewBlock([]byte("some data"))
|
||||
missingBlock := blocks.NewBlock([]byte("missingBlock"))
|
||||
emptyBlock := blocks.NewBlock([]byte{})
|
||||
|
||||
err := bs.Put(block)
|
||||
require.NoError(t, err)
|
||||
|
||||
blockSize, err := bs.GetSize(block.Cid())
|
||||
require.NoError(t, err)
|
||||
require.Len(t, block.RawData(), blockSize)
|
||||
|
||||
err = bs.Put(emptyBlock)
|
||||
require.NoError(t, err)
|
||||
|
||||
emptySize, err := bs.GetSize(emptyBlock.Cid())
|
||||
require.NoError(t, err)
|
||||
require.Zero(t, emptySize)
|
||||
|
||||
missingSize, err := bs.GetSize(missingBlock.Cid())
|
||||
require.Equal(t, blockstore.ErrNotFound, err)
|
||||
require.Equal(t, -1, missingSize)
|
||||
}
|
||||
|
||||
func (s *Suite) TestAllKeysSimple(t *testing.T) {
|
||||
bs, _ := s.NewBlockstore(t)
|
||||
if c, ok := bs.(io.Closer); ok {
|
||||
defer func() { require.NoError(t, c.Close()) }()
|
||||
}
|
||||
|
||||
keys := insertBlocks(t, bs, 100)
|
||||
|
||||
ctx := context.Background()
|
||||
ch, err := bs.AllKeysChan(ctx)
|
||||
require.NoError(t, err)
|
||||
actual := collect(ch)
|
||||
|
||||
require.ElementsMatch(t, keys, actual)
|
||||
}
|
||||
|
||||
func (s *Suite) TestAllKeysRespectsContext(t *testing.T) {
|
||||
bs, _ := s.NewBlockstore(t)
|
||||
if c, ok := bs.(io.Closer); ok {
|
||||
defer func() { require.NoError(t, c.Close()) }()
|
||||
}
|
||||
|
||||
_ = insertBlocks(t, bs, 100)
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
ch, err := bs.AllKeysChan(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
// consume 2, then cancel context.
|
||||
v, ok := <-ch
|
||||
require.NotEqual(t, cid.Undef, v)
|
||||
require.True(t, ok)
|
||||
|
||||
v, ok = <-ch
|
||||
require.NotEqual(t, cid.Undef, v)
|
||||
require.True(t, ok)
|
||||
|
||||
cancel()
|
||||
// pull one value out to avoid race
|
||||
_, _ = <-ch
|
||||
|
||||
v, ok = <-ch
|
||||
require.Equal(t, cid.Undef, v)
|
||||
require.False(t, ok)
|
||||
}
|
||||
|
||||
func (s *Suite) TestDoubleClose(t *testing.T) {
|
||||
bs, _ := s.NewBlockstore(t)
|
||||
c, ok := bs.(io.Closer)
|
||||
if !ok {
|
||||
t.SkipNow()
|
||||
}
|
||||
require.NoError(t, c.Close())
|
||||
require.NoError(t, c.Close())
|
||||
}
|
||||
|
||||
func (s *Suite) TestReopenPutGet(t *testing.T) {
|
||||
bs, path := s.NewBlockstore(t)
|
||||
c, ok := bs.(io.Closer)
|
||||
if !ok {
|
||||
t.SkipNow()
|
||||
}
|
||||
|
||||
orig := blocks.NewBlock([]byte("some data"))
|
||||
err := bs.Put(orig)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = c.Close()
|
||||
require.NoError(t, err)
|
||||
|
||||
bs, err = s.OpenBlockstore(t, path)
|
||||
require.NoError(t, err)
|
||||
|
||||
fetched, err := bs.Get(orig.Cid())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, orig.RawData(), fetched.RawData())
|
||||
|
||||
err = bs.(io.Closer).Close()
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func (s *Suite) TestPutMany(t *testing.T) {
|
||||
bs, _ := s.NewBlockstore(t)
|
||||
if c, ok := bs.(io.Closer); ok {
|
||||
defer func() { require.NoError(t, c.Close()) }()
|
||||
}
|
||||
|
||||
blks := []blocks.Block{
|
||||
blocks.NewBlock([]byte("foo1")),
|
||||
blocks.NewBlock([]byte("foo2")),
|
||||
blocks.NewBlock([]byte("foo3")),
|
||||
}
|
||||
err := bs.PutMany(blks)
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, blk := range blks {
|
||||
fetched, err := bs.Get(blk.Cid())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, blk.RawData(), fetched.RawData())
|
||||
|
||||
ok, err := bs.Has(blk.Cid())
|
||||
require.NoError(t, err)
|
||||
require.True(t, ok)
|
||||
}
|
||||
|
||||
ch, err := bs.AllKeysChan(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
cids := collect(ch)
|
||||
require.Len(t, cids, 3)
|
||||
}
|
||||
|
||||
func (s *Suite) TestDelete(t *testing.T) {
|
||||
bs, _ := s.NewBlockstore(t)
|
||||
if c, ok := bs.(io.Closer); ok {
|
||||
defer func() { require.NoError(t, c.Close()) }()
|
||||
}
|
||||
|
||||
blks := []blocks.Block{
|
||||
blocks.NewBlock([]byte("foo1")),
|
||||
blocks.NewBlock([]byte("foo2")),
|
||||
blocks.NewBlock([]byte("foo3")),
|
||||
}
|
||||
err := bs.PutMany(blks)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = bs.DeleteBlock(blks[1].Cid())
|
||||
require.NoError(t, err)
|
||||
|
||||
ch, err := bs.AllKeysChan(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
cids := collect(ch)
|
||||
require.Len(t, cids, 2)
|
||||
require.ElementsMatch(t, cids, []cid.Cid{
|
||||
cid.NewCidV1(cid.Raw, blks[0].Cid().Hash()),
|
||||
cid.NewCidV1(cid.Raw, blks[2].Cid().Hash()),
|
||||
})
|
||||
|
||||
has, err := bs.Has(blks[1].Cid())
|
||||
require.NoError(t, err)
|
||||
require.False(t, has)
|
||||
|
||||
}
|
||||
|
||||
func insertBlocks(t *testing.T, bs blockstore.BasicBlockstore, count int) []cid.Cid {
|
||||
keys := make([]cid.Cid, count)
|
||||
for i := 0; i < count; i++ {
|
||||
block := blocks.NewBlock([]byte(fmt.Sprintf("some data %d", i)))
|
||||
err := bs.Put(block)
|
||||
require.NoError(t, err)
|
||||
// NewBlock assigns a CIDv0; we convert it to CIDv1 because that's what
|
||||
// the store returns.
|
||||
keys[i] = cid.NewCidV1(cid.Raw, block.Multihash())
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
func collect(ch <-chan cid.Cid) []cid.Cid {
|
||||
var keys []cid.Cid
|
||||
for k := range ch {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
return keys
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package blockstore
|
||||
|
||||
import (
|
||||
cid "github.com/ipfs/go-cid"
|
||||
ds "github.com/ipfs/go-datastore"
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
|
||||
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
)
|
||||
|
||||
var log = logging.Logger("blockstore")
|
||||
|
||||
var ErrNotFound = blockstore.ErrNotFound
|
||||
|
||||
// Blockstore is the blockstore interface used by Lotus. It is the union
|
||||
// of the basic go-ipfs blockstore, with other capabilities required by Lotus,
|
||||
// e.g. View or Sync.
|
||||
type Blockstore interface {
|
||||
blockstore.Blockstore
|
||||
blockstore.Viewer
|
||||
BatchDeleter
|
||||
}
|
||||
|
||||
// BasicBlockstore is an alias to the original IPFS Blockstore.
|
||||
type BasicBlockstore = blockstore.Blockstore
|
||||
|
||||
type Viewer = blockstore.Viewer
|
||||
|
||||
type BatchDeleter interface {
|
||||
DeleteMany(cids []cid.Cid) error
|
||||
}
|
||||
|
||||
// WrapIDStore wraps the underlying blockstore in an "identity" blockstore.
|
||||
// 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 and returns them on get/has, ignoring the contents of the
|
||||
// blockstore.
|
||||
func WrapIDStore(bstore blockstore.Blockstore) Blockstore {
|
||||
if is, ok := bstore.(*idstore); ok {
|
||||
// already wrapped
|
||||
return is
|
||||
}
|
||||
|
||||
if bs, ok := bstore.(Blockstore); ok {
|
||||
// we need to wrap our own because we don't want to neuter the DeleteMany method
|
||||
// the underlying blockstore has implemented an (efficient) DeleteMany
|
||||
return NewIDStore(bs)
|
||||
}
|
||||
|
||||
// The underlying blockstore does not implement DeleteMany, so we need to shim it.
|
||||
// This is less efficient as it'll iterate and perform single deletes.
|
||||
return NewIDStore(Adapt(bstore))
|
||||
}
|
||||
|
||||
// FromDatastore creates a new blockstore backed by the given datastore.
|
||||
func FromDatastore(dstore ds.Batching) Blockstore {
|
||||
return WrapIDStore(blockstore.NewBlockstore(dstore))
|
||||
}
|
||||
|
||||
type adaptedBlockstore struct {
|
||||
blockstore.Blockstore
|
||||
}
|
||||
|
||||
var _ Blockstore = (*adaptedBlockstore)(nil)
|
||||
|
||||
func (a *adaptedBlockstore) View(cid cid.Cid, callback func([]byte) error) error {
|
||||
blk, err := a.Get(cid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return callback(blk.RawData())
|
||||
}
|
||||
|
||||
func (a *adaptedBlockstore) DeleteMany(cids []cid.Cid) error {
|
||||
for _, cid := range cids {
|
||||
err := a.DeleteBlock(cid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Adapt adapts a standard blockstore to a Lotus blockstore by
|
||||
// enriching it with the extra methods that Lotus requires (e.g. View, Sync).
|
||||
//
|
||||
// View proxies over to Get and calls the callback with the value supplied by Get.
|
||||
// Sync noops.
|
||||
func Adapt(bs blockstore.Blockstore) Blockstore {
|
||||
if ret, ok := bs.(Blockstore); ok {
|
||||
return ret
|
||||
}
|
||||
return &adaptedBlockstore{bs}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
package blockstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
block "github.com/ipfs/go-block-format"
|
||||
"github.com/ipfs/go-cid"
|
||||
)
|
||||
|
||||
// buflog is a logger for the buffered blockstore. It is subscoped from the
|
||||
// blockstore logger.
|
||||
var buflog = log.Named("buf")
|
||||
|
||||
type BufferedBlockstore struct {
|
||||
read Blockstore
|
||||
write Blockstore
|
||||
}
|
||||
|
||||
func NewBuffered(base Blockstore) *BufferedBlockstore {
|
||||
var buf Blockstore
|
||||
if os.Getenv("LOTUS_DISABLE_VM_BUF") == "iknowitsabadidea" {
|
||||
buflog.Warn("VM BLOCKSTORE BUFFERING IS DISABLED")
|
||||
buf = base
|
||||
} else {
|
||||
buf = NewMemory()
|
||||
}
|
||||
|
||||
bs := &BufferedBlockstore{
|
||||
read: base,
|
||||
write: buf,
|
||||
}
|
||||
return bs
|
||||
}
|
||||
|
||||
func NewTieredBstore(r Blockstore, w Blockstore) *BufferedBlockstore {
|
||||
return &BufferedBlockstore{
|
||||
read: r,
|
||||
write: w,
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
_ Blockstore = (*BufferedBlockstore)(nil)
|
||||
_ Viewer = (*BufferedBlockstore)(nil)
|
||||
)
|
||||
|
||||
func (bs *BufferedBlockstore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
|
||||
a, err := bs.read.AllKeysChan(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b, err := bs.write.AllKeysChan(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out := make(chan cid.Cid)
|
||||
go func() {
|
||||
defer close(out)
|
||||
for a != nil || b != nil {
|
||||
select {
|
||||
case val, ok := <-a:
|
||||
if !ok {
|
||||
a = nil
|
||||
} else {
|
||||
select {
|
||||
case out <- val:
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
case val, ok := <-b:
|
||||
if !ok {
|
||||
b = nil
|
||||
} else {
|
||||
select {
|
||||
case out <- val:
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (bs *BufferedBlockstore) DeleteBlock(c cid.Cid) error {
|
||||
if err := bs.read.DeleteBlock(c); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return bs.write.DeleteBlock(c)
|
||||
}
|
||||
|
||||
func (bs *BufferedBlockstore) DeleteMany(cids []cid.Cid) error {
|
||||
if err := bs.read.DeleteMany(cids); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return bs.write.DeleteMany(cids)
|
||||
}
|
||||
|
||||
func (bs *BufferedBlockstore) View(c cid.Cid, callback func([]byte) error) error {
|
||||
// both stores are viewable.
|
||||
if err := bs.write.View(c, callback); err == ErrNotFound {
|
||||
// not found in write blockstore; fall through.
|
||||
} else {
|
||||
return err // propagate errors, or nil, i.e. found.
|
||||
}
|
||||
return bs.read.View(c, callback)
|
||||
}
|
||||
|
||||
func (bs *BufferedBlockstore) Get(c cid.Cid) (block.Block, error) {
|
||||
if out, err := bs.write.Get(c); err != nil {
|
||||
if err != ErrNotFound {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
return out, nil
|
||||
}
|
||||
|
||||
return bs.read.Get(c)
|
||||
}
|
||||
|
||||
func (bs *BufferedBlockstore) GetSize(c cid.Cid) (int, error) {
|
||||
s, err := bs.read.GetSize(c)
|
||||
if err == ErrNotFound || s == 0 {
|
||||
return bs.write.GetSize(c)
|
||||
}
|
||||
|
||||
return s, err
|
||||
}
|
||||
|
||||
func (bs *BufferedBlockstore) Put(blk block.Block) error {
|
||||
has, err := bs.read.Has(blk.Cid()) // TODO: consider dropping this check
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if has {
|
||||
return nil
|
||||
}
|
||||
|
||||
return bs.write.Put(blk)
|
||||
}
|
||||
|
||||
func (bs *BufferedBlockstore) Has(c cid.Cid) (bool, error) {
|
||||
has, err := bs.write.Has(c)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if has {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return bs.read.Has(c)
|
||||
}
|
||||
|
||||
func (bs *BufferedBlockstore) HashOnRead(hor bool) {
|
||||
bs.read.HashOnRead(hor)
|
||||
bs.write.HashOnRead(hor)
|
||||
}
|
||||
|
||||
func (bs *BufferedBlockstore) PutMany(blks []block.Block) error {
|
||||
return bs.write.PutMany(blks)
|
||||
}
|
||||
|
||||
func (bs *BufferedBlockstore) Read() Blockstore {
|
||||
return bs.read
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package blockstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
)
|
||||
|
||||
type CacheOpts = blockstore.CacheOpts
|
||||
|
||||
func DefaultCacheOpts() CacheOpts {
|
||||
return CacheOpts{
|
||||
HasBloomFilterSize: 0,
|
||||
HasBloomFilterHashes: 0,
|
||||
HasARCCacheSize: 512 << 10,
|
||||
}
|
||||
}
|
||||
|
||||
func CachedBlockstore(ctx context.Context, bs Blockstore, opts CacheOpts) (Blockstore, error) {
|
||||
cached, err := blockstore.CachedBlockstore(ctx, bs, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return WrapIDStore(cached), nil
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// Package blockstore and subpackages contain most of the blockstore
|
||||
// implementations used by Lotus.
|
||||
//
|
||||
// Blockstores not ultimately constructed out of the building blocks in this
|
||||
// package may not work properly.
|
||||
//
|
||||
// This package re-exports parts of the go-ipfs-blockstore package such that
|
||||
// no other package needs to import it directly, for ergonomics and traceability.
|
||||
package blockstore
|
||||
@@ -0,0 +1,106 @@
|
||||
package blockstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
blocks "github.com/ipfs/go-block-format"
|
||||
"github.com/ipfs/go-cid"
|
||||
)
|
||||
|
||||
// UnwrapFallbackStore takes a blockstore, and returns the underlying blockstore
|
||||
// if it was a FallbackStore. Otherwise, it just returns the supplied store
|
||||
// unmodified.
|
||||
func UnwrapFallbackStore(bs Blockstore) (Blockstore, bool) {
|
||||
if fbs, ok := bs.(*FallbackStore); ok {
|
||||
return fbs.Blockstore, true
|
||||
}
|
||||
return bs, false
|
||||
}
|
||||
|
||||
// FallbackStore is a read-through store that queries another (potentially
|
||||
// remote) source if the block is not found locally. If the block is found
|
||||
// during the fallback, it stores it in the local store.
|
||||
type FallbackStore struct {
|
||||
Blockstore
|
||||
|
||||
lk sync.RWMutex
|
||||
// missFn is the function that will be invoked on a local miss to pull the
|
||||
// block from elsewhere.
|
||||
missFn func(context.Context, cid.Cid) (blocks.Block, error)
|
||||
}
|
||||
|
||||
var _ Blockstore = (*FallbackStore)(nil)
|
||||
|
||||
func (fbs *FallbackStore) SetFallback(missFn func(context.Context, cid.Cid) (blocks.Block, error)) {
|
||||
fbs.lk.Lock()
|
||||
defer fbs.lk.Unlock()
|
||||
|
||||
fbs.missFn = missFn
|
||||
}
|
||||
|
||||
func (fbs *FallbackStore) getFallback(c cid.Cid) (blocks.Block, error) {
|
||||
log.Warnf("fallbackstore: block not found locally, fetching from the network; cid: %s", c)
|
||||
fbs.lk.RLock()
|
||||
defer fbs.lk.RUnlock()
|
||||
|
||||
if fbs.missFn == nil {
|
||||
// FallbackStore wasn't configured yet (chainstore/bitswap aren't up yet)
|
||||
// Wait for a bit and retry
|
||||
fbs.lk.RUnlock()
|
||||
time.Sleep(5 * time.Second)
|
||||
fbs.lk.RLock()
|
||||
|
||||
if fbs.missFn == nil {
|
||||
log.Errorw("fallbackstore: missFn not configured yet")
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.TODO(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
b, err := fbs.missFn(ctx, c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// chain bitswap puts blocks in temp blockstore which is cleaned up
|
||||
// every few min (to drop any messages we fetched but don't want)
|
||||
// in this case we want to keep this block around
|
||||
if err := fbs.Put(b); err != nil {
|
||||
return nil, xerrors.Errorf("persisting fallback-fetched block: %w", err)
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (fbs *FallbackStore) Get(c cid.Cid) (blocks.Block, error) {
|
||||
b, err := fbs.Blockstore.Get(c)
|
||||
switch err {
|
||||
case nil:
|
||||
return b, nil
|
||||
case ErrNotFound:
|
||||
return fbs.getFallback(c)
|
||||
default:
|
||||
return b, err
|
||||
}
|
||||
}
|
||||
|
||||
func (fbs *FallbackStore) GetSize(c cid.Cid) (int, error) {
|
||||
sz, err := fbs.Blockstore.GetSize(c)
|
||||
switch err {
|
||||
case nil:
|
||||
return sz, nil
|
||||
case ErrNotFound:
|
||||
b, err := fbs.getFallback(c)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return len(b.RawData()), nil
|
||||
default:
|
||||
return sz, err
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
package blockstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
blocks "github.com/ipfs/go-block-format"
|
||||
cid "github.com/ipfs/go-cid"
|
||||
mh "github.com/multiformats/go-multihash"
|
||||
)
|
||||
|
||||
var _ Blockstore = (*idstore)(nil)
|
||||
|
||||
type idstore struct {
|
||||
bs Blockstore
|
||||
}
|
||||
|
||||
func NewIDStore(bs Blockstore) Blockstore {
|
||||
return &idstore{bs: bs}
|
||||
}
|
||||
|
||||
func decodeCid(cid cid.Cid) (inline bool, data []byte, err error) {
|
||||
if cid.Prefix().MhType != mh.IDENTITY {
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
dmh, err := mh.Decode(cid.Hash())
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
|
||||
if dmh.Code == mh.IDENTITY {
|
||||
return true, dmh.Digest, nil
|
||||
}
|
||||
|
||||
return false, nil, err
|
||||
}
|
||||
|
||||
func (b *idstore) Has(cid cid.Cid) (bool, error) {
|
||||
inline, _, err := decodeCid(cid)
|
||||
if err != nil {
|
||||
return false, xerrors.Errorf("error decoding Cid: %w", err)
|
||||
}
|
||||
|
||||
if inline {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return b.bs.Has(cid)
|
||||
}
|
||||
|
||||
func (b *idstore) Get(cid cid.Cid) (blocks.Block, error) {
|
||||
inline, data, err := decodeCid(cid)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("error decoding Cid: %w", err)
|
||||
}
|
||||
|
||||
if inline {
|
||||
return blocks.NewBlockWithCid(data, cid)
|
||||
}
|
||||
|
||||
return b.bs.Get(cid)
|
||||
}
|
||||
|
||||
func (b *idstore) GetSize(cid cid.Cid) (int, error) {
|
||||
inline, data, err := decodeCid(cid)
|
||||
if err != nil {
|
||||
return 0, xerrors.Errorf("error decoding Cid: %w", err)
|
||||
}
|
||||
|
||||
if inline {
|
||||
return len(data), err
|
||||
}
|
||||
|
||||
return b.bs.GetSize(cid)
|
||||
}
|
||||
|
||||
func (b *idstore) View(cid cid.Cid, cb func([]byte) error) error {
|
||||
inline, data, err := decodeCid(cid)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("error decoding Cid: %w", err)
|
||||
}
|
||||
|
||||
if inline {
|
||||
return cb(data)
|
||||
}
|
||||
|
||||
return b.bs.View(cid, cb)
|
||||
}
|
||||
|
||||
func (b *idstore) Put(blk blocks.Block) error {
|
||||
inline, _, err := decodeCid(blk.Cid())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("error decoding Cid: %w", err)
|
||||
}
|
||||
|
||||
if inline {
|
||||
return nil
|
||||
}
|
||||
|
||||
return b.bs.Put(blk)
|
||||
}
|
||||
|
||||
func (b *idstore) PutMany(blks []blocks.Block) error {
|
||||
toPut := make([]blocks.Block, 0, len(blks))
|
||||
for _, blk := range blks {
|
||||
inline, _, err := decodeCid(blk.Cid())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("error decoding Cid: %w", err)
|
||||
}
|
||||
|
||||
if inline {
|
||||
continue
|
||||
}
|
||||
toPut = append(toPut, blk)
|
||||
}
|
||||
|
||||
if len(toPut) > 0 {
|
||||
return b.bs.PutMany(toPut)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *idstore) DeleteBlock(cid cid.Cid) error {
|
||||
inline, _, err := decodeCid(cid)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("error decoding Cid: %w", err)
|
||||
}
|
||||
|
||||
if inline {
|
||||
return nil
|
||||
}
|
||||
|
||||
return b.bs.DeleteBlock(cid)
|
||||
}
|
||||
|
||||
func (b *idstore) DeleteMany(cids []cid.Cid) error {
|
||||
toDelete := make([]cid.Cid, 0, len(cids))
|
||||
for _, cid := range cids {
|
||||
inline, _, err := decodeCid(cid)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("error decoding Cid: %w", err)
|
||||
}
|
||||
|
||||
if inline {
|
||||
continue
|
||||
}
|
||||
toDelete = append(toDelete, cid)
|
||||
}
|
||||
|
||||
if len(toDelete) > 0 {
|
||||
return b.bs.DeleteMany(toDelete)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *idstore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
|
||||
return b.bs.AllKeysChan(ctx)
|
||||
}
|
||||
|
||||
func (b *idstore) HashOnRead(enabled bool) {
|
||||
b.bs.HashOnRead(enabled)
|
||||
}
|
||||
|
||||
func (b *idstore) Close() error {
|
||||
if c, ok := b.bs.(io.Closer); ok {
|
||||
return c.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package ipfsbstore
|
||||
package blockstore
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -16,53 +16,75 @@ import (
|
||||
iface "github.com/ipfs/interface-go-ipfs-core"
|
||||
"github.com/ipfs/interface-go-ipfs-core/options"
|
||||
"github.com/ipfs/interface-go-ipfs-core/path"
|
||||
|
||||
"github.com/filecoin-project/lotus/lib/blockstore"
|
||||
)
|
||||
|
||||
type IpfsBstore struct {
|
||||
ctx context.Context
|
||||
api iface.CoreAPI
|
||||
type IPFSBlockstore struct {
|
||||
ctx context.Context
|
||||
api, offlineAPI iface.CoreAPI
|
||||
}
|
||||
|
||||
func NewIpfsBstore(ctx context.Context) (*IpfsBstore, error) {
|
||||
var _ BasicBlockstore = (*IPFSBlockstore)(nil)
|
||||
|
||||
func NewLocalIPFSBlockstore(ctx context.Context, onlineMode bool) (Blockstore, error) {
|
||||
localApi, err := httpapi.NewLocalApi()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("getting local ipfs api: %w", err)
|
||||
}
|
||||
api, err := localApi.WithOptions(options.Api.Offline(true))
|
||||
api, err := localApi.WithOptions(options.Api.Offline(!onlineMode))
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("setting offline mode: %s", err)
|
||||
}
|
||||
|
||||
return &IpfsBstore{
|
||||
ctx: ctx,
|
||||
api: api,
|
||||
}, nil
|
||||
offlineAPI := api
|
||||
if onlineMode {
|
||||
offlineAPI, err = localApi.WithOptions(options.Api.Offline(true))
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("applying offline mode: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
bs := &IPFSBlockstore{
|
||||
ctx: ctx,
|
||||
api: api,
|
||||
offlineAPI: offlineAPI,
|
||||
}
|
||||
|
||||
return Adapt(bs), nil
|
||||
}
|
||||
|
||||
func NewRemoteIpfsBstore(ctx context.Context, maddr multiaddr.Multiaddr) (*IpfsBstore, error) {
|
||||
func NewRemoteIPFSBlockstore(ctx context.Context, maddr multiaddr.Multiaddr, onlineMode bool) (Blockstore, error) {
|
||||
httpApi, err := httpapi.NewApi(maddr)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("setting remote ipfs api: %w", err)
|
||||
}
|
||||
api, err := httpApi.WithOptions(options.Api.Offline(true))
|
||||
api, err := httpApi.WithOptions(options.Api.Offline(!onlineMode))
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("applying offline mode: %s", err)
|
||||
}
|
||||
|
||||
return &IpfsBstore{
|
||||
ctx: ctx,
|
||||
api: api,
|
||||
}, nil
|
||||
offlineAPI := api
|
||||
if onlineMode {
|
||||
offlineAPI, err = httpApi.WithOptions(options.Api.Offline(true))
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("applying offline mode: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
bs := &IPFSBlockstore{
|
||||
ctx: ctx,
|
||||
api: api,
|
||||
offlineAPI: offlineAPI,
|
||||
}
|
||||
|
||||
return Adapt(bs), nil
|
||||
}
|
||||
|
||||
func (i *IpfsBstore) DeleteBlock(cid cid.Cid) error {
|
||||
func (i *IPFSBlockstore) DeleteBlock(cid cid.Cid) error {
|
||||
return xerrors.Errorf("not supported")
|
||||
}
|
||||
|
||||
func (i *IpfsBstore) Has(cid cid.Cid) (bool, error) {
|
||||
_, err := i.api.Block().Stat(i.ctx, path.IpldPath(cid))
|
||||
func (i *IPFSBlockstore) Has(cid cid.Cid) (bool, error) {
|
||||
_, err := i.offlineAPI.Block().Stat(i.ctx, path.IpldPath(cid))
|
||||
if err != nil {
|
||||
// The underlying client is running in Offline mode.
|
||||
// Stat() will fail with an err if the block isn't in the
|
||||
@@ -77,7 +99,7 @@ func (i *IpfsBstore) Has(cid cid.Cid) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (i *IpfsBstore) Get(cid cid.Cid) (blocks.Block, error) {
|
||||
func (i *IPFSBlockstore) Get(cid cid.Cid) (blocks.Block, error) {
|
||||
rd, err := i.api.Block().Get(i.ctx, path.IpldPath(cid))
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("getting ipfs block: %w", err)
|
||||
@@ -91,7 +113,7 @@ func (i *IpfsBstore) Get(cid cid.Cid) (blocks.Block, error) {
|
||||
return blocks.NewBlockWithCid(data, cid)
|
||||
}
|
||||
|
||||
func (i *IpfsBstore) GetSize(cid cid.Cid) (int, error) {
|
||||
func (i *IPFSBlockstore) GetSize(cid cid.Cid) (int, error) {
|
||||
st, err := i.api.Block().Stat(i.ctx, path.IpldPath(cid))
|
||||
if err != nil {
|
||||
return 0, xerrors.Errorf("getting ipfs block: %w", err)
|
||||
@@ -100,7 +122,7 @@ func (i *IpfsBstore) GetSize(cid cid.Cid) (int, error) {
|
||||
return st.Size(), nil
|
||||
}
|
||||
|
||||
func (i *IpfsBstore) Put(block blocks.Block) error {
|
||||
func (i *IPFSBlockstore) Put(block blocks.Block) error {
|
||||
mhd, err := multihash.Decode(block.Cid().Hash())
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -112,7 +134,7 @@ func (i *IpfsBstore) Put(block blocks.Block) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (i *IpfsBstore) PutMany(blocks []blocks.Block) error {
|
||||
func (i *IPFSBlockstore) PutMany(blocks []blocks.Block) error {
|
||||
// TODO: could be done in parallel
|
||||
|
||||
for _, block := range blocks {
|
||||
@@ -124,12 +146,10 @@ func (i *IpfsBstore) PutMany(blocks []blocks.Block) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *IpfsBstore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
|
||||
func (i *IPFSBlockstore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
|
||||
return nil, xerrors.Errorf("not supported")
|
||||
}
|
||||
|
||||
func (i *IpfsBstore) HashOnRead(enabled bool) {
|
||||
func (i *IPFSBlockstore) HashOnRead(enabled bool) {
|
||||
return // TODO: We could technically support this, but..
|
||||
}
|
||||
|
||||
var _ blockstore.Blockstore = &IpfsBstore{}
|
||||
@@ -5,38 +5,60 @@ import (
|
||||
|
||||
blocks "github.com/ipfs/go-block-format"
|
||||
"github.com/ipfs/go-cid"
|
||||
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
)
|
||||
|
||||
type MemStore map[cid.Cid]blocks.Block
|
||||
// NewMemory returns a temporary memory-backed blockstore.
|
||||
func NewMemory() MemBlockstore {
|
||||
return make(MemBlockstore)
|
||||
}
|
||||
|
||||
func (m MemStore) DeleteBlock(k cid.Cid) error {
|
||||
// MemBlockstore is a terminal blockstore that keeps blocks in memory.
|
||||
type MemBlockstore map[cid.Cid]blocks.Block
|
||||
|
||||
func (m MemBlockstore) DeleteBlock(k cid.Cid) error {
|
||||
delete(m, k)
|
||||
return nil
|
||||
}
|
||||
func (m MemStore) Has(k cid.Cid) (bool, error) {
|
||||
|
||||
func (m MemBlockstore) DeleteMany(ks []cid.Cid) error {
|
||||
for _, k := range ks {
|
||||
delete(m, k)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m MemBlockstore) Has(k cid.Cid) (bool, error) {
|
||||
_, ok := m[k]
|
||||
return ok, nil
|
||||
}
|
||||
func (m MemStore) Get(k cid.Cid) (blocks.Block, error) {
|
||||
|
||||
func (m MemBlockstore) View(k cid.Cid, callback func([]byte) error) error {
|
||||
b, ok := m[k]
|
||||
if !ok {
|
||||
return nil, blockstore.ErrNotFound
|
||||
return ErrNotFound
|
||||
}
|
||||
return callback(b.RawData())
|
||||
}
|
||||
|
||||
func (m MemBlockstore) Get(k cid.Cid) (blocks.Block, error) {
|
||||
b, ok := m[k]
|
||||
if !ok {
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// GetSize returns the CIDs mapped BlockSize
|
||||
func (m MemStore) GetSize(k cid.Cid) (int, error) {
|
||||
func (m MemBlockstore) GetSize(k cid.Cid) (int, error) {
|
||||
b, ok := m[k]
|
||||
if !ok {
|
||||
return 0, blockstore.ErrNotFound
|
||||
return 0, ErrNotFound
|
||||
}
|
||||
return len(b.RawData()), nil
|
||||
}
|
||||
|
||||
// Put puts a given block to the underlying datastore
|
||||
func (m MemStore) Put(b blocks.Block) error {
|
||||
func (m MemBlockstore) Put(b blocks.Block) error {
|
||||
// Convert to a basic block for safety, but try to reuse the existing
|
||||
// block if it's already a basic block.
|
||||
k := b.Cid()
|
||||
@@ -54,7 +76,7 @@ func (m MemStore) Put(b blocks.Block) error {
|
||||
|
||||
// PutMany puts a slice of blocks at the same time using batching
|
||||
// capabilities of the underlying datastore whenever possible.
|
||||
func (m MemStore) PutMany(bs []blocks.Block) error {
|
||||
func (m MemBlockstore) PutMany(bs []blocks.Block) error {
|
||||
for _, b := range bs {
|
||||
_ = m.Put(b) // can't fail
|
||||
}
|
||||
@@ -64,7 +86,7 @@ func (m MemStore) PutMany(bs []blocks.Block) error {
|
||||
// AllKeysChan returns a channel from which
|
||||
// the CIDs in the Blockstore can be read. It should respect
|
||||
// the given context, closing the channel if it becomes Done.
|
||||
func (m MemStore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
|
||||
func (m MemBlockstore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
|
||||
ch := make(chan cid.Cid, len(m))
|
||||
for k := range m {
|
||||
ch <- k
|
||||
@@ -75,6 +97,6 @@ func (m MemStore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
|
||||
|
||||
// HashOnRead specifies if every read block should be
|
||||
// rehashed to make sure it matches its CID.
|
||||
func (m MemStore) HashOnRead(enabled bool) {
|
||||
func (m MemBlockstore) HashOnRead(enabled bool) {
|
||||
// no-op
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
package blockstore
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"go.opencensus.io/stats"
|
||||
"go.opencensus.io/stats/view"
|
||||
"go.opencensus.io/tag"
|
||||
)
|
||||
|
||||
//
|
||||
// Currently unused, but kept in repo in case we introduce one of the candidate
|
||||
// cache implementations (Freecache, Ristretto), both of which report these
|
||||
// metrics.
|
||||
//
|
||||
|
||||
// CacheMetricsEmitInterval is the interval at which metrics are emitted onto
|
||||
// OpenCensus.
|
||||
var CacheMetricsEmitInterval = 5 * time.Second
|
||||
|
||||
var (
|
||||
CacheName, _ = tag.NewKey("cache_name")
|
||||
)
|
||||
|
||||
// CacheMeasures groups all metrics emitted by the blockstore caches.
|
||||
var CacheMeasures = struct {
|
||||
HitRatio *stats.Float64Measure
|
||||
Hits *stats.Int64Measure
|
||||
Misses *stats.Int64Measure
|
||||
Entries *stats.Int64Measure
|
||||
QueriesServed *stats.Int64Measure
|
||||
Adds *stats.Int64Measure
|
||||
Updates *stats.Int64Measure
|
||||
Evictions *stats.Int64Measure
|
||||
CostAdded *stats.Int64Measure
|
||||
CostEvicted *stats.Int64Measure
|
||||
SetsDropped *stats.Int64Measure
|
||||
SetsRejected *stats.Int64Measure
|
||||
QueriesDropped *stats.Int64Measure
|
||||
}{
|
||||
HitRatio: stats.Float64("blockstore/cache/hit_ratio", "Hit ratio of blockstore cache", stats.UnitDimensionless),
|
||||
Hits: stats.Int64("blockstore/cache/hits", "Total number of hits at blockstore cache", stats.UnitDimensionless),
|
||||
Misses: stats.Int64("blockstore/cache/misses", "Total number of misses at blockstore cache", stats.UnitDimensionless),
|
||||
Entries: stats.Int64("blockstore/cache/entry_count", "Total number of entries currently in the blockstore cache", stats.UnitDimensionless),
|
||||
QueriesServed: stats.Int64("blockstore/cache/queries_served", "Total number of queries served by the blockstore cache", stats.UnitDimensionless),
|
||||
Adds: stats.Int64("blockstore/cache/adds", "Total number of adds to blockstore cache", stats.UnitDimensionless),
|
||||
Updates: stats.Int64("blockstore/cache/updates", "Total number of updates in blockstore cache", stats.UnitDimensionless),
|
||||
Evictions: stats.Int64("blockstore/cache/evictions", "Total number of evictions from blockstore cache", stats.UnitDimensionless),
|
||||
CostAdded: stats.Int64("blockstore/cache/cost_added", "Total cost (byte size) of entries added into blockstore cache", stats.UnitBytes),
|
||||
CostEvicted: stats.Int64("blockstore/cache/cost_evicted", "Total cost (byte size) of entries evicted by blockstore cache", stats.UnitBytes),
|
||||
SetsDropped: stats.Int64("blockstore/cache/sets_dropped", "Total number of sets dropped by blockstore cache", stats.UnitDimensionless),
|
||||
SetsRejected: stats.Int64("blockstore/cache/sets_rejected", "Total number of sets rejected by blockstore cache", stats.UnitDimensionless),
|
||||
QueriesDropped: stats.Int64("blockstore/cache/queries_dropped", "Total number of queries dropped by blockstore cache", stats.UnitDimensionless),
|
||||
}
|
||||
|
||||
// CacheViews groups all cache-related default views.
|
||||
var CacheViews = struct {
|
||||
HitRatio *view.View
|
||||
Hits *view.View
|
||||
Misses *view.View
|
||||
Entries *view.View
|
||||
QueriesServed *view.View
|
||||
Adds *view.View
|
||||
Updates *view.View
|
||||
Evictions *view.View
|
||||
CostAdded *view.View
|
||||
CostEvicted *view.View
|
||||
SetsDropped *view.View
|
||||
SetsRejected *view.View
|
||||
QueriesDropped *view.View
|
||||
}{
|
||||
HitRatio: &view.View{
|
||||
Measure: CacheMeasures.HitRatio,
|
||||
Aggregation: view.LastValue(),
|
||||
TagKeys: []tag.Key{CacheName},
|
||||
},
|
||||
Hits: &view.View{
|
||||
Measure: CacheMeasures.Hits,
|
||||
Aggregation: view.LastValue(),
|
||||
TagKeys: []tag.Key{CacheName},
|
||||
},
|
||||
Misses: &view.View{
|
||||
Measure: CacheMeasures.Misses,
|
||||
Aggregation: view.LastValue(),
|
||||
TagKeys: []tag.Key{CacheName},
|
||||
},
|
||||
Entries: &view.View{
|
||||
Measure: CacheMeasures.Entries,
|
||||
Aggregation: view.LastValue(),
|
||||
TagKeys: []tag.Key{CacheName},
|
||||
},
|
||||
QueriesServed: &view.View{
|
||||
Measure: CacheMeasures.QueriesServed,
|
||||
Aggregation: view.LastValue(),
|
||||
TagKeys: []tag.Key{CacheName},
|
||||
},
|
||||
Adds: &view.View{
|
||||
Measure: CacheMeasures.Adds,
|
||||
Aggregation: view.LastValue(),
|
||||
TagKeys: []tag.Key{CacheName},
|
||||
},
|
||||
Updates: &view.View{
|
||||
Measure: CacheMeasures.Updates,
|
||||
Aggregation: view.LastValue(),
|
||||
TagKeys: []tag.Key{CacheName},
|
||||
},
|
||||
Evictions: &view.View{
|
||||
Measure: CacheMeasures.Evictions,
|
||||
Aggregation: view.LastValue(),
|
||||
TagKeys: []tag.Key{CacheName},
|
||||
},
|
||||
CostAdded: &view.View{
|
||||
Measure: CacheMeasures.CostAdded,
|
||||
Aggregation: view.LastValue(),
|
||||
TagKeys: []tag.Key{CacheName},
|
||||
},
|
||||
CostEvicted: &view.View{
|
||||
Measure: CacheMeasures.CostEvicted,
|
||||
Aggregation: view.LastValue(),
|
||||
TagKeys: []tag.Key{CacheName},
|
||||
},
|
||||
SetsDropped: &view.View{
|
||||
Measure: CacheMeasures.SetsDropped,
|
||||
Aggregation: view.LastValue(),
|
||||
TagKeys: []tag.Key{CacheName},
|
||||
},
|
||||
SetsRejected: &view.View{
|
||||
Measure: CacheMeasures.SetsRejected,
|
||||
Aggregation: view.LastValue(),
|
||||
TagKeys: []tag.Key{CacheName},
|
||||
},
|
||||
QueriesDropped: &view.View{
|
||||
Measure: CacheMeasures.QueriesDropped,
|
||||
Aggregation: view.LastValue(),
|
||||
TagKeys: []tag.Key{CacheName},
|
||||
},
|
||||
}
|
||||
|
||||
// DefaultViews exports all default views for this package.
|
||||
var DefaultViews = []*view.View{
|
||||
CacheViews.HitRatio,
|
||||
CacheViews.Hits,
|
||||
CacheViews.Misses,
|
||||
CacheViews.Entries,
|
||||
CacheViews.QueriesServed,
|
||||
CacheViews.Adds,
|
||||
CacheViews.Updates,
|
||||
CacheViews.Evictions,
|
||||
CacheViews.CostAdded,
|
||||
CacheViews.CostEvicted,
|
||||
CacheViews.SetsDropped,
|
||||
CacheViews.SetsRejected,
|
||||
CacheViews.QueriesDropped,
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package splitstore
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
cid "github.com/ipfs/go-cid"
|
||||
)
|
||||
|
||||
// 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 a probabilistic result is acceptable, it can be backed by a bloom filter (default).
|
||||
type MarkSet interface {
|
||||
Mark(cid.Cid) error
|
||||
Has(cid.Cid) (bool, error)
|
||||
Close() error
|
||||
}
|
||||
|
||||
// markBytes is deliberately a non-nil empty byte slice for serialization.
|
||||
var markBytes = []byte{}
|
||||
|
||||
type MarkSetEnv interface {
|
||||
Create(name string, sizeHint int64) (MarkSet, error)
|
||||
Close() error
|
||||
}
|
||||
|
||||
func OpenMarkSetEnv(path string, mtype string) (MarkSetEnv, error) {
|
||||
switch mtype {
|
||||
case "", "bloom":
|
||||
return NewBloomMarkSetEnv()
|
||||
case "bolt":
|
||||
return NewBoltMarkSetEnv(filepath.Join(path, "markset.bolt"))
|
||||
default:
|
||||
return nil, xerrors.Errorf("unknown mark set type %s", mtype)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package splitstore
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
bbloom "github.com/ipfs/bbloom"
|
||||
cid "github.com/ipfs/go-cid"
|
||||
)
|
||||
|
||||
const (
|
||||
BloomFilterMinSize = 10_000_000
|
||||
BloomFilterProbability = 0.01
|
||||
)
|
||||
|
||||
type BloomMarkSetEnv struct{}
|
||||
|
||||
var _ MarkSetEnv = (*BloomMarkSetEnv)(nil)
|
||||
|
||||
type BloomMarkSet struct {
|
||||
salt []byte
|
||||
bf *bbloom.Bloom
|
||||
}
|
||||
|
||||
var _ MarkSet = (*BloomMarkSet)(nil)
|
||||
|
||||
func NewBloomMarkSetEnv() (*BloomMarkSetEnv, error) {
|
||||
return &BloomMarkSetEnv{}, nil
|
||||
}
|
||||
|
||||
func (e *BloomMarkSetEnv) Create(name string, sizeHint int64) (MarkSet, error) {
|
||||
size := int64(BloomFilterMinSize)
|
||||
for size < sizeHint {
|
||||
size += BloomFilterMinSize
|
||||
}
|
||||
|
||||
salt := make([]byte, 4)
|
||||
_, err := rand.Read(salt)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("error reading salt: %w", err)
|
||||
}
|
||||
|
||||
bf, err := bbloom.New(float64(size), BloomFilterProbability)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("error creating bloom filter: %w", err)
|
||||
}
|
||||
|
||||
return &BloomMarkSet{salt: salt, bf: bf}, nil
|
||||
}
|
||||
|
||||
func (e *BloomMarkSetEnv) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *BloomMarkSet) saltedKey(cid cid.Cid) []byte {
|
||||
hash := cid.Hash()
|
||||
key := make([]byte, len(s.salt)+len(hash))
|
||||
n := copy(key, s.salt)
|
||||
copy(key[n:], hash)
|
||||
rehash := sha256.Sum256(key)
|
||||
return rehash[:]
|
||||
}
|
||||
|
||||
func (s *BloomMarkSet) Mark(cid cid.Cid) error {
|
||||
s.bf.Add(s.saltedKey(cid))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *BloomMarkSet) Has(cid cid.Cid) (bool, error) {
|
||||
return s.bf.Has(s.saltedKey(cid)), nil
|
||||
}
|
||||
|
||||
func (s *BloomMarkSet) Close() error {
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
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,138 @@
|
||||
package splitstore
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
cid "github.com/ipfs/go-cid"
|
||||
"github.com/multiformats/go-multihash"
|
||||
)
|
||||
|
||||
func TestBoltMarkSet(t *testing.T) {
|
||||
testMarkSet(t, "bolt")
|
||||
}
|
||||
|
||||
func TestBloomMarkSet(t *testing.T) {
|
||||
testMarkSet(t, "bloom")
|
||||
}
|
||||
|
||||
func testMarkSet(t *testing.T, lsType string) {
|
||||
t.Helper()
|
||||
|
||||
path, err := ioutil.TempDir("", "sweep-test.*")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
env, err := OpenMarkSetEnv(path, lsType)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer env.Close() //nolint:errcheck
|
||||
|
||||
hotSet, err := env.Create("hot", 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
coldSet, err := env.Create("cold", 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
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 MarkSet, cid cid.Cid) {
|
||||
has, err := s.Has(cid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !has {
|
||||
t.Fatal("mark not found")
|
||||
}
|
||||
}
|
||||
|
||||
mustNotHave := func(s MarkSet, cid cid.Cid) {
|
||||
has, err := s.Has(cid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if has {
|
||||
t.Fatal("unexpected mark")
|
||||
}
|
||||
}
|
||||
|
||||
k1 := makeCid("a")
|
||||
k2 := makeCid("b")
|
||||
k3 := makeCid("c")
|
||||
k4 := makeCid("d")
|
||||
|
||||
hotSet.Mark(k1) //nolint
|
||||
hotSet.Mark(k2) //nolint
|
||||
coldSet.Mark(k3) //nolint
|
||||
|
||||
mustHave(hotSet, k1)
|
||||
mustHave(hotSet, k2)
|
||||
mustNotHave(hotSet, k3)
|
||||
mustNotHave(hotSet, k4)
|
||||
|
||||
mustNotHave(coldSet, k1)
|
||||
mustNotHave(coldSet, k2)
|
||||
mustHave(coldSet, k3)
|
||||
mustNotHave(coldSet, k4)
|
||||
|
||||
// close them and reopen to redo the dance
|
||||
|
||||
err = hotSet.Close()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = coldSet.Close()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
hotSet, err = env.Create("hot", 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
coldSet, err = env.Create("cold", 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
hotSet.Mark(k3) //nolint
|
||||
hotSet.Mark(k4) //nolint
|
||||
coldSet.Mark(k1) //nolint
|
||||
|
||||
mustNotHave(hotSet, k1)
|
||||
mustNotHave(hotSet, k2)
|
||||
mustHave(hotSet, k3)
|
||||
mustHave(hotSet, k4)
|
||||
|
||||
mustHave(coldSet, k1)
|
||||
mustNotHave(coldSet, k2)
|
||||
mustNotHave(coldSet, k3)
|
||||
mustNotHave(coldSet, k4)
|
||||
|
||||
err = hotSet.Close()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = coldSet.Close()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,255 @@
|
||||
package splitstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/lotus/blockstore"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/types/mock"
|
||||
|
||||
cid "github.com/ipfs/go-cid"
|
||||
datastore "github.com/ipfs/go-datastore"
|
||||
dssync "github.com/ipfs/go-datastore/sync"
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
CompactionThreshold = 5
|
||||
CompactionCold = 1
|
||||
CompactionBoundary = 2
|
||||
logging.SetLogLevel("splitstore", "DEBUG")
|
||||
}
|
||||
|
||||
func testSplitStore(t *testing.T, cfg *Config) {
|
||||
chain := &mockChain{}
|
||||
// genesis
|
||||
genBlock := mock.MkBlock(nil, 0, 0)
|
||||
genTs := mock.TipSet(genBlock)
|
||||
chain.push(genTs)
|
||||
|
||||
// the myriads of stores
|
||||
ds := dssync.MutexWrap(datastore.NewMapDatastore())
|
||||
hot := blockstore.NewMemorySync()
|
||||
cold := blockstore.NewMemorySync()
|
||||
|
||||
// put the genesis block to cold store
|
||||
blk, err := genBlock.ToStorageBlock()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = cold.Put(blk)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// open the splitstore
|
||||
ss, err := Open("", ds, hot, cold, cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer ss.Close() //nolint
|
||||
|
||||
err = ss.Start(chain)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// make some tipsets, but not enough to cause compaction
|
||||
mkBlock := func(curTs *types.TipSet, i int) *types.TipSet {
|
||||
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)
|
||||
}
|
||||
ts := mock.TipSet(blk)
|
||||
chain.push(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() {
|
||||
for atomic.LoadInt32(&ss.compacting) == 1 {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
curTs := genTs
|
||||
for i := 1; i < 5; i++ {
|
||||
curTs = mkBlock(curTs, i)
|
||||
waitForCompaction()
|
||||
}
|
||||
|
||||
mkGarbageBlock(genTs, 1)
|
||||
|
||||
// count objects in the cold and hot stores
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
countBlocks := func(bs blockstore.Blockstore) int {
|
||||
count := 0
|
||||
ch, err := bs.AllKeysChan(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for range ch {
|
||||
count++
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
coldCnt := countBlocks(cold)
|
||||
hotCnt := countBlocks(hot)
|
||||
|
||||
if coldCnt != 1 {
|
||||
t.Errorf("expected %d blocks, but got %d", 1, coldCnt)
|
||||
}
|
||||
|
||||
if hotCnt != 5 {
|
||||
t.Errorf("expected %d blocks, but got %d", 5, hotCnt)
|
||||
}
|
||||
|
||||
// trigger a compaction
|
||||
for i := 5; i < 10; i++ {
|
||||
curTs = mkBlock(curTs, i)
|
||||
waitForCompaction()
|
||||
}
|
||||
|
||||
coldCnt = countBlocks(cold)
|
||||
hotCnt = countBlocks(hot)
|
||||
|
||||
if !cfg.EnableFullCompaction {
|
||||
if coldCnt != 5 {
|
||||
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 coldCnt != 3 {
|
||||
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 {
|
||||
if coldCnt != 2 {
|
||||
t.Errorf("expected %d cold blocks, but got %d", 2, coldCnt)
|
||||
}
|
||||
|
||||
if hotCnt != 7 {
|
||||
t.Errorf("expected %d hot blocks, but got %d", 7, hotCnt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSplitStoreSimpleCompaction(t *testing.T) {
|
||||
testSplitStore(t, &Config{TrackingStoreType: "mem"})
|
||||
}
|
||||
|
||||
func TestSplitStoreFullCompactionWithoutGC(t *testing.T) {
|
||||
testSplitStore(t, &Config{
|
||||
TrackingStoreType: "mem",
|
||||
EnableFullCompaction: true,
|
||||
})
|
||||
}
|
||||
|
||||
func TestSplitStoreFullCompactionWithGC(t *testing.T) {
|
||||
testSplitStore(t, &Config{
|
||||
TrackingStoreType: "mem",
|
||||
EnableFullCompaction: true,
|
||||
EnableGC: true,
|
||||
})
|
||||
}
|
||||
|
||||
type mockChain struct {
|
||||
sync.Mutex
|
||||
tipsets []*types.TipSet
|
||||
listener func(revert []*types.TipSet, apply []*types.TipSet) error
|
||||
}
|
||||
|
||||
func (c *mockChain) push(ts *types.TipSet) {
|
||||
c.Lock()
|
||||
c.tipsets = append(c.tipsets, ts)
|
||||
c.Unlock()
|
||||
|
||||
if c.listener != nil {
|
||||
err := c.listener(nil, []*types.TipSet{ts})
|
||||
if err != nil {
|
||||
log.Errorf("mockchain: error dispatching listener: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *mockChain) GetTipsetByHeight(_ context.Context, epoch abi.ChainEpoch, _ *types.TipSet, _ bool) (*types.TipSet, error) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
iEpoch := int(epoch)
|
||||
if iEpoch > len(c.tipsets) {
|
||||
return nil, fmt.Errorf("bad epoch %d", epoch)
|
||||
}
|
||||
|
||||
return c.tipsets[iEpoch-1], nil
|
||||
}
|
||||
|
||||
func (c *mockChain) GetHeaviestTipSet() *types.TipSet {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
return c.tipsets[len(c.tipsets)-1]
|
||||
}
|
||||
|
||||
func (c *mockChain) SubscribeHeadChanges(change func(revert []*types.TipSet, apply []*types.TipSet) error) {
|
||||
c.listener = change
|
||||
}
|
||||
|
||||
func (c *mockChain) WalkSnapshot(_ context.Context, ts *types.TipSet, epochs abi.ChainEpoch, _ bool, _ bool, f func(cid.Cid) error) error {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
start := int(ts.Height()) - 1
|
||||
end := start - int(epochs)
|
||||
if end < 0 {
|
||||
end = -1
|
||||
}
|
||||
for i := start; i > end; i-- {
|
||||
ts := c.tipsets[i]
|
||||
for _, cid := range ts.Cids() {
|
||||
err := f(cid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
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 }
|
||||
@@ -0,0 +1,120 @@
|
||||
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()
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package blockstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
blocks "github.com/ipfs/go-block-format"
|
||||
"github.com/ipfs/go-cid"
|
||||
)
|
||||
|
||||
// NewMemorySync returns a thread-safe in-memory blockstore.
|
||||
func NewMemorySync() *SyncBlockstore {
|
||||
return &SyncBlockstore{bs: make(MemBlockstore)}
|
||||
}
|
||||
|
||||
// SyncBlockstore is a terminal blockstore that is a synchronized version
|
||||
// of MemBlockstore.
|
||||
type SyncBlockstore struct {
|
||||
mu sync.RWMutex
|
||||
bs MemBlockstore // specifically use a memStore to save indirection overhead.
|
||||
}
|
||||
|
||||
func (m *SyncBlockstore) DeleteBlock(k cid.Cid) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
return m.bs.DeleteBlock(k)
|
||||
}
|
||||
|
||||
func (m *SyncBlockstore) DeleteMany(ks []cid.Cid) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
return m.bs.DeleteMany(ks)
|
||||
}
|
||||
|
||||
func (m *SyncBlockstore) Has(k cid.Cid) (bool, error) {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
return m.bs.Has(k)
|
||||
}
|
||||
|
||||
func (m *SyncBlockstore) View(k cid.Cid, callback func([]byte) error) error {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
|
||||
return m.bs.View(k, callback)
|
||||
}
|
||||
|
||||
func (m *SyncBlockstore) Get(k cid.Cid) (blocks.Block, error) {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
return m.bs.Get(k)
|
||||
}
|
||||
|
||||
func (m *SyncBlockstore) GetSize(k cid.Cid) (int, error) {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
return m.bs.GetSize(k)
|
||||
}
|
||||
|
||||
func (m *SyncBlockstore) Put(b blocks.Block) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
return m.bs.Put(b)
|
||||
}
|
||||
|
||||
func (m *SyncBlockstore) PutMany(bs []blocks.Block) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
return m.bs.PutMany(bs)
|
||||
}
|
||||
|
||||
func (m *SyncBlockstore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
// this blockstore implementation doesn't do any async work.
|
||||
return m.bs.AllKeysChan(ctx)
|
||||
}
|
||||
|
||||
func (m *SyncBlockstore) HashOnRead(enabled bool) {
|
||||
// noop
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
package blockstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
blocks "github.com/ipfs/go-block-format"
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/raulk/clock"
|
||||
"go.uber.org/multierr"
|
||||
)
|
||||
|
||||
// TimedCacheBlockstore is a blockstore that keeps blocks for at least the
|
||||
// specified caching interval before discarding them. Garbage collection must
|
||||
// be started and stopped by calling Start/Stop.
|
||||
//
|
||||
// Under the covers, it's implemented with an active and an inactive blockstore
|
||||
// that are rotated every cache time interval. This means all blocks will be
|
||||
// stored at most 2x the cache interval.
|
||||
//
|
||||
// Create a new instance by calling the NewTimedCacheBlockstore constructor.
|
||||
type TimedCacheBlockstore struct {
|
||||
mu sync.RWMutex
|
||||
active, inactive MemBlockstore
|
||||
clock clock.Clock
|
||||
interval time.Duration
|
||||
closeCh chan struct{}
|
||||
doneRotatingCh chan struct{}
|
||||
}
|
||||
|
||||
func NewTimedCacheBlockstore(interval time.Duration) *TimedCacheBlockstore {
|
||||
b := &TimedCacheBlockstore{
|
||||
active: NewMemory(),
|
||||
inactive: NewMemory(),
|
||||
interval: interval,
|
||||
clock: clock.New(),
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (t *TimedCacheBlockstore) Start(_ context.Context) error {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
if t.closeCh != nil {
|
||||
return fmt.Errorf("already started")
|
||||
}
|
||||
t.closeCh = make(chan struct{})
|
||||
go func() {
|
||||
ticker := t.clock.Ticker(t.interval)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
t.rotate()
|
||||
if t.doneRotatingCh != nil {
|
||||
t.doneRotatingCh <- struct{}{}
|
||||
}
|
||||
case <-t.closeCh:
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TimedCacheBlockstore) Stop(_ context.Context) error {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
if t.closeCh == nil {
|
||||
return fmt.Errorf("not started")
|
||||
}
|
||||
select {
|
||||
case <-t.closeCh:
|
||||
// already closed
|
||||
default:
|
||||
close(t.closeCh)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TimedCacheBlockstore) rotate() {
|
||||
newBs := NewMemory()
|
||||
|
||||
t.mu.Lock()
|
||||
t.inactive, t.active = t.active, newBs
|
||||
t.mu.Unlock()
|
||||
}
|
||||
|
||||
func (t *TimedCacheBlockstore) Put(b blocks.Block) error {
|
||||
// Don't check the inactive set here. We want to keep this block for at
|
||||
// least one interval.
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
return t.active.Put(b)
|
||||
}
|
||||
|
||||
func (t *TimedCacheBlockstore) PutMany(bs []blocks.Block) error {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
return t.active.PutMany(bs)
|
||||
}
|
||||
|
||||
func (t *TimedCacheBlockstore) View(k cid.Cid, callback func([]byte) error) error {
|
||||
t.mu.RLock()
|
||||
defer t.mu.RUnlock()
|
||||
err := t.active.View(k, callback)
|
||||
if err == ErrNotFound {
|
||||
err = t.inactive.View(k, callback)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (t *TimedCacheBlockstore) Get(k cid.Cid) (blocks.Block, error) {
|
||||
t.mu.RLock()
|
||||
defer t.mu.RUnlock()
|
||||
b, err := t.active.Get(k)
|
||||
if err == ErrNotFound {
|
||||
b, err = t.inactive.Get(k)
|
||||
}
|
||||
return b, err
|
||||
}
|
||||
|
||||
func (t *TimedCacheBlockstore) GetSize(k cid.Cid) (int, error) {
|
||||
t.mu.RLock()
|
||||
defer t.mu.RUnlock()
|
||||
size, err := t.active.GetSize(k)
|
||||
if err == ErrNotFound {
|
||||
size, err = t.inactive.GetSize(k)
|
||||
}
|
||||
return size, err
|
||||
}
|
||||
|
||||
func (t *TimedCacheBlockstore) Has(k cid.Cid) (bool, error) {
|
||||
t.mu.RLock()
|
||||
defer t.mu.RUnlock()
|
||||
if has, err := t.active.Has(k); err != nil {
|
||||
return false, err
|
||||
} else if has {
|
||||
return true, nil
|
||||
}
|
||||
return t.inactive.Has(k)
|
||||
}
|
||||
|
||||
func (t *TimedCacheBlockstore) HashOnRead(_ bool) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
func (t *TimedCacheBlockstore) DeleteBlock(k cid.Cid) error {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
return multierr.Combine(t.active.DeleteBlock(k), t.inactive.DeleteBlock(k))
|
||||
}
|
||||
|
||||
func (t *TimedCacheBlockstore) DeleteMany(ks []cid.Cid) error {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
return multierr.Combine(t.active.DeleteMany(ks), t.inactive.DeleteMany(ks))
|
||||
}
|
||||
|
||||
func (t *TimedCacheBlockstore) AllKeysChan(_ context.Context) (<-chan cid.Cid, error) {
|
||||
t.mu.RLock()
|
||||
defer t.mu.RUnlock()
|
||||
|
||||
ch := make(chan cid.Cid, len(t.active)+len(t.inactive))
|
||||
for c := range t.active {
|
||||
ch <- c
|
||||
}
|
||||
for c := range t.inactive {
|
||||
if _, ok := t.active[c]; ok {
|
||||
continue
|
||||
}
|
||||
ch <- c
|
||||
}
|
||||
close(ch)
|
||||
return ch, nil
|
||||
}
|
||||
@@ -1,21 +1,27 @@
|
||||
package timedbs_test
|
||||
package blockstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/raulk/clock"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
blocks "github.com/ipfs/go-block-format"
|
||||
"github.com/ipfs/go-cid"
|
||||
|
||||
"github.com/filecoin-project/lotus/lib/timedbs"
|
||||
)
|
||||
|
||||
func TestTimedBSSimple(t *testing.T) {
|
||||
tc := timedbs.NewTimedCacheBS(10 * time.Millisecond)
|
||||
func TestTimedCacheBlockstoreSimple(t *testing.T) {
|
||||
tc := NewTimedCacheBlockstore(10 * time.Millisecond)
|
||||
mClock := clock.NewMock()
|
||||
mClock.Set(time.Now())
|
||||
tc.clock = mClock
|
||||
tc.doneRotatingCh = make(chan struct{})
|
||||
|
||||
_ = tc.Start(context.Background())
|
||||
mClock.Add(1) // IDK why it is needed but it makes it work
|
||||
|
||||
defer func() {
|
||||
_ = tc.Stop(context.Background())
|
||||
}()
|
||||
@@ -36,7 +42,8 @@ func TestTimedBSSimple(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.True(t, has)
|
||||
|
||||
time.Sleep(15 * time.Millisecond)
|
||||
mClock.Add(10 * time.Millisecond)
|
||||
<-tc.doneRotatingCh
|
||||
|
||||
// We should still have everything.
|
||||
has, err = tc.Has(b1.Cid())
|
||||
@@ -60,8 +67,8 @@ func TestTimedBSSimple(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.ElementsMatch(t, ks, []cid.Cid{b1.Cid(), b2.Cid(), b3.Cid()})
|
||||
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
mClock.Add(10 * time.Millisecond)
|
||||
<-tc.doneRotatingCh
|
||||
// should still have b2, and b3, but not b1
|
||||
|
||||
has, err = tc.Has(b1.Cid())
|
||||
@@ -0,0 +1,119 @@
|
||||
package blockstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
blocks "github.com/ipfs/go-block-format"
|
||||
"github.com/ipfs/go-cid"
|
||||
)
|
||||
|
||||
type unionBlockstore []Blockstore
|
||||
|
||||
// Union returns an unioned blockstore.
|
||||
//
|
||||
// * Reads return from the first blockstore that has the value, querying in the
|
||||
// supplied order.
|
||||
// * Writes (puts and deltes) are broadcast to all stores.
|
||||
//
|
||||
func Union(stores ...Blockstore) Blockstore {
|
||||
return unionBlockstore(stores)
|
||||
}
|
||||
|
||||
func (m unionBlockstore) Has(cid cid.Cid) (has bool, err error) {
|
||||
for _, bs := range m {
|
||||
if has, err = bs.Has(cid); has || err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
return has, err
|
||||
}
|
||||
|
||||
func (m unionBlockstore) Get(cid cid.Cid) (blk blocks.Block, err error) {
|
||||
for _, bs := range m {
|
||||
if blk, err = bs.Get(cid); err == nil || err != ErrNotFound {
|
||||
break
|
||||
}
|
||||
}
|
||||
return blk, err
|
||||
}
|
||||
|
||||
func (m unionBlockstore) View(cid cid.Cid, callback func([]byte) error) (err error) {
|
||||
for _, bs := range m {
|
||||
if err = bs.View(cid, callback); err == nil || err != ErrNotFound {
|
||||
break
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (m unionBlockstore) GetSize(cid cid.Cid) (size int, err error) {
|
||||
for _, bs := range m {
|
||||
if size, err = bs.GetSize(cid); err == nil || err != ErrNotFound {
|
||||
break
|
||||
}
|
||||
}
|
||||
return size, err
|
||||
}
|
||||
|
||||
func (m unionBlockstore) Put(block blocks.Block) (err error) {
|
||||
for _, bs := range m {
|
||||
if err = bs.Put(block); err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (m unionBlockstore) PutMany(blks []blocks.Block) (err error) {
|
||||
for _, bs := range m {
|
||||
if err = bs.PutMany(blks); err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (m unionBlockstore) DeleteBlock(cid cid.Cid) (err error) {
|
||||
for _, bs := range m {
|
||||
if err = bs.DeleteBlock(cid); err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (m unionBlockstore) DeleteMany(cids []cid.Cid) (err error) {
|
||||
for _, bs := range m {
|
||||
if err = bs.DeleteMany(cids); err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (m unionBlockstore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
|
||||
// this does not deduplicate; this interface needs to be revisited.
|
||||
outCh := make(chan cid.Cid)
|
||||
|
||||
go func() {
|
||||
defer close(outCh)
|
||||
|
||||
for _, bs := range m {
|
||||
ch, err := bs.AllKeysChan(ctx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for cid := range ch {
|
||||
outCh <- cid
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return outCh, nil
|
||||
}
|
||||
|
||||
func (m unionBlockstore) HashOnRead(enabled bool) {
|
||||
for _, bs := range m {
|
||||
bs.HashOnRead(enabled)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package blockstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
blocks "github.com/ipfs/go-block-format"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var (
|
||||
b0 = blocks.NewBlock([]byte("abc"))
|
||||
b1 = blocks.NewBlock([]byte("foo"))
|
||||
b2 = blocks.NewBlock([]byte("bar"))
|
||||
)
|
||||
|
||||
func TestUnionBlockstore_Get(t *testing.T) {
|
||||
m1 := NewMemory()
|
||||
m2 := NewMemory()
|
||||
|
||||
_ = m1.Put(b1)
|
||||
_ = m2.Put(b2)
|
||||
|
||||
u := Union(m1, m2)
|
||||
|
||||
v1, err := u.Get(b1.Cid())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, b1.RawData(), v1.RawData())
|
||||
|
||||
v2, err := u.Get(b2.Cid())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, b2.RawData(), v2.RawData())
|
||||
}
|
||||
|
||||
func TestUnionBlockstore_Put_PutMany_Delete_AllKeysChan(t *testing.T) {
|
||||
m1 := NewMemory()
|
||||
m2 := NewMemory()
|
||||
|
||||
u := Union(m1, m2)
|
||||
|
||||
err := u.Put(b0)
|
||||
require.NoError(t, err)
|
||||
|
||||
var has bool
|
||||
|
||||
// write was broadcasted to all stores.
|
||||
has, _ = m1.Has(b0.Cid())
|
||||
require.True(t, has)
|
||||
|
||||
has, _ = m2.Has(b0.Cid())
|
||||
require.True(t, has)
|
||||
|
||||
has, _ = u.Has(b0.Cid())
|
||||
require.True(t, has)
|
||||
|
||||
// put many.
|
||||
err = u.PutMany([]blocks.Block{b1, b2})
|
||||
require.NoError(t, err)
|
||||
|
||||
// write was broadcasted to all stores.
|
||||
has, _ = m1.Has(b1.Cid())
|
||||
require.True(t, has)
|
||||
|
||||
has, _ = m1.Has(b2.Cid())
|
||||
require.True(t, has)
|
||||
|
||||
has, _ = m2.Has(b1.Cid())
|
||||
require.True(t, has)
|
||||
|
||||
has, _ = m2.Has(b2.Cid())
|
||||
require.True(t, has)
|
||||
|
||||
// also in the union store.
|
||||
has, _ = u.Has(b1.Cid())
|
||||
require.True(t, has)
|
||||
|
||||
has, _ = u.Has(b2.Cid())
|
||||
require.True(t, has)
|
||||
|
||||
// deleted from all stores.
|
||||
err = u.DeleteBlock(b1.Cid())
|
||||
require.NoError(t, err)
|
||||
|
||||
has, _ = u.Has(b1.Cid())
|
||||
require.False(t, has)
|
||||
|
||||
has, _ = m1.Has(b1.Cid())
|
||||
require.False(t, has)
|
||||
|
||||
has, _ = m2.Has(b1.Cid())
|
||||
require.False(t, has)
|
||||
|
||||
// check that AllKeysChan returns b0 and b2, twice (once per backing store)
|
||||
ch, err := u.AllKeysChan(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
var i int
|
||||
for range ch {
|
||||
i++
|
||||
}
|
||||
require.Equal(t, 4, i)
|
||||
}
|
||||
+9
-19
@@ -2,11 +2,9 @@ package build
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/filecoin-project/lotus/lib/addrutil"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
rice "github.com/GeertJohan/go.rice"
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
@@ -17,24 +15,16 @@ func BuiltinBootstrap() ([]peer.AddrInfo, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var out []peer.AddrInfo
|
||||
|
||||
b := rice.MustFindBox("bootstrap")
|
||||
err := b.Walk("", func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to walk box: %w", err)
|
||||
|
||||
if BootstrappersFile != "" {
|
||||
spi := b.MustString(BootstrappersFile)
|
||||
if spi == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(path, ".pi") {
|
||||
return nil
|
||||
}
|
||||
spi := b.MustString(path)
|
||||
if spi == "" {
|
||||
return nil
|
||||
}
|
||||
pi, err := addrutil.ParseAddresses(context.TODO(), strings.Split(strings.TrimSpace(spi), "\n"))
|
||||
out = append(out, pi...)
|
||||
return err
|
||||
})
|
||||
return out, err
|
||||
return addrutil.ParseAddresses(context.TODO(), strings.Split(strings.TrimSpace(spi), "\n"))
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
/dns4/bootstrap-0.butterfly.fildev.network/tcp/1347/p2p/12D3KooWRkaF18SR3E6qL6dkGrozT8QJUV5VbhE9E7BZtPmHqdWJ
|
||||
/dns4/bootstrap-1.butterfly.fildev.network/tcp/1347/p2p/12D3KooWJcJUc23WJjJHGSboGcU3t76z9Lb7CghrH2tiBiDCY4ux
|
||||
@@ -0,0 +1,4 @@
|
||||
/dns4/bootstrap-0.calibration.fildev.network/tcp/1347/p2p/12D3KooWRLZAseMo9h7fRD6ojn6YYDXHsBSavX5YmjBZ9ngtAEec
|
||||
/dns4/bootstrap-1.calibration.fildev.network/tcp/1347/p2p/12D3KooWJFtDXgZEQMEkjJPSrbfdvh2xfjVKrXeNFG1t8ioJXAzv
|
||||
/dns4/bootstrap-2.calibration.fildev.network/tcp/1347/p2p/12D3KooWP1uB9Lo7yCA3S17TD4Y5wStP5Nk7Vqh53m8GsFjkyujD
|
||||
/dns4/bootstrap-3.calibration.fildev.network/tcp/1347/p2p/12D3KooWLrPM4WPK1YRGPCUwndWcDX8GCYgms3DiuofUmxwvhMCn
|
||||
@@ -0,0 +1,4 @@
|
||||
/dns4/bootstrap-2.nerpa.interplanetary.dev/tcp/1347/p2p/12D3KooWQcL6ReWmR6ASWx4iT7EiAmxKDQpvgq1MKNTQZp5NPnWW
|
||||
/dns4/bootstrap-0.nerpa.interplanetary.dev/tcp/1347/p2p/12D3KooWGyJCwCm7EfupM15CFPXM4c7zRVHwwwjcuy9umaGeztMX
|
||||
/dns4/bootstrap-3.nerpa.interplanetary.dev/tcp/1347/p2p/12D3KooWNK9RmfksKXSCQj7ZwAM7L6roqbN4kwJteihq7yPvSgPs
|
||||
/dns4/bootstrap-1.nerpa.interplanetary.dev/tcp/1347/p2p/12D3KooWCWSaH6iUyXYspYxELjDfzToBsyVGVz3QvC7ysXv7wESo
|
||||
+1
-1
@@ -14,7 +14,7 @@ func MaybeGenesis() []byte {
|
||||
log.Warnf("loading built-in genesis: %s", err)
|
||||
return nil
|
||||
}
|
||||
genBytes, err := builtinGen.Bytes("devnet.car")
|
||||
genBytes, err := builtinGen.Bytes(GenesisFile)
|
||||
if err != nil {
|
||||
log.Warnf("loading built-in genesis: %s", err)
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,9 @@
|
||||
package build
|
||||
|
||||
import (
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
)
|
||||
|
||||
func IsNearUpgrade(epoch, upgradeEpoch abi.ChainEpoch) bool {
|
||||
return epoch > upgradeEpoch-Finality && epoch < upgradeEpoch+Finality
|
||||
}
|
||||
+52
-10
@@ -3,25 +3,40 @@
|
||||
package build
|
||||
|
||||
import (
|
||||
"math"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/policy"
|
||||
)
|
||||
|
||||
const UpgradeBreezeHeight = -1
|
||||
const BootstrappersFile = ""
|
||||
const GenesisFile = ""
|
||||
|
||||
var UpgradeBreezeHeight = abi.ChainEpoch(-1)
|
||||
|
||||
const BreezeGasTampingDuration = 0
|
||||
|
||||
const UpgradeSmokeHeight = -1
|
||||
const UpgradeIgnitionHeight = -2
|
||||
const UpgradeRefuelHeight = -3
|
||||
const UpgradeTapeHeight = -4
|
||||
var UpgradeSmokeHeight = abi.ChainEpoch(-1)
|
||||
var UpgradeIgnitionHeight = abi.ChainEpoch(-2)
|
||||
var UpgradeRefuelHeight = abi.ChainEpoch(-3)
|
||||
var UpgradeTapeHeight = abi.ChainEpoch(-4)
|
||||
|
||||
var UpgradeActorsV2Height = abi.ChainEpoch(10)
|
||||
var UpgradeLiftoffHeight = abi.ChainEpoch(-5)
|
||||
|
||||
var UpgradeKumquatHeight = abi.ChainEpoch(15)
|
||||
var UpgradeCalicoHeight = abi.ChainEpoch(20)
|
||||
var UpgradePersianHeight = abi.ChainEpoch(25)
|
||||
var UpgradeOrangeHeight = abi.ChainEpoch(27)
|
||||
var UpgradeClausHeight = abi.ChainEpoch(30)
|
||||
|
||||
var UpgradeActorsV3Height = abi.ChainEpoch(35)
|
||||
|
||||
var UpgradeNorwegianHeight = abi.ChainEpoch(40)
|
||||
|
||||
var UpgradeActorsV4Height = abi.ChainEpoch(45)
|
||||
|
||||
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||
0: DrandMainnet,
|
||||
}
|
||||
@@ -31,11 +46,36 @@ func init() {
|
||||
policy.SetConsensusMinerMinPower(abi.NewStoragePower(2048))
|
||||
policy.SetMinVerifiedDealSize(abi.NewStoragePower(256))
|
||||
|
||||
if os.Getenv("LOTUS_DISABLE_V2_ACTOR_MIGRATION") == "1" {
|
||||
UpgradeActorsV2Height = math.MaxInt64
|
||||
UpgradeLiftoffHeight = 11
|
||||
getUpgradeHeight := func(ev string, def abi.ChainEpoch) abi.ChainEpoch {
|
||||
hs, found := os.LookupEnv(ev)
|
||||
if found {
|
||||
h, err := strconv.Atoi(hs)
|
||||
if err != nil {
|
||||
log.Panicf("failed to parse %s env var", ev)
|
||||
}
|
||||
|
||||
return abi.ChainEpoch(h)
|
||||
}
|
||||
|
||||
return def
|
||||
}
|
||||
|
||||
UpgradeBreezeHeight = getUpgradeHeight("LOTUS_BREEZE_HEIGHT", UpgradeBreezeHeight)
|
||||
UpgradeSmokeHeight = getUpgradeHeight("LOTUS_SMOKE_HEIGHT", UpgradeSmokeHeight)
|
||||
UpgradeIgnitionHeight = getUpgradeHeight("LOTUS_IGNITION_HEIGHT", UpgradeIgnitionHeight)
|
||||
UpgradeRefuelHeight = getUpgradeHeight("LOTUS_REFUEL_HEIGHT", UpgradeRefuelHeight)
|
||||
UpgradeTapeHeight = getUpgradeHeight("LOTUS_TAPE_HEIGHT", UpgradeTapeHeight)
|
||||
UpgradeActorsV2Height = getUpgradeHeight("LOTUS_ACTORSV2_HEIGHT", UpgradeActorsV2Height)
|
||||
UpgradeLiftoffHeight = getUpgradeHeight("LOTUS_LIFTOFF_HEIGHT", UpgradeLiftoffHeight)
|
||||
UpgradeKumquatHeight = getUpgradeHeight("LOTUS_KUMQUAT_HEIGHT", UpgradeKumquatHeight)
|
||||
UpgradeCalicoHeight = getUpgradeHeight("LOTUS_CALICO_HEIGHT", UpgradeCalicoHeight)
|
||||
UpgradePersianHeight = getUpgradeHeight("LOTUS_PERSIAN_HEIGHT", UpgradePersianHeight)
|
||||
UpgradeOrangeHeight = getUpgradeHeight("LOTUS_ORANGE_HEIGHT", UpgradeOrangeHeight)
|
||||
UpgradeClausHeight = getUpgradeHeight("LOTUS_CLAUS_HEIGHT", UpgradeClausHeight)
|
||||
UpgradeActorsV3Height = getUpgradeHeight("LOTUS_ACTORSV3_HEIGHT", UpgradeActorsV3Height)
|
||||
UpgradeNorwegianHeight = getUpgradeHeight("LOTUS_NORWEGIAN_HEIGHT", UpgradeNorwegianHeight)
|
||||
UpgradeActorsV4Height = getUpgradeHeight("LOTUS_ACTORSV4_HEIGHT", UpgradeActorsV4Height)
|
||||
|
||||
BuildType |= Build2k
|
||||
}
|
||||
|
||||
@@ -51,3 +91,5 @@ const SlashablePowerDelay = 20
|
||||
|
||||
// Epochs
|
||||
const InteractivePoRepConfidence = 6
|
||||
|
||||
const BootstrapPeerThreshold = 1
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
// +build butterflynet
|
||||
|
||||
package build
|
||||
|
||||
import (
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/lotus/chain/actors/policy"
|
||||
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
|
||||
)
|
||||
|
||||
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||
0: DrandMainnet,
|
||||
}
|
||||
|
||||
const BootstrappersFile = "butterflynet.pi"
|
||||
const GenesisFile = "butterflynet.car"
|
||||
|
||||
const UpgradeBreezeHeight = -1
|
||||
const BreezeGasTampingDuration = 120
|
||||
const UpgradeSmokeHeight = -2
|
||||
const UpgradeIgnitionHeight = -3
|
||||
const UpgradeRefuelHeight = -4
|
||||
|
||||
var UpgradeActorsV2Height = abi.ChainEpoch(30)
|
||||
|
||||
const UpgradeTapeHeight = 60
|
||||
const UpgradeLiftoffHeight = -5
|
||||
const UpgradeKumquatHeight = 90
|
||||
const UpgradeCalicoHeight = 120
|
||||
const UpgradePersianHeight = 150
|
||||
const UpgradeClausHeight = 180
|
||||
const UpgradeOrangeHeight = 210
|
||||
const UpgradeActorsV3Height = 240
|
||||
const UpgradeNorwegianHeight = UpgradeActorsV3Height + (builtin2.EpochsInHour * 12)
|
||||
const UpgradeActorsV4Height = 8922
|
||||
|
||||
func init() {
|
||||
policy.SetConsensusMinerMinPower(abi.NewStoragePower(2 << 30))
|
||||
policy.SetSupportedProofTypes(
|
||||
abi.RegisteredSealProof_StackedDrg512MiBV1,
|
||||
)
|
||||
|
||||
SetAddressNetwork(address.Testnet)
|
||||
|
||||
Devnet = true
|
||||
}
|
||||
|
||||
const BlockDelaySecs = uint64(builtin2.EpochDurationSeconds)
|
||||
|
||||
const PropagationDelaySecs = uint64(6)
|
||||
|
||||
// BootstrapPeerThreshold is the minimum number peers we need to track for a sync worker to start
|
||||
const BootstrapPeerThreshold = 2
|
||||
@@ -0,0 +1,66 @@
|
||||
// +build calibnet
|
||||
|
||||
package build
|
||||
|
||||
import (
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/lotus/chain/actors/policy"
|
||||
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
|
||||
)
|
||||
|
||||
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||
0: DrandMainnet,
|
||||
}
|
||||
|
||||
const BootstrappersFile = "calibnet.pi"
|
||||
const GenesisFile = "calibnet.car"
|
||||
|
||||
const UpgradeBreezeHeight = -1
|
||||
const BreezeGasTampingDuration = 120
|
||||
|
||||
const UpgradeSmokeHeight = -2
|
||||
|
||||
const UpgradeIgnitionHeight = -3
|
||||
const UpgradeRefuelHeight = -4
|
||||
|
||||
var UpgradeActorsV2Height = abi.ChainEpoch(30)
|
||||
|
||||
const UpgradeTapeHeight = 60
|
||||
|
||||
const UpgradeLiftoffHeight = -5
|
||||
|
||||
const UpgradeKumquatHeight = 90
|
||||
|
||||
const UpgradeCalicoHeight = 100
|
||||
const UpgradePersianHeight = UpgradeCalicoHeight + (builtin2.EpochsInHour * 1)
|
||||
|
||||
const UpgradeClausHeight = 250
|
||||
|
||||
const UpgradeOrangeHeight = 300
|
||||
|
||||
const UpgradeActorsV3Height = 600
|
||||
const UpgradeNorwegianHeight = 114000
|
||||
|
||||
const UpgradeActorsV4Height = 193789
|
||||
|
||||
func init() {
|
||||
policy.SetConsensusMinerMinPower(abi.NewStoragePower(32 << 30))
|
||||
policy.SetSupportedProofTypes(
|
||||
abi.RegisteredSealProof_StackedDrg32GiBV1,
|
||||
abi.RegisteredSealProof_StackedDrg64GiBV1,
|
||||
)
|
||||
|
||||
SetAddressNetwork(address.Testnet)
|
||||
|
||||
Devnet = true
|
||||
|
||||
BuildType = BuildCalibnet
|
||||
}
|
||||
|
||||
const BlockDelaySecs = uint64(builtin2.EpochDurationSeconds)
|
||||
|
||||
const PropagationDelaySecs = uint64(6)
|
||||
|
||||
// BootstrapPeerThreshold is the minimum number peers we need to track for a sync worker to start
|
||||
const BootstrapPeerThreshold = 4
|
||||
+40
-10
@@ -1,6 +1,9 @@
|
||||
// +build !debug
|
||||
// +build !2k
|
||||
// +build !testground
|
||||
// +build !calibnet
|
||||
// +build !nerpanet
|
||||
// +build !butterflynet
|
||||
|
||||
package build
|
||||
|
||||
@@ -11,8 +14,7 @@ import (
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/lotus/chain/actors/policy"
|
||||
|
||||
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
|
||||
)
|
||||
|
||||
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||
@@ -20,7 +22,11 @@ var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||
UpgradeSmokeHeight: DrandMainnet,
|
||||
}
|
||||
|
||||
const BootstrappersFile = "mainnet.pi"
|
||||
const GenesisFile = "mainnet.car"
|
||||
|
||||
const UpgradeBreezeHeight = 41280
|
||||
|
||||
const BreezeGasTampingDuration = 120
|
||||
|
||||
const UpgradeSmokeHeight = 51000
|
||||
@@ -28,7 +34,7 @@ const UpgradeSmokeHeight = 51000
|
||||
const UpgradeIgnitionHeight = 94000
|
||||
const UpgradeRefuelHeight = 130800
|
||||
|
||||
var UpgradeActorsV2Height = abi.ChainEpoch(138720)
|
||||
const UpgradeActorsV2Height = 138720
|
||||
|
||||
const UpgradeTapeHeight = 140760
|
||||
|
||||
@@ -37,24 +43,48 @@ const UpgradeTapeHeight = 140760
|
||||
// We still have upgrades and state changes to do, but can happen after signaling timing here.
|
||||
const UpgradeLiftoffHeight = 148888
|
||||
|
||||
const UpgradeKumquatHeight = 170000
|
||||
|
||||
const UpgradeCalicoHeight = 265200
|
||||
const UpgradePersianHeight = UpgradeCalicoHeight + (builtin2.EpochsInHour * 60)
|
||||
|
||||
const UpgradeOrangeHeight = 336458
|
||||
|
||||
// 2020-12-22T02:00:00Z
|
||||
const UpgradeClausHeight = 343200
|
||||
|
||||
// 2021-03-04T00:00:30Z
|
||||
var UpgradeActorsV3Height = abi.ChainEpoch(550321)
|
||||
|
||||
// 2021-04-12T22:00:00Z
|
||||
const UpgradeNorwegianHeight = 665280
|
||||
|
||||
// 2021-04-29T06:00:00Z
|
||||
var UpgradeActorsV4Height = abi.ChainEpoch(712320)
|
||||
|
||||
func init() {
|
||||
policy.SetConsensusMinerMinPower(abi.NewStoragePower(10 << 40))
|
||||
policy.SetSupportedProofTypes(
|
||||
abi.RegisteredSealProof_StackedDrg32GiBV1,
|
||||
abi.RegisteredSealProof_StackedDrg64GiBV1,
|
||||
)
|
||||
|
||||
if os.Getenv("LOTUS_USE_TEST_ADDRESSES") != "1" {
|
||||
SetAddressNetwork(address.Mainnet)
|
||||
}
|
||||
|
||||
if os.Getenv("LOTUS_DISABLE_V2_ACTOR_MIGRATION") == "1" {
|
||||
UpgradeActorsV2Height = math.MaxInt64
|
||||
if os.Getenv("LOTUS_DISABLE_V3_ACTOR_MIGRATION") == "1" {
|
||||
UpgradeActorsV3Height = math.MaxInt64
|
||||
}
|
||||
|
||||
if os.Getenv("LOTUS_DISABLE_V4_ACTOR_MIGRATION") == "1" {
|
||||
UpgradeActorsV4Height = math.MaxInt64
|
||||
}
|
||||
|
||||
Devnet = false
|
||||
|
||||
BuildType = BuildMainnet
|
||||
}
|
||||
|
||||
const BlockDelaySecs = uint64(builtin0.EpochDurationSeconds)
|
||||
const BlockDelaySecs = uint64(builtin2.EpochDurationSeconds)
|
||||
|
||||
const PropagationDelaySecs = uint64(6)
|
||||
|
||||
// BootstrapPeerThreshold is the minimum number peers we need to track for a sync worker to start
|
||||
const BootstrapPeerThreshold = 4
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
// +build nerpanet
|
||||
|
||||
package build
|
||||
|
||||
import (
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/lotus/chain/actors/policy"
|
||||
|
||||
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
|
||||
)
|
||||
|
||||
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||
0: DrandMainnet,
|
||||
}
|
||||
|
||||
const BootstrappersFile = "nerpanet.pi"
|
||||
const GenesisFile = "nerpanet.car"
|
||||
|
||||
const UpgradeBreezeHeight = -1
|
||||
const BreezeGasTampingDuration = 0
|
||||
|
||||
const UpgradeSmokeHeight = -1
|
||||
|
||||
const UpgradeIgnitionHeight = -2
|
||||
const UpgradeRefuelHeight = -3
|
||||
|
||||
const UpgradeLiftoffHeight = -5
|
||||
|
||||
const UpgradeActorsV2Height = 30 // critical: the network can bootstrap from v1 only
|
||||
const UpgradeTapeHeight = 60
|
||||
|
||||
const UpgradeKumquatHeight = 90
|
||||
|
||||
const UpgradeCalicoHeight = 100
|
||||
const UpgradePersianHeight = UpgradeCalicoHeight + (builtin2.EpochsInHour * 1)
|
||||
|
||||
const UpgradeClausHeight = 250
|
||||
|
||||
const UpgradeOrangeHeight = 300
|
||||
|
||||
const UpgradeActorsV3Height = 600
|
||||
const UpgradeNorwegianHeight = 999999
|
||||
const UpgradeActorsV4Height = 99999999
|
||||
|
||||
func init() {
|
||||
// Minimum block production power is set to 4 TiB
|
||||
// Rationale is to discourage small-scale miners from trying to take over the network
|
||||
// One needs to invest in ~2.3x the compute to break consensus, making it not worth it
|
||||
//
|
||||
// DOWNSIDE: the fake-seals need to be kept alive/protected, otherwise network will seize
|
||||
//
|
||||
policy.SetConsensusMinerMinPower(abi.NewStoragePower(4 << 40))
|
||||
|
||||
policy.SetSupportedProofTypes(
|
||||
abi.RegisteredSealProof_StackedDrg512MiBV1,
|
||||
abi.RegisteredSealProof_StackedDrg32GiBV1,
|
||||
abi.RegisteredSealProof_StackedDrg64GiBV1,
|
||||
)
|
||||
|
||||
// Lower the most time-consuming parts of PoRep
|
||||
policy.SetPreCommitChallengeDelay(10)
|
||||
|
||||
// TODO - make this a variable
|
||||
//miner.WPoStChallengeLookback = abi.ChainEpoch(2)
|
||||
|
||||
Devnet = false
|
||||
}
|
||||
|
||||
const BlockDelaySecs = uint64(builtin2.EpochDurationSeconds)
|
||||
|
||||
const PropagationDelaySecs = uint64(6)
|
||||
|
||||
// BootstrapPeerThreshold is the minimum number peers we need to track for a sync worker to start
|
||||
const BootstrapPeerThreshold = 4
|
||||
@@ -1,36 +1,13 @@
|
||||
package build
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
|
||||
"github.com/libp2p/go-libp2p-core/protocol"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
||||
|
||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||
)
|
||||
|
||||
func DefaultSectorSize() abi.SectorSize {
|
||||
szs := make([]abi.SectorSize, 0, len(miner0.SupportedProofTypes))
|
||||
for spt := range miner0.SupportedProofTypes {
|
||||
ss, err := spt.SectorSize()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
szs = append(szs, ss)
|
||||
}
|
||||
|
||||
sort.Slice(szs, func(i, j int) bool {
|
||||
return szs[i] < szs[j]
|
||||
})
|
||||
|
||||
return szs[0]
|
||||
}
|
||||
|
||||
// Core network constants
|
||||
|
||||
func BlocksTopic(netName dtypes.NetworkName) string { return "/fil/blocks/" + string(netName) }
|
||||
@@ -39,14 +16,15 @@ func DhtProtocolName(netName dtypes.NetworkName) protocol.ID {
|
||||
return protocol.ID("/fil/kad/" + string(netName))
|
||||
}
|
||||
|
||||
func UseNewestNetwork() bool {
|
||||
// TODO: Put these in a container we can iterate over
|
||||
if UpgradeBreezeHeight <= 0 && UpgradeSmokeHeight <= 0 && UpgradeActorsV2Height <= 0 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func SetAddressNetwork(n address.Network) {
|
||||
address.CurrentNetwork = n
|
||||
}
|
||||
|
||||
func MustParseAddress(addr string) address.Address {
|
||||
ret, err := address.NewFromString(addr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
@@ -7,12 +7,12 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/lotus/chain/actors/policy"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/policy"
|
||||
)
|
||||
|
||||
// /////
|
||||
@@ -25,14 +25,14 @@ const UnixfsLinksPerLevel = 1024
|
||||
// Consensus / Network
|
||||
|
||||
const AllowableClockDriftSecs = uint64(1)
|
||||
const NewestNetworkVersion = network.Version5
|
||||
const NewestNetworkVersion = network.Version9
|
||||
const ActorUpgradeNetworkVersion = network.Version4
|
||||
|
||||
// Epochs
|
||||
const ForkLengthThreshold = Finality
|
||||
|
||||
// Blocks (e)
|
||||
var BlocksPerEpoch = uint64(builtin.ExpectedLeadersPerEpoch)
|
||||
var BlocksPerEpoch = uint64(builtin2.ExpectedLeadersPerEpoch)
|
||||
|
||||
// Epochs
|
||||
const Finality = policy.ChainFinality
|
||||
@@ -61,6 +61,9 @@ const TicketRandomnessLookback = abi.ChainEpoch(1)
|
||||
|
||||
const AddressMainnetEnvVar = "_mainnet_"
|
||||
|
||||
// the 'f' prefix doesn't matter
|
||||
var ZeroAddress = MustParseAddress("f3yaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaby2smx7a")
|
||||
|
||||
// /////
|
||||
// Devnet settings
|
||||
|
||||
@@ -116,4 +119,4 @@ const PackingEfficiencyDenom = 5
|
||||
|
||||
// Actor consts
|
||||
// TODO: Pull from actors when its made not private
|
||||
var MinDealDuration = abi.ChainEpoch(180 * builtin.EpochsInDay)
|
||||
var MinDealDuration = abi.ChainEpoch(180 * builtin2.EpochsInDay)
|
||||
|
||||
+27
-12
@@ -12,7 +12,8 @@ import (
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
|
||||
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/policy"
|
||||
)
|
||||
@@ -21,14 +22,14 @@ var (
|
||||
UnixfsChunkSize = uint64(1 << 20)
|
||||
UnixfsLinksPerLevel = 1024
|
||||
|
||||
BlocksPerEpoch = uint64(builtin.ExpectedLeadersPerEpoch)
|
||||
BlocksPerEpoch = uint64(builtin2.ExpectedLeadersPerEpoch)
|
||||
BlockMessageLimit = 512
|
||||
BlockGasLimit = int64(100_000_000_000)
|
||||
BlockGasTarget = int64(BlockGasLimit / 2)
|
||||
BaseFeeMaxChangeDenom = int64(8) // 12.5%
|
||||
InitialBaseFee = int64(100e6)
|
||||
MinimumBaseFee = int64(100)
|
||||
BlockDelaySecs = uint64(builtin.EpochDurationSeconds)
|
||||
BlockDelaySecs = uint64(builtin2.EpochDurationSeconds)
|
||||
PropagationDelaySecs = uint64(6)
|
||||
|
||||
AllowableClockDriftSecs = uint64(1)
|
||||
@@ -72,7 +73,7 @@ var (
|
||||
|
||||
// Actor consts
|
||||
// TODO: Pull from actors when its made not private
|
||||
MinDealDuration = abi.ChainEpoch(180 * builtin.EpochsInDay)
|
||||
MinDealDuration = abi.ChainEpoch(180 * builtin2.EpochsInDay)
|
||||
|
||||
PackingEfficiencyNum int64 = 4
|
||||
PackingEfficiencyDenom int64 = 5
|
||||
@@ -80,19 +81,33 @@ var (
|
||||
UpgradeBreezeHeight abi.ChainEpoch = -1
|
||||
BreezeGasTampingDuration abi.ChainEpoch = 0
|
||||
|
||||
UpgradeSmokeHeight abi.ChainEpoch = -1
|
||||
UpgradeIgnitionHeight abi.ChainEpoch = -2
|
||||
UpgradeRefuelHeight abi.ChainEpoch = -3
|
||||
UpgradeTapeHeight abi.ChainEpoch = -4
|
||||
UpgradeActorsV2Height abi.ChainEpoch = 10
|
||||
UpgradeLiftoffHeight abi.ChainEpoch = -5
|
||||
UpgradeSmokeHeight abi.ChainEpoch = -1
|
||||
UpgradeIgnitionHeight abi.ChainEpoch = -2
|
||||
UpgradeRefuelHeight abi.ChainEpoch = -3
|
||||
UpgradeTapeHeight abi.ChainEpoch = -4
|
||||
UpgradeActorsV2Height abi.ChainEpoch = 10
|
||||
UpgradeLiftoffHeight abi.ChainEpoch = -5
|
||||
UpgradeKumquatHeight abi.ChainEpoch = -6
|
||||
UpgradeCalicoHeight abi.ChainEpoch = -7
|
||||
UpgradePersianHeight abi.ChainEpoch = -8
|
||||
UpgradeOrangeHeight abi.ChainEpoch = -9
|
||||
UpgradeClausHeight abi.ChainEpoch = -10
|
||||
UpgradeActorsV3Height abi.ChainEpoch = -11
|
||||
UpgradeNorwegianHeight abi.ChainEpoch = -12
|
||||
UpgradeActorsV4Height abi.ChainEpoch = -13
|
||||
|
||||
DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||
0: DrandMainnet,
|
||||
}
|
||||
|
||||
NewestNetworkVersion = network.Version5
|
||||
NewestNetworkVersion = network.Version9
|
||||
ActorUpgradeNetworkVersion = network.Version4
|
||||
|
||||
Devnet = true
|
||||
Devnet = true
|
||||
ZeroAddress = MustParseAddress("f3yaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaby2smx7a")
|
||||
|
||||
BootstrappersFile = ""
|
||||
GenesisFile = ""
|
||||
)
|
||||
|
||||
const BootstrapPeerThreshold = 1
|
||||
|
||||
@@ -3,5 +3,7 @@
|
||||
package build
|
||||
|
||||
import (
|
||||
_ "github.com/GeertJohan/go.rice/rice"
|
||||
_ "github.com/golang/mock/mockgen"
|
||||
_ "github.com/whyrusleeping/bencher"
|
||||
)
|
||||
|
||||
+12
-76
@@ -1,100 +1,36 @@
|
||||
package build
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
var CurrentCommit string
|
||||
var BuildType int
|
||||
|
||||
const (
|
||||
BuildDefault = 0
|
||||
Build2k = 0x1
|
||||
BuildDebug = 0x3
|
||||
BuildDefault = 0
|
||||
BuildMainnet = 0x1
|
||||
Build2k = 0x2
|
||||
BuildDebug = 0x3
|
||||
BuildCalibnet = 0x4
|
||||
)
|
||||
|
||||
func buildType() string {
|
||||
switch BuildType {
|
||||
case BuildDefault:
|
||||
return ""
|
||||
case BuildDebug:
|
||||
return "+debug"
|
||||
case BuildMainnet:
|
||||
return "+mainnet"
|
||||
case Build2k:
|
||||
return "+2k"
|
||||
case BuildDebug:
|
||||
return "+debug"
|
||||
case BuildCalibnet:
|
||||
return "+calibnet"
|
||||
default:
|
||||
return "+huh?"
|
||||
}
|
||||
}
|
||||
|
||||
// BuildVersion is the local build version, set by build system
|
||||
const BuildVersion = "1.0.0"
|
||||
const BuildVersion = "1.8.0"
|
||||
|
||||
func UserVersion() string {
|
||||
return BuildVersion + buildType() + CurrentCommit
|
||||
}
|
||||
|
||||
type Version uint32
|
||||
|
||||
func newVer(major, minor, patch uint8) Version {
|
||||
return Version(uint32(major)<<16 | uint32(minor)<<8 | uint32(patch))
|
||||
}
|
||||
|
||||
// Ints returns (major, minor, patch) versions
|
||||
func (ve Version) Ints() (uint32, uint32, uint32) {
|
||||
v := uint32(ve)
|
||||
return (v & majorOnlyMask) >> 16, (v & minorOnlyMask) >> 8, v & patchOnlyMask
|
||||
}
|
||||
|
||||
func (ve Version) String() string {
|
||||
vmj, vmi, vp := ve.Ints()
|
||||
return fmt.Sprintf("%d.%d.%d", vmj, vmi, vp)
|
||||
}
|
||||
|
||||
func (ve Version) EqMajorMinor(v2 Version) bool {
|
||||
return ve&minorMask == v2&minorMask
|
||||
}
|
||||
|
||||
type NodeType int
|
||||
|
||||
const (
|
||||
NodeUnknown NodeType = iota
|
||||
|
||||
NodeFull
|
||||
NodeMiner
|
||||
NodeWorker
|
||||
)
|
||||
|
||||
var RunningNodeType NodeType
|
||||
|
||||
func VersionForType(nodeType NodeType) (Version, error) {
|
||||
switch nodeType {
|
||||
case NodeFull:
|
||||
return FullAPIVersion, nil
|
||||
case NodeMiner:
|
||||
return MinerAPIVersion, nil
|
||||
case NodeWorker:
|
||||
return WorkerAPIVersion, nil
|
||||
default:
|
||||
return Version(0), xerrors.Errorf("unknown node type %d", nodeType)
|
||||
}
|
||||
}
|
||||
|
||||
// semver versions of the rpc api exposed
|
||||
var (
|
||||
FullAPIVersion = newVer(0, 17, 0)
|
||||
MinerAPIVersion = newVer(0, 15, 0)
|
||||
WorkerAPIVersion = newVer(0, 15, 0)
|
||||
)
|
||||
|
||||
//nolint:varcheck,deadcode
|
||||
const (
|
||||
majorMask = 0xff0000
|
||||
minorMask = 0xffff00
|
||||
patchMask = 0xffffff
|
||||
|
||||
majorOnlyMask = 0xff0000
|
||||
minorOnlyMask = 0x00ff00
|
||||
patchOnlyMask = 0x0000ff
|
||||
)
|
||||
|
||||
@@ -2,16 +2,9 @@ package adt
|
||||
|
||||
import (
|
||||
"github.com/ipfs/go-cid"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/cbor"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
|
||||
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
|
||||
adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt"
|
||||
)
|
||||
|
||||
type Map interface {
|
||||
@@ -24,26 +17,6 @@ type Map interface {
|
||||
ForEach(v cbor.Unmarshaler, fn func(key string) error) error
|
||||
}
|
||||
|
||||
func AsMap(store Store, root cid.Cid, version actors.Version) (Map, error) {
|
||||
switch version {
|
||||
case actors.Version0:
|
||||
return adt0.AsMap(store, root)
|
||||
case actors.Version2:
|
||||
return adt2.AsMap(store, root)
|
||||
}
|
||||
return nil, xerrors.Errorf("unknown network version: %d", version)
|
||||
}
|
||||
|
||||
func NewMap(store Store, version actors.Version) (Map, error) {
|
||||
switch version {
|
||||
case actors.Version0:
|
||||
return adt0.MakeEmptyMap(store), nil
|
||||
case actors.Version2:
|
||||
return adt2.MakeEmptyMap(store), nil
|
||||
}
|
||||
return nil, xerrors.Errorf("unknown network version: %d", version)
|
||||
}
|
||||
|
||||
type Array interface {
|
||||
Root() (cid.Cid, error)
|
||||
|
||||
@@ -54,23 +27,3 @@ type Array interface {
|
||||
|
||||
ForEach(v cbor.Unmarshaler, fn func(idx int64) error) error
|
||||
}
|
||||
|
||||
func AsArray(store Store, root cid.Cid, version network.Version) (Array, error) {
|
||||
switch actors.VersionForNetwork(version) {
|
||||
case actors.Version0:
|
||||
return adt0.AsArray(store, root)
|
||||
case actors.Version2:
|
||||
return adt2.AsArray(store, root)
|
||||
}
|
||||
return nil, xerrors.Errorf("unknown network version: %d", version)
|
||||
}
|
||||
|
||||
func NewArray(store Store, version actors.Version) (Array, error) {
|
||||
switch version {
|
||||
case actors.Version0:
|
||||
return adt0.MakeEmptyArray(store), nil
|
||||
case actors.Version2:
|
||||
return adt2.MakeEmptyArray(store), nil
|
||||
}
|
||||
return nil, xerrors.Errorf("unknown network version: %d", version)
|
||||
}
|
||||
|
||||
@@ -12,34 +12,35 @@ import (
|
||||
typegen "github.com/whyrusleeping/cbor-gen"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/runtime"
|
||||
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
|
||||
|
||||
bstore "github.com/filecoin-project/lotus/lib/blockstore"
|
||||
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
|
||||
adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt"
|
||||
|
||||
bstore "github.com/filecoin-project/lotus/blockstore"
|
||||
)
|
||||
|
||||
func TestDiffAdtArray(t *testing.T) {
|
||||
ctxstoreA := newContextStore()
|
||||
ctxstoreB := newContextStore()
|
||||
|
||||
arrA := adt0.MakeEmptyArray(ctxstoreA)
|
||||
arrB := adt0.MakeEmptyArray(ctxstoreB)
|
||||
arrA := adt2.MakeEmptyArray(ctxstoreA)
|
||||
arrB := adt2.MakeEmptyArray(ctxstoreB)
|
||||
|
||||
require.NoError(t, arrA.Set(0, runtime.CBORBytes([]byte{0}))) // delete
|
||||
require.NoError(t, arrA.Set(0, builtin2.CBORBytes([]byte{0}))) // delete
|
||||
|
||||
require.NoError(t, arrA.Set(1, runtime.CBORBytes([]byte{0}))) // modify
|
||||
require.NoError(t, arrB.Set(1, runtime.CBORBytes([]byte{1})))
|
||||
require.NoError(t, arrA.Set(1, builtin2.CBORBytes([]byte{0}))) // modify
|
||||
require.NoError(t, arrB.Set(1, builtin2.CBORBytes([]byte{1})))
|
||||
|
||||
require.NoError(t, arrA.Set(2, runtime.CBORBytes([]byte{1}))) // delete
|
||||
require.NoError(t, arrA.Set(2, builtin2.CBORBytes([]byte{1}))) // delete
|
||||
|
||||
require.NoError(t, arrA.Set(3, runtime.CBORBytes([]byte{0}))) // noop
|
||||
require.NoError(t, arrB.Set(3, runtime.CBORBytes([]byte{0})))
|
||||
require.NoError(t, arrA.Set(3, builtin2.CBORBytes([]byte{0}))) // noop
|
||||
require.NoError(t, arrB.Set(3, builtin2.CBORBytes([]byte{0})))
|
||||
|
||||
require.NoError(t, arrA.Set(4, runtime.CBORBytes([]byte{0}))) // modify
|
||||
require.NoError(t, arrB.Set(4, runtime.CBORBytes([]byte{6})))
|
||||
require.NoError(t, arrA.Set(4, builtin2.CBORBytes([]byte{0}))) // modify
|
||||
require.NoError(t, arrB.Set(4, builtin2.CBORBytes([]byte{6})))
|
||||
|
||||
require.NoError(t, arrB.Set(5, runtime.CBORBytes{8})) // add
|
||||
require.NoError(t, arrB.Set(6, runtime.CBORBytes{9})) // add
|
||||
require.NoError(t, arrB.Set(5, builtin2.CBORBytes{8})) // add
|
||||
require.NoError(t, arrB.Set(6, builtin2.CBORBytes{9})) // add
|
||||
|
||||
changes := new(TestDiffArray)
|
||||
|
||||
@@ -76,24 +77,24 @@ func TestDiffAdtMap(t *testing.T) {
|
||||
ctxstoreA := newContextStore()
|
||||
ctxstoreB := newContextStore()
|
||||
|
||||
mapA := adt0.MakeEmptyMap(ctxstoreA)
|
||||
mapB := adt0.MakeEmptyMap(ctxstoreB)
|
||||
mapA := adt2.MakeEmptyMap(ctxstoreA)
|
||||
mapB := adt2.MakeEmptyMap(ctxstoreB)
|
||||
|
||||
require.NoError(t, mapA.Put(abi.UIntKey(0), runtime.CBORBytes([]byte{0}))) // delete
|
||||
require.NoError(t, mapA.Put(abi.UIntKey(0), builtin2.CBORBytes([]byte{0}))) // delete
|
||||
|
||||
require.NoError(t, mapA.Put(abi.UIntKey(1), runtime.CBORBytes([]byte{0}))) // modify
|
||||
require.NoError(t, mapB.Put(abi.UIntKey(1), runtime.CBORBytes([]byte{1})))
|
||||
require.NoError(t, mapA.Put(abi.UIntKey(1), builtin2.CBORBytes([]byte{0}))) // modify
|
||||
require.NoError(t, mapB.Put(abi.UIntKey(1), builtin2.CBORBytes([]byte{1})))
|
||||
|
||||
require.NoError(t, mapA.Put(abi.UIntKey(2), runtime.CBORBytes([]byte{1}))) // delete
|
||||
require.NoError(t, mapA.Put(abi.UIntKey(2), builtin2.CBORBytes([]byte{1}))) // delete
|
||||
|
||||
require.NoError(t, mapA.Put(abi.UIntKey(3), runtime.CBORBytes([]byte{0}))) // noop
|
||||
require.NoError(t, mapB.Put(abi.UIntKey(3), runtime.CBORBytes([]byte{0})))
|
||||
require.NoError(t, mapA.Put(abi.UIntKey(3), builtin2.CBORBytes([]byte{0}))) // noop
|
||||
require.NoError(t, mapB.Put(abi.UIntKey(3), builtin2.CBORBytes([]byte{0})))
|
||||
|
||||
require.NoError(t, mapA.Put(abi.UIntKey(4), runtime.CBORBytes([]byte{0}))) // modify
|
||||
require.NoError(t, mapB.Put(abi.UIntKey(4), runtime.CBORBytes([]byte{6})))
|
||||
require.NoError(t, mapA.Put(abi.UIntKey(4), builtin2.CBORBytes([]byte{0}))) // modify
|
||||
require.NoError(t, mapB.Put(abi.UIntKey(4), builtin2.CBORBytes([]byte{6})))
|
||||
|
||||
require.NoError(t, mapB.Put(abi.UIntKey(5), runtime.CBORBytes{8})) // add
|
||||
require.NoError(t, mapB.Put(abi.UIntKey(6), runtime.CBORBytes{9})) // add
|
||||
require.NoError(t, mapB.Put(abi.UIntKey(5), builtin2.CBORBytes{8})) // add
|
||||
require.NoError(t, mapB.Put(abi.UIntKey(6), builtin2.CBORBytes{9})) // add
|
||||
|
||||
changes := new(TestDiffMap)
|
||||
|
||||
@@ -144,7 +145,7 @@ func (t *TestDiffMap) AsKey(key string) (abi.Keyer, error) {
|
||||
}
|
||||
|
||||
func (t *TestDiffMap) Add(key string, val *typegen.Deferred) error {
|
||||
v := new(runtime.CBORBytes)
|
||||
v := new(builtin2.CBORBytes)
|
||||
err := v.UnmarshalCBOR(bytes.NewReader(val.Raw))
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -161,13 +162,13 @@ func (t *TestDiffMap) Add(key string, val *typegen.Deferred) error {
|
||||
}
|
||||
|
||||
func (t *TestDiffMap) Modify(key string, from, to *typegen.Deferred) error {
|
||||
vFrom := new(runtime.CBORBytes)
|
||||
vFrom := new(builtin2.CBORBytes)
|
||||
err := vFrom.UnmarshalCBOR(bytes.NewReader(from.Raw))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
vTo := new(runtime.CBORBytes)
|
||||
vTo := new(builtin2.CBORBytes)
|
||||
err = vTo.UnmarshalCBOR(bytes.NewReader(to.Raw))
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -194,7 +195,7 @@ func (t *TestDiffMap) Modify(key string, from, to *typegen.Deferred) error {
|
||||
}
|
||||
|
||||
func (t *TestDiffMap) Remove(key string, val *typegen.Deferred) error {
|
||||
v := new(runtime.CBORBytes)
|
||||
v := new(builtin2.CBORBytes)
|
||||
err := v.UnmarshalCBOR(bytes.NewReader(val.Raw))
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -212,7 +213,7 @@ func (t *TestDiffMap) Remove(key string, val *typegen.Deferred) error {
|
||||
|
||||
type adtMapDiffResult struct {
|
||||
key uint64
|
||||
val runtime.CBORBytes
|
||||
val builtin2.CBORBytes
|
||||
}
|
||||
|
||||
type TestAdtMapDiffModified struct {
|
||||
@@ -222,7 +223,7 @@ type TestAdtMapDiffModified struct {
|
||||
|
||||
type adtArrayDiffResult struct {
|
||||
key uint64
|
||||
val runtime.CBORBytes
|
||||
val builtin2.CBORBytes
|
||||
}
|
||||
|
||||
type TestDiffArray struct {
|
||||
@@ -239,7 +240,7 @@ type TestAdtArrayDiffModified struct {
|
||||
}
|
||||
|
||||
func (t *TestDiffArray) Add(key uint64, val *typegen.Deferred) error {
|
||||
v := new(runtime.CBORBytes)
|
||||
v := new(builtin2.CBORBytes)
|
||||
err := v.UnmarshalCBOR(bytes.NewReader(val.Raw))
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -252,13 +253,13 @@ func (t *TestDiffArray) Add(key uint64, val *typegen.Deferred) error {
|
||||
}
|
||||
|
||||
func (t *TestDiffArray) Modify(key uint64, from, to *typegen.Deferred) error {
|
||||
vFrom := new(runtime.CBORBytes)
|
||||
vFrom := new(builtin2.CBORBytes)
|
||||
err := vFrom.UnmarshalCBOR(bytes.NewReader(from.Raw))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
vTo := new(runtime.CBORBytes)
|
||||
vTo := new(builtin2.CBORBytes)
|
||||
err = vTo.UnmarshalCBOR(bytes.NewReader(to.Raw))
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -280,7 +281,7 @@ func (t *TestDiffArray) Modify(key uint64, from, to *typegen.Deferred) error {
|
||||
}
|
||||
|
||||
func (t *TestDiffArray) Remove(key uint64, val *typegen.Deferred) error {
|
||||
v := new(runtime.CBORBytes)
|
||||
v := new(builtin2.CBORBytes)
|
||||
err := v.UnmarshalCBOR(bytes.NewReader(val.Raw))
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -294,7 +295,7 @@ func (t *TestDiffArray) Remove(key uint64, val *typegen.Deferred) error {
|
||||
|
||||
func newContextStore() Store {
|
||||
ctx := context.Background()
|
||||
bs := bstore.NewTemporarySync()
|
||||
bs := bstore.NewMemorySync()
|
||||
store := cbornode.NewCborStore(bs)
|
||||
return WrapStore(ctx, store)
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ import (
|
||||
|
||||
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
|
||||
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
|
||||
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -22,14 +24,26 @@ func init() {
|
||||
builtin.RegisterActorState(builtin2.AccountActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
|
||||
return load2(store, root)
|
||||
})
|
||||
builtin.RegisterActorState(builtin3.AccountActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
|
||||
return load3(store, root)
|
||||
})
|
||||
builtin.RegisterActorState(builtin4.AccountActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
|
||||
return load4(store, root)
|
||||
})
|
||||
}
|
||||
|
||||
var Methods = builtin4.MethodsAccount
|
||||
|
||||
func Load(store adt.Store, act *types.Actor) (State, error) {
|
||||
switch act.Code {
|
||||
case builtin0.AccountActorCodeID:
|
||||
return load0(store, act.Head)
|
||||
case builtin2.AccountActorCodeID:
|
||||
return load2(store, act.Head)
|
||||
case builtin3.AccountActorCodeID:
|
||||
return load3(store, act.Head)
|
||||
case builtin4.AccountActorCodeID:
|
||||
return load4(store, act.Head)
|
||||
}
|
||||
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package account
|
||||
|
||||
import (
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/ipfs/go-cid"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||
|
||||
account3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/account"
|
||||
)
|
||||
|
||||
var _ State = (*state3)(nil)
|
||||
|
||||
func load3(store adt.Store, root cid.Cid) (State, error) {
|
||||
out := state3{store: store}
|
||||
err := store.Get(store.Context(), root, &out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
type state3 struct {
|
||||
account3.State
|
||||
store adt.Store
|
||||
}
|
||||
|
||||
func (s *state3) PubkeyAddress() (address.Address, error) {
|
||||
return s.Address, nil
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package account
|
||||
|
||||
import (
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/ipfs/go-cid"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||
|
||||
account4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/account"
|
||||
)
|
||||
|
||||
var _ State = (*state4)(nil)
|
||||
|
||||
func load4(store adt.Store, root cid.Cid) (State, error) {
|
||||
out := state4{store: store}
|
||||
err := store.Get(store.Context(), root, &out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
type state4 struct {
|
||||
account4.State
|
||||
store adt.Store
|
||||
}
|
||||
|
||||
func (s *state4) PubkeyAddress() (address.Address, error) {
|
||||
return s.Address, nil
|
||||
}
|
||||
@@ -2,12 +2,13 @@ package builtin
|
||||
|
||||
import (
|
||||
"github.com/filecoin-project/go-address"
|
||||
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
|
||||
smoothing2 "github.com/filecoin-project/specs-actors/v2/actors/util/smoothing"
|
||||
"github.com/ipfs/go-cid"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
|
||||
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
|
||||
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/cbor"
|
||||
@@ -15,9 +16,13 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
|
||||
smoothing0 "github.com/filecoin-project/specs-actors/actors/util/smoothing"
|
||||
smoothing2 "github.com/filecoin-project/specs-actors/v2/actors/util/smoothing"
|
||||
smoothing3 "github.com/filecoin-project/specs-actors/v3/actors/util/smoothing"
|
||||
smoothing4 "github.com/filecoin-project/specs-actors/v4/actors/util/smoothing"
|
||||
|
||||
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
||||
proof0 "github.com/filecoin-project/specs-actors/actors/runtime/proof"
|
||||
smoothing0 "github.com/filecoin-project/specs-actors/actors/util/smoothing"
|
||||
)
|
||||
|
||||
var SystemActorAddr = builtin0.SystemActorAddr
|
||||
@@ -27,7 +32,23 @@ var SaftAddress = makeAddress("t0122")
|
||||
var ReserveAddress = makeAddress("t090")
|
||||
var RootVerifierAddress = makeAddress("t080")
|
||||
|
||||
// TODO: Why does actors have 2 different versions of this?
|
||||
var (
|
||||
ExpectedLeadersPerEpoch = builtin0.ExpectedLeadersPerEpoch
|
||||
)
|
||||
|
||||
const (
|
||||
EpochDurationSeconds = builtin0.EpochDurationSeconds
|
||||
EpochsInDay = builtin0.EpochsInDay
|
||||
SecondsInDay = builtin0.SecondsInDay
|
||||
)
|
||||
|
||||
const (
|
||||
MethodSend = builtin4.MethodSend
|
||||
MethodConstructor = builtin4.MethodConstructor
|
||||
)
|
||||
|
||||
// These are all just type aliases across actor versions 0, 2, & 3. In the future, that might change
|
||||
// and we might need to do something fancier.
|
||||
type SectorInfo = proof0.SectorInfo
|
||||
type PoStProof = proof0.PoStProof
|
||||
type FilterEstimate = smoothing0.FilterEstimate
|
||||
@@ -36,13 +57,21 @@ func FromV0FilterEstimate(v0 smoothing0.FilterEstimate) FilterEstimate {
|
||||
return (FilterEstimate)(v0)
|
||||
}
|
||||
|
||||
// Doesn't change between actors v0 and v1
|
||||
// Doesn't change between actors v0, v2, and v3.
|
||||
func QAPowerForWeight(size abi.SectorSize, duration abi.ChainEpoch, dealWeight, verifiedWeight abi.DealWeight) abi.StoragePower {
|
||||
return miner0.QAPowerForWeight(size, duration, dealWeight, verifiedWeight)
|
||||
}
|
||||
|
||||
func FromV2FilterEstimate(v1 smoothing2.FilterEstimate) FilterEstimate {
|
||||
return (FilterEstimate)(v1)
|
||||
func FromV2FilterEstimate(v2 smoothing2.FilterEstimate) FilterEstimate {
|
||||
return (FilterEstimate)(v2)
|
||||
}
|
||||
|
||||
func FromV3FilterEstimate(v3 smoothing3.FilterEstimate) FilterEstimate {
|
||||
return (FilterEstimate)(v3)
|
||||
}
|
||||
|
||||
func FromV4FilterEstimate(v4 smoothing4.FilterEstimate) FilterEstimate {
|
||||
return (FilterEstimate)(v4)
|
||||
}
|
||||
|
||||
type ActorStateLoader func(store adt.Store, root cid.Cid) (cbor.Marshaler, error)
|
||||
@@ -67,30 +96,48 @@ func ActorNameByCode(c cid.Cid) string {
|
||||
return builtin0.ActorNameByCode(c)
|
||||
case builtin2.IsBuiltinActor(c):
|
||||
return builtin2.ActorNameByCode(c)
|
||||
case builtin3.IsBuiltinActor(c):
|
||||
return builtin3.ActorNameByCode(c)
|
||||
case builtin4.IsBuiltinActor(c):
|
||||
return builtin4.ActorNameByCode(c)
|
||||
default:
|
||||
return "<unknown>"
|
||||
}
|
||||
}
|
||||
|
||||
func IsBuiltinActor(c cid.Cid) bool {
|
||||
return builtin0.IsBuiltinActor(c) || builtin2.IsBuiltinActor(c)
|
||||
return builtin0.IsBuiltinActor(c) ||
|
||||
builtin2.IsBuiltinActor(c) ||
|
||||
builtin3.IsBuiltinActor(c) ||
|
||||
builtin4.IsBuiltinActor(c)
|
||||
}
|
||||
|
||||
func IsAccountActor(c cid.Cid) bool {
|
||||
return c == builtin0.AccountActorCodeID || c == builtin2.AccountActorCodeID
|
||||
return c == builtin0.AccountActorCodeID ||
|
||||
c == builtin2.AccountActorCodeID ||
|
||||
c == builtin3.AccountActorCodeID ||
|
||||
c == builtin4.AccountActorCodeID
|
||||
}
|
||||
|
||||
func IsStorageMinerActor(c cid.Cid) bool {
|
||||
return c == builtin0.StorageMinerActorCodeID || c == builtin2.StorageMinerActorCodeID
|
||||
return c == builtin0.StorageMinerActorCodeID ||
|
||||
c == builtin2.StorageMinerActorCodeID ||
|
||||
c == builtin3.StorageMinerActorCodeID ||
|
||||
c == builtin4.StorageMinerActorCodeID
|
||||
}
|
||||
|
||||
func IsMultisigActor(c cid.Cid) bool {
|
||||
return c == builtin0.MultisigActorCodeID || c == builtin2.MultisigActorCodeID
|
||||
|
||||
return c == builtin0.MultisigActorCodeID ||
|
||||
c == builtin2.MultisigActorCodeID ||
|
||||
c == builtin3.MultisigActorCodeID ||
|
||||
c == builtin4.MultisigActorCodeID
|
||||
}
|
||||
|
||||
func IsPaymentChannelActor(c cid.Cid) bool {
|
||||
return c == builtin0.PaymentChannelActorCodeID || c == builtin2.PaymentChannelActorCodeID
|
||||
return c == builtin0.PaymentChannelActorCodeID ||
|
||||
c == builtin2.PaymentChannelActorCodeID ||
|
||||
c == builtin3.PaymentChannelActorCodeID ||
|
||||
c == builtin4.PaymentChannelActorCodeID
|
||||
}
|
||||
|
||||
func makeAddress(addr string) address.Address {
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package cron
|
||||
|
||||
import (
|
||||
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
|
||||
)
|
||||
|
||||
var (
|
||||
Address = builtin4.CronActorAddr
|
||||
Methods = builtin4.MethodsCron
|
||||
)
|
||||
@@ -0,0 +1,152 @@
|
||||
package init
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
typegen "github.com/whyrusleeping/cbor-gen"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||
)
|
||||
|
||||
func DiffAddressMap(pre, cur State) (*AddressMapChanges, error) {
|
||||
prem, err := pre.addressMap()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
curm, err := cur.addressMap()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
preRoot, err := prem.Root()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
curRoot, err := curm.Root()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
results := new(AddressMapChanges)
|
||||
// no change.
|
||||
if curRoot.Equals(preRoot) {
|
||||
return results, nil
|
||||
}
|
||||
|
||||
err = adt.DiffAdtMap(prem, curm, &addressMapDiffer{results, pre, cur})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
type addressMapDiffer struct {
|
||||
Results *AddressMapChanges
|
||||
pre, adter State
|
||||
}
|
||||
|
||||
type AddressMapChanges struct {
|
||||
Added []AddressPair
|
||||
Modified []AddressChange
|
||||
Removed []AddressPair
|
||||
}
|
||||
|
||||
func (i *addressMapDiffer) AsKey(key string) (abi.Keyer, error) {
|
||||
addr, err := address.NewFromBytes([]byte(key))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return abi.AddrKey(addr), nil
|
||||
}
|
||||
|
||||
func (i *addressMapDiffer) Add(key string, val *typegen.Deferred) error {
|
||||
pkAddr, err := address.NewFromBytes([]byte(key))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
id := new(typegen.CborInt)
|
||||
if err := id.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
|
||||
return err
|
||||
}
|
||||
idAddr, err := address.NewIDAddress(uint64(*id))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i.Results.Added = append(i.Results.Added, AddressPair{
|
||||
ID: idAddr,
|
||||
PK: pkAddr,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *addressMapDiffer) Modify(key string, from, to *typegen.Deferred) error {
|
||||
pkAddr, err := address.NewFromBytes([]byte(key))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fromID := new(typegen.CborInt)
|
||||
if err := fromID.UnmarshalCBOR(bytes.NewReader(from.Raw)); err != nil {
|
||||
return err
|
||||
}
|
||||
fromIDAddr, err := address.NewIDAddress(uint64(*fromID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
toID := new(typegen.CborInt)
|
||||
if err := toID.UnmarshalCBOR(bytes.NewReader(to.Raw)); err != nil {
|
||||
return err
|
||||
}
|
||||
toIDAddr, err := address.NewIDAddress(uint64(*toID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
i.Results.Modified = append(i.Results.Modified, AddressChange{
|
||||
From: AddressPair{
|
||||
ID: fromIDAddr,
|
||||
PK: pkAddr,
|
||||
},
|
||||
To: AddressPair{
|
||||
ID: toIDAddr,
|
||||
PK: pkAddr,
|
||||
},
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *addressMapDiffer) Remove(key string, val *typegen.Deferred) error {
|
||||
pkAddr, err := address.NewFromBytes([]byte(key))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
id := new(typegen.CborInt)
|
||||
if err := id.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
|
||||
return err
|
||||
}
|
||||
idAddr, err := address.NewIDAddress(uint64(*id))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i.Results.Removed = append(i.Results.Removed, AddressPair{
|
||||
ID: idAddr,
|
||||
PK: pkAddr,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
type AddressChange struct {
|
||||
From AddressPair
|
||||
To AddressPair
|
||||
}
|
||||
|
||||
type AddressPair struct {
|
||||
ID address.Address
|
||||
PK address.Address
|
||||
}
|
||||
@@ -15,6 +15,8 @@ import (
|
||||
|
||||
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
|
||||
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
|
||||
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -24,9 +26,18 @@ func init() {
|
||||
builtin.RegisterActorState(builtin2.InitActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
|
||||
return load2(store, root)
|
||||
})
|
||||
builtin.RegisterActorState(builtin3.InitActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
|
||||
return load3(store, root)
|
||||
})
|
||||
builtin.RegisterActorState(builtin4.InitActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
|
||||
return load4(store, root)
|
||||
})
|
||||
}
|
||||
|
||||
var Address = builtin0.InitActorAddr
|
||||
var (
|
||||
Address = builtin4.InitActorAddr
|
||||
Methods = builtin4.MethodsInit
|
||||
)
|
||||
|
||||
func Load(store adt.Store, act *types.Actor) (State, error) {
|
||||
switch act.Code {
|
||||
@@ -34,6 +45,10 @@ func Load(store adt.Store, act *types.Actor) (State, error) {
|
||||
return load0(store, act.Head)
|
||||
case builtin2.InitActorCodeID:
|
||||
return load2(store, act.Head)
|
||||
case builtin3.InitActorCodeID:
|
||||
return load3(store, act.Head)
|
||||
case builtin4.InitActorCodeID:
|
||||
return load4(store, act.Head)
|
||||
}
|
||||
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
|
||||
}
|
||||
@@ -54,4 +69,6 @@ type State interface {
|
||||
|
||||
// Sets the network's name. This should only be used on upgrade/fork.
|
||||
SetNetworkName(name string) error
|
||||
|
||||
addressMap() (adt.Map, error)
|
||||
}
|
||||
|
||||
@@ -79,3 +79,7 @@ func (s *state0) Remove(addrs ...address.Address) (err error) {
|
||||
s.State.AddressMap = amr
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *state0) addressMap() (adt.Map, error) {
|
||||
return adt0.AsMap(s.store, s.AddressMap)
|
||||
}
|
||||
|
||||
@@ -79,3 +79,7 @@ func (s *state2) Remove(addrs ...address.Address) (err error) {
|
||||
s.State.AddressMap = amr
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *state2) addressMap() (adt.Map, error) {
|
||||
return adt2.AsMap(s.store, s.AddressMap)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
package init
|
||||
|
||||
import (
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
|
||||
"github.com/ipfs/go-cid"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||
|
||||
init3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/init"
|
||||
adt3 "github.com/filecoin-project/specs-actors/v3/actors/util/adt"
|
||||
)
|
||||
|
||||
var _ State = (*state3)(nil)
|
||||
|
||||
func load3(store adt.Store, root cid.Cid) (State, error) {
|
||||
out := state3{store: store}
|
||||
err := store.Get(store.Context(), root, &out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
type state3 struct {
|
||||
init3.State
|
||||
store adt.Store
|
||||
}
|
||||
|
||||
func (s *state3) ResolveAddress(address address.Address) (address.Address, bool, error) {
|
||||
return s.State.ResolveAddress(s.store, address)
|
||||
}
|
||||
|
||||
func (s *state3) MapAddressToNewID(address address.Address) (address.Address, error) {
|
||||
return s.State.MapAddressToNewID(s.store, address)
|
||||
}
|
||||
|
||||
func (s *state3) ForEachActor(cb func(id abi.ActorID, address address.Address) error) error {
|
||||
addrs, err := adt3.AsMap(s.store, s.State.AddressMap, builtin3.DefaultHamtBitwidth)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var actorID cbg.CborInt
|
||||
return addrs.ForEach(&actorID, func(key string) error {
|
||||
addr, err := address.NewFromBytes([]byte(key))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return cb(abi.ActorID(actorID), addr)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *state3) NetworkName() (dtypes.NetworkName, error) {
|
||||
return dtypes.NetworkName(s.State.NetworkName), nil
|
||||
}
|
||||
|
||||
func (s *state3) SetNetworkName(name string) error {
|
||||
s.State.NetworkName = name
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *state3) Remove(addrs ...address.Address) (err error) {
|
||||
m, err := adt3.AsMap(s.store, s.State.AddressMap, builtin3.DefaultHamtBitwidth)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, addr := range addrs {
|
||||
if err = m.Delete(abi.AddrKey(addr)); err != nil {
|
||||
return xerrors.Errorf("failed to delete entry for address: %s; err: %w", addr, err)
|
||||
}
|
||||
}
|
||||
amr, err := m.Root()
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to get address map root: %w", err)
|
||||
}
|
||||
s.State.AddressMap = amr
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *state3) addressMap() (adt.Map, error) {
|
||||
return adt3.AsMap(s.store, s.AddressMap, builtin3.DefaultHamtBitwidth)
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package init
|
||||
|
||||
import (
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
|
||||
"github.com/ipfs/go-cid"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||
|
||||
init4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/init"
|
||||
adt4 "github.com/filecoin-project/specs-actors/v4/actors/util/adt"
|
||||
)
|
||||
|
||||
var _ State = (*state4)(nil)
|
||||
|
||||
func load4(store adt.Store, root cid.Cid) (State, error) {
|
||||
out := state4{store: store}
|
||||
err := store.Get(store.Context(), root, &out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
type state4 struct {
|
||||
init4.State
|
||||
store adt.Store
|
||||
}
|
||||
|
||||
func (s *state4) ResolveAddress(address address.Address) (address.Address, bool, error) {
|
||||
return s.State.ResolveAddress(s.store, address)
|
||||
}
|
||||
|
||||
func (s *state4) MapAddressToNewID(address address.Address) (address.Address, error) {
|
||||
return s.State.MapAddressToNewID(s.store, address)
|
||||
}
|
||||
|
||||
func (s *state4) ForEachActor(cb func(id abi.ActorID, address address.Address) error) error {
|
||||
addrs, err := adt4.AsMap(s.store, s.State.AddressMap, builtin4.DefaultHamtBitwidth)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var actorID cbg.CborInt
|
||||
return addrs.ForEach(&actorID, func(key string) error {
|
||||
addr, err := address.NewFromBytes([]byte(key))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return cb(abi.ActorID(actorID), addr)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *state4) NetworkName() (dtypes.NetworkName, error) {
|
||||
return dtypes.NetworkName(s.State.NetworkName), nil
|
||||
}
|
||||
|
||||
func (s *state4) SetNetworkName(name string) error {
|
||||
s.State.NetworkName = name
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *state4) Remove(addrs ...address.Address) (err error) {
|
||||
m, err := adt4.AsMap(s.store, s.State.AddressMap, builtin4.DefaultHamtBitwidth)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, addr := range addrs {
|
||||
if err = m.Delete(abi.AddrKey(addr)); err != nil {
|
||||
return xerrors.Errorf("failed to delete entry for address: %s; err: %w", addr, err)
|
||||
}
|
||||
}
|
||||
amr, err := m.Root()
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to get address map root: %w", err)
|
||||
}
|
||||
s.State.AddressMap = amr
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *state4) addressMap() (adt.Map, error) {
|
||||
return adt4.AsMap(s.store, s.AddressMap, builtin4.DefaultHamtBitwidth)
|
||||
}
|
||||
@@ -12,6 +12,8 @@ import (
|
||||
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
market0 "github.com/filecoin-project/specs-actors/actors/builtin/market"
|
||||
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
|
||||
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
|
||||
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin"
|
||||
@@ -25,9 +27,18 @@ func init() {
|
||||
builtin.RegisterActorState(builtin2.StorageMarketActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
|
||||
return load2(store, root)
|
||||
})
|
||||
builtin.RegisterActorState(builtin3.StorageMarketActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
|
||||
return load3(store, root)
|
||||
})
|
||||
builtin.RegisterActorState(builtin4.StorageMarketActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
|
||||
return load4(store, root)
|
||||
})
|
||||
}
|
||||
|
||||
var Address = builtin0.StorageMarketActorAddr
|
||||
var (
|
||||
Address = builtin4.StorageMarketActorAddr
|
||||
Methods = builtin4.MethodsMarket
|
||||
)
|
||||
|
||||
func Load(store adt.Store, act *types.Actor) (st State, err error) {
|
||||
switch act.Code {
|
||||
@@ -35,6 +46,10 @@ func Load(store adt.Store, act *types.Actor) (st State, err error) {
|
||||
return load0(store, act.Head)
|
||||
case builtin2.StorageMarketActorCodeID:
|
||||
return load2(store, act.Head)
|
||||
case builtin3.StorageMarketActorCodeID:
|
||||
return load3(store, act.Head)
|
||||
case builtin4.StorageMarketActorCodeID:
|
||||
return load4(store, act.Head)
|
||||
}
|
||||
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
|
||||
}
|
||||
@@ -78,6 +93,7 @@ type DealProposals interface {
|
||||
type PublishStorageDealsParams = market0.PublishStorageDealsParams
|
||||
type PublishStorageDealsReturn = market0.PublishStorageDealsReturn
|
||||
type VerifyDealsForActivationParams = market0.VerifyDealsForActivationParams
|
||||
type WithdrawBalanceParams = market0.WithdrawBalanceParams
|
||||
|
||||
type ClientDealProposal = market0.ClientDealProposal
|
||||
|
||||
|
||||
@@ -0,0 +1,205 @@
|
||||
package market
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/ipfs/go-cid"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
|
||||
market3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/market"
|
||||
adt3 "github.com/filecoin-project/specs-actors/v3/actors/util/adt"
|
||||
)
|
||||
|
||||
var _ State = (*state3)(nil)
|
||||
|
||||
func load3(store adt.Store, root cid.Cid) (State, error) {
|
||||
out := state3{store: store}
|
||||
err := store.Get(store.Context(), root, &out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
type state3 struct {
|
||||
market3.State
|
||||
store adt.Store
|
||||
}
|
||||
|
||||
func (s *state3) TotalLocked() (abi.TokenAmount, error) {
|
||||
fml := types.BigAdd(s.TotalClientLockedCollateral, s.TotalProviderLockedCollateral)
|
||||
fml = types.BigAdd(fml, s.TotalClientStorageFee)
|
||||
return fml, nil
|
||||
}
|
||||
|
||||
func (s *state3) BalancesChanged(otherState State) (bool, error) {
|
||||
otherState2, ok := otherState.(*state3)
|
||||
if !ok {
|
||||
// there's no way to compare different versions of the state, so let's
|
||||
// just say that means the state of balances has changed
|
||||
return true, nil
|
||||
}
|
||||
return !s.State.EscrowTable.Equals(otherState2.State.EscrowTable) || !s.State.LockedTable.Equals(otherState2.State.LockedTable), nil
|
||||
}
|
||||
|
||||
func (s *state3) StatesChanged(otherState State) (bool, error) {
|
||||
otherState2, ok := otherState.(*state3)
|
||||
if !ok {
|
||||
// there's no way to compare different versions of the state, so let's
|
||||
// just say that means the state of balances has changed
|
||||
return true, nil
|
||||
}
|
||||
return !s.State.States.Equals(otherState2.State.States), nil
|
||||
}
|
||||
|
||||
func (s *state3) States() (DealStates, error) {
|
||||
stateArray, err := adt3.AsArray(s.store, s.State.States, market3.StatesAmtBitwidth)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &dealStates3{stateArray}, nil
|
||||
}
|
||||
|
||||
func (s *state3) ProposalsChanged(otherState State) (bool, error) {
|
||||
otherState2, ok := otherState.(*state3)
|
||||
if !ok {
|
||||
// there's no way to compare different versions of the state, so let's
|
||||
// just say that means the state of balances has changed
|
||||
return true, nil
|
||||
}
|
||||
return !s.State.Proposals.Equals(otherState2.State.Proposals), nil
|
||||
}
|
||||
|
||||
func (s *state3) Proposals() (DealProposals, error) {
|
||||
proposalArray, err := adt3.AsArray(s.store, s.State.Proposals, market3.ProposalsAmtBitwidth)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &dealProposals3{proposalArray}, nil
|
||||
}
|
||||
|
||||
func (s *state3) EscrowTable() (BalanceTable, error) {
|
||||
bt, err := adt3.AsBalanceTable(s.store, s.State.EscrowTable)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &balanceTable3{bt}, nil
|
||||
}
|
||||
|
||||
func (s *state3) LockedTable() (BalanceTable, error) {
|
||||
bt, err := adt3.AsBalanceTable(s.store, s.State.LockedTable)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &balanceTable3{bt}, nil
|
||||
}
|
||||
|
||||
func (s *state3) VerifyDealsForActivation(
|
||||
minerAddr address.Address, deals []abi.DealID, currEpoch, sectorExpiry abi.ChainEpoch,
|
||||
) (weight, verifiedWeight abi.DealWeight, err error) {
|
||||
w, vw, _, err := market3.ValidateDealsForActivation(&s.State, s.store, deals, minerAddr, sectorExpiry, currEpoch)
|
||||
return w, vw, err
|
||||
}
|
||||
|
||||
type balanceTable3 struct {
|
||||
*adt3.BalanceTable
|
||||
}
|
||||
|
||||
func (bt *balanceTable3) ForEach(cb func(address.Address, abi.TokenAmount) error) error {
|
||||
asMap := (*adt3.Map)(bt.BalanceTable)
|
||||
var ta abi.TokenAmount
|
||||
return asMap.ForEach(&ta, func(key string) error {
|
||||
a, err := address.NewFromBytes([]byte(key))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return cb(a, ta)
|
||||
})
|
||||
}
|
||||
|
||||
type dealStates3 struct {
|
||||
adt.Array
|
||||
}
|
||||
|
||||
func (s *dealStates3) Get(dealID abi.DealID) (*DealState, bool, error) {
|
||||
var deal2 market3.DealState
|
||||
found, err := s.Array.Get(uint64(dealID), &deal2)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
if !found {
|
||||
return nil, false, nil
|
||||
}
|
||||
deal := fromV3DealState(deal2)
|
||||
return &deal, true, nil
|
||||
}
|
||||
|
||||
func (s *dealStates3) ForEach(cb func(dealID abi.DealID, ds DealState) error) error {
|
||||
var ds1 market3.DealState
|
||||
return s.Array.ForEach(&ds1, func(idx int64) error {
|
||||
return cb(abi.DealID(idx), fromV3DealState(ds1))
|
||||
})
|
||||
}
|
||||
|
||||
func (s *dealStates3) decode(val *cbg.Deferred) (*DealState, error) {
|
||||
var ds1 market3.DealState
|
||||
if err := ds1.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ds := fromV3DealState(ds1)
|
||||
return &ds, nil
|
||||
}
|
||||
|
||||
func (s *dealStates3) array() adt.Array {
|
||||
return s.Array
|
||||
}
|
||||
|
||||
func fromV3DealState(v1 market3.DealState) DealState {
|
||||
return (DealState)(v1)
|
||||
}
|
||||
|
||||
type dealProposals3 struct {
|
||||
adt.Array
|
||||
}
|
||||
|
||||
func (s *dealProposals3) Get(dealID abi.DealID) (*DealProposal, bool, error) {
|
||||
var proposal2 market3.DealProposal
|
||||
found, err := s.Array.Get(uint64(dealID), &proposal2)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
if !found {
|
||||
return nil, false, nil
|
||||
}
|
||||
proposal := fromV3DealProposal(proposal2)
|
||||
return &proposal, true, nil
|
||||
}
|
||||
|
||||
func (s *dealProposals3) ForEach(cb func(dealID abi.DealID, dp DealProposal) error) error {
|
||||
var dp1 market3.DealProposal
|
||||
return s.Array.ForEach(&dp1, func(idx int64) error {
|
||||
return cb(abi.DealID(idx), fromV3DealProposal(dp1))
|
||||
})
|
||||
}
|
||||
|
||||
func (s *dealProposals3) decode(val *cbg.Deferred) (*DealProposal, error) {
|
||||
var dp1 market3.DealProposal
|
||||
if err := dp1.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dp := fromV3DealProposal(dp1)
|
||||
return &dp, nil
|
||||
}
|
||||
|
||||
func (s *dealProposals3) array() adt.Array {
|
||||
return s.Array
|
||||
}
|
||||
|
||||
func fromV3DealProposal(v1 market3.DealProposal) DealProposal {
|
||||
return (DealProposal)(v1)
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user