From 4eaf89666f2c5e2b9703592a9aa257700f20031a Mon Sep 17 00:00:00 2001 From: emad22552 Date: Tue, 26 Oct 2021 14:00:41 +0330 Subject: [PATCH 001/385] fix manual-stateless-deal with interactive fix checking manual-stateless-deal with interactive deal making as --manual-stateless-deal can not be combined with interactive deal mode. --- cli/client.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cli/client.go b/cli/client.go index daaf5f3fe44..20493b97ee7 100644 --- a/cli/client.go +++ b/cli/client.go @@ -356,7 +356,13 @@ The minimum value is 518400 (6 months).`, &CidBaseFlag, }, Action: func(cctx *cli.Context) error { + + expectedArgsMsg := "expected 4 args: dataCid, miner, price, duration" + if !cctx.Args().Present() { + if cctx.Bool("manual-stateless-deal") { + return xerrors.New("--manual-stateless-deal can not be combined with interactive deal mode: you must specify the " + expectedArgsMsg) + } return interactiveDeal(cctx) } @@ -369,7 +375,7 @@ The minimum value is 518400 (6 months).`, afmt := NewAppFmt(cctx.App) if cctx.NArg() != 4 { - return xerrors.New("expected 4 args: dataCid, miner, price, duration") + return xerrors.New(expectedArgsMsg) } // [data, miner, price, dur] From 662c51605fc59a7998aa29b80d9399d6e3af6e68 Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Fri, 10 Sep 2021 15:12:43 +0200 Subject: [PATCH 002/385] feat: retrieve from any cid (not just root cid) --- go.mod | 16 ++-- go.sum | 36 +++++---- itests/deals_anycid_test.go | 143 ++++++++++++++++++++++++++++++++++++ itests/kit/deals.go | 11 ++- itests/kit/files.go | 25 +++++-- markets/dagstore/wrapper.go | 24 ++++++ 6 files changed, 222 insertions(+), 33 deletions(-) create mode 100644 itests/deals_anycid_test.go diff --git a/go.mod b/go.mod index 37e6bb9165c..daeb3847d2a 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/elastic/gosigar v0.14.1 github.com/etclabscore/go-openrpc-reflect v0.0.36 github.com/fatih/color v1.13.0 - github.com/filecoin-project/dagstore v0.4.3 + github.com/filecoin-project/dagstore v0.4.4-0.20210915102524-cd372c4b14d5 github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200910194244-f640612a1a1f github.com/filecoin-project/go-address v0.0.6 github.com/filecoin-project/go-bitfield v0.2.4 @@ -36,11 +36,11 @@ require ( github.com/filecoin-project/go-data-transfer v1.11.4 github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 - github.com/filecoin-project/go-fil-markets v1.13.3 - github.com/filecoin-project/go-jsonrpc v0.1.5 - github.com/filecoin-project/go-padreader v0.0.1 - github.com/filecoin-project/go-paramfetch v0.0.2 - github.com/filecoin-project/go-state-types v0.1.1 + github.com/filecoin-project/go-fil-markets v1.12.1-0.20210916145046-d81117f778de + github.com/filecoin-project/go-jsonrpc v0.1.4-0.20210217175800-45ea43ac2bec + github.com/filecoin-project/go-padreader v0.0.0-20210723183308-812a16dc01b1 + github.com/filecoin-project/go-paramfetch v0.0.2-0.20210614165157-25a6c7769498 + github.com/filecoin-project/go-state-types v0.1.1-0.20210810190654-139e0e79e69e github.com/filecoin-project/go-statemachine v1.0.1 github.com/filecoin-project/go-statestore v0.1.1 github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b @@ -98,7 +98,7 @@ require ( github.com/ipfs/go-unixfs v0.2.6 github.com/ipfs/interface-go-ipfs-core v0.4.0 github.com/ipld/go-car v0.3.2-0.20211001225732-32d0d9933823 - github.com/ipld/go-car/v2 v2.0.3-0.20210811121346-c514a30114d7 + github.com/ipld/go-car/v2 v2.0.3-0.20210910134712-2d2568297f26 github.com/ipld/go-codec-dagpb v1.3.0 github.com/ipld/go-ipld-prime v0.12.3 github.com/ipld/go-ipld-selector-text-lite v0.0.0 @@ -139,7 +139,7 @@ require ( github.com/streadway/quantile v0.0.0-20150917103942-b0c588724d25 github.com/stretchr/testify v1.7.0 github.com/syndtr/goleveldb v1.0.0 - github.com/urfave/cli/v2 v2.2.0 + github.com/urfave/cli/v2 v2.3.0 github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba github.com/whyrusleeping/cbor-gen v0.0.0-20210713220151-be142a5ae1a8 github.com/whyrusleeping/ledger-filecoin-go v0.9.1-0.20201010031517-c3dcc1bddce4 diff --git a/go.sum b/go.sum index 6019140fce8..0eb3c7d054d 100644 --- a/go.sum +++ b/go.sum @@ -302,8 +302,8 @@ github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGE github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/filecoin-project/dagstore v0.4.2/go.mod h1:WY5OoLfnwISCk6eASSF927KKPqLPIlTwmG1qHpA08KY= -github.com/filecoin-project/dagstore v0.4.3 h1:yeFl6+2BRY1gOVp/hrZuFa24s7LY0Qqkqx/Gh8lidZs= -github.com/filecoin-project/dagstore v0.4.3/go.mod h1:dm/91AO5UaDd3bABFjg/5fmRH99vvpS7g1mykqvz6KQ= +github.com/filecoin-project/dagstore v0.4.4-0.20210915102524-cd372c4b14d5 h1:wtKBSxmV5ohSeZHS86TrLtw6m1dO88QaNo6az/QRrYU= +github.com/filecoin-project/dagstore v0.4.4-0.20210915102524-cd372c4b14d5/go.mod h1:dsWYxyEYa5aB62UXJcQhwlIaBOS+kkrKQgYGxwAnmkE= github.com/filecoin-project/go-address v0.0.3/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= github.com/filecoin-project/go-address v0.0.5/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= github.com/filecoin-project/go-address v0.0.6 h1:DWQtj38ax+ogHwyH3VULRIoT8E6loyXqsk/p81xoY7M= @@ -327,6 +327,7 @@ github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod github.com/filecoin-project/go-crypto v0.0.1 h1:AcvpSGGCgjaY8y1az6AMfKQWreF/pWO2JJGLl6gCq6o= github.com/filecoin-project/go-crypto v0.0.1/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= github.com/filecoin-project/go-data-transfer v1.0.1/go.mod h1:UxvfUAY9v3ub0a21BSK9u3pB2aq30Y0KMsG+w9/ysyo= +github.com/filecoin-project/go-data-transfer v1.10.0/go.mod h1:uQtqy6vUAY5v70ZHdkF5mJ8CjVtjj/JA3aOoaqzWTVw= github.com/filecoin-project/go-data-transfer v1.11.4 h1:jKvlx0/C8HSyLRn/G1P9TjtfBtFU9jbCvCVFmWbyYVQ= github.com/filecoin-project/go-data-transfer v1.11.4/go.mod h1:2MitLI0ebCkLlPKM7NRggP/t9d+gCcREUKkCKqWRCwU= github.com/filecoin-project/go-ds-versioning v0.1.0 h1:y/X6UksYTsK8TLCI7rttCKEvl8btmWxyFMEeeWGUxIQ= @@ -338,8 +339,8 @@ github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+ github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7LXep5bFEVOVmQWHJvl2mgsGo= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8= github.com/filecoin-project/go-fil-markets v1.0.5-0.20201113164554-c5eba40d5335/go.mod h1:AJySOJC00JRWEZzRG2KsfUnqEf5ITXxeX09BE9N4f9c= -github.com/filecoin-project/go-fil-markets v1.13.3 h1:iMCpG7I4fb+YLcgDnMaqZiZiyFZWNvrwHqiFPHB0/tQ= -github.com/filecoin-project/go-fil-markets v1.13.3/go.mod h1:38zuj8AgDvOfdakFLpC/syYIYgXTzkq7xqBJ6T1AuG4= +github.com/filecoin-project/go-fil-markets v1.12.1-0.20210916145046-d81117f778de h1:QTcLAfS3DAWtWvwCG49wjN8jX0sJArnwOyyKQwbvBmU= +github.com/filecoin-project/go-fil-markets v1.12.1-0.20210916145046-d81117f778de/go.mod h1:XuuZFaFujI47nrgfQJiq7jWB+6rRya6nm7Sj6uXQ80U= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= @@ -347,24 +348,22 @@ github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0/go.mod h1:7aWZdaQ1b16BVoQUYR+ github.com/filecoin-project/go-hamt-ipld/v3 v3.0.1/go.mod h1:gXpNmr3oQx8l3o7qkGyDjJjYSRX7hp/FGOStdqrWyDI= github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0 h1:rVVNq0x6RGQIzCo1iiJlGFm9AGIZzeifggxtKMU7zmI= github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0/go.mod h1:bxmzgT8tmeVQA1/gvBwFmYdT8SOFUwB3ovSUfG1Ux0g= -github.com/filecoin-project/go-jsonrpc v0.1.5 h1:ckxqZ09ivBAVf5CSmxxrqqNHC7PJm3GYGtYKiNQ+vGk= -github.com/filecoin-project/go-jsonrpc v0.1.5/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4= +github.com/filecoin-project/go-jsonrpc v0.1.4-0.20210217175800-45ea43ac2bec h1:rGI5I7fdU4viManxmDdbk5deZO7afe6L1Wc04dAmlOM= +github.com/filecoin-project/go-jsonrpc v0.1.4-0.20210217175800-45ea43ac2bec/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4= github.com/filecoin-project/go-multistore v0.0.3/go.mod h1:kaNqCC4IhU4B1uyr7YWFHd23TL4KM32aChS0jNkyUvQ= github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20/go.mod h1:mPn+LRRd5gEKNAtc+r3ScpW2JRU/pj4NBKdADYWHiak= +github.com/filecoin-project/go-padreader v0.0.0-20210723183308-812a16dc01b1 h1:0BogtftbcgyBx4lP2JWM00ZK7/pXmgnrDqKp9aLTgVs= github.com/filecoin-project/go-padreader v0.0.0-20210723183308-812a16dc01b1/go.mod h1:VYVPJqwpsfmtoHnAmPx6MUwmrK6HIcDqZJiuZhtmfLQ= -github.com/filecoin-project/go-padreader v0.0.1 h1:8h2tVy5HpoNbr2gBRr+WD6zV6VD6XHig+ynSGJg8ZOs= -github.com/filecoin-project/go-padreader v0.0.1/go.mod h1:VYVPJqwpsfmtoHnAmPx6MUwmrK6HIcDqZJiuZhtmfLQ= -github.com/filecoin-project/go-paramfetch v0.0.2 h1:a6W3Ij6CKhwHYYlx+5mqvBIyw4CabZH2ojdEaoAZ6/g= -github.com/filecoin-project/go-paramfetch v0.0.2/go.mod h1:1FH85P8U+DUEmWk1Jkw3Bw7FrwTVUNHk/95PSPG+dts= +github.com/filecoin-project/go-paramfetch v0.0.2-0.20210614165157-25a6c7769498 h1:G10ezOvpH1CLXQ19EA9VWNwyL0mg536ujSayjV0yg0k= +github.com/filecoin-project/go-paramfetch v0.0.2-0.20210614165157-25a6c7769498/go.mod h1:1FH85P8U+DUEmWk1Jkw3Bw7FrwTVUNHk/95PSPG+dts= github.com/filecoin-project/go-state-types v0.0.0-20200903145444-247639ffa6ad/go.mod h1:IQ0MBPnonv35CJHtWSN3YY1Hz2gkPru1Q9qoaYLxx9I= github.com/filecoin-project/go-state-types v0.0.0-20200904021452-1883f36ca2f4/go.mod h1:IQ0MBPnonv35CJHtWSN3YY1Hz2gkPru1Q9qoaYLxx9I= github.com/filecoin-project/go-state-types v0.0.0-20200928172055-2df22083d8ab/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-state-types v0.0.0-20201102161440-c8033295a1fc/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-state-types v0.1.0/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-state-types v0.1.1-0.20210506134452-99b279731c48/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= +github.com/filecoin-project/go-state-types v0.1.1-0.20210810190654-139e0e79e69e h1:XAgb6HmgXaGRklNjhZoNMSIYriKLqjWXIqYMotg6iSs= github.com/filecoin-project/go-state-types v0.1.1-0.20210810190654-139e0e79e69e/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= -github.com/filecoin-project/go-state-types v0.1.1 h1:LR260vya4p++atgf256W6yV3Lxl5mKrBFcEZePWQrdg= -github.com/filecoin-project/go-state-types v0.1.1/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= github.com/filecoin-project/go-statemachine v1.0.1 h1:LQ60+JDVjMdLxXmVFM2jjontzOYnfVE7u02CXV3WKSw= github.com/filecoin-project/go-statemachine v1.0.1/go.mod h1:jZdXXiHa61n4NmgWFG4w8tnqgvZVHYbJ3yW7+y8bF54= @@ -742,6 +741,7 @@ github.com/ipfs/go-fs-lock v0.0.6/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28 github.com/ipfs/go-graphsync v0.1.0/go.mod h1:jMXfqIEDFukLPZHqDPp8tJMbHO9Rmeb9CEGevngQbmE= github.com/ipfs/go-graphsync v0.4.2/go.mod h1:/VmbZTUdUMTbNkgzAiCEucIIAU3BkLE2cZrDCVUhyi0= github.com/ipfs/go-graphsync v0.4.3/go.mod h1:mPOwDYv128gf8gxPFgXnz4fNrSYPsWyqisJ7ych+XDY= +github.com/ipfs/go-graphsync v0.9.0/go.mod h1:J62ahWT9JbPsFL2UWsUM5rOu0lZJ0LOIH1chHdxGGcw= github.com/ipfs/go-graphsync v0.10.0/go.mod h1:cKIshzTaa5rCZjryH5xmSKZVGX9uk1wvwGvz2WEha5Y= github.com/ipfs/go-graphsync v0.10.4 h1:1WZhyOPxgxLvHTIC2GoLltaBrjZ+JuXC2oKAEiX8f3Y= github.com/ipfs/go-graphsync v0.10.4/go.mod h1:oei4tnWAKnZ6LPnapZGPYVVbyiKV1UP3f8BeLU7Z4JQ= @@ -861,12 +861,13 @@ github.com/ipfs/iptb-plugins v0.3.0/go.mod h1:5QtOvckeIw4bY86gSH4fgh3p3gCSMn3FmI github.com/ipld/go-car v0.1.0/go.mod h1:RCWzaUh2i4mOEkB3W45Vc+9jnS/M6Qay5ooytiBHl3g= github.com/ipld/go-car v0.1.1-0.20200923150018-8cdef32e2da4/go.mod h1:xrMEcuSq+D1vEwl+YAXsg/JfA98XGpXDwnkIL4Aimqw= github.com/ipld/go-car v0.1.1-0.20201119040415-11b6074b6d4d/go.mod h1:2Gys8L8MJ6zkh1gktTSXreY63t4UbyvNp5JaudTyxHQ= +github.com/ipld/go-car v0.3.1-0.20210601190600-f512dac51e8e/go.mod h1:wUxBdwOLA9/0HZBi3fnTBzla0MuwlqgJLyrhOg1XaKI= github.com/ipld/go-car v0.3.2-0.20211001225732-32d0d9933823 h1:8JMSJ0k71fU9lIUrpVwEdoX4KoxiTEX8cZG97v/hTDw= github.com/ipld/go-car v0.3.2-0.20211001225732-32d0d9933823/go.mod h1:jSlTph+i/q1jLFoiKKeN69KGG0fXpwrcD0izu5C1Tpo= github.com/ipld/go-car/v2 v2.0.0-beta1.0.20210721090610-5a9d1b217d25/go.mod h1:I2ACeeg6XNBe5pdh5TaR7Ambhfa7If9KXxmXgZsYENU= github.com/ipld/go-car/v2 v2.0.2/go.mod h1:I2ACeeg6XNBe5pdh5TaR7Ambhfa7If9KXxmXgZsYENU= -github.com/ipld/go-car/v2 v2.0.3-0.20210811121346-c514a30114d7 h1:6Z0beJSZNsRY+7udoqUl4gQ/tqtrPuRvDySrlsvbqZA= -github.com/ipld/go-car/v2 v2.0.3-0.20210811121346-c514a30114d7/go.mod h1:I2ACeeg6XNBe5pdh5TaR7Ambhfa7If9KXxmXgZsYENU= +github.com/ipld/go-car/v2 v2.0.3-0.20210910134712-2d2568297f26 h1:IBXjeOANJGYZVJ9jsvf0Tu+ANQ9FLstscJgzfJgwA8c= +github.com/ipld/go-car/v2 v2.0.3-0.20210910134712-2d2568297f26/go.mod h1:bBmZNBj4jfOHrd4Cu/koFhqwsCnZ5RrGXU1wwWqDr20= github.com/ipld/go-codec-dagpb v1.2.0/go.mod h1:6nBN7X7h8EOsEejZGqC7tej5drsdBAXbMHyBT+Fne5s= github.com/ipld/go-codec-dagpb v1.3.0 h1:czTcaoAuNNyIYWs6Qe01DJ+sEX7B+1Z0LcXjSatMGe8= github.com/ipld/go-codec-dagpb v1.3.0/go.mod h1:ga4JTU3abYApDC3pZ00BC2RSvC3qfBb9MSJkMLSwnhA= @@ -878,6 +879,7 @@ github.com/ipld/go-ipld-prime v0.9.0/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/j github.com/ipld/go-ipld-prime v0.9.1-0.20210324083106-dc342a9917db/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= github.com/ipld/go-ipld-prime v0.10.0/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= github.com/ipld/go-ipld-prime v0.11.0/go.mod h1:+WIAkokurHmZ/KwzDOMUuoeJgaRQktHtEaLglS3ZeV8= +github.com/ipld/go-ipld-prime v0.12.0/go.mod h1:hy8b93WleDMRKumOJnTIrr0MbbFbx9GD6Kzxa53Xppc= github.com/ipld/go-ipld-prime v0.12.3-0.20210930132912-0b3aef3ca569/go.mod h1:PaeLYq8k6dJLmDUSLrzkEpoGV4PEfe/1OtFN/eALOc8= github.com/ipld/go-ipld-prime v0.12.3 h1:furVobw7UBLQZwlEwfE26tYORy3PAK8VYSgZOSr3JMQ= github.com/ipld/go-ipld-prime v0.12.3/go.mod h1:PaeLYq8k6dJLmDUSLrzkEpoGV4PEfe/1OtFN/eALOc8= @@ -1482,8 +1484,9 @@ github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPw github.com/multiformats/go-multicodec v0.2.0/go.mod h1:/y4YVwkfMyry5kFbMTbLJKErhycTIftytRV+llXdyS4= github.com/multiformats/go-multicodec v0.2.1-0.20210713081508-b421db6850ae/go.mod h1:qGGaQmioCDh+TeFOnxrbU0DaIPw8yFgAZgFG0V7p1qQ= github.com/multiformats/go-multicodec v0.2.1-0.20210714093213-b2b5bd6fe68b/go.mod h1:qGGaQmioCDh+TeFOnxrbU0DaIPw8yFgAZgFG0V7p1qQ= -github.com/multiformats/go-multicodec v0.3.0 h1:tstDwfIjiHbnIjeM5Lp+pMrSeN+LCMsEwOrkPmWm03A= github.com/multiformats/go-multicodec v0.3.0/go.mod h1:qGGaQmioCDh+TeFOnxrbU0DaIPw8yFgAZgFG0V7p1qQ= +github.com/multiformats/go-multicodec v0.3.1-0.20210902112759-1539a079fd61 h1:ZrUuMKNgJ52qHPoQ+bx0h0uBfcWmN7Px+4uKSZeesiI= +github.com/multiformats/go-multicodec v0.3.1-0.20210902112759-1539a079fd61/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ= github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= @@ -1794,8 +1797,9 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.0.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= -github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4= github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= +github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= +github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.0.1 h1:tY9CJiPnMXf1ERmG2EyK7gNUd+c6RKGD0IfU8WdUSz8= diff --git a/itests/deals_anycid_test.go b/itests/deals_anycid_test.go new file mode 100644 index 00000000000..5060847b9bf --- /dev/null +++ b/itests/deals_anycid_test.go @@ -0,0 +1,143 @@ +package itests + +import ( + "context" + "fmt" + "os" + "testing" + "time" + + "github.com/filecoin-project/lotus/api" + + ipld "github.com/ipfs/go-ipld-format" + + "github.com/filecoin-project/go-fil-markets/shared" + + "github.com/ipld/go-car" + + "github.com/stretchr/testify/require" + + "github.com/filecoin-project/lotus/node/modules/dtypes" + + "github.com/filecoin-project/go-fil-markets/storagemarket" + "github.com/filecoin-project/lotus/node" + "github.com/filecoin-project/lotus/node/modules" + + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/policy" + "github.com/filecoin-project/lotus/itests/kit" + logging "github.com/ipfs/go-log/v2" +) + +func TestDealRetrieveByAnyCid(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode") + } + + ctx := context.Background() + oldDelay := policy.GetPreCommitChallengeDelay() + policy.SetPreCommitChallengeDelay(5) + t.Cleanup(func() { + policy.SetPreCommitChallengeDelay(oldDelay) + }) + + // Allow 8MB sectors + kit.EnableLargeSectors(t) + policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg8MiBV1) + kit.QuietMiningLogs() + //logging.SetLogLevel("dagstore.invidx", "debug") + logging.SetLogLevel("markets-rtvl", "debug") + logging.SetLogLevel("markets-rtvl-reval", "debug") + + // For these tests where the block time is artificially short, just use + // a deal start epoch that is guaranteed to be far enough in the future + // so that the deal starts sealing in time + startEpoch := abi.ChainEpoch(2 << 12) + + // Override the dependency injection for the blockstore accessor, so that + // we can get a reference to the blockstore containing our deal later in + // the test + var bsa storagemarket.BlockstoreAccessor + bsaFn := func(importmgr dtypes.ClientImportMgr) storagemarket.BlockstoreAccessor { + bsa = modules.StorageBlockstoreAccessor(importmgr) + return bsa + } + bsaOpt := kit.ConstructorOpts(node.Override(new(storagemarket.BlockstoreAccessor), bsaFn)) + + // Allow 512MB sectors + eightMBSectorsOpt := kit.SectorSize(8 << 20) + + // Create a client, and a miner with its own full node + _, client, miner, ens := kit.EnsembleTwoOne(t, kit.MockProofs(), bsaOpt, eightMBSectorsOpt) + ens.InterconnectAll().BeginMining(250 * time.Millisecond) + + dh := kit.NewDealHarness(t, client, miner, miner) + + //res, path := client.CreateImportFile(ctx, 5, 140*1024*1024) + dagOpts := kit.GeneratedDAGOpts{ + ChunkSize: 1024, + Maxlinks: 2, + } + carv1FilePath, _ := kit.CreateRandomCARv1(t, 5, 8*1024, dagOpts) + res, err := client.ClientImport(ctx, api.FileRef{Path: carv1FilePath, IsCAR: true}) + require.NoError(t, err) + + // Get the blockstore for the file + bs, err := bsa.Get(res.Root) + require.NoError(t, err) + + // Get all CIDs from the file + sc := car.NewSelectiveCar(ctx, bs, []car.Dag{{Root: res.Root, Selector: shared.AllSelector()}}) + prepared, err := sc.Prepare() + require.NoError(t, err) + cids := prepared.Cids() + // fmt.Println(cids) + for i, c := range cids { + blk, err := bs.Get(c) + require.NoError(t, err) + + nd, err := ipld.Decode(blk) + require.NoError(t, err) + + fmt.Println(i, c, len(nd.Links())) + + if i > 100 { + break + } + } + + // Create a storage deal + dp := dh.DefaultStartDealParams() + dp.Data.Root = res.Root + dp.DealStartEpoch = startEpoch + dp.EpochPrice = abi.NewTokenAmount(62500000) // minimum asking price + dealCid := dh.StartDeal(ctx, dp) + + // Wait for the deal to be sealed + dh.WaitDealSealed(ctx, dealCid, false, false, nil) + + ask, err := miner.MarketGetRetrievalAsk(ctx) + require.NoError(t, err) + ask.PricePerByte = abi.NewTokenAmount(0) + ask.UnsealPrice = abi.NewTokenAmount(0) + err = miner.MarketSetRetrievalAsk(ctx, ask) + require.NoError(t, err) + + // Fetch the deal data + info, err := client.ClientGetDealInfo(ctx, *dealCid) + require.NoError(t, err) + + //targetCid := res.Root + targetCid := cids[1] + offer, err := client.ClientMinerQueryOffer(ctx, miner.ActorAddr, targetCid, &info.PieceCID) + require.NoError(t, err) + require.Empty(t, offer.Err) + + outPath := dh.PerformRetrievalForOffer(ctx, false, offer) + stat, err := os.Stat(outPath) + require.NoError(t, err) + fmt.Println(stat) + + // TODO: compare stored vs retrieved blocks + //kit.AssertFilesEqual(t, path, outPath) +} diff --git a/itests/kit/deals.go b/itests/kit/deals.go index 4a9af69e627..3a7d941ff61 100644 --- a/itests/kit/deals.go +++ b/itests/kit/deals.go @@ -303,15 +303,19 @@ func (dh *DealHarness) StartSealingWaiting(ctx context.Context) { } } -func (dh *DealHarness) PerformRetrieval(ctx context.Context, deal *cid.Cid, root cid.Cid, carExport bool) (path string) { +func (dh *DealHarness) PerformRetrieval(ctx context.Context, dealCid *cid.Cid, root cid.Cid, carExport bool) (path string) { // perform retrieval. - info, err := dh.client.ClientGetDealInfo(ctx, *deal) + info, err := dh.client.ClientGetDealInfo(ctx, *dealCid) require.NoError(dh.t, err) offers, err := dh.client.ClientFindData(ctx, root, &info.PieceCID) require.NoError(dh.t, err) require.NotEmpty(dh.t, offers, "no offers") + return dh.PerformRetrievalForOffer(ctx, carExport, offers[0]) +} + +func (dh *DealHarness) PerformRetrievalForOffer(ctx context.Context, carExport bool, offer api.QueryOffer) string { carFile, err := ioutil.TempFile(dh.t.TempDir(), "ret-car") require.NoError(dh.t, err) @@ -325,7 +329,8 @@ func (dh *DealHarness) PerformRetrieval(ctx context.Context, deal *cid.Cid, root IsCAR: carExport, } - updates, err := dh.client.ClientRetrieveWithEvents(ctx, offers[0].Order(caddr), ref) + order := offer.Order(caddr) + updates, err := dh.client.ClientRetrieveWithEvents(ctx, order, ref) require.NoError(dh.t, err) for update := range updates { diff --git a/itests/kit/files.go b/itests/kit/files.go index 9babac94144..d69c6d7767e 100644 --- a/itests/kit/files.go +++ b/itests/kit/files.go @@ -29,7 +29,7 @@ import ( "github.com/stretchr/testify/require" ) -const unixfsChunkSize uint64 = 1 << 10 +const unixfsChunkSize int64 = 1 << 10 var defaultHashFunction = uint64(mh.BLAKE2B_MIN + 31) @@ -54,7 +54,7 @@ func CreateRandomFile(t *testing.T, rseed, size int) (path string) { // CreateRandomFile creates a normal file with the provided seed and the // provided size and then transforms it to a CARv1 file and returns it. -func CreateRandomCARv1(t *testing.T, rseed, size int) (carV1FilePath string, origFilePath string) { +func CreateRandomCARv1(t *testing.T, rseed, size int, opts ...GeneratedDAGOpts) (carV1FilePath string, origFilePath string) { ctx := context.Background() if size == 0 { size = 1600 @@ -75,7 +75,7 @@ func CreateRandomCARv1(t *testing.T, rseed, size int) (carV1FilePath string, ori bs := bstore.NewBlockstore(dssync.MutexWrap(ds.NewMapDatastore())) dagSvc := merkledag.NewDAGService(blockservice.New(bs, offline.Exchange(bs))) - root := writeUnixfsDAG(ctx, t, file, dagSvc) + root := writeUnixfsDAG(ctx, t, file, dagSvc, opts...) // create a CARv1 file from the DAG tmp, err := os.CreateTemp(t.TempDir(), "randcarv1") @@ -92,7 +92,20 @@ func CreateRandomCARv1(t *testing.T, rseed, size int) (carV1FilePath string, ori return tmp.Name(), file.Name() } -func writeUnixfsDAG(ctx context.Context, t *testing.T, rd io.Reader, dag ipldformat.DAGService) cid.Cid { +type GeneratedDAGOpts struct { + ChunkSize int64 + Maxlinks int +} + +func writeUnixfsDAG(ctx context.Context, t *testing.T, rd io.Reader, dag ipldformat.DAGService, opts ...GeneratedDAGOpts) cid.Cid { + dagOpts := GeneratedDAGOpts{ + ChunkSize: unixfsChunkSize, + Maxlinks: 1024, + } + if len(opts) > 0 { + dagOpts = opts[0] + } + rpf := files.NewReaderFile(rd) // generate the dag and get the root @@ -103,7 +116,7 @@ func writeUnixfsDAG(ctx context.Context, t *testing.T, rd io.Reader, dag ipldfor bufferedDS := ipldformat.NewBufferedDAG(ctx, dag) params := ihelper.DagBuilderParams{ - Maxlinks: 1024, + Maxlinks: dagOpts.Maxlinks, RawLeaves: true, CidBuilder: cidutil.InlineBuilder{ Builder: prefix, @@ -112,7 +125,7 @@ func writeUnixfsDAG(ctx context.Context, t *testing.T, rd io.Reader, dag ipldfor Dagserv: bufferedDS, } - db, err := params.New(chunk.NewSizeSplitter(rpf, int64(unixfsChunkSize))) + db, err := params.New(chunk.NewSizeSplitter(rpf, dagOpts.ChunkSize)) require.NoError(t, err) nd, err := balanced.Layout(db) diff --git a/markets/dagstore/wrapper.go b/markets/dagstore/wrapper.go index 3d92886598e..6a32c011aae 100644 --- a/markets/dagstore/wrapper.go +++ b/markets/dagstore/wrapper.go @@ -3,6 +3,7 @@ package dagstore import ( "context" "errors" + "fmt" "math" "os" "path/filepath" @@ -398,6 +399,29 @@ func (w *Wrapper) markRegistrationComplete() error { return file.Close() } +// Get all the pieces that contain a block +func (w *Wrapper) GetPiecesContainingBlock(blockCID cid.Cid) ([]cid.Cid, error) { + // Pieces are stored as "shards" in the DAG store + shardKeys, err := w.dagst.GetShardKeysForCid(blockCID) + if err != nil { + return nil, xerrors.Errorf("getting pieces containing block %s: %w", blockCID, err) + } + + // Convert from shard key to cid + pieceCids := make([]cid.Cid, 0, len(shardKeys)) + for _, k := range shardKeys { + c, err := cid.Parse(k.String()) + if err != nil { + prefix := fmt.Sprintf("getting pieces containing block %s:", blockCID) + return nil, xerrors.Errorf(prefix+" converting shard key %s to piece cid: %w", k, err) + } + + pieceCids = append(pieceCids, c) + } + + return pieceCids, nil +} + func (w *Wrapper) Close() error { // Cancel the context w.cancel() From 053317e33471362f988930044e16c510b9e873cf Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Fri, 17 Sep 2021 11:27:53 +0400 Subject: [PATCH 003/385] test for retrieval by any cid --- itests/deals_anycid_test.go | 37 +++++++++++++++++++++++-------------- itests/kit/deals.go | 13 ++++--------- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/itests/deals_anycid_test.go b/itests/deals_anycid_test.go index 5060847b9bf..29c802b4be5 100644 --- a/itests/deals_anycid_test.go +++ b/itests/deals_anycid_test.go @@ -1,6 +1,7 @@ package itests import ( + "bufio" "context" "fmt" "os" @@ -76,9 +77,9 @@ func TestDealRetrieveByAnyCid(t *testing.T) { //res, path := client.CreateImportFile(ctx, 5, 140*1024*1024) dagOpts := kit.GeneratedDAGOpts{ ChunkSize: 1024, - Maxlinks: 2, + Maxlinks: 10, } - carv1FilePath, _ := kit.CreateRandomCARv1(t, 5, 8*1024, dagOpts) + carv1FilePath, _ := kit.CreateRandomCARv1(t, 5, 100*1024, dagOpts) res, err := client.ClientImport(ctx, api.FileRef{Path: carv1FilePath, IsCAR: true}) require.NoError(t, err) @@ -91,7 +92,6 @@ func TestDealRetrieveByAnyCid(t *testing.T) { prepared, err := sc.Prepare() require.NoError(t, err) cids := prepared.Cids() - // fmt.Println(cids) for i, c := range cids { blk, err := bs.Get(c) require.NoError(t, err) @@ -127,17 +127,26 @@ func TestDealRetrieveByAnyCid(t *testing.T) { info, err := client.ClientGetDealInfo(ctx, *dealCid) require.NoError(t, err) - //targetCid := res.Root - targetCid := cids[1] - offer, err := client.ClientMinerQueryOffer(ctx, miner.ActorAddr, targetCid, &info.PieceCID) - require.NoError(t, err) - require.Empty(t, offer.Err) + cidIndices := []int{1, 11, 27, 32, 47} - outPath := dh.PerformRetrievalForOffer(ctx, false, offer) - stat, err := os.Stat(outPath) - require.NoError(t, err) - fmt.Println(stat) + for _, val := range cidIndices { + fmt.Println("performing retrieval for cid at index", val) + targetCid := cids[val] + offer, err := client.ClientMinerQueryOffer(ctx, miner.ActorAddr, targetCid, &info.PieceCID) + require.NoError(t, err) + require.Empty(t, offer.Err) + + outPath := dh.PerformRetrievalForOffer(ctx, true, offer) + _, err = os.Stat(outPath) + require.NoError(t, err) + + f, err := os.Open(outPath) + require.NoError(t, err) + defer f.Close() + + ch, _, _ := car.ReadHeader(bufio.NewReader(f)) + require.EqualValues(t, ch.Roots[0], targetCid) + } - // TODO: compare stored vs retrieved blocks - //kit.AssertFilesEqual(t, path, outPath) + fmt.Println("finised test") } diff --git a/itests/kit/deals.go b/itests/kit/deals.go index 3a7d941ff61..64842eb7fad 100644 --- a/itests/kit/deals.go +++ b/itests/kit/deals.go @@ -316,16 +316,16 @@ func (dh *DealHarness) PerformRetrieval(ctx context.Context, dealCid *cid.Cid, r } func (dh *DealHarness) PerformRetrievalForOffer(ctx context.Context, carExport bool, offer api.QueryOffer) string { - carFile, err := ioutil.TempFile(dh.t.TempDir(), "ret-car") + outputF, err := ioutil.TempFile(dh.t.TempDir(), "ret-car") require.NoError(dh.t, err) - defer carFile.Close() //nolint:errcheck + defer outputF.Close() //nolint:errcheck caddr, err := dh.client.WalletDefaultAddress(ctx) require.NoError(dh.t, err) ref := &api.FileRef{ - Path: carFile.Name(), + Path: outputF.Name(), IsCAR: carExport, } @@ -337,12 +337,7 @@ func (dh *DealHarness) PerformRetrievalForOffer(ctx context.Context, carExport b require.Emptyf(dh.t, update.Err, "retrieval failed: %s", update.Err) } - ret := carFile.Name() - if carExport { - actualFile := dh.ExtractFileFromCAR(ctx, carFile) - ret = actualFile.Name() - _ = actualFile.Close() //nolint:errcheck - } + ret := outputF.Name() return ret } From 4d87f16e958293cbcb2bd335a0ad8fe0efd1b538 Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Fri, 17 Sep 2021 12:52:31 +0400 Subject: [PATCH 004/385] better comparision in test --- itests/deals_anycid_test.go | 46 ++++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/itests/deals_anycid_test.go b/itests/deals_anycid_test.go index 29c802b4be5..88ef0d6fdad 100644 --- a/itests/deals_anycid_test.go +++ b/itests/deals_anycid_test.go @@ -4,10 +4,13 @@ import ( "bufio" "context" "fmt" + "io/ioutil" "os" "testing" "time" + "github.com/ipld/go-car/v2/blockstore" + "github.com/filecoin-project/lotus/api" ipld "github.com/ipfs/go-ipld-format" @@ -128,25 +131,52 @@ func TestDealRetrieveByAnyCid(t *testing.T) { require.NoError(t, err) cidIndices := []int{1, 11, 27, 32, 47} - for _, val := range cidIndices { fmt.Println("performing retrieval for cid at index", val) + targetCid := cids[val] offer, err := client.ClientMinerQueryOffer(ctx, miner.ActorAddr, targetCid, &info.PieceCID) require.NoError(t, err) require.Empty(t, offer.Err) - outPath := dh.PerformRetrievalForOffer(ctx, true, offer) - _, err = os.Stat(outPath) + // retrieve in a CAR file and ensure roots match + outputCar := dh.PerformRetrievalForOffer(ctx, true, offer) + _, err = os.Stat(outputCar) require.NoError(t, err) - - f, err := os.Open(outPath) + f, err := os.Open(outputCar) require.NoError(t, err) - defer f.Close() - ch, _, _ := car.ReadHeader(bufio.NewReader(f)) require.EqualValues(t, ch.Roots[0], targetCid) + require.NoError(t, f.Close()) + + // create CAR from original file starting at targetCid and ensure it matches the retrieved CAR file. + tmp, err := os.CreateTemp(t.TempDir(), "randcarv1") + require.NoError(t, err) + rd, err := blockstore.OpenReadOnly(carv1FilePath, blockstore.UseWholeCIDs(true)) + require.NoError(t, err) + err = car.NewSelectiveCar( + ctx, + rd, + []car.Dag{{ + Root: targetCid, + Selector: shared.AllSelector(), + }}, + ).Write(tmp) + require.NoError(t, tmp.Close()) + require.NoError(t, rd.Close()) + + originalF, err := os.Open(tmp.Name()) + require.NoError(t, err) + obz, err := ioutil.ReadAll(originalF) + require.NoError(t, err) + + rf, err := os.Open(outputCar) + require.NoError(t, err) + bz, err := ioutil.ReadAll(rf) + require.NoError(t, err) + require.EqualValues(t, obz, bz) + fmt.Println("car files match") } - fmt.Println("finised test") + fmt.Println("finished test") } From e309293a4759449e0cc88ae260003283b0056f69 Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Fri, 17 Sep 2021 15:32:29 +0200 Subject: [PATCH 005/385] fix: lint fixes --- itests/deals_anycid_test.go | 61 ++++++++++++------------------------- 1 file changed, 19 insertions(+), 42 deletions(-) diff --git a/itests/deals_anycid_test.go b/itests/deals_anycid_test.go index 88ef0d6fdad..ad97a634a4b 100644 --- a/itests/deals_anycid_test.go +++ b/itests/deals_anycid_test.go @@ -3,34 +3,25 @@ package itests import ( "bufio" "context" - "fmt" - "io/ioutil" "os" "testing" "time" - "github.com/ipld/go-car/v2/blockstore" - - "github.com/filecoin-project/lotus/api" - + "github.com/filecoin-project/go-state-types/abi" ipld "github.com/ipfs/go-ipld-format" - - "github.com/filecoin-project/go-fil-markets/shared" - "github.com/ipld/go-car" - + "github.com/ipld/go-car/v2/blockstore" "github.com/stretchr/testify/require" - "github.com/filecoin-project/lotus/node/modules/dtypes" - + "github.com/filecoin-project/go-fil-markets/shared" "github.com/filecoin-project/go-fil-markets/storagemarket" - "github.com/filecoin-project/lotus/node" - "github.com/filecoin-project/lotus/node/modules" - "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/itests/kit" - logging "github.com/ipfs/go-log/v2" + "github.com/filecoin-project/lotus/node" + "github.com/filecoin-project/lotus/node/modules" + "github.com/filecoin-project/lotus/node/modules/dtypes" ) func TestDealRetrieveByAnyCid(t *testing.T) { @@ -46,12 +37,8 @@ func TestDealRetrieveByAnyCid(t *testing.T) { }) // Allow 8MB sectors - kit.EnableLargeSectors(t) policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg8MiBV1) kit.QuietMiningLogs() - //logging.SetLogLevel("dagstore.invidx", "debug") - logging.SetLogLevel("markets-rtvl", "debug") - logging.SetLogLevel("markets-rtvl-reval", "debug") // For these tests where the block time is artificially short, just use // a deal start epoch that is guaranteed to be far enough in the future @@ -68,7 +55,7 @@ func TestDealRetrieveByAnyCid(t *testing.T) { } bsaOpt := kit.ConstructorOpts(node.Override(new(storagemarket.BlockstoreAccessor), bsaFn)) - // Allow 512MB sectors + // Allow 8MB sectors eightMBSectorsOpt := kit.SectorSize(8 << 20) // Create a client, and a miner with its own full node @@ -77,10 +64,14 @@ func TestDealRetrieveByAnyCid(t *testing.T) { dh := kit.NewDealHarness(t, client, miner, miner) - //res, path := client.CreateImportFile(ctx, 5, 140*1024*1024) + // Generate a DAG with multiple levels, so that we can test the case where + // the client requests a CID for a block which is not the root block but + // does have a subtree below it in the DAG dagOpts := kit.GeneratedDAGOpts{ + // Max size of a block ChunkSize: 1024, - Maxlinks: 10, + // Max links from a block to other blocks + Maxlinks: 10, } carv1FilePath, _ := kit.CreateRandomCARv1(t, 5, 100*1024, dagOpts) res, err := client.ClientImport(ctx, api.FileRef{Path: carv1FilePath, IsCAR: true}) @@ -102,11 +93,7 @@ func TestDealRetrieveByAnyCid(t *testing.T) { nd, err := ipld.Decode(blk) require.NoError(t, err) - fmt.Println(i, c, len(nd.Links())) - - if i > 100 { - break - } + t.Log(i, c, len(nd.Links())) } // Create a storage deal @@ -130,9 +117,10 @@ func TestDealRetrieveByAnyCid(t *testing.T) { info, err := client.ClientGetDealInfo(ctx, *dealCid) require.NoError(t, err) + // Make retrievals against CIDs at different levels in the DAG cidIndices := []int{1, 11, 27, 32, 47} for _, val := range cidIndices { - fmt.Println("performing retrieval for cid at index", val) + t.Logf("performing retrieval for cid at index %d", val) targetCid := cids[val] offer, err := client.ClientMinerQueryOffer(ctx, miner.ActorAddr, targetCid, &info.PieceCID) @@ -165,18 +153,7 @@ func TestDealRetrieveByAnyCid(t *testing.T) { require.NoError(t, tmp.Close()) require.NoError(t, rd.Close()) - originalF, err := os.Open(tmp.Name()) - require.NoError(t, err) - obz, err := ioutil.ReadAll(originalF) - require.NoError(t, err) - - rf, err := os.Open(outputCar) - require.NoError(t, err) - bz, err := ioutil.ReadAll(rf) - require.NoError(t, err) - require.EqualValues(t, obz, bz) - fmt.Println("car files match") + kit.AssertFilesEqual(t, tmp.Name(), outputCar) + t.Log("car files match") } - - fmt.Println("finished test") } From 3c37078a856b6de01de74f428ada31b5bcac67a9 Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Fri, 17 Sep 2021 15:35:37 +0200 Subject: [PATCH 006/385] fix: dagstore wrapper test --- markets/dagstore/wrapper_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/markets/dagstore/wrapper_test.go b/markets/dagstore/wrapper_test.go index 9d3e6939e99..578dc0b74a2 100644 --- a/markets/dagstore/wrapper_test.go +++ b/markets/dagstore/wrapper_test.go @@ -132,6 +132,10 @@ type mockDagStore struct { close chan struct{} } +func (m *mockDagStore) GetShardKeysForCid(c cid.Cid) ([]shard.Key, error) { + panic("implement me") +} + func (m *mockDagStore) DestroyShard(ctx context.Context, key shard.Key, out chan dagstore.ShardResult, _ dagstore.DestroyOpts) error { panic("implement me") } From 189f5f8aaec28c5e6d275ac8ba709e454b9cc986 Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Mon, 20 Sep 2021 10:04:21 +0400 Subject: [PATCH 007/385] fix deals test --- itests/deals_anycid_test.go | 1 + itests/kit/deals.go | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/itests/deals_anycid_test.go b/itests/deals_anycid_test.go index ad97a634a4b..6b314908bd1 100644 --- a/itests/deals_anycid_test.go +++ b/itests/deals_anycid_test.go @@ -150,6 +150,7 @@ func TestDealRetrieveByAnyCid(t *testing.T) { Selector: shared.AllSelector(), }}, ).Write(tmp) + require.NoError(t, err) require.NoError(t, tmp.Close()) require.NoError(t, rd.Close()) diff --git a/itests/kit/deals.go b/itests/kit/deals.go index 64842eb7fad..c96d18acfb5 100644 --- a/itests/kit/deals.go +++ b/itests/kit/deals.go @@ -377,6 +377,7 @@ type RunConcurrentDealsOpts struct { } func (dh *DealHarness) RunConcurrentDeals(opts RunConcurrentDealsOpts) { + ctx := context.Background() errgrp, _ := errgroup.WithContext(context.Background()) for i := 0; i < opts.N; i++ { i := i @@ -402,7 +403,18 @@ func (dh *DealHarness) RunConcurrentDeals(opts RunConcurrentDealsOpts) { dh.t.Logf("retrieving deal %d/%d", i, opts.N) outPath := dh.PerformRetrieval(context.Background(), deal, res.Root, opts.CarExport) - AssertFilesEqual(dh.t, inPath, outPath) + + if opts.CarExport { + f, err := os.Open(outPath) + require.NoError(dh.t, err) + actualFile := dh.ExtractFileFromCAR(ctx, f) + require.NoError(dh.t, f.Close()) + + AssertFilesEqual(dh.t, inPath, actualFile.Name()) + } else { + AssertFilesEqual(dh.t, inPath, outPath) + } + return nil }) } From 025d8ebc59f406c7d3e9879ecea6037c915daa0a Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Mon, 20 Sep 2021 12:08:43 +0200 Subject: [PATCH 008/385] feat: include TestDealRetrieveByAnyCid in CI --- .circleci/config.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 30f2d5c01fd..721a620fe3b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -785,6 +785,11 @@ workflows: suite: itest-deals_512mb target: "./itests/deals_512mb_test.go" + - test: + name: test-itest-deals_anycid + suite: itest-deals_anycid + target: "./itests/deals_anycid_test.go" + - test: name: test-itest-deals_concurrent suite: itest-deals_concurrent From 588d6ec828cbee7382fc711d5bc69ef08cffd6d6 Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Mon, 20 Sep 2021 13:26:55 +0200 Subject: [PATCH 009/385] fix: docs-gen --- documentation/en/cli-lotus-miner.md | 153 +++++++++----------- documentation/en/cli-lotus-worker.md | 6 +- documentation/en/cli-lotus.md | 203 ++++++++++++--------------- 3 files changed, 153 insertions(+), 209 deletions(-) diff --git a/documentation/en/cli-lotus-miner.md b/documentation/en/cli-lotus-miner.md index a88a1af4226..d5b94fb8965 100644 --- a/documentation/en/cli-lotus-miner.md +++ b/documentation/en/cli-lotus-miner.md @@ -78,7 +78,6 @@ OPTIONS: --gas-premium value set gas premium for initialization messages in AttoFIL (default: "0") --from value select which address to send actor creation message from --help, -h show help (default: false) - --version, -v print the version (default: false) ``` @@ -160,8 +159,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -203,11 +201,11 @@ USAGE: DESCRIPTION: The backup command writes a copy of node metadata under the specified path - -Online backups: -For security reasons, the daemon must be have LOTUS_BACKUP_BASE_PATH env var set -to a path where backup files are supposed to be saved, and the path specified in -this command must be within this base path + + Online backups: + For security reasons, the daemon must be have LOTUS_BACKUP_BASE_PATH env var set + to a path where backup files are supposed to be saved, and the path specified in + this command must be within this base path OPTIONS: --offline create backup without the node running (default: false) @@ -249,8 +247,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -339,8 +336,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -433,7 +429,6 @@ OPTIONS: --hide-sectors-info hide sectors info (default: false) --blocks value Log of produced newest blocks and rewards(Miner Fee excluded) (default: 0) --help, -h show help (default: false) - --version, -v print the version (default: false) ``` @@ -464,8 +459,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -512,8 +506,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -540,23 +533,22 @@ USAGE: DESCRIPTION: Set the log level for logging systems: - - The system flag can be specified multiple times. - - eg) log set-level --system chain --system chainxchg debug - - Available Levels: - debug - info - warn - error - - Environment Variables: - GOLOG_LOG_LEVEL - Default log level for all log systems - GOLOG_LOG_FMT - Change output log format (json, nocolor) - GOLOG_FILE - Write logs to file - GOLOG_OUTPUT - Specify whether to output to file, stderr, stdout or a combination, i.e. file+stderr - + + The system flag can be specified multiple times. + + eg) log set-level --system chain --system chainxchg debug + + Available Levels: + debug + info + warn + error + + Environment Variables: + GOLOG_LOG_LEVEL - Default log level for all log systems + GOLOG_LOG_FMT - Change output log format (json, nocolor) + GOLOG_FILE - Write logs to file + GOLOG_OUTPUT - Specify whether to output to file, stderr, stdout or a combination, i.e. file+stderr OPTIONS: --system value limit to log system @@ -634,8 +626,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -683,8 +674,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -856,8 +846,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -876,8 +865,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -980,8 +968,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -1051,8 +1038,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -1149,8 +1135,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -1278,8 +1263,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -1298,8 +1282,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -1357,8 +1340,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -1433,8 +1415,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -1518,8 +1499,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -1687,7 +1667,6 @@ COMMANDS: OPTIONS: --really-do-it pass this flag if you know what you are doing (default: false) --help, -h show help (default: false) - --version, -v print the version (default: false) ``` @@ -1798,8 +1777,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -1848,8 +1826,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -1931,9 +1908,9 @@ USAGE: DESCRIPTION: Sectors can be stored across many filesystem paths. These -commands provide ways to manage the storage the miner will used to store sectors -long term for proving (references as 'store') as well as how sectors will be -stored while moving through the sealing pipeline (references as 'seal'). + commands provide ways to manage the storage the miner will used to store sectors + long term for proving (references as 'store') as well as how sectors will be + stored while moving through the sealing pipeline (references as 'seal'). COMMANDS: attach attach local storage path @@ -1943,8 +1920,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -1958,24 +1934,23 @@ USAGE: DESCRIPTION: Storage can be attached to the miner using this command. The storage volume -list is stored local to the miner in $LOTUS_MINER_PATH/storage.json. We do not -recommend manually modifying this value without further understanding of the -storage system. - -Each storage volume contains a configuration file which describes the -capabilities of the volume. When the '--init' flag is provided, this file will -be created using the additional flags. - -Weight -A high weight value means data will be more likely to be stored in this path - -Seal -Data for the sealing process will be stored here - -Store -Finalized sectors that will be moved here for long term storage and be proven -over time + list is stored local to the miner in $LOTUS_MINER_PATH/storage.json. We do not + recommend manually modifying this value without further understanding of the + storage system. + + Each storage volume contains a configuration file which describes the + capabilities of the volume. When the '--init' flag is provided, this file will + be created using the additional flags. + Weight + A high weight value means data will be more likely to be stored in this path + + Seal + Data for the sealing process will be stored here + + Store + Finalized sectors that will be moved here for long term storage and be proven + over time OPTIONS: --init initialize the path first (default: false) @@ -2000,9 +1975,8 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --color use color in display output (default: depends on output being a TTY) - --help, -h show help (default: false) - --version, -v print the version (default: false) + --color use color in display output (default: depends on output being a TTY) + --help, -h show help (default: false) ``` @@ -2063,8 +2037,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` diff --git a/documentation/en/cli-lotus-worker.md b/documentation/en/cli-lotus-worker.md index da6cefd18ab..3914a9cc0e4 100644 --- a/documentation/en/cli-lotus-worker.md +++ b/documentation/en/cli-lotus-worker.md @@ -75,8 +75,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -139,8 +138,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` diff --git a/documentation/en/cli-lotus.md b/documentation/en/cli-lotus.md index b0c5739188a..28f14c85a53 100644 --- a/documentation/en/cli-lotus.md +++ b/documentation/en/cli-lotus.md @@ -71,7 +71,6 @@ OPTIONS: --restore value restore from backup file --restore-config value config file to use when restoring from backup --help, -h show help (default: false) - --version, -v print the version (default: false) ``` @@ -98,11 +97,11 @@ USAGE: DESCRIPTION: The backup command writes a copy of node metadata under the specified path - -Online backups: -For security reasons, the daemon must be have LOTUS_BACKUP_BASE_PATH env var set -to a path where backup files are supposed to be saved, and the path specified in -this command must be within this base path + + Online backups: + For security reasons, the daemon must be have LOTUS_BACKUP_BASE_PATH env var set + to a path where backup files are supposed to be saved, and the path specified in + this command must be within this base path OPTIONS: --offline create backup without the node running (default: false) @@ -124,8 +123,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -218,8 +216,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -372,8 +369,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -445,8 +441,7 @@ COMMANDS: cancel-transfer Force cancel a data transfer OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -607,13 +602,13 @@ CATEGORY: DESCRIPTION: Make a deal with a miner. -dataCid comes from running 'lotus client import'. -miner is the address of the miner you wish to make a deal with. -price is measured in FIL/Epoch. Miners usually don't accept a bid -lower than their advertised ask (which is in FIL/GiB/Epoch). You can check a miners listed price -with 'lotus client query-ask '. -duration is how long the miner should store the data for, in blocks. -The minimum value is 518400 (6 months). + dataCid comes from running 'lotus client import'. + miner is the address of the miner you wish to make a deal with. + price is measured in FIL/Epoch. Miners usually don't accept a bid + lower than their advertised ask (which is in FIL/GiB/Epoch). You can check a miners listed price + with 'lotus client query-ask '. + duration is how long the miner should store the data for, in blocks. + The minimum value is 518400 (6 months). OPTIONS: --manual-piece-cid value manually specify piece commitment for data (dataCid must be to a car file) @@ -873,7 +868,6 @@ COMMANDS: OPTIONS: --confidence value number of block confirmations to wait for (default: 5) --help, -h show help (default: false) - --version, -v print the version (default: false) ``` @@ -1125,8 +1119,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -1215,8 +1208,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -1265,8 +1257,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -1417,8 +1408,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -1470,8 +1460,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -1621,7 +1610,6 @@ COMMANDS: OPTIONS: --tipset value specify tipset to call method on (pass comma separated array of cids) --help, -h show help (default: false) - --version, -v print the version (default: false) ``` @@ -1906,8 +1894,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -1992,8 +1979,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -2064,10 +2050,9 @@ USAGE: DESCRIPTION: Collect object size and ipld link count for an object. - - When a base is provided it will be walked first, and all links visisted - will be ignored when the passed in object is walked. - + + When a base is provided it will be walked first, and all links visisted + will be ignored when the passed in object is walked. OPTIONS: --base value ignore links found in this obj @@ -2117,34 +2102,33 @@ USAGE: DESCRIPTION: Get ipld node under a specified path: - - lotus chain get /ipfs/[cid]/some/path - - Path prefixes: - - /ipfs/[cid], /ipld/[cid] - traverse IPLD path - - /pstate - traverse from head.ParentStateRoot - - Note: - You can use special path elements to traverse through some data structures: - - /ipfs/[cid]/@H:elem - get 'elem' from hamt - - /ipfs/[cid]/@Hi:123 - get varint elem 123 from hamt - - /ipfs/[cid]/@Hu:123 - get uvarint elem 123 from hamt - - /ipfs/[cid]/@Ha:t01 - get element under Addr(t01).Bytes - - /ipfs/[cid]/@A:10 - get 10th amt element - - .../@Ha:t01/@state - get pretty map-based actor state - - List of --as-type types: - - raw - - block - - message - - smessage, signedmessage - - actor - - amt - - hamt-epoch - - hamt-address - - cronevent - - account-state - + + lotus chain get /ipfs/[cid]/some/path + + Path prefixes: + - /ipfs/[cid], /ipld/[cid] - traverse IPLD path + - /pstate - traverse from head.ParentStateRoot + + Note: + You can use special path elements to traverse through some data structures: + - /ipfs/[cid]/@H:elem - get 'elem' from hamt + - /ipfs/[cid]/@Hi:123 - get varint elem 123 from hamt + - /ipfs/[cid]/@Hu:123 - get uvarint elem 123 from hamt + - /ipfs/[cid]/@Ha:t01 - get element under Addr(t01).Bytes + - /ipfs/[cid]/@A:10 - get 10th amt element + - .../@Ha:t01/@state - get pretty map-based actor state + + List of --as-type types: + - raw + - block + - message + - smessage, signedmessage + - actor + - amt + - hamt-epoch + - hamt-address + - cronevent + - account-state OPTIONS: --as-type value specify type to interpret output as @@ -2164,18 +2148,17 @@ USAGE: DESCRIPTION: Bisect the chain state tree: - - lotus chain bisect [min height] [max height] '1/2/3/state/path' 'shell command' 'args' - - Returns the first tipset in which condition is true - v - [start] FFFFFFFTTT [end] - - Example: find height at which deal ID 100 000 appeared - - lotus chain bisect 1 32000 '@Ha:t03/1' jq -e '.[2] > 100000' - - For special path elements see 'chain get' help - + + lotus chain bisect [min height] [max height] '1/2/3/state/path' 'shell command' 'args' + + Returns the first tipset in which condition is true + v + [start] FFFFFFFTTT [end] + + Example: find height at which deal ID 100 000 appeared + - lotus chain bisect 1 32000 '@Ha:t03/1' jq -e '.[2] > 100000' + + For special path elements see 'chain get' help OPTIONS: --help, -h show help (default: false) @@ -2255,8 +2238,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -2288,8 +2270,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -2326,7 +2307,6 @@ OPTIONS: --max-fee value Spend up to X FIL per DisputeWindowedPoSt message --from value optionally specify the account to send messages from --help, -h show help (default: false) - --version, -v print the version (default: false) ``` @@ -2372,8 +2352,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -2400,23 +2379,22 @@ USAGE: DESCRIPTION: Set the log level for logging systems: - - The system flag can be specified multiple times. - - eg) log set-level --system chain --system chainxchg debug - - Available Levels: - debug - info - warn - error - - Environment Variables: - GOLOG_LOG_LEVEL - Default log level for all log systems - GOLOG_LOG_FMT - Change output log format (json, nocolor) - GOLOG_FILE - Write logs to file - GOLOG_OUTPUT - Specify whether to output to file, stderr, stdout or a combination, i.e. file+stderr - + + The system flag can be specified multiple times. + + eg) log set-level --system chain --system chainxchg debug + + Available Levels: + debug + info + warn + error + + Environment Variables: + GOLOG_LOG_LEVEL - Default log level for all log systems + GOLOG_LOG_FMT - Change output log format (json, nocolor) + GOLOG_FILE - Write logs to file + GOLOG_OUTPUT - Specify whether to output to file, stderr, stdout or a combination, i.e. file+stderr OPTIONS: --system value limit to log system @@ -2492,8 +2470,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -2621,8 +2598,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -2641,8 +2617,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -2700,8 +2675,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` @@ -2775,8 +2749,7 @@ COMMANDS: help, h Shows a list of commands or help for one command OPTIONS: - --help, -h show help (default: false) - --version, -v print the version (default: false) + --help, -h show help (default: false) ``` From a633f93707e36688be21e1e36a07409ad7db253e Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Fri, 12 Nov 2021 12:28:43 +0100 Subject: [PATCH 010/385] upgrade go modules --- go.mod | 10 +++++----- go.sum | 22 ++++++++++------------ 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/go.mod b/go.mod index daeb3847d2a..6d2c76d5421 100644 --- a/go.mod +++ b/go.mod @@ -36,11 +36,11 @@ require ( github.com/filecoin-project/go-data-transfer v1.11.4 github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 - github.com/filecoin-project/go-fil-markets v1.12.1-0.20210916145046-d81117f778de - github.com/filecoin-project/go-jsonrpc v0.1.4-0.20210217175800-45ea43ac2bec - github.com/filecoin-project/go-padreader v0.0.0-20210723183308-812a16dc01b1 - github.com/filecoin-project/go-paramfetch v0.0.2-0.20210614165157-25a6c7769498 - github.com/filecoin-project/go-state-types v0.1.1-0.20210810190654-139e0e79e69e + github.com/filecoin-project/go-fil-markets v1.13.3 + github.com/filecoin-project/go-jsonrpc v0.1.5 + github.com/filecoin-project/go-padreader v0.0.1 + github.com/filecoin-project/go-paramfetch v0.0.2 + github.com/filecoin-project/go-state-types v0.1.1 github.com/filecoin-project/go-statemachine v1.0.1 github.com/filecoin-project/go-statestore v0.1.1 github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b diff --git a/go.sum b/go.sum index 0eb3c7d054d..d12c2ae1da7 100644 --- a/go.sum +++ b/go.sum @@ -327,7 +327,6 @@ github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod github.com/filecoin-project/go-crypto v0.0.1 h1:AcvpSGGCgjaY8y1az6AMfKQWreF/pWO2JJGLl6gCq6o= github.com/filecoin-project/go-crypto v0.0.1/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= github.com/filecoin-project/go-data-transfer v1.0.1/go.mod h1:UxvfUAY9v3ub0a21BSK9u3pB2aq30Y0KMsG+w9/ysyo= -github.com/filecoin-project/go-data-transfer v1.10.0/go.mod h1:uQtqy6vUAY5v70ZHdkF5mJ8CjVtjj/JA3aOoaqzWTVw= github.com/filecoin-project/go-data-transfer v1.11.4 h1:jKvlx0/C8HSyLRn/G1P9TjtfBtFU9jbCvCVFmWbyYVQ= github.com/filecoin-project/go-data-transfer v1.11.4/go.mod h1:2MitLI0ebCkLlPKM7NRggP/t9d+gCcREUKkCKqWRCwU= github.com/filecoin-project/go-ds-versioning v0.1.0 h1:y/X6UksYTsK8TLCI7rttCKEvl8btmWxyFMEeeWGUxIQ= @@ -339,8 +338,8 @@ github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+ github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7LXep5bFEVOVmQWHJvl2mgsGo= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8= github.com/filecoin-project/go-fil-markets v1.0.5-0.20201113164554-c5eba40d5335/go.mod h1:AJySOJC00JRWEZzRG2KsfUnqEf5ITXxeX09BE9N4f9c= -github.com/filecoin-project/go-fil-markets v1.12.1-0.20210916145046-d81117f778de h1:QTcLAfS3DAWtWvwCG49wjN8jX0sJArnwOyyKQwbvBmU= -github.com/filecoin-project/go-fil-markets v1.12.1-0.20210916145046-d81117f778de/go.mod h1:XuuZFaFujI47nrgfQJiq7jWB+6rRya6nm7Sj6uXQ80U= +github.com/filecoin-project/go-fil-markets v1.13.3 h1:iMCpG7I4fb+YLcgDnMaqZiZiyFZWNvrwHqiFPHB0/tQ= +github.com/filecoin-project/go-fil-markets v1.13.3/go.mod h1:38zuj8AgDvOfdakFLpC/syYIYgXTzkq7xqBJ6T1AuG4= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= @@ -348,22 +347,24 @@ github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0/go.mod h1:7aWZdaQ1b16BVoQUYR+ github.com/filecoin-project/go-hamt-ipld/v3 v3.0.1/go.mod h1:gXpNmr3oQx8l3o7qkGyDjJjYSRX7hp/FGOStdqrWyDI= github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0 h1:rVVNq0x6RGQIzCo1iiJlGFm9AGIZzeifggxtKMU7zmI= github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0/go.mod h1:bxmzgT8tmeVQA1/gvBwFmYdT8SOFUwB3ovSUfG1Ux0g= -github.com/filecoin-project/go-jsonrpc v0.1.4-0.20210217175800-45ea43ac2bec h1:rGI5I7fdU4viManxmDdbk5deZO7afe6L1Wc04dAmlOM= -github.com/filecoin-project/go-jsonrpc v0.1.4-0.20210217175800-45ea43ac2bec/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4= +github.com/filecoin-project/go-jsonrpc v0.1.5 h1:ckxqZ09ivBAVf5CSmxxrqqNHC7PJm3GYGtYKiNQ+vGk= +github.com/filecoin-project/go-jsonrpc v0.1.5/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4= github.com/filecoin-project/go-multistore v0.0.3/go.mod h1:kaNqCC4IhU4B1uyr7YWFHd23TL4KM32aChS0jNkyUvQ= github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20/go.mod h1:mPn+LRRd5gEKNAtc+r3ScpW2JRU/pj4NBKdADYWHiak= -github.com/filecoin-project/go-padreader v0.0.0-20210723183308-812a16dc01b1 h1:0BogtftbcgyBx4lP2JWM00ZK7/pXmgnrDqKp9aLTgVs= github.com/filecoin-project/go-padreader v0.0.0-20210723183308-812a16dc01b1/go.mod h1:VYVPJqwpsfmtoHnAmPx6MUwmrK6HIcDqZJiuZhtmfLQ= -github.com/filecoin-project/go-paramfetch v0.0.2-0.20210614165157-25a6c7769498 h1:G10ezOvpH1CLXQ19EA9VWNwyL0mg536ujSayjV0yg0k= -github.com/filecoin-project/go-paramfetch v0.0.2-0.20210614165157-25a6c7769498/go.mod h1:1FH85P8U+DUEmWk1Jkw3Bw7FrwTVUNHk/95PSPG+dts= +github.com/filecoin-project/go-padreader v0.0.1 h1:8h2tVy5HpoNbr2gBRr+WD6zV6VD6XHig+ynSGJg8ZOs= +github.com/filecoin-project/go-padreader v0.0.1/go.mod h1:VYVPJqwpsfmtoHnAmPx6MUwmrK6HIcDqZJiuZhtmfLQ= +github.com/filecoin-project/go-paramfetch v0.0.2 h1:a6W3Ij6CKhwHYYlx+5mqvBIyw4CabZH2ojdEaoAZ6/g= +github.com/filecoin-project/go-paramfetch v0.0.2/go.mod h1:1FH85P8U+DUEmWk1Jkw3Bw7FrwTVUNHk/95PSPG+dts= github.com/filecoin-project/go-state-types v0.0.0-20200903145444-247639ffa6ad/go.mod h1:IQ0MBPnonv35CJHtWSN3YY1Hz2gkPru1Q9qoaYLxx9I= github.com/filecoin-project/go-state-types v0.0.0-20200904021452-1883f36ca2f4/go.mod h1:IQ0MBPnonv35CJHtWSN3YY1Hz2gkPru1Q9qoaYLxx9I= github.com/filecoin-project/go-state-types v0.0.0-20200928172055-2df22083d8ab/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-state-types v0.0.0-20201102161440-c8033295a1fc/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-state-types v0.1.0/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-state-types v0.1.1-0.20210506134452-99b279731c48/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= -github.com/filecoin-project/go-state-types v0.1.1-0.20210810190654-139e0e79e69e h1:XAgb6HmgXaGRklNjhZoNMSIYriKLqjWXIqYMotg6iSs= github.com/filecoin-project/go-state-types v0.1.1-0.20210810190654-139e0e79e69e/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= +github.com/filecoin-project/go-state-types v0.1.1 h1:LR260vya4p++atgf256W6yV3Lxl5mKrBFcEZePWQrdg= +github.com/filecoin-project/go-state-types v0.1.1/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= github.com/filecoin-project/go-statemachine v1.0.1 h1:LQ60+JDVjMdLxXmVFM2jjontzOYnfVE7u02CXV3WKSw= github.com/filecoin-project/go-statemachine v1.0.1/go.mod h1:jZdXXiHa61n4NmgWFG4w8tnqgvZVHYbJ3yW7+y8bF54= @@ -741,7 +742,6 @@ github.com/ipfs/go-fs-lock v0.0.6/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28 github.com/ipfs/go-graphsync v0.1.0/go.mod h1:jMXfqIEDFukLPZHqDPp8tJMbHO9Rmeb9CEGevngQbmE= github.com/ipfs/go-graphsync v0.4.2/go.mod h1:/VmbZTUdUMTbNkgzAiCEucIIAU3BkLE2cZrDCVUhyi0= github.com/ipfs/go-graphsync v0.4.3/go.mod h1:mPOwDYv128gf8gxPFgXnz4fNrSYPsWyqisJ7ych+XDY= -github.com/ipfs/go-graphsync v0.9.0/go.mod h1:J62ahWT9JbPsFL2UWsUM5rOu0lZJ0LOIH1chHdxGGcw= github.com/ipfs/go-graphsync v0.10.0/go.mod h1:cKIshzTaa5rCZjryH5xmSKZVGX9uk1wvwGvz2WEha5Y= github.com/ipfs/go-graphsync v0.10.4 h1:1WZhyOPxgxLvHTIC2GoLltaBrjZ+JuXC2oKAEiX8f3Y= github.com/ipfs/go-graphsync v0.10.4/go.mod h1:oei4tnWAKnZ6LPnapZGPYVVbyiKV1UP3f8BeLU7Z4JQ= @@ -861,7 +861,6 @@ github.com/ipfs/iptb-plugins v0.3.0/go.mod h1:5QtOvckeIw4bY86gSH4fgh3p3gCSMn3FmI github.com/ipld/go-car v0.1.0/go.mod h1:RCWzaUh2i4mOEkB3W45Vc+9jnS/M6Qay5ooytiBHl3g= github.com/ipld/go-car v0.1.1-0.20200923150018-8cdef32e2da4/go.mod h1:xrMEcuSq+D1vEwl+YAXsg/JfA98XGpXDwnkIL4Aimqw= github.com/ipld/go-car v0.1.1-0.20201119040415-11b6074b6d4d/go.mod h1:2Gys8L8MJ6zkh1gktTSXreY63t4UbyvNp5JaudTyxHQ= -github.com/ipld/go-car v0.3.1-0.20210601190600-f512dac51e8e/go.mod h1:wUxBdwOLA9/0HZBi3fnTBzla0MuwlqgJLyrhOg1XaKI= github.com/ipld/go-car v0.3.2-0.20211001225732-32d0d9933823 h1:8JMSJ0k71fU9lIUrpVwEdoX4KoxiTEX8cZG97v/hTDw= github.com/ipld/go-car v0.3.2-0.20211001225732-32d0d9933823/go.mod h1:jSlTph+i/q1jLFoiKKeN69KGG0fXpwrcD0izu5C1Tpo= github.com/ipld/go-car/v2 v2.0.0-beta1.0.20210721090610-5a9d1b217d25/go.mod h1:I2ACeeg6XNBe5pdh5TaR7Ambhfa7If9KXxmXgZsYENU= @@ -879,7 +878,6 @@ github.com/ipld/go-ipld-prime v0.9.0/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/j github.com/ipld/go-ipld-prime v0.9.1-0.20210324083106-dc342a9917db/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= github.com/ipld/go-ipld-prime v0.10.0/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= github.com/ipld/go-ipld-prime v0.11.0/go.mod h1:+WIAkokurHmZ/KwzDOMUuoeJgaRQktHtEaLglS3ZeV8= -github.com/ipld/go-ipld-prime v0.12.0/go.mod h1:hy8b93WleDMRKumOJnTIrr0MbbFbx9GD6Kzxa53Xppc= github.com/ipld/go-ipld-prime v0.12.3-0.20210930132912-0b3aef3ca569/go.mod h1:PaeLYq8k6dJLmDUSLrzkEpoGV4PEfe/1OtFN/eALOc8= github.com/ipld/go-ipld-prime v0.12.3 h1:furVobw7UBLQZwlEwfE26tYORy3PAK8VYSgZOSr3JMQ= github.com/ipld/go-ipld-prime v0.12.3/go.mod h1:PaeLYq8k6dJLmDUSLrzkEpoGV4PEfe/1OtFN/eALOc8= From 627d4fbf745736b6b1b0e3daf4896f2cd44a7156 Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Wed, 10 Nov 2021 17:28:23 +0100 Subject: [PATCH 011/385] wip: storage miner index provider --- go.mod | 19 ++-- go.sum | 79 +++++++++++--- itests/deals_concurrent_test.go | 17 ++- itests/kit/deals.go | 9 ++ markets/dagstore/wrapper.go | 7 +- node/builder_miner.go | 2 + node/config/def.go | 9 ++ node/config/types.go | 29 +++-- node/modules/storageminer.go | 3 + node/modules/storageminer_idxprov.go | 158 +++++++++++++++++++++++++++ 10 files changed, 292 insertions(+), 40 deletions(-) create mode 100644 node/modules/storageminer_idxprov.go diff --git a/go.mod b/go.mod index 6d2c76d5421..a6009b334d9 100644 --- a/go.mod +++ b/go.mod @@ -26,14 +26,14 @@ require ( github.com/elastic/gosigar v0.14.1 github.com/etclabscore/go-openrpc-reflect v0.0.36 github.com/fatih/color v1.13.0 - github.com/filecoin-project/dagstore v0.4.4-0.20210915102524-cd372c4b14d5 + github.com/filecoin-project/dagstore v0.5.0 github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200910194244-f640612a1a1f github.com/filecoin-project/go-address v0.0.6 github.com/filecoin-project/go-bitfield v0.2.4 github.com/filecoin-project/go-cbor-util v0.0.1 - github.com/filecoin-project/go-commp-utils v0.1.2 + github.com/filecoin-project/go-commp-utils v0.1.3 github.com/filecoin-project/go-crypto v0.0.1 - github.com/filecoin-project/go-data-transfer v1.11.4 + github.com/filecoin-project/go-data-transfer v1.11.6-0.20211116162442-2d8068920bda github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 github.com/filecoin-project/go-fil-markets v1.13.3 @@ -44,6 +44,7 @@ require ( github.com/filecoin-project/go-statemachine v1.0.1 github.com/filecoin-project/go-statestore v0.1.1 github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b + github.com/filecoin-project/index-provider v0.0.0-20211116104945-9f8f1785e3c2 github.com/filecoin-project/specs-actors v0.9.14 github.com/filecoin-project/specs-actors/v2 v2.3.5 github.com/filecoin-project/specs-actors/v3 v3.1.1 @@ -66,7 +67,7 @@ require ( github.com/icza/backscanner v0.0.0-20210726202459-ac2ffc679f94 github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab github.com/ipfs/bbloom v0.0.4 - github.com/ipfs/go-bitswap v0.3.4 + github.com/ipfs/go-bitswap v0.4.0 github.com/ipfs/go-block-format v0.0.3 github.com/ipfs/go-blockservice v0.1.7 github.com/ipfs/go-cid v0.1.0 @@ -97,10 +98,10 @@ require ( github.com/ipfs/go-path v0.0.7 github.com/ipfs/go-unixfs v0.2.6 github.com/ipfs/interface-go-ipfs-core v0.4.0 - github.com/ipld/go-car v0.3.2-0.20211001225732-32d0d9933823 - github.com/ipld/go-car/v2 v2.0.3-0.20210910134712-2d2568297f26 + github.com/ipld/go-car v0.3.2 + github.com/ipld/go-car/v2 v2.1.0 github.com/ipld/go-codec-dagpb v1.3.0 - github.com/ipld/go-ipld-prime v0.12.3 + github.com/ipld/go-ipld-prime v0.14.0 github.com/ipld/go-ipld-selector-text-lite v0.0.0 github.com/kelseyhightower/envconfig v1.4.0 github.com/libp2p/go-buffer-pool v0.0.2 @@ -114,7 +115,7 @@ require ( github.com/libp2p/go-libp2p-noise v0.2.2 github.com/libp2p/go-libp2p-peerstore v0.3.0 github.com/libp2p/go-libp2p-pubsub v0.5.6 - github.com/libp2p/go-libp2p-quic-transport v0.11.2 + github.com/libp2p/go-libp2p-quic-transport v0.12.0 github.com/libp2p/go-libp2p-record v0.1.3 github.com/libp2p/go-libp2p-routing-helpers v0.2.3 github.com/libp2p/go-libp2p-swarm v0.5.3 @@ -128,7 +129,7 @@ require ( github.com/multiformats/go-multiaddr v0.4.1 github.com/multiformats/go-multiaddr-dns v0.3.1 github.com/multiformats/go-multibase v0.0.3 - github.com/multiformats/go-multihash v0.0.16 + github.com/multiformats/go-multihash v0.1.0 github.com/multiformats/go-varint v0.0.6 github.com/open-rpc/meta-schema v0.0.0-20201029221707-1b72ef2ea333 github.com/opentracing/opentracing-go v1.2.0 diff --git a/go.sum b/go.sum index d12c2ae1da7..84a34761e9d 100644 --- a/go.sum +++ b/go.sum @@ -89,6 +89,7 @@ github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/akavel/rsrc v0.8.0 h1:zjWn7ukO9Kc5Q62DOJCcxGpXC18RawVtYAGdz2aLlfw= github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= +github.com/akrylysov/pogreb v0.10.1/go.mod h1:pNs6QmpQ1UlTJKDezuRWmaqkgUE2TuU0YTWyqJZ7+lI= github.com/alecthomas/jsonschema v0.0.0-20200530073317-71f438968921 h1:T3+cD5fYvuH36h7EZq+TDpm+d8a6FSD4pQsbmuGGQ8o= github.com/alecthomas/jsonschema v0.0.0-20200530073317-71f438968921/go.mod h1:/n6+1/DWPltRLWL/VKyUxg6tzsl5kHUCcraimt4vr60= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -302,8 +303,8 @@ github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGE github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/filecoin-project/dagstore v0.4.2/go.mod h1:WY5OoLfnwISCk6eASSF927KKPqLPIlTwmG1qHpA08KY= -github.com/filecoin-project/dagstore v0.4.4-0.20210915102524-cd372c4b14d5 h1:wtKBSxmV5ohSeZHS86TrLtw6m1dO88QaNo6az/QRrYU= -github.com/filecoin-project/dagstore v0.4.4-0.20210915102524-cd372c4b14d5/go.mod h1:dsWYxyEYa5aB62UXJcQhwlIaBOS+kkrKQgYGxwAnmkE= +github.com/filecoin-project/dagstore v0.5.0 h1:akiheGtSCU7aGon6T74bwNbDhYW0XZCTsnORKNmzSgU= +github.com/filecoin-project/dagstore v0.5.0/go.mod h1:Id2VG7uZxnF6NWR3JX1evNA83JonnU0U7Fc2r14Vltc= github.com/filecoin-project/go-address v0.0.3/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= github.com/filecoin-project/go-address v0.0.5/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= github.com/filecoin-project/go-address v0.0.6 h1:DWQtj38ax+ogHwyH3VULRIoT8E6loyXqsk/p81xoY7M= @@ -321,14 +322,17 @@ github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2/go.m github.com/filecoin-project/go-cbor-util v0.0.1 h1:E1LYZYTtjfAQwCReho0VXvbu8t3CYAVPiMx8EiV/VAs= github.com/filecoin-project/go-cbor-util v0.0.1/go.mod h1:pqTiPHobNkOVM5thSRsHYjyQfq7O5QSCMhvuu9JoDlg= github.com/filecoin-project/go-commp-utils v0.1.1-0.20210427191551-70bf140d31c7/go.mod h1:6s95K91mCyHY51RPWECZieD3SGWTqIFLf1mPOes9l5U= -github.com/filecoin-project/go-commp-utils v0.1.2 h1:SKLRuGdx/6WlolaWKaUzzUYWGGePuARyO4guxOPxvt4= -github.com/filecoin-project/go-commp-utils v0.1.2/go.mod h1:6s95K91mCyHY51RPWECZieD3SGWTqIFLf1mPOes9l5U= +github.com/filecoin-project/go-commp-utils v0.1.3 h1:rTxbkNXZU7FLgdkBk8RsQIEOuPONHykEoX3xGk41Fkw= +github.com/filecoin-project/go-commp-utils v0.1.3/go.mod h1:3ENlD1pZySaUout0p9ANQrY3fDFoXdqyX04J+dWpK30= github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= github.com/filecoin-project/go-crypto v0.0.1 h1:AcvpSGGCgjaY8y1az6AMfKQWreF/pWO2JJGLl6gCq6o= github.com/filecoin-project/go-crypto v0.0.1/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= +github.com/filecoin-project/go-dagaggregator-unixfs v0.2.0/go.mod h1:WTuJWgBQY0omnQqa8kRPT9O0Uj5wQOgslVMUuTeHdJ8= github.com/filecoin-project/go-data-transfer v1.0.1/go.mod h1:UxvfUAY9v3ub0a21BSK9u3pB2aq30Y0KMsG+w9/ysyo= -github.com/filecoin-project/go-data-transfer v1.11.4 h1:jKvlx0/C8HSyLRn/G1P9TjtfBtFU9jbCvCVFmWbyYVQ= +github.com/filecoin-project/go-data-transfer v1.10.1/go.mod h1:CSDMCrPK2lVGodNB1wPEogjFvM9nVGyiL1GNbBRTSdw= github.com/filecoin-project/go-data-transfer v1.11.4/go.mod h1:2MitLI0ebCkLlPKM7NRggP/t9d+gCcREUKkCKqWRCwU= +github.com/filecoin-project/go-data-transfer v1.11.6-0.20211116162442-2d8068920bda h1:JeKScBtyL1KzBPNatXCiFoY3RPMj7IOSCgFfdNdA6y4= +github.com/filecoin-project/go-data-transfer v1.11.6-0.20211116162442-2d8068920bda/go.mod h1:BaTx3YYc+qxNgCmLVKPwLCqNoLvX7naE0oLt5oD4QGc= github.com/filecoin-project/go-ds-versioning v0.1.0 h1:y/X6UksYTsK8TLCI7rttCKEvl8btmWxyFMEeeWGUxIQ= github.com/filecoin-project/go-ds-versioning v0.1.0/go.mod h1:mp16rb4i2QPmxBnmanUx8i/XANp+PFCCJWiAb+VW4/s= github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= @@ -347,8 +351,14 @@ github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0/go.mod h1:7aWZdaQ1b16BVoQUYR+ github.com/filecoin-project/go-hamt-ipld/v3 v3.0.1/go.mod h1:gXpNmr3oQx8l3o7qkGyDjJjYSRX7hp/FGOStdqrWyDI= github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0 h1:rVVNq0x6RGQIzCo1iiJlGFm9AGIZzeifggxtKMU7zmI= github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0/go.mod h1:bxmzgT8tmeVQA1/gvBwFmYdT8SOFUwB3ovSUfG1Ux0g= +github.com/filecoin-project/go-indexer-core v0.2.2/go.mod h1:wV+NmrF8fHG6Xii3ecoZf2JW3laGTe5xtsWz609jo+Y= +github.com/filecoin-project/go-indexer-core v0.2.3 h1:kaUL2r8CuihK53lhmtCScffb7Bzs+N1yRGpwvxzCN+U= +github.com/filecoin-project/go-indexer-core v0.2.3/go.mod h1:MSe5aRWmfRB+5syR4yDV+OApgJU+MUJ4rl9VUuzwCfc= github.com/filecoin-project/go-jsonrpc v0.1.5 h1:ckxqZ09ivBAVf5CSmxxrqqNHC7PJm3GYGtYKiNQ+vGk= github.com/filecoin-project/go-jsonrpc v0.1.5/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4= +github.com/filecoin-project/go-legs v0.0.0-20211013165050-9ab325b6d2eb/go.mod h1:lKwBnslfNGG7JnsP9uQZl3yK7f74fit1MyHcwuuOP3k= +github.com/filecoin-project/go-legs v0.0.0-20211112111427-68d536862db9 h1:NWe71o5Kgi/0/eMlPJKF//nnIPwOR73AXRk6R/+LLA4= +github.com/filecoin-project/go-legs v0.0.0-20211112111427-68d536862db9/go.mod h1:g32LVimhcYPte22LK8XslKqLBem54QxuMQmkrzbAyEI= github.com/filecoin-project/go-multistore v0.0.3/go.mod h1:kaNqCC4IhU4B1uyr7YWFHd23TL4KM32aChS0jNkyUvQ= github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20/go.mod h1:mPn+LRRd5gEKNAtc+r3ScpW2JRU/pj4NBKdADYWHiak= github.com/filecoin-project/go-padreader v0.0.0-20210723183308-812a16dc01b1/go.mod h1:VYVPJqwpsfmtoHnAmPx6MUwmrK6HIcDqZJiuZhtmfLQ= @@ -373,6 +383,8 @@ github.com/filecoin-project/go-statestore v0.1.1 h1:ufMFq00VqnT2CAuDpcGnwLnCX1I/ github.com/filecoin-project/go-statestore v0.1.1/go.mod h1:LFc9hD+fRxPqiHiaqUEZOinUJB4WARkRfNl10O7kTnI= github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b h1:fkRZSPrYpk42PV3/lIXiL0LHetxde7vyYYvSsttQtfg= github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b/go.mod h1:Q0GQOBtKf1oE10eSXSlhN45kDBdGvEcVOqMiffqX+N8= +github.com/filecoin-project/index-provider v0.0.0-20211116104945-9f8f1785e3c2 h1:1nxYiIU+IT4joHR8a6+R7iyzNbLKBJP+yOio1pU5wRc= +github.com/filecoin-project/index-provider v0.0.0-20211116104945-9f8f1785e3c2/go.mod h1:TRec/t1PaPURTDD1uTT2UZceNF+HOViCpDvleqDr9ks= github.com/filecoin-project/specs-actors v0.9.4/go.mod h1:BStZQzx5x7TmCkLv0Bpa07U6cPKol6fd3w9KjMPZ6Z4= github.com/filecoin-project/specs-actors v0.9.12/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= github.com/filecoin-project/specs-actors v0.9.13/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= @@ -395,6 +407,8 @@ github.com/filecoin-project/specs-actors/v6 v6.0.1 h1:laxvHNsvrq83Y9n+W7znVCePi3 github.com/filecoin-project/specs-actors/v6 v6.0.1/go.mod h1:V1AYfi5GkHXipx1mnVivoICZh3wtwPxDVuds+fbfQtk= github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506 h1:Ur/l2+6qN+lQiqjozWWc5p9UDaAMDZKTlDS98oRnlIw= github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506/go.mod h1:nJRRM7Aa9XVvygr3W9k6xGF46RWzr2zxF/iGoAIfA/g= +github.com/filecoin-project/storetheindex v0.0.0-20211019180831-2704585e5f99 h1:qdlA/LrP6UeYFkyXdZzzQaaUNvKXjRIP5j86peIzgvI= +github.com/filecoin-project/storetheindex v0.0.0-20211019180831-2704585e5f99/go.mod h1:IwKNyPe59SXmss9mKhx2GzkJXTBSmSjl1FiQTwFdsus= github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg= github.com/filecoin-project/test-vectors/schema v0.0.5/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= @@ -407,11 +421,15 @@ github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiD github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goblin v0.0.0-20210519012713-85d372ac71e2/go.mod h1:VzmDKDJVZI3aJmnRI9VjAn9nJ8qPPsN1fqzr9dqInIo= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= -github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= +github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss= +github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/gammazero/keymutex v0.0.2/go.mod h1:qtzWCCLMisQUmVa4dvqHVgwfh4BP2YB7JxNDGXnsKrs= +github.com/gammazero/radixtree v0.2.5 h1:muPQ4eEgCkUymFWPiVQRuXOQv4IhWg8YXH2r71MoqPM= +github.com/gammazero/radixtree v0.2.5/go.mod h1:VPqqCDZ3YZZxAzUUsIF/ytFBigVWV7JIV1Stld8hri0= github.com/gbrlsnchs/jwt/v3 v3.0.1 h1:lbUmgAKpxnClrKloyIwpxm4OuWeDl5wLk52G91ODPw4= github.com/gbrlsnchs/jwt/v3 v3.0.1/go.mod h1:AncDcjXz18xetI3A6STfXq2w+LuTx8pQ8bGEwRN8zVM= github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= @@ -673,8 +691,9 @@ github.com/ipfs/go-bitswap v0.0.9/go.mod h1:kAPf5qgn2W2DrgAcscZ3HrM9qh4pH+X8Fkk3 github.com/ipfs/go-bitswap v0.1.0/go.mod h1:FFJEf18E9izuCqUtHxbWEvq+reg7o4CW5wSAE1wsxj0= github.com/ipfs/go-bitswap v0.1.2/go.mod h1:qxSWS4NXGs7jQ6zQvoPY3+NmOfHHG47mhkiLzBpJQIs= github.com/ipfs/go-bitswap v0.1.8/go.mod h1:TOWoxllhccevbWFUR2N7B1MTSVVge1s6XSMiCSA4MzM= -github.com/ipfs/go-bitswap v0.3.4 h1:AhJhRrG8xkxh6x87b4wWs+4U4y3DVB3doI8yFNqgQME= github.com/ipfs/go-bitswap v0.3.4/go.mod h1:4T7fvNv/LmOys+21tnLzGKncMeeXUYUd1nUiJ2teMvI= +github.com/ipfs/go-bitswap v0.4.0 h1:bLiqrpef1na4wdqGLqHKv954s1zz6KFghfmQWCPjBik= +github.com/ipfs/go-bitswap v0.4.0/go.mod h1:J2sAsp9UKxLgHDektSy3y3Q9OfQjM9sjhKBR1dlwrMg= github.com/ipfs/go-block-format v0.0.1/go.mod h1:DK/YYcsSUIVAFNwo/KZCdIIbpN0ROH/baNLgayt4pFc= github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY= github.com/ipfs/go-block-format v0.0.3 h1:r8t66QstRp/pd/or4dpnbVfXT5Gt7lOqRvC+/dDTpMc= @@ -683,6 +702,7 @@ github.com/ipfs/go-blockservice v0.0.7/go.mod h1:EOfb9k/Y878ZTRY/CH0x5+ATtaipfbR github.com/ipfs/go-blockservice v0.1.0/go.mod h1:hzmMScl1kXHg3M2BjTymbVPjv627N7sYcvYaKbop39M= github.com/ipfs/go-blockservice v0.1.3/go.mod h1:OTZhFpkgY48kNzbgyvcexW9cHrpjBYIjSR0KoDOFOLU= github.com/ipfs/go-blockservice v0.1.4-0.20200624145336-a978cec6e834/go.mod h1:OTZhFpkgY48kNzbgyvcexW9cHrpjBYIjSR0KoDOFOLU= +github.com/ipfs/go-blockservice v0.1.4/go.mod h1:OTZhFpkgY48kNzbgyvcexW9cHrpjBYIjSR0KoDOFOLU= github.com/ipfs/go-blockservice v0.1.5/go.mod h1:yLk8lBJCBRWRqerqCSVi3cE/Dncdt3vGC/PJMVKhLTY= github.com/ipfs/go-blockservice v0.1.7 h1:yVe9te0M7ow8i+PPkx03YFSpxqzXx594d6h+34D6qMg= github.com/ipfs/go-blockservice v0.1.7/go.mod h1:GmS+BAt4hrwBKkzE11AFDQUrnvqjwFatGS2MY7wOjEM= @@ -742,6 +762,8 @@ github.com/ipfs/go-fs-lock v0.0.6/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28 github.com/ipfs/go-graphsync v0.1.0/go.mod h1:jMXfqIEDFukLPZHqDPp8tJMbHO9Rmeb9CEGevngQbmE= github.com/ipfs/go-graphsync v0.4.2/go.mod h1:/VmbZTUdUMTbNkgzAiCEucIIAU3BkLE2cZrDCVUhyi0= github.com/ipfs/go-graphsync v0.4.3/go.mod h1:mPOwDYv128gf8gxPFgXnz4fNrSYPsWyqisJ7ych+XDY= +github.com/ipfs/go-graphsync v0.9.1/go.mod h1:J62ahWT9JbPsFL2UWsUM5rOu0lZJ0LOIH1chHdxGGcw= +github.com/ipfs/go-graphsync v0.9.3/go.mod h1:J62ahWT9JbPsFL2UWsUM5rOu0lZJ0LOIH1chHdxGGcw= github.com/ipfs/go-graphsync v0.10.0/go.mod h1:cKIshzTaa5rCZjryH5xmSKZVGX9uk1wvwGvz2WEha5Y= github.com/ipfs/go-graphsync v0.10.4 h1:1WZhyOPxgxLvHTIC2GoLltaBrjZ+JuXC2oKAEiX8f3Y= github.com/ipfs/go-graphsync v0.10.4/go.mod h1:oei4tnWAKnZ6LPnapZGPYVVbyiKV1UP3f8BeLU7Z4JQ= @@ -753,6 +775,7 @@ github.com/ipfs/go-ipfs-blockstore v0.1.6/go.mod h1:Jxm3XMVjh6R17WvxFEiyKBLUGr86 github.com/ipfs/go-ipfs-blockstore v1.0.0/go.mod h1:knLVdhVU9L7CC4T+T4nvGdeUIPAXlnd9zmXfp+9MIjU= github.com/ipfs/go-ipfs-blockstore v1.0.1/go.mod h1:MGNZlHNEnR4KGgPHM3/k8lBySIOK2Ve+0KjZubKlaOE= github.com/ipfs/go-ipfs-blockstore v1.0.3/go.mod h1:MGNZlHNEnR4KGgPHM3/k8lBySIOK2Ve+0KjZubKlaOE= +github.com/ipfs/go-ipfs-blockstore v1.0.4-0.20210205083733-fb07d7bc5aec/go.mod h1:feuklK+m9POeWJzYQO7l05yNEgUiX5oELBNA8/Be33E= github.com/ipfs/go-ipfs-blockstore v1.0.4 h1:DZdeya9Vu4ttvlGheQPGrj6kWehXnYZRFCp9EsZQ1hI= github.com/ipfs/go-ipfs-blockstore v1.0.4/go.mod h1:uL7/gTJ8QIZ3MtA3dWf+s1a0U3fJy2fcEZAsovpRp+w= github.com/ipfs/go-ipfs-blocksutil v0.0.1 h1:Eh/H4pc1hsvhzsQoMEP3Bke/aW5P5rVM1IWFJMcGIPQ= @@ -831,6 +854,7 @@ github.com/ipfs/go-merkledag v0.2.3/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB github.com/ipfs/go-merkledag v0.2.4/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= github.com/ipfs/go-merkledag v0.3.1/go.mod h1:fvkZNNZixVW6cKSZ/JfLlON5OlgTXNdRLz0p6QG/I2M= github.com/ipfs/go-merkledag v0.3.2/go.mod h1:fvkZNNZixVW6cKSZ/JfLlON5OlgTXNdRLz0p6QG/I2M= +github.com/ipfs/go-merkledag v0.4.0/go.mod h1:XshXBkhyeS63YNGisLL1uDSfuTyrQIxVUOg3ojR5MOE= github.com/ipfs/go-merkledag v0.4.1 h1:CEEQZnwRkszN06oezuasHwDD823Xcr4p4zluUN9vXqs= github.com/ipfs/go-merkledag v0.4.1/go.mod h1:56biPaS6e+IS0eXkEt6A8tG+BUQaEIFqDqJuFfQDBoE= github.com/ipfs/go-metrics-interface v0.0.1 h1:j+cpbjYvu4R8zbleSs36gvB7jR+wsL2fGD6n0jO4kdg= @@ -843,6 +867,7 @@ github.com/ipfs/go-peertaskqueue v0.0.4/go.mod h1:03H8fhyeMfKNFWqzYEVyMbcPUeYrqP github.com/ipfs/go-peertaskqueue v0.1.0/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= github.com/ipfs/go-peertaskqueue v0.1.1/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= github.com/ipfs/go-peertaskqueue v0.2.0/go.mod h1:5/eNrBEbtSKWCG+kQK8K8fGNixoYUnr+P7jivavs9lY= +github.com/ipfs/go-peertaskqueue v0.4.0/go.mod h1:KL9F49hXJMoXCad8e5anivjN+kWdr+CyGcyh4K6doLc= github.com/ipfs/go-peertaskqueue v0.6.0 h1:BT1/PuNViVomiz1PnnP5+WmKsTNHrxIDvkZrkj4JhOg= github.com/ipfs/go-peertaskqueue v0.6.0/go.mod h1:M/akTIE/z1jGNXMU7kFB4TeSEFvj68ow0Rrb04donIU= github.com/ipfs/go-todocounter v0.0.1/go.mod h1:l5aErvQc8qKE2r7NDMjmq5UNAvuZy0rC8BHOplkWvZ4= @@ -861,12 +886,14 @@ github.com/ipfs/iptb-plugins v0.3.0/go.mod h1:5QtOvckeIw4bY86gSH4fgh3p3gCSMn3FmI github.com/ipld/go-car v0.1.0/go.mod h1:RCWzaUh2i4mOEkB3W45Vc+9jnS/M6Qay5ooytiBHl3g= github.com/ipld/go-car v0.1.1-0.20200923150018-8cdef32e2da4/go.mod h1:xrMEcuSq+D1vEwl+YAXsg/JfA98XGpXDwnkIL4Aimqw= github.com/ipld/go-car v0.1.1-0.20201119040415-11b6074b6d4d/go.mod h1:2Gys8L8MJ6zkh1gktTSXreY63t4UbyvNp5JaudTyxHQ= -github.com/ipld/go-car v0.3.2-0.20211001225732-32d0d9933823 h1:8JMSJ0k71fU9lIUrpVwEdoX4KoxiTEX8cZG97v/hTDw= github.com/ipld/go-car v0.3.2-0.20211001225732-32d0d9933823/go.mod h1:jSlTph+i/q1jLFoiKKeN69KGG0fXpwrcD0izu5C1Tpo= +github.com/ipld/go-car v0.3.2 h1:V9wt/80FNfbMRWSD98W5br6fyjUAyVgI2lDOTZX16Lg= +github.com/ipld/go-car v0.3.2/go.mod h1:WEjynkVt04dr0GwJhry0KlaTeSDEiEYyMPOxDBQ17KE= github.com/ipld/go-car/v2 v2.0.0-beta1.0.20210721090610-5a9d1b217d25/go.mod h1:I2ACeeg6XNBe5pdh5TaR7Ambhfa7If9KXxmXgZsYENU= github.com/ipld/go-car/v2 v2.0.2/go.mod h1:I2ACeeg6XNBe5pdh5TaR7Ambhfa7If9KXxmXgZsYENU= -github.com/ipld/go-car/v2 v2.0.3-0.20210910134712-2d2568297f26 h1:IBXjeOANJGYZVJ9jsvf0Tu+ANQ9FLstscJgzfJgwA8c= -github.com/ipld/go-car/v2 v2.0.3-0.20210910134712-2d2568297f26/go.mod h1:bBmZNBj4jfOHrd4Cu/koFhqwsCnZ5RrGXU1wwWqDr20= +github.com/ipld/go-car/v2 v2.0.3-0.20210920144420-f35d88ce16ca/go.mod h1:Xr6GwkDhv8dtOtgHzOynAkIOg0t0YiPc5DxBPppWqZA= +github.com/ipld/go-car/v2 v2.1.0 h1:t8R/WXUSkfu1K1gpPk76mytCxsEdMjGcMIgpOq3/Cnw= +github.com/ipld/go-car/v2 v2.1.0/go.mod h1:Xr6GwkDhv8dtOtgHzOynAkIOg0t0YiPc5DxBPppWqZA= github.com/ipld/go-codec-dagpb v1.2.0/go.mod h1:6nBN7X7h8EOsEejZGqC7tej5drsdBAXbMHyBT+Fne5s= github.com/ipld/go-codec-dagpb v1.3.0 h1:czTcaoAuNNyIYWs6Qe01DJ+sEX7B+1Z0LcXjSatMGe8= github.com/ipld/go-codec-dagpb v1.3.0/go.mod h1:ga4JTU3abYApDC3pZ00BC2RSvC3qfBb9MSJkMLSwnhA= @@ -878,15 +905,18 @@ github.com/ipld/go-ipld-prime v0.9.0/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/j github.com/ipld/go-ipld-prime v0.9.1-0.20210324083106-dc342a9917db/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= github.com/ipld/go-ipld-prime v0.10.0/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= github.com/ipld/go-ipld-prime v0.11.0/go.mod h1:+WIAkokurHmZ/KwzDOMUuoeJgaRQktHtEaLglS3ZeV8= +github.com/ipld/go-ipld-prime v0.12.0/go.mod h1:hy8b93WleDMRKumOJnTIrr0MbbFbx9GD6Kzxa53Xppc= github.com/ipld/go-ipld-prime v0.12.3-0.20210930132912-0b3aef3ca569/go.mod h1:PaeLYq8k6dJLmDUSLrzkEpoGV4PEfe/1OtFN/eALOc8= -github.com/ipld/go-ipld-prime v0.12.3 h1:furVobw7UBLQZwlEwfE26tYORy3PAK8VYSgZOSr3JMQ= github.com/ipld/go-ipld-prime v0.12.3/go.mod h1:PaeLYq8k6dJLmDUSLrzkEpoGV4PEfe/1OtFN/eALOc8= +github.com/ipld/go-ipld-prime v0.14.0 h1:2FnBqUjmmgxgZD6/zB3eygWlmIsHNGrZ57L99x3xD6Q= +github.com/ipld/go-ipld-prime v0.14.0/go.mod h1:9ASQLwUFLptCov6lIYc70GRB4V7UTyLD0IJtrDJe6ZM= github.com/ipld/go-ipld-prime-proto v0.0.0-20191113031812-e32bd156a1e5/go.mod h1:gcvzoEDBjwycpXt3LBE061wT9f46szXGHAmj9uoP6fU= github.com/ipld/go-ipld-prime-proto v0.0.0-20200428191222-c1ffdadc01e1/go.mod h1:OAV6xBmuTLsPZ+epzKkPB1e25FHk/vCtyatkdHcArLs= github.com/ipld/go-ipld-prime-proto v0.0.0-20200922192210-9a2bfd4440a6/go.mod h1:3pHYooM9Ea65jewRwrb2u5uHZCNkNTe9ABsVB+SrkH0= github.com/ipld/go-ipld-prime-proto v0.1.0/go.mod h1:11zp8f3sHVgIqtb/c9Kr5ZGqpnCLF1IVTNOez9TopzE= github.com/ipld/go-ipld-selector-text-lite v0.0.0 h1:MLU1YUAgd3Z+RfVCXUbvxH1RQjEe+larJ9jmlW1aMgA= github.com/ipld/go-ipld-selector-text-lite v0.0.0/go.mod h1:U2CQmFb+uWzfIEF3I1arrDa5rwtj00PrpiwwCO+k1RM= +github.com/ipld/go-storethehash v0.0.0-20210915160027-d72ca9b0968c/go.mod h1:PwE6iq8TiWJRI3zMGA1RtkFAnrDMK93dLA5SUeu0lH8= github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52 h1:QG4CGBqCeuBo6aZlGAamSkxWdgWfZGeE49eUOWJPA4c= github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52/go.mod h1:fdg+/X9Gg4AsAIzWpEHwnqd+QY3b7lajxyjE1m4hkq4= github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= @@ -972,8 +1002,9 @@ github.com/koron/go-ssdp v0.0.2/go.mod h1:XoLfkAiA2KeZsYh4DbHxD7h3nR2AZNqVQOa+LJ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= @@ -1017,6 +1048,7 @@ github.com/libp2p/go-libp2p v0.9.2/go.mod h1:cunHNLDVus66Ct9iXXcjKRLdmHdFdHVe1TA github.com/libp2p/go-libp2p v0.10.0/go.mod h1:yBJNpb+mGJdgrwbKAKrhPU0u3ogyNFTfjJ6bdM+Q/G8= github.com/libp2p/go-libp2p v0.13.0/go.mod h1:pM0beYdACRfHO1WcJlp65WXyG2A6NqYM+t2DTVAJxMo= github.com/libp2p/go-libp2p v0.14.0/go.mod h1:dsQrWLAoIn+GkHPN/U+yypizkHiB9tnv79Os+kSgQ4Q= +github.com/libp2p/go-libp2p v0.14.3/go.mod h1:d12V4PdKbpL0T1/gsUNN8DfgMuRPDX8bS2QxCZlwRH0= github.com/libp2p/go-libp2p v0.14.4/go.mod h1:EIRU0Of4J5S8rkockZM7eJp2S0UrCyi55m2kJVru3rM= github.com/libp2p/go-libp2p v0.15.0 h1:jbMbdmtizfpvl1+oQuGJzfGhttAtuxUCavF3enwFncg= github.com/libp2p/go-libp2p v0.15.0/go.mod h1:8Ljmwon0cZZYKrOCjFeLwQEK8bqR42dOheUZ1kSKhP0= @@ -1159,13 +1191,15 @@ github.com/libp2p/go-libp2p-protocol v0.0.1/go.mod h1:Af9n4PiruirSDjHycM1QuiMi/1 github.com/libp2p/go-libp2p-protocol v0.1.0/go.mod h1:KQPHpAabB57XQxGrXCNvbL6UEXfQqUgC/1adR2Xtflk= github.com/libp2p/go-libp2p-pubsub v0.1.1/go.mod h1:ZwlKzRSe1eGvSIdU5bD7+8RZN/Uzw0t1Bp9R1znpR/Q= github.com/libp2p/go-libp2p-pubsub v0.3.2-0.20200527132641-c0712c6e92cf/go.mod h1:TxPOBuo1FPdsTjFnv+FGZbNbWYsp74Culx+4ViQpato= +github.com/libp2p/go-libp2p-pubsub v0.5.4/go.mod h1:gVOzwebXVdSMDQBTfH8ACO5EJ4SQrvsHqCmYsCZpD0E= github.com/libp2p/go-libp2p-pubsub v0.5.6 h1:YkO3gG9J1mQBEMRrM5obiG3JD0L8RcrzIpoeLeiYqH8= github.com/libp2p/go-libp2p-pubsub v0.5.6/go.mod h1:gVOzwebXVdSMDQBTfH8ACO5EJ4SQrvsHqCmYsCZpD0E= github.com/libp2p/go-libp2p-quic-transport v0.1.1/go.mod h1:wqG/jzhF3Pu2NrhJEvE+IE0NTHNXslOPn9JQzyCAxzU= github.com/libp2p/go-libp2p-quic-transport v0.5.0/go.mod h1:IEcuC5MLxvZ5KuHKjRu+dr3LjCT1Be3rcD/4d8JrX8M= github.com/libp2p/go-libp2p-quic-transport v0.10.0/go.mod h1:RfJbZ8IqXIhxBRm5hqUEJqjiiY8xmEuq3HUDS993MkA= -github.com/libp2p/go-libp2p-quic-transport v0.11.2 h1:p1YQDZRHH4Cv2LPtHubqlQ9ggz4CKng/REZuXZbZMhM= github.com/libp2p/go-libp2p-quic-transport v0.11.2/go.mod h1:wlanzKtIh6pHrq+0U3p3DY9PJfGqxMgPaGKaK5LifwQ= +github.com/libp2p/go-libp2p-quic-transport v0.12.0 h1:7IjDH4XNkmJbOMD+mxRloTe4LzMTq+vqvm2nYNL1N7M= +github.com/libp2p/go-libp2p-quic-transport v0.12.0/go.mod h1:EKHqxZbWE/FhDJZ6ebyZ/4v3X9zyuuuKIN0XR9vANT0= github.com/libp2p/go-libp2p-record v0.0.1/go.mod h1:grzqg263Rug/sRex85QrDOLntdFAymLDLm7lxMgU79Q= github.com/libp2p/go-libp2p-record v0.1.0/go.mod h1:ujNc8iuE5dlKWVy6wuL6dd58t0n7xI4hAIl8pE6wu5Q= github.com/libp2p/go-libp2p-record v0.1.1/go.mod h1:VRgKajOyMVgP/F0L5g3kH7SVskp17vFi2xheb5uMJtg= @@ -1290,6 +1324,7 @@ github.com/libp2p/go-tcp-transport v0.1.0/go.mod h1:oJ8I5VXryj493DEJ7OsBieu8fcg2 github.com/libp2p/go-tcp-transport v0.1.1/go.mod h1:3HzGvLbx6etZjnFlERyakbaYPdfjg2pWP97dFZworkY= github.com/libp2p/go-tcp-transport v0.2.0/go.mod h1:vX2U0CnWimU4h0SGSEsg++AzvBcroCGYw28kh94oLe0= github.com/libp2p/go-tcp-transport v0.2.1/go.mod h1:zskiJ70MEfWz2MKxvFB/Pv+tPIB1PpPUrHIWQ8aFw7M= +github.com/libp2p/go-tcp-transport v0.2.3/go.mod h1:9dvr03yqrPyYGIEN6Dy5UvdJZjyPFvl1S/igQ5QD1SU= github.com/libp2p/go-tcp-transport v0.2.4/go.mod h1:9dvr03yqrPyYGIEN6Dy5UvdJZjyPFvl1S/igQ5QD1SU= github.com/libp2p/go-tcp-transport v0.2.7/go.mod h1:lue9p1b3VmZj1MhhEGB/etmvF/nBQ0X9CW2DutBT3MM= github.com/libp2p/go-tcp-transport v0.2.8 h1:aLjX+Nkz+kIz3uA56WtlGKRSAnKDvnqKmv1qF4EyyE4= @@ -1326,8 +1361,9 @@ github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0U github.com/lucas-clemente/quic-go v0.11.2/go.mod h1:PpMmPfPKO9nKJ/psF49ESTAGQSdfXxlg1otPbEB2nOw= github.com/lucas-clemente/quic-go v0.16.0/go.mod h1:I0+fcNTdb9eS1ZcjQZbDVPGchJ86chcIxPALn9lEJqE= github.com/lucas-clemente/quic-go v0.19.3/go.mod h1:ADXpNbTQjq1hIzCpB+y/k5iz4n4z4IwqoLb94Kh5Hu8= -github.com/lucas-clemente/quic-go v0.21.2 h1:8LqqL7nBQFDUINadW0fHV/xSaCQJgmJC0Gv+qUnjd78= github.com/lucas-clemente/quic-go v0.21.2/go.mod h1:vF5M1XqhBAHgbjKcJOXY3JZz3GP0T3FQhz/uyOUS38Q= +github.com/lucas-clemente/quic-go v0.23.0 h1:5vFnKtZ6nHDFsc/F3uuiF4T3y/AXaQdxjUqiVw26GZE= +github.com/lucas-clemente/quic-go v0.23.0/go.mod h1:paZuzjXCE5mj6sikVLMvqXk8lJV2AsqtJ6bDhjEfxx0= github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac= github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lufia/iostat v1.1.0/go.mod h1:rEPNA0xXgjHQjuI5Cy05sLlS2oRcSlWHRLrvh/AQ+Pg= @@ -1350,12 +1386,12 @@ github.com/marten-seemann/qtls v0.9.1/go.mod h1:T1MmAdDPyISzxlK6kjRr0pcZFBVd1OZb github.com/marten-seemann/qtls v0.10.0/go.mod h1:UvMd1oaYDACI99/oZUYLzMCkBXQVT0aGm99sJhbT8hs= github.com/marten-seemann/qtls-go1-15 v0.1.1/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= github.com/marten-seemann/qtls-go1-15 v0.1.4/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= -github.com/marten-seemann/qtls-go1-15 v0.1.5 h1:Ci4EIUN6Rlb+D6GmLdej/bCQ4nPYNtVXQB+xjiXE1nk= github.com/marten-seemann/qtls-go1-15 v0.1.5/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= github.com/marten-seemann/qtls-go1-16 v0.1.4 h1:xbHbOGGhrenVtII6Co8akhLEdrawwB2iHl5yhJRpnco= github.com/marten-seemann/qtls-go1-16 v0.1.4/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk= -github.com/marten-seemann/qtls-go1-17 v0.1.0-rc.1 h1:/rpmWuGvceLwwWuaKPdjpR4JJEUH0tq64/I3hvzaNLM= github.com/marten-seemann/qtls-go1-17 v0.1.0-rc.1/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8= +github.com/marten-seemann/qtls-go1-17 v0.1.0 h1:P9ggrs5xtwiqXv/FHNwntmuLMNq3KaSIG93AtAZ48xk= +github.com/marten-seemann/qtls-go1-17 v0.1.0/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8= github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -1493,8 +1529,9 @@ github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpK github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= github.com/multiformats/go-multihash v0.0.14/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= github.com/multiformats/go-multihash v0.0.15/go.mod h1:D6aZrWNLFTV/ynMpKsNtB40mJzmCl4jb1alC0OvHiHg= -github.com/multiformats/go-multihash v0.0.16 h1:D2qsyy1WVculJbGv69pWmQ36ehxFoA5NiIUr1OEs6qI= github.com/multiformats/go-multihash v0.0.16/go.mod h1:zhfEIgVnB/rPMfxgFw15ZmGoNaKyNUIE4IWHG/kC+Ag= +github.com/multiformats/go-multihash v0.1.0 h1:CgAgwqk3//SVEw3T+6DqI4mWMyRuDwZtOWcJT0q9+EA= +github.com/multiformats/go-multihash v0.1.0/go.mod h1:RJlXsxt6vHGaia+S8We0ErjhojtKzPP2AH4+kYM7k84= github.com/multiformats/go-multistream v0.0.1/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= github.com/multiformats/go-multistream v0.0.4/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= @@ -1590,6 +1627,7 @@ github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 h1:1/WtZae0yGtPq+TI6+ github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9/go.mod h1:x3N5drFsm2uilKKuuYo6LdyD8vZAW55sH/9w+pbo1sw= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -1671,6 +1709,9 @@ github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= @@ -1866,6 +1907,7 @@ github.com/xorcare/golden v0.6.0/go.mod h1:7T39/ZMvaSEZlBPoYfVFmsBLmUl3uz9IuzWj/ github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542 h1:oWgZJmC1DorFZDpfMfWg7xk29yEOZiXmo/wZl+utTI8= github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542/go.mod h1:7T39/ZMvaSEZlBPoYfVFmsBLmUl3uz9IuzWj/U6FtvQ= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/ybbus/jsonrpc/v2 v2.1.6/go.mod h1:rIuG1+ORoiqocf9xs/v+ecaAVeo3zcZHQgInyKFMeg0= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -2025,6 +2067,7 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= @@ -2486,6 +2529,8 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= howett.net/plist v0.0.0-20181124034731-591f970eefbb h1:jhnBjNi9UFpfpl8YZhA9CrOqpnJdvzuiHsl/dnxl11M= howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0= +lukechampine.com/blake3 v1.1.6 h1:H3cROdztr7RCfoaTpGZFQsrqvweFLrqS73j7L7cmR5c= +lukechampine.com/blake3 v1.1.6/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA= modernc.org/cc v1.0.0 h1:nPibNuDEx6tvYrUAtvDTTw98rx5juGsa5zuDnKwEEQQ= modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= modernc.org/fileutil v1.0.0/go.mod h1:JHsWpkrk/CnVV1H/eGlFf85BEpfkrp56ro8nojIq9Q8= diff --git a/itests/deals_concurrent_test.go b/itests/deals_concurrent_test.go index c0458e8d1dd..6507a5f27e4 100644 --- a/itests/deals_concurrent_test.go +++ b/itests/deals_concurrent_test.go @@ -7,13 +7,15 @@ import ( "testing" "time" - "github.com/filecoin-project/lotus/chain/actors/policy" "github.com/stretchr/testify/require" datatransfer "github.com/filecoin-project/go-data-transfer" + "github.com/filecoin-project/go-fil-markets/shared_testutil" "github.com/filecoin-project/go-state-types/abi" + provider "github.com/filecoin-project/index-provider" "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/itests/kit" "github.com/filecoin-project/lotus/node" "github.com/filecoin-project/lotus/node/modules" @@ -46,15 +48,18 @@ func TestDealWithMarketAndMinerNode(t *testing.T) { runTest := func(t *testing.T, n int, fastRetrieval bool, carExport bool) { api.RunningNodeType = api.NodeMiner // TODO(anteva): fix me - client, main, market, _ := kit.EnsembleWithMinerAndMarketNodes(t, kit.ThroughRPC()) + idxProv := shared_testutil.NewMockIndexProvider() + idxProvOpt := kit.ConstructorOpts(node.Override(new(provider.Interface), idxProv)) + client, main, market, _ := kit.EnsembleWithMinerAndMarketNodes(t, kit.ThroughRPC(), idxProvOpt) dh := kit.NewDealHarness(t, client, main, market) dh.RunConcurrentDeals(kit.RunConcurrentDealsOpts{ - N: n, - FastRetrieval: fastRetrieval, - CarExport: carExport, - StartEpoch: startEpoch, + N: n, + FastRetrieval: fastRetrieval, + CarExport: carExport, + StartEpoch: startEpoch, + IndexerProvider: idxProv, }) } diff --git a/itests/kit/deals.go b/itests/kit/deals.go index c96d18acfb5..09527525f11 100644 --- a/itests/kit/deals.go +++ b/itests/kit/deals.go @@ -10,6 +10,7 @@ import ( "testing" "time" + "github.com/filecoin-project/go-fil-markets/shared_testutil" "github.com/filecoin-project/go-fil-markets/storagemarket" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/lotus/api" @@ -374,6 +375,7 @@ type RunConcurrentDealsOpts struct { CarExport bool StartEpoch abi.ChainEpoch UseCARFileForStorageDeal bool + IndexerProvider *shared_testutil.MockIndexProvider } func (dh *DealHarness) RunConcurrentDeals(opts RunConcurrentDealsOpts) { @@ -400,6 +402,13 @@ func (dh *DealHarness) RunConcurrentDeals(opts RunConcurrentDealsOpts) { UseCARFileForStorageDeal: opts.UseCARFileForStorageDeal, }) + // Check that the storage provider announced the deal to indexers + if opts.IndexerProvider != nil { + notifs := opts.IndexerProvider.GetNotifs() + _, ok := notifs[string(deal.Bytes())] + require.True(dh.t, ok) + } + dh.t.Logf("retrieving deal %d/%d", i, opts.N) outPath := dh.PerformRetrieval(context.Background(), deal, res.Root, opts.CarExport) diff --git a/markets/dagstore/wrapper.go b/markets/dagstore/wrapper.go index 6a32c011aae..2fcb54382bb 100644 --- a/markets/dagstore/wrapper.go +++ b/markets/dagstore/wrapper.go @@ -15,6 +15,7 @@ import ( levelds "github.com/ipfs/go-ds-leveldb" measure "github.com/ipfs/go-ds-measure" logging "github.com/ipfs/go-log/v2" + carindex "github.com/ipld/go-car/v2/index" ldbopts "github.com/syndtr/goleveldb/leveldb/opt" "golang.org/x/xerrors" @@ -402,7 +403,7 @@ func (w *Wrapper) markRegistrationComplete() error { // Get all the pieces that contain a block func (w *Wrapper) GetPiecesContainingBlock(blockCID cid.Cid) ([]cid.Cid, error) { // Pieces are stored as "shards" in the DAG store - shardKeys, err := w.dagst.GetShardKeysForCid(blockCID) + shardKeys, err := w.dagst.ShardsContainingMultihash(blockCID.Hash()) if err != nil { return nil, xerrors.Errorf("getting pieces containing block %s: %w", blockCID, err) } @@ -422,6 +423,10 @@ func (w *Wrapper) GetPiecesContainingBlock(blockCID cid.Cid) ([]cid.Cid, error) return pieceCids, nil } +func (w *Wrapper) GetIterableIndexForPiece(pieceCid cid.Cid) (carindex.IterableIndex, error) { + return w.dagst.GetIterableIndex(shard.KeyFromCID(pieceCid)) +} + func (w *Wrapper) Close() error { // Cancel the context w.cancel() diff --git a/node/builder_miner.go b/node/builder_miner.go index 3447eb3e6dc..aeb12eb9a13 100644 --- a/node/builder_miner.go +++ b/node/builder_miner.go @@ -12,6 +12,7 @@ import ( "github.com/filecoin-project/go-fil-markets/storagemarket" "github.com/filecoin-project/go-fil-markets/storagemarket/impl/storedask" "github.com/filecoin-project/go-state-types/abi" + provider "github.com/filecoin-project/index-provider" storage2 "github.com/filecoin-project/specs-storage/storage" "github.com/filecoin-project/lotus/api" @@ -163,6 +164,7 @@ func ConfigStorageMiner(c interface{}) Option { Override(HandleRetrievalKey, modules.HandleRetrieval), // Markets (storage) + Override(new(provider.Interface), modules.IndexerProvider(cfg.IndexerProvider)), Override(new(dtypes.ProviderDataTransfer), modules.NewProviderDAGServiceDataTransfer), Override(new(*storedask.StoredAsk), modules.NewStorageAsk), Override(new(dtypes.StorageDealFilter), modules.BasicDealFilter(cfg.Dealmaking, nil)), diff --git a/node/config/def.go b/node/config/def.go index 735107e2940..6c518d20930 100644 --- a/node/config/def.go +++ b/node/config/def.go @@ -176,6 +176,15 @@ func DefaultStorageMiner() *StorageMiner { }, }, + IndexerProvider: IndexerProviderConfig{ + ListenAddresses: []string{ + "/ip4/0.0.0.0/tcp/0", + "/ip6/::/tcp/0", + }, + + MaxSimultaneousTransfers: DefaultSimultaneousTransfers, + }, + Subsystems: MinerSubsystemConfig{ EnableMining: true, EnableSealing: true, diff --git a/node/config/types.go b/node/config/types.go index 1be40029e17..44c40e30654 100644 --- a/node/config/types.go +++ b/node/config/types.go @@ -3,6 +3,8 @@ package config import ( "github.com/ipfs/go-cid" + "github.com/filecoin-project/index-provider/config" + "github.com/filecoin-project/lotus/chain/types" sectorstorage "github.com/filecoin-project/lotus/extern/sector-storage" ) @@ -43,13 +45,14 @@ type Backup struct { type StorageMiner struct { Common - Subsystems MinerSubsystemConfig - Dealmaking DealmakingConfig - Sealing SealingConfig - Storage sectorstorage.SealerConfig - Fees MinerFeeConfig - Addresses MinerAddressConfig - DAGStore DAGStoreConfig + Subsystems MinerSubsystemConfig + Dealmaking DealmakingConfig + IndexerProvider IndexerProviderConfig + Sealing SealingConfig + Storage sectorstorage.SealerConfig + Fees MinerFeeConfig + Addresses MinerAddressConfig + DAGStore DAGStoreConfig } type DAGStoreConfig struct { @@ -146,6 +149,18 @@ type DealmakingConfig struct { RetrievalPricing *RetrievalPricing } +type IndexerProviderConfig struct { + config.Ingest + + // Binding address for the libp2p host - 0 means random port. + // Format: multiaddress; see https://multiformats.io/multiaddr/ + ListenAddresses []string + + // The maximum number of simultaneous data transfers between the indexers + // and the indexer provider + MaxSimultaneousTransfers uint64 +} + type RetrievalPricing struct { Strategy string // possible values: "default", "external" diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index 1a2dfc19f94..3389c2beeda 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -34,6 +34,7 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-statestore" "github.com/filecoin-project/go-storedcounter" + provider "github.com/filecoin-project/index-provider" "github.com/ipfs/go-cid" "github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore/namespace" @@ -581,6 +582,7 @@ func StorageProvider(minerAddress dtypes.MinerAddress, h host.Host, ds dtypes.MetadataDS, r repo.LockedRepo, pieceStore dtypes.ProviderPieceStore, + indexer provider.Interface, dataTransfer dtypes.ProviderDataTransfer, spn storagemarket.StorageProviderNode, df dtypes.StorageDealFilter, @@ -609,6 +611,7 @@ func StorageProvider(minerAddress dtypes.MinerAddress, namespace.Wrap(ds, datastore.NewKey("/deals/provider")), store, dsw, + indexer, pieceStore, dataTransfer, spn, diff --git a/node/modules/storageminer_idxprov.go b/node/modules/storageminer_idxprov.go new file mode 100644 index 00000000000..7022823a8d9 --- /dev/null +++ b/node/modules/storageminer_idxprov.go @@ -0,0 +1,158 @@ +package modules + +import ( + "context" + "fmt" + "os" + "path/filepath" + + "golang.org/x/xerrors" + + "github.com/ipfs/go-datastore" + "github.com/ipfs/go-graphsync" + graphsyncimpl "github.com/ipfs/go-graphsync/impl" + gsnet "github.com/ipfs/go-graphsync/network" + cidlink "github.com/ipld/go-ipld-prime/linking/cid" + "github.com/libp2p/go-libp2p" + ci "github.com/libp2p/go-libp2p-core/crypto" + "github.com/libp2p/go-libp2p-core/peer" + "github.com/libp2p/go-libp2p-core/peerstore" + "go.uber.org/fx" + + datatransfer "github.com/filecoin-project/go-data-transfer" + dtimpl "github.com/filecoin-project/go-data-transfer/impl" + dtnet "github.com/filecoin-project/go-data-transfer/network" + dtgstransport "github.com/filecoin-project/go-data-transfer/transport/graphsync" + provider "github.com/filecoin-project/index-provider" + "github.com/filecoin-project/index-provider/engine" + p2pserver "github.com/filecoin-project/index-provider/server/provider/libp2p" + "github.com/ipfs/go-datastore/namespace" + "github.com/libp2p/go-libp2p-core/host" + + "github.com/filecoin-project/lotus/build" + marketevents "github.com/filecoin-project/lotus/markets/loggers" + "github.com/filecoin-project/lotus/node/config" + "github.com/filecoin-project/lotus/node/modules/dtypes" + "github.com/filecoin-project/lotus/node/modules/helpers" + "github.com/filecoin-project/lotus/node/repo" +) + +type IdxProv struct { + fx.In + + helpers.MetricsCtx + fx.Lifecycle + Repo repo.LockedRepo + Datastore dtypes.MetadataDS + PeerID peer.ID + peerstore.Peerstore +} + +func IndexerProvider(cfg config.IndexerProviderConfig) func(params IdxProv) (provider.Interface, error) { + return func(args IdxProv) (provider.Interface, error) { + ipds := namespace.Wrap(args.Datastore, datastore.NewKey("/indexer-provider")) + + pkey := args.Peerstore.PrivKey(args.PeerID) + if pkey == nil { + return nil, fmt.Errorf("missing private key for node ID: %s", args.PeerID.Pretty()) + } + + h, err := createIndexerProviderHost(args.MetricsCtx, args.Lifecycle, pkey, args.Peerstore, cfg.ListenAddresses) + if err != nil { + return nil, xerrors.Errorf("creating indexer provider host: %w", err) + } + + dt, err := newIndexerProviderDataTransfer(cfg, args.MetricsCtx, args.Lifecycle, args.Repo, h, ipds) + if err != nil { + return nil, err + } + + e, err := engine.New(cfg.Ingest, pkey, dt, h, ipds, nil) + if err != nil { + return nil, xerrors.Errorf("creating indexer provider engine: %w", err) + } + + args.Lifecycle.Append(fx.Hook{ + OnStart: func(ctx context.Context) error { + // Start the engine + err := e.Start(ctx) + if err != nil { + return xerrors.Errorf("starting indexer provider engine: %s", err) + } + + // Add a handler to libp2p that listens for incoming index requests + p2pserver.New(ctx, h, e) + + return nil + }, + OnStop: func(ctx context.Context) error { + return e.Shutdown(ctx) + }, + }) + + return e, nil + } +} + +func createIndexerProviderHost(mctx helpers.MetricsCtx, lc fx.Lifecycle, pkey ci.PrivKey, pstore peerstore.Peerstore, listenAddrs []string) (host.Host, error) { + ctx := helpers.LifecycleCtx(mctx, lc) + + opts := []libp2p.Option{ + libp2p.Identity(pkey), + libp2p.Peerstore(pstore), + libp2p.ListenAddrStrings(listenAddrs...), + libp2p.Ping(true), + libp2p.UserAgent("lotus-indexer-provider-" + build.UserVersion()), + } + + h, err := libp2p.New(ctx, opts...) + if err != nil { + return nil, err + } + + lc.Append(fx.Hook{ + OnStop: func(ctx context.Context) error { + return h.Close() + }, + }) + + return h, nil +} + +func newIndexerProviderDataTransfer(cfg config.IndexerProviderConfig, mctx helpers.MetricsCtx, lc fx.Lifecycle, r repo.LockedRepo, h host.Host, ds datastore.Batching) (datatransfer.Manager, error) { + net := dtnet.NewFromLibp2pHost(h) + + // Set up graphsync + gs := newIndexerProviderGraphsync(cfg, mctx, lc, h) + + // Set up data transfer + dtDs := namespace.Wrap(ds, datastore.NewKey("/datatransfer/transfers")) + transport := dtgstransport.NewTransport(h.ID(), gs, net) + dtPath := filepath.Join(r.Path(), "indexer-provider", "data-transfer") + err := os.MkdirAll(dtPath, 0755) //nolint: gosec + if err != nil && !os.IsExist(err) { + return nil, xerrors.Errorf("creating indexer provider data transfer dir %s: %w", dtPath, err) + } + + dt, err := dtimpl.NewDataTransfer(dtDs, dtPath, net, transport) + if err != nil { + return nil, xerrors.Errorf("creating indexer provider data transfer module: %w", err) + } + + dt.OnReady(marketevents.ReadyLogger("indexer-provider data transfer")) + lc.Append(fx.Hook{ + OnStart: dt.Start, + OnStop: dt.Stop, + }) + return dt, nil +} + +func newIndexerProviderGraphsync(cfg config.IndexerProviderConfig, mctx helpers.MetricsCtx, lc fx.Lifecycle, h host.Host) graphsync.GraphExchange { + graphsyncNetwork := gsnet.NewFromLibp2pHost(h) + return graphsyncimpl.New(helpers.LifecycleCtx(mctx, lc), + graphsyncNetwork, + cidlink.DefaultLinkSystem(), + graphsyncimpl.MaxInProgressIncomingRequests(cfg.MaxSimultaneousTransfers), + graphsyncimpl.MaxLinksPerIncomingRequests(config.MaxTraversalLinks), + graphsyncimpl.MaxLinksPerOutgoingRequests(config.MaxTraversalLinks)) +} From bfee6699d21d10a9fbfe880d12f70ede3de3a5bf Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Wed, 17 Nov 2021 11:42:14 +0400 Subject: [PATCH 012/385] update go mod and inject store the hash index in dagstore --- go.mod | 15 +++---- go.sum | 81 ++++++++++++++++++++++++++----------- itests/deals_anycid_test.go | 2 +- itests/kit/files.go | 2 +- markets/dagstore/wrapper.go | 20 ++++++++- node/impl/client/client.go | 4 +- 6 files changed, 88 insertions(+), 36 deletions(-) diff --git a/go.mod b/go.mod index 6d2c76d5421..8d71c36378d 100644 --- a/go.mod +++ b/go.mod @@ -26,17 +26,18 @@ require ( github.com/elastic/gosigar v0.14.1 github.com/etclabscore/go-openrpc-reflect v0.0.36 github.com/fatih/color v1.13.0 - github.com/filecoin-project/dagstore v0.4.4-0.20210915102524-cd372c4b14d5 + github.com/filecoin-project/dagstore v0.5.0 github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200910194244-f640612a1a1f github.com/filecoin-project/go-address v0.0.6 github.com/filecoin-project/go-bitfield v0.2.4 github.com/filecoin-project/go-cbor-util v0.0.1 github.com/filecoin-project/go-commp-utils v0.1.2 github.com/filecoin-project/go-crypto v0.0.1 - github.com/filecoin-project/go-data-transfer v1.11.4 + github.com/filecoin-project/go-data-transfer v1.11.6 github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 - github.com/filecoin-project/go-fil-markets v1.13.3 + github.com/filecoin-project/go-fil-markets v1.13.3-0.20211117072527-8713155662ff + github.com/filecoin-project/go-indexer-core v0.2.4 github.com/filecoin-project/go-jsonrpc v0.1.5 github.com/filecoin-project/go-padreader v0.0.1 github.com/filecoin-project/go-paramfetch v0.0.2 @@ -97,10 +98,10 @@ require ( github.com/ipfs/go-path v0.0.7 github.com/ipfs/go-unixfs v0.2.6 github.com/ipfs/interface-go-ipfs-core v0.4.0 - github.com/ipld/go-car v0.3.2-0.20211001225732-32d0d9933823 - github.com/ipld/go-car/v2 v2.0.3-0.20210910134712-2d2568297f26 + github.com/ipld/go-car v0.3.2 + github.com/ipld/go-car/v2 v2.1.0 github.com/ipld/go-codec-dagpb v1.3.0 - github.com/ipld/go-ipld-prime v0.12.3 + github.com/ipld/go-ipld-prime v0.14.0 github.com/ipld/go-ipld-selector-text-lite v0.0.0 github.com/kelseyhightower/envconfig v1.4.0 github.com/libp2p/go-buffer-pool v0.0.2 @@ -128,7 +129,7 @@ require ( github.com/multiformats/go-multiaddr v0.4.1 github.com/multiformats/go-multiaddr-dns v0.3.1 github.com/multiformats/go-multibase v0.0.3 - github.com/multiformats/go-multihash v0.0.16 + github.com/multiformats/go-multihash v0.1.0 github.com/multiformats/go-varint v0.0.6 github.com/open-rpc/meta-schema v0.0.0-20201029221707-1b72ef2ea333 github.com/opentracing/opentracing-go v1.2.0 diff --git a/go.sum b/go.sum index d12c2ae1da7..f6da54a9c4b 100644 --- a/go.sum +++ b/go.sum @@ -89,6 +89,7 @@ github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/akavel/rsrc v0.8.0 h1:zjWn7ukO9Kc5Q62DOJCcxGpXC18RawVtYAGdz2aLlfw= github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= +github.com/akrylysov/pogreb v0.10.1/go.mod h1:pNs6QmpQ1UlTJKDezuRWmaqkgUE2TuU0YTWyqJZ7+lI= github.com/alecthomas/jsonschema v0.0.0-20200530073317-71f438968921 h1:T3+cD5fYvuH36h7EZq+TDpm+d8a6FSD4pQsbmuGGQ8o= github.com/alecthomas/jsonschema v0.0.0-20200530073317-71f438968921/go.mod h1:/n6+1/DWPltRLWL/VKyUxg6tzsl5kHUCcraimt4vr60= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -301,9 +302,8 @@ github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/filecoin-project/dagstore v0.4.2/go.mod h1:WY5OoLfnwISCk6eASSF927KKPqLPIlTwmG1qHpA08KY= -github.com/filecoin-project/dagstore v0.4.4-0.20210915102524-cd372c4b14d5 h1:wtKBSxmV5ohSeZHS86TrLtw6m1dO88QaNo6az/QRrYU= -github.com/filecoin-project/dagstore v0.4.4-0.20210915102524-cd372c4b14d5/go.mod h1:dsWYxyEYa5aB62UXJcQhwlIaBOS+kkrKQgYGxwAnmkE= +github.com/filecoin-project/dagstore v0.5.0 h1:akiheGtSCU7aGon6T74bwNbDhYW0XZCTsnORKNmzSgU= +github.com/filecoin-project/dagstore v0.5.0/go.mod h1:Id2VG7uZxnF6NWR3JX1evNA83JonnU0U7Fc2r14Vltc= github.com/filecoin-project/go-address v0.0.3/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= github.com/filecoin-project/go-address v0.0.5/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= github.com/filecoin-project/go-address v0.0.6 h1:DWQtj38ax+ogHwyH3VULRIoT8E6loyXqsk/p81xoY7M= @@ -326,9 +326,12 @@ github.com/filecoin-project/go-commp-utils v0.1.2/go.mod h1:6s95K91mCyHY51RPWECZ github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= github.com/filecoin-project/go-crypto v0.0.1 h1:AcvpSGGCgjaY8y1az6AMfKQWreF/pWO2JJGLl6gCq6o= github.com/filecoin-project/go-crypto v0.0.1/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= +github.com/filecoin-project/go-dagaggregator-unixfs v0.2.0/go.mod h1:WTuJWgBQY0omnQqa8kRPT9O0Uj5wQOgslVMUuTeHdJ8= github.com/filecoin-project/go-data-transfer v1.0.1/go.mod h1:UxvfUAY9v3ub0a21BSK9u3pB2aq30Y0KMsG+w9/ysyo= -github.com/filecoin-project/go-data-transfer v1.11.4 h1:jKvlx0/C8HSyLRn/G1P9TjtfBtFU9jbCvCVFmWbyYVQ= +github.com/filecoin-project/go-data-transfer v1.10.1/go.mod h1:CSDMCrPK2lVGodNB1wPEogjFvM9nVGyiL1GNbBRTSdw= github.com/filecoin-project/go-data-transfer v1.11.4/go.mod h1:2MitLI0ebCkLlPKM7NRggP/t9d+gCcREUKkCKqWRCwU= +github.com/filecoin-project/go-data-transfer v1.11.6 h1:DWAAxdfyR09b+aYeY1PFUzAL/mOPW0Rb+LORRdh2n4w= +github.com/filecoin-project/go-data-transfer v1.11.6/go.mod h1:IDeRWWO0RU+wG7I2o4ELcGDm9zcO+cMXRo8ElGlYLvw= github.com/filecoin-project/go-ds-versioning v0.1.0 h1:y/X6UksYTsK8TLCI7rttCKEvl8btmWxyFMEeeWGUxIQ= github.com/filecoin-project/go-ds-versioning v0.1.0/go.mod h1:mp16rb4i2QPmxBnmanUx8i/XANp+PFCCJWiAb+VW4/s= github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= @@ -338,8 +341,8 @@ github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+ github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7LXep5bFEVOVmQWHJvl2mgsGo= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8= github.com/filecoin-project/go-fil-markets v1.0.5-0.20201113164554-c5eba40d5335/go.mod h1:AJySOJC00JRWEZzRG2KsfUnqEf5ITXxeX09BE9N4f9c= -github.com/filecoin-project/go-fil-markets v1.13.3 h1:iMCpG7I4fb+YLcgDnMaqZiZiyFZWNvrwHqiFPHB0/tQ= -github.com/filecoin-project/go-fil-markets v1.13.3/go.mod h1:38zuj8AgDvOfdakFLpC/syYIYgXTzkq7xqBJ6T1AuG4= +github.com/filecoin-project/go-fil-markets v1.13.3-0.20211117072527-8713155662ff h1:R+3i3v9We8eEqdBJ4RVOPdZt5R6b+E/joJ/xVP2sA4s= +github.com/filecoin-project/go-fil-markets v1.13.3-0.20211117072527-8713155662ff/go.mod h1:neN4U0gdo7g716+t3njUBI9+ft9HBe0veJYG0XdlwXo= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= @@ -347,8 +350,15 @@ github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0/go.mod h1:7aWZdaQ1b16BVoQUYR+ github.com/filecoin-project/go-hamt-ipld/v3 v3.0.1/go.mod h1:gXpNmr3oQx8l3o7qkGyDjJjYSRX7hp/FGOStdqrWyDI= github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0 h1:rVVNq0x6RGQIzCo1iiJlGFm9AGIZzeifggxtKMU7zmI= github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0/go.mod h1:bxmzgT8tmeVQA1/gvBwFmYdT8SOFUwB3ovSUfG1Ux0g= +github.com/filecoin-project/go-indexer-core v0.2.2/go.mod h1:wV+NmrF8fHG6Xii3ecoZf2JW3laGTe5xtsWz609jo+Y= +github.com/filecoin-project/go-indexer-core v0.2.3/go.mod h1:MSe5aRWmfRB+5syR4yDV+OApgJU+MUJ4rl9VUuzwCfc= +github.com/filecoin-project/go-indexer-core v0.2.4 h1:90vvxoBeNZN+h4W+vZ+VsoxKaDBr/bfZJJNByapGeM0= +github.com/filecoin-project/go-indexer-core v0.2.4/go.mod h1:MSe5aRWmfRB+5syR4yDV+OApgJU+MUJ4rl9VUuzwCfc= github.com/filecoin-project/go-jsonrpc v0.1.5 h1:ckxqZ09ivBAVf5CSmxxrqqNHC7PJm3GYGtYKiNQ+vGk= github.com/filecoin-project/go-jsonrpc v0.1.5/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4= +github.com/filecoin-project/go-legs v0.0.0-20211013165050-9ab325b6d2eb/go.mod h1:lKwBnslfNGG7JnsP9uQZl3yK7f74fit1MyHcwuuOP3k= +github.com/filecoin-project/go-legs v0.0.0-20211112111427-68d536862db9 h1:NWe71o5Kgi/0/eMlPJKF//nnIPwOR73AXRk6R/+LLA4= +github.com/filecoin-project/go-legs v0.0.0-20211112111427-68d536862db9/go.mod h1:g32LVimhcYPte22LK8XslKqLBem54QxuMQmkrzbAyEI= github.com/filecoin-project/go-multistore v0.0.3/go.mod h1:kaNqCC4IhU4B1uyr7YWFHd23TL4KM32aChS0jNkyUvQ= github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20/go.mod h1:mPn+LRRd5gEKNAtc+r3ScpW2JRU/pj4NBKdADYWHiak= github.com/filecoin-project/go-padreader v0.0.0-20210723183308-812a16dc01b1/go.mod h1:VYVPJqwpsfmtoHnAmPx6MUwmrK6HIcDqZJiuZhtmfLQ= @@ -373,6 +383,8 @@ github.com/filecoin-project/go-statestore v0.1.1 h1:ufMFq00VqnT2CAuDpcGnwLnCX1I/ github.com/filecoin-project/go-statestore v0.1.1/go.mod h1:LFc9hD+fRxPqiHiaqUEZOinUJB4WARkRfNl10O7kTnI= github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b h1:fkRZSPrYpk42PV3/lIXiL0LHetxde7vyYYvSsttQtfg= github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b/go.mod h1:Q0GQOBtKf1oE10eSXSlhN45kDBdGvEcVOqMiffqX+N8= +github.com/filecoin-project/index-provider v0.0.0-20211116211010-ae6b83454d89 h1:QwKK+eB+7jKbdtQxkBcoiWF2z3LusoPIj2N5UcZsV0w= +github.com/filecoin-project/index-provider v0.0.0-20211116211010-ae6b83454d89/go.mod h1:wu0yi7NbT3VzYr3s0n2zheg3mpdSP09A0hBFIQfUs44= github.com/filecoin-project/specs-actors v0.9.4/go.mod h1:BStZQzx5x7TmCkLv0Bpa07U6cPKol6fd3w9KjMPZ6Z4= github.com/filecoin-project/specs-actors v0.9.12/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= github.com/filecoin-project/specs-actors v0.9.13/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= @@ -395,6 +407,8 @@ github.com/filecoin-project/specs-actors/v6 v6.0.1 h1:laxvHNsvrq83Y9n+W7znVCePi3 github.com/filecoin-project/specs-actors/v6 v6.0.1/go.mod h1:V1AYfi5GkHXipx1mnVivoICZh3wtwPxDVuds+fbfQtk= github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506 h1:Ur/l2+6qN+lQiqjozWWc5p9UDaAMDZKTlDS98oRnlIw= github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506/go.mod h1:nJRRM7Aa9XVvygr3W9k6xGF46RWzr2zxF/iGoAIfA/g= +github.com/filecoin-project/storetheindex v0.0.0-20211019180831-2704585e5f99 h1:qdlA/LrP6UeYFkyXdZzzQaaUNvKXjRIP5j86peIzgvI= +github.com/filecoin-project/storetheindex v0.0.0-20211019180831-2704585e5f99/go.mod h1:IwKNyPe59SXmss9mKhx2GzkJXTBSmSjl1FiQTwFdsus= github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg= github.com/filecoin-project/test-vectors/schema v0.0.5/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= @@ -407,11 +421,16 @@ github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiD github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goblin v0.0.0-20210519012713-85d372ac71e2/go.mod h1:VzmDKDJVZI3aJmnRI9VjAn9nJ8qPPsN1fqzr9dqInIo= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= -github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= +github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss= +github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/gammazero/keymutex v0.0.2 h1:cmpLBJHdEwn+WlR5Z/o9/BN92znSZTp5AKPQDpu1QcI= +github.com/gammazero/keymutex v0.0.2/go.mod h1:qtzWCCLMisQUmVa4dvqHVgwfh4BP2YB7JxNDGXnsKrs= +github.com/gammazero/radixtree v0.2.5 h1:muPQ4eEgCkUymFWPiVQRuXOQv4IhWg8YXH2r71MoqPM= +github.com/gammazero/radixtree v0.2.5/go.mod h1:VPqqCDZ3YZZxAzUUsIF/ytFBigVWV7JIV1Stld8hri0= github.com/gbrlsnchs/jwt/v3 v3.0.1 h1:lbUmgAKpxnClrKloyIwpxm4OuWeDl5wLk52G91ODPw4= github.com/gbrlsnchs/jwt/v3 v3.0.1/go.mod h1:AncDcjXz18xetI3A6STfXq2w+LuTx8pQ8bGEwRN8zVM= github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= @@ -683,7 +702,7 @@ github.com/ipfs/go-blockservice v0.0.7/go.mod h1:EOfb9k/Y878ZTRY/CH0x5+ATtaipfbR github.com/ipfs/go-blockservice v0.1.0/go.mod h1:hzmMScl1kXHg3M2BjTymbVPjv627N7sYcvYaKbop39M= github.com/ipfs/go-blockservice v0.1.3/go.mod h1:OTZhFpkgY48kNzbgyvcexW9cHrpjBYIjSR0KoDOFOLU= github.com/ipfs/go-blockservice v0.1.4-0.20200624145336-a978cec6e834/go.mod h1:OTZhFpkgY48kNzbgyvcexW9cHrpjBYIjSR0KoDOFOLU= -github.com/ipfs/go-blockservice v0.1.5/go.mod h1:yLk8lBJCBRWRqerqCSVi3cE/Dncdt3vGC/PJMVKhLTY= +github.com/ipfs/go-blockservice v0.1.4/go.mod h1:OTZhFpkgY48kNzbgyvcexW9cHrpjBYIjSR0KoDOFOLU= github.com/ipfs/go-blockservice v0.1.7 h1:yVe9te0M7ow8i+PPkx03YFSpxqzXx594d6h+34D6qMg= github.com/ipfs/go-blockservice v0.1.7/go.mod h1:GmS+BAt4hrwBKkzE11AFDQUrnvqjwFatGS2MY7wOjEM= github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= @@ -742,6 +761,8 @@ github.com/ipfs/go-fs-lock v0.0.6/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28 github.com/ipfs/go-graphsync v0.1.0/go.mod h1:jMXfqIEDFukLPZHqDPp8tJMbHO9Rmeb9CEGevngQbmE= github.com/ipfs/go-graphsync v0.4.2/go.mod h1:/VmbZTUdUMTbNkgzAiCEucIIAU3BkLE2cZrDCVUhyi0= github.com/ipfs/go-graphsync v0.4.3/go.mod h1:mPOwDYv128gf8gxPFgXnz4fNrSYPsWyqisJ7ych+XDY= +github.com/ipfs/go-graphsync v0.9.1/go.mod h1:J62ahWT9JbPsFL2UWsUM5rOu0lZJ0LOIH1chHdxGGcw= +github.com/ipfs/go-graphsync v0.9.3/go.mod h1:J62ahWT9JbPsFL2UWsUM5rOu0lZJ0LOIH1chHdxGGcw= github.com/ipfs/go-graphsync v0.10.0/go.mod h1:cKIshzTaa5rCZjryH5xmSKZVGX9uk1wvwGvz2WEha5Y= github.com/ipfs/go-graphsync v0.10.4 h1:1WZhyOPxgxLvHTIC2GoLltaBrjZ+JuXC2oKAEiX8f3Y= github.com/ipfs/go-graphsync v0.10.4/go.mod h1:oei4tnWAKnZ6LPnapZGPYVVbyiKV1UP3f8BeLU7Z4JQ= @@ -753,6 +774,7 @@ github.com/ipfs/go-ipfs-blockstore v0.1.6/go.mod h1:Jxm3XMVjh6R17WvxFEiyKBLUGr86 github.com/ipfs/go-ipfs-blockstore v1.0.0/go.mod h1:knLVdhVU9L7CC4T+T4nvGdeUIPAXlnd9zmXfp+9MIjU= github.com/ipfs/go-ipfs-blockstore v1.0.1/go.mod h1:MGNZlHNEnR4KGgPHM3/k8lBySIOK2Ve+0KjZubKlaOE= github.com/ipfs/go-ipfs-blockstore v1.0.3/go.mod h1:MGNZlHNEnR4KGgPHM3/k8lBySIOK2Ve+0KjZubKlaOE= +github.com/ipfs/go-ipfs-blockstore v1.0.4-0.20210205083733-fb07d7bc5aec/go.mod h1:feuklK+m9POeWJzYQO7l05yNEgUiX5oELBNA8/Be33E= github.com/ipfs/go-ipfs-blockstore v1.0.4 h1:DZdeya9Vu4ttvlGheQPGrj6kWehXnYZRFCp9EsZQ1hI= github.com/ipfs/go-ipfs-blockstore v1.0.4/go.mod h1:uL7/gTJ8QIZ3MtA3dWf+s1a0U3fJy2fcEZAsovpRp+w= github.com/ipfs/go-ipfs-blocksutil v0.0.1 h1:Eh/H4pc1hsvhzsQoMEP3Bke/aW5P5rVM1IWFJMcGIPQ= @@ -831,6 +853,7 @@ github.com/ipfs/go-merkledag v0.2.3/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB github.com/ipfs/go-merkledag v0.2.4/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= github.com/ipfs/go-merkledag v0.3.1/go.mod h1:fvkZNNZixVW6cKSZ/JfLlON5OlgTXNdRLz0p6QG/I2M= github.com/ipfs/go-merkledag v0.3.2/go.mod h1:fvkZNNZixVW6cKSZ/JfLlON5OlgTXNdRLz0p6QG/I2M= +github.com/ipfs/go-merkledag v0.4.0/go.mod h1:XshXBkhyeS63YNGisLL1uDSfuTyrQIxVUOg3ojR5MOE= github.com/ipfs/go-merkledag v0.4.1 h1:CEEQZnwRkszN06oezuasHwDD823Xcr4p4zluUN9vXqs= github.com/ipfs/go-merkledag v0.4.1/go.mod h1:56biPaS6e+IS0eXkEt6A8tG+BUQaEIFqDqJuFfQDBoE= github.com/ipfs/go-metrics-interface v0.0.1 h1:j+cpbjYvu4R8zbleSs36gvB7jR+wsL2fGD6n0jO4kdg= @@ -861,12 +884,11 @@ github.com/ipfs/iptb-plugins v0.3.0/go.mod h1:5QtOvckeIw4bY86gSH4fgh3p3gCSMn3FmI github.com/ipld/go-car v0.1.0/go.mod h1:RCWzaUh2i4mOEkB3W45Vc+9jnS/M6Qay5ooytiBHl3g= github.com/ipld/go-car v0.1.1-0.20200923150018-8cdef32e2da4/go.mod h1:xrMEcuSq+D1vEwl+YAXsg/JfA98XGpXDwnkIL4Aimqw= github.com/ipld/go-car v0.1.1-0.20201119040415-11b6074b6d4d/go.mod h1:2Gys8L8MJ6zkh1gktTSXreY63t4UbyvNp5JaudTyxHQ= -github.com/ipld/go-car v0.3.2-0.20211001225732-32d0d9933823 h1:8JMSJ0k71fU9lIUrpVwEdoX4KoxiTEX8cZG97v/hTDw= -github.com/ipld/go-car v0.3.2-0.20211001225732-32d0d9933823/go.mod h1:jSlTph+i/q1jLFoiKKeN69KGG0fXpwrcD0izu5C1Tpo= -github.com/ipld/go-car/v2 v2.0.0-beta1.0.20210721090610-5a9d1b217d25/go.mod h1:I2ACeeg6XNBe5pdh5TaR7Ambhfa7If9KXxmXgZsYENU= -github.com/ipld/go-car/v2 v2.0.2/go.mod h1:I2ACeeg6XNBe5pdh5TaR7Ambhfa7If9KXxmXgZsYENU= -github.com/ipld/go-car/v2 v2.0.3-0.20210910134712-2d2568297f26 h1:IBXjeOANJGYZVJ9jsvf0Tu+ANQ9FLstscJgzfJgwA8c= -github.com/ipld/go-car/v2 v2.0.3-0.20210910134712-2d2568297f26/go.mod h1:bBmZNBj4jfOHrd4Cu/koFhqwsCnZ5RrGXU1wwWqDr20= +github.com/ipld/go-car v0.3.2 h1:V9wt/80FNfbMRWSD98W5br6fyjUAyVgI2lDOTZX16Lg= +github.com/ipld/go-car v0.3.2/go.mod h1:WEjynkVt04dr0GwJhry0KlaTeSDEiEYyMPOxDBQ17KE= +github.com/ipld/go-car/v2 v2.0.3-0.20210920144420-f35d88ce16ca/go.mod h1:Xr6GwkDhv8dtOtgHzOynAkIOg0t0YiPc5DxBPppWqZA= +github.com/ipld/go-car/v2 v2.1.0 h1:t8R/WXUSkfu1K1gpPk76mytCxsEdMjGcMIgpOq3/Cnw= +github.com/ipld/go-car/v2 v2.1.0/go.mod h1:Xr6GwkDhv8dtOtgHzOynAkIOg0t0YiPc5DxBPppWqZA= github.com/ipld/go-codec-dagpb v1.2.0/go.mod h1:6nBN7X7h8EOsEejZGqC7tej5drsdBAXbMHyBT+Fne5s= github.com/ipld/go-codec-dagpb v1.3.0 h1:czTcaoAuNNyIYWs6Qe01DJ+sEX7B+1Z0LcXjSatMGe8= github.com/ipld/go-codec-dagpb v1.3.0/go.mod h1:ga4JTU3abYApDC3pZ00BC2RSvC3qfBb9MSJkMLSwnhA= @@ -878,15 +900,18 @@ github.com/ipld/go-ipld-prime v0.9.0/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/j github.com/ipld/go-ipld-prime v0.9.1-0.20210324083106-dc342a9917db/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= github.com/ipld/go-ipld-prime v0.10.0/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= github.com/ipld/go-ipld-prime v0.11.0/go.mod h1:+WIAkokurHmZ/KwzDOMUuoeJgaRQktHtEaLglS3ZeV8= -github.com/ipld/go-ipld-prime v0.12.3-0.20210930132912-0b3aef3ca569/go.mod h1:PaeLYq8k6dJLmDUSLrzkEpoGV4PEfe/1OtFN/eALOc8= -github.com/ipld/go-ipld-prime v0.12.3 h1:furVobw7UBLQZwlEwfE26tYORy3PAK8VYSgZOSr3JMQ= +github.com/ipld/go-ipld-prime v0.12.0/go.mod h1:hy8b93WleDMRKumOJnTIrr0MbbFbx9GD6Kzxa53Xppc= github.com/ipld/go-ipld-prime v0.12.3/go.mod h1:PaeLYq8k6dJLmDUSLrzkEpoGV4PEfe/1OtFN/eALOc8= +github.com/ipld/go-ipld-prime v0.14.0 h1:2FnBqUjmmgxgZD6/zB3eygWlmIsHNGrZ57L99x3xD6Q= +github.com/ipld/go-ipld-prime v0.14.0/go.mod h1:9ASQLwUFLptCov6lIYc70GRB4V7UTyLD0IJtrDJe6ZM= github.com/ipld/go-ipld-prime-proto v0.0.0-20191113031812-e32bd156a1e5/go.mod h1:gcvzoEDBjwycpXt3LBE061wT9f46szXGHAmj9uoP6fU= github.com/ipld/go-ipld-prime-proto v0.0.0-20200428191222-c1ffdadc01e1/go.mod h1:OAV6xBmuTLsPZ+epzKkPB1e25FHk/vCtyatkdHcArLs= github.com/ipld/go-ipld-prime-proto v0.0.0-20200922192210-9a2bfd4440a6/go.mod h1:3pHYooM9Ea65jewRwrb2u5uHZCNkNTe9ABsVB+SrkH0= github.com/ipld/go-ipld-prime-proto v0.1.0/go.mod h1:11zp8f3sHVgIqtb/c9Kr5ZGqpnCLF1IVTNOez9TopzE= github.com/ipld/go-ipld-selector-text-lite v0.0.0 h1:MLU1YUAgd3Z+RfVCXUbvxH1RQjEe+larJ9jmlW1aMgA= github.com/ipld/go-ipld-selector-text-lite v0.0.0/go.mod h1:U2CQmFb+uWzfIEF3I1arrDa5rwtj00PrpiwwCO+k1RM= +github.com/ipld/go-storethehash v0.0.0-20210915160027-d72ca9b0968c h1:izfvqCuEqk2V7BRkh7GCm7lyKC2ItyAbzUu4WgNmggc= +github.com/ipld/go-storethehash v0.0.0-20210915160027-d72ca9b0968c/go.mod h1:PwE6iq8TiWJRI3zMGA1RtkFAnrDMK93dLA5SUeu0lH8= github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52 h1:QG4CGBqCeuBo6aZlGAamSkxWdgWfZGeE49eUOWJPA4c= github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52/go.mod h1:fdg+/X9Gg4AsAIzWpEHwnqd+QY3b7lajxyjE1m4hkq4= github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= @@ -972,8 +997,9 @@ github.com/koron/go-ssdp v0.0.2/go.mod h1:XoLfkAiA2KeZsYh4DbHxD7h3nR2AZNqVQOa+LJ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= @@ -1159,6 +1185,7 @@ github.com/libp2p/go-libp2p-protocol v0.0.1/go.mod h1:Af9n4PiruirSDjHycM1QuiMi/1 github.com/libp2p/go-libp2p-protocol v0.1.0/go.mod h1:KQPHpAabB57XQxGrXCNvbL6UEXfQqUgC/1adR2Xtflk= github.com/libp2p/go-libp2p-pubsub v0.1.1/go.mod h1:ZwlKzRSe1eGvSIdU5bD7+8RZN/Uzw0t1Bp9R1znpR/Q= github.com/libp2p/go-libp2p-pubsub v0.3.2-0.20200527132641-c0712c6e92cf/go.mod h1:TxPOBuo1FPdsTjFnv+FGZbNbWYsp74Culx+4ViQpato= +github.com/libp2p/go-libp2p-pubsub v0.5.4/go.mod h1:gVOzwebXVdSMDQBTfH8ACO5EJ4SQrvsHqCmYsCZpD0E= github.com/libp2p/go-libp2p-pubsub v0.5.6 h1:YkO3gG9J1mQBEMRrM5obiG3JD0L8RcrzIpoeLeiYqH8= github.com/libp2p/go-libp2p-pubsub v0.5.6/go.mod h1:gVOzwebXVdSMDQBTfH8ACO5EJ4SQrvsHqCmYsCZpD0E= github.com/libp2p/go-libp2p-quic-transport v0.1.1/go.mod h1:wqG/jzhF3Pu2NrhJEvE+IE0NTHNXslOPn9JQzyCAxzU= @@ -1326,8 +1353,9 @@ github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0U github.com/lucas-clemente/quic-go v0.11.2/go.mod h1:PpMmPfPKO9nKJ/psF49ESTAGQSdfXxlg1otPbEB2nOw= github.com/lucas-clemente/quic-go v0.16.0/go.mod h1:I0+fcNTdb9eS1ZcjQZbDVPGchJ86chcIxPALn9lEJqE= github.com/lucas-clemente/quic-go v0.19.3/go.mod h1:ADXpNbTQjq1hIzCpB+y/k5iz4n4z4IwqoLb94Kh5Hu8= -github.com/lucas-clemente/quic-go v0.21.2 h1:8LqqL7nBQFDUINadW0fHV/xSaCQJgmJC0Gv+qUnjd78= github.com/lucas-clemente/quic-go v0.21.2/go.mod h1:vF5M1XqhBAHgbjKcJOXY3JZz3GP0T3FQhz/uyOUS38Q= +github.com/lucas-clemente/quic-go v0.23.0 h1:5vFnKtZ6nHDFsc/F3uuiF4T3y/AXaQdxjUqiVw26GZE= +github.com/lucas-clemente/quic-go v0.23.0/go.mod h1:paZuzjXCE5mj6sikVLMvqXk8lJV2AsqtJ6bDhjEfxx0= github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac= github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lufia/iostat v1.1.0/go.mod h1:rEPNA0xXgjHQjuI5Cy05sLlS2oRcSlWHRLrvh/AQ+Pg= @@ -1350,12 +1378,12 @@ github.com/marten-seemann/qtls v0.9.1/go.mod h1:T1MmAdDPyISzxlK6kjRr0pcZFBVd1OZb github.com/marten-seemann/qtls v0.10.0/go.mod h1:UvMd1oaYDACI99/oZUYLzMCkBXQVT0aGm99sJhbT8hs= github.com/marten-seemann/qtls-go1-15 v0.1.1/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= github.com/marten-seemann/qtls-go1-15 v0.1.4/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= -github.com/marten-seemann/qtls-go1-15 v0.1.5 h1:Ci4EIUN6Rlb+D6GmLdej/bCQ4nPYNtVXQB+xjiXE1nk= github.com/marten-seemann/qtls-go1-15 v0.1.5/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= github.com/marten-seemann/qtls-go1-16 v0.1.4 h1:xbHbOGGhrenVtII6Co8akhLEdrawwB2iHl5yhJRpnco= github.com/marten-seemann/qtls-go1-16 v0.1.4/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk= -github.com/marten-seemann/qtls-go1-17 v0.1.0-rc.1 h1:/rpmWuGvceLwwWuaKPdjpR4JJEUH0tq64/I3hvzaNLM= github.com/marten-seemann/qtls-go1-17 v0.1.0-rc.1/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8= +github.com/marten-seemann/qtls-go1-17 v0.1.0 h1:P9ggrs5xtwiqXv/FHNwntmuLMNq3KaSIG93AtAZ48xk= +github.com/marten-seemann/qtls-go1-17 v0.1.0/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8= github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -1480,8 +1508,6 @@ github.com/multiformats/go-multibase v0.0.2/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/g github.com/multiformats/go-multibase v0.0.3 h1:l/B6bJDQjvQ5G52jw4QGSYeOTZoAwIO77RblWplfIqk= github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= github.com/multiformats/go-multicodec v0.2.0/go.mod h1:/y4YVwkfMyry5kFbMTbLJKErhycTIftytRV+llXdyS4= -github.com/multiformats/go-multicodec v0.2.1-0.20210713081508-b421db6850ae/go.mod h1:qGGaQmioCDh+TeFOnxrbU0DaIPw8yFgAZgFG0V7p1qQ= -github.com/multiformats/go-multicodec v0.2.1-0.20210714093213-b2b5bd6fe68b/go.mod h1:qGGaQmioCDh+TeFOnxrbU0DaIPw8yFgAZgFG0V7p1qQ= github.com/multiformats/go-multicodec v0.3.0/go.mod h1:qGGaQmioCDh+TeFOnxrbU0DaIPw8yFgAZgFG0V7p1qQ= github.com/multiformats/go-multicodec v0.3.1-0.20210902112759-1539a079fd61 h1:ZrUuMKNgJ52qHPoQ+bx0h0uBfcWmN7Px+4uKSZeesiI= github.com/multiformats/go-multicodec v0.3.1-0.20210902112759-1539a079fd61/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ= @@ -1493,8 +1519,9 @@ github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpK github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= github.com/multiformats/go-multihash v0.0.14/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= github.com/multiformats/go-multihash v0.0.15/go.mod h1:D6aZrWNLFTV/ynMpKsNtB40mJzmCl4jb1alC0OvHiHg= -github.com/multiformats/go-multihash v0.0.16 h1:D2qsyy1WVculJbGv69pWmQ36ehxFoA5NiIUr1OEs6qI= github.com/multiformats/go-multihash v0.0.16/go.mod h1:zhfEIgVnB/rPMfxgFw15ZmGoNaKyNUIE4IWHG/kC+Ag= +github.com/multiformats/go-multihash v0.1.0 h1:CgAgwqk3//SVEw3T+6DqI4mWMyRuDwZtOWcJT0q9+EA= +github.com/multiformats/go-multihash v0.1.0/go.mod h1:RJlXsxt6vHGaia+S8We0ErjhojtKzPP2AH4+kYM7k84= github.com/multiformats/go-multistream v0.0.1/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= github.com/multiformats/go-multistream v0.0.4/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= @@ -1590,6 +1617,7 @@ github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 h1:1/WtZae0yGtPq+TI6+ github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9/go.mod h1:x3N5drFsm2uilKKuuYo6LdyD8vZAW55sH/9w+pbo1sw= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -1671,6 +1699,9 @@ github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= @@ -1866,6 +1897,7 @@ github.com/xorcare/golden v0.6.0/go.mod h1:7T39/ZMvaSEZlBPoYfVFmsBLmUl3uz9IuzWj/ github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542 h1:oWgZJmC1DorFZDpfMfWg7xk29yEOZiXmo/wZl+utTI8= github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542/go.mod h1:7T39/ZMvaSEZlBPoYfVFmsBLmUl3uz9IuzWj/U6FtvQ= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/ybbus/jsonrpc/v2 v2.1.6/go.mod h1:rIuG1+ORoiqocf9xs/v+ecaAVeo3zcZHQgInyKFMeg0= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -2025,6 +2057,7 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= @@ -2486,6 +2519,8 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= howett.net/plist v0.0.0-20181124034731-591f970eefbb h1:jhnBjNi9UFpfpl8YZhA9CrOqpnJdvzuiHsl/dnxl11M= howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0= +lukechampine.com/blake3 v1.1.6 h1:H3cROdztr7RCfoaTpGZFQsrqvweFLrqS73j7L7cmR5c= +lukechampine.com/blake3 v1.1.6/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA= modernc.org/cc v1.0.0 h1:nPibNuDEx6tvYrUAtvDTTw98rx5juGsa5zuDnKwEEQQ= modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= modernc.org/fileutil v1.0.0/go.mod h1:JHsWpkrk/CnVV1H/eGlFf85BEpfkrp56ro8nojIq9Q8= diff --git a/itests/deals_anycid_test.go b/itests/deals_anycid_test.go index 6b314908bd1..b7799f2980c 100644 --- a/itests/deals_anycid_test.go +++ b/itests/deals_anycid_test.go @@ -133,7 +133,7 @@ func TestDealRetrieveByAnyCid(t *testing.T) { require.NoError(t, err) f, err := os.Open(outputCar) require.NoError(t, err) - ch, _, _ := car.ReadHeader(bufio.NewReader(f)) + ch, _ := car.ReadHeader(bufio.NewReader(f)) require.EqualValues(t, ch.Roots[0], targetCid) require.NoError(t, f.Close()) diff --git a/itests/kit/files.go b/itests/kit/files.go index d69c6d7767e..26dba1b4ba7 100644 --- a/itests/kit/files.go +++ b/itests/kit/files.go @@ -83,7 +83,7 @@ func CreateRandomCARv1(t *testing.T, rseed, size int, opts ...GeneratedDAGOpts) require.NoError(t, car.WriteCar(ctx, dagSvc, []cid.Cid{root}, tmp)) _, err = tmp.Seek(0, io.SeekStart) require.NoError(t, err) - hd, _, err := car.ReadHeader(bufio.NewReader(tmp)) + hd, err := car.ReadHeader(bufio.NewReader(tmp)) require.NoError(t, err) require.EqualValues(t, 1, hd.Version) require.Len(t, hd.Roots, 1) diff --git a/markets/dagstore/wrapper.go b/markets/dagstore/wrapper.go index 6a32c011aae..b6c8801de6e 100644 --- a/markets/dagstore/wrapper.go +++ b/markets/dagstore/wrapper.go @@ -10,6 +10,10 @@ import ( "sync" "time" + carindex "github.com/ipld/go-car/v2/index" + + "github.com/filecoin-project/go-indexer-core/store/storethehash" + "github.com/ipfs/go-cid" ds "github.com/ipfs/go-datastore" levelds "github.com/ipfs/go-ds-leveldb" @@ -80,8 +84,14 @@ func NewDAGStore(cfg config.DAGStoreConfig, minerApi MinerAPI) (*dagstore.DAGSto irepo, err := index.NewFSRepo(indexDir) if err != nil { - return nil, nil, xerrors.Errorf("failed to initialise dagstore index repo") + return nil, nil, xerrors.Errorf("failed to initialise dagstore index repo: %w", err) + } + + store, err := storethehash.New(indexDir) + if err != nil { + return nil, nil, xerrors.Errorf("failed to initialise store the index: %w", err) } + topIndex := index.NewInverted(store) dcfg := dagstore.Config{ TransientsDir: transientsDir, @@ -90,6 +100,7 @@ func NewDAGStore(cfg config.DAGStoreConfig, minerApi MinerAPI) (*dagstore.DAGSto MountRegistry: registry, FailureCh: failureCh, TraceCh: traceCh, + TopLevelIndex: topIndex, // not limiting fetches globally, as the Lotus mount does // conditional throttling. MaxConcurrentIndex: cfg.MaxConcurrentIndex, @@ -270,6 +281,11 @@ func (w *Wrapper) RegisterShard(ctx context.Context, pieceCid cid.Cid, carPath s return nil } +func (w *Wrapper) GetIterableIndexForPiece(pieceCid cid.Cid) (carindex.IterableIndex, error) { + key := shard.KeyFromCID(pieceCid) + return w.dagst.GetIterableIndex(key) +} + func (w *Wrapper) MigrateDeals(ctx context.Context, deals []storagemarket.MinerDeal) (bool, error) { log := log.Named("migrator") @@ -402,7 +418,7 @@ func (w *Wrapper) markRegistrationComplete() error { // Get all the pieces that contain a block func (w *Wrapper) GetPiecesContainingBlock(blockCID cid.Cid) ([]cid.Cid, error) { // Pieces are stored as "shards" in the DAG store - shardKeys, err := w.dagst.GetShardKeysForCid(blockCID) + shardKeys, err := w.dagst.ShardsContainingMultihash(blockCID.Hash()) if err != nil { return nil, xerrors.Errorf("getting pieces containing block %s: %w", blockCID, err) } diff --git a/node/impl/client/client.go b/node/impl/client/client.go index 199a2122dd9..cb0f8aa5093 100644 --- a/node/impl/client/client.go +++ b/node/impl/client/client.go @@ -516,7 +516,7 @@ func (a *API) ClientImport(ctx context.Context, ref api.FileRef) (res *api.Impor } defer f.Close() //nolint:errcheck - hd, _, err := car.ReadHeader(bufio.NewReader(f)) + hd, err := car.ReadHeader(bufio.NewReader(f)) if err != nil { return nil, xerrors.Errorf("failed to read CAR header: %w", err) } @@ -1196,7 +1196,7 @@ func (a *API) ClientCalcCommP(ctx context.Context, inpath string) (*api.CommPRet } // check that the data is a car file; if it's not, retrieval won't work - _, _, err = car.ReadHeader(bufio.NewReader(rdr)) + _, err = car.ReadHeader(bufio.NewReader(rdr)) if err != nil { return nil, xerrors.Errorf("not a car file: %w", err) } From f8c675bc5e0bbada3ab0f342443a00a8162906ce Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Wed, 17 Nov 2021 14:48:28 +0400 Subject: [PATCH 013/385] green tests --- go.mod | 2 +- go.sum | 8 +++----- markets/dagstore/wrapper.go | 20 ++++++-------------- 3 files changed, 10 insertions(+), 20 deletions(-) diff --git a/go.mod b/go.mod index 8d71c36378d..06a6799b6e2 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,6 @@ require ( github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 github.com/filecoin-project/go-fil-markets v1.13.3-0.20211117072527-8713155662ff - github.com/filecoin-project/go-indexer-core v0.2.4 github.com/filecoin-project/go-jsonrpc v0.1.5 github.com/filecoin-project/go-padreader v0.0.1 github.com/filecoin-project/go-paramfetch v0.0.2 @@ -45,6 +44,7 @@ require ( github.com/filecoin-project/go-statemachine v1.0.1 github.com/filecoin-project/go-statestore v0.1.1 github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b + github.com/filecoin-project/index-provider v0.0.0-20211117103856-70cd9b7ab68b github.com/filecoin-project/specs-actors v0.9.14 github.com/filecoin-project/specs-actors/v2 v2.3.5 github.com/filecoin-project/specs-actors/v3 v3.1.1 diff --git a/go.sum b/go.sum index f6da54a9c4b..4831d889bfd 100644 --- a/go.sum +++ b/go.sum @@ -351,9 +351,8 @@ github.com/filecoin-project/go-hamt-ipld/v3 v3.0.1/go.mod h1:gXpNmr3oQx8l3o7qkGy github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0 h1:rVVNq0x6RGQIzCo1iiJlGFm9AGIZzeifggxtKMU7zmI= github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0/go.mod h1:bxmzgT8tmeVQA1/gvBwFmYdT8SOFUwB3ovSUfG1Ux0g= github.com/filecoin-project/go-indexer-core v0.2.2/go.mod h1:wV+NmrF8fHG6Xii3ecoZf2JW3laGTe5xtsWz609jo+Y= +github.com/filecoin-project/go-indexer-core v0.2.3 h1:kaUL2r8CuihK53lhmtCScffb7Bzs+N1yRGpwvxzCN+U= github.com/filecoin-project/go-indexer-core v0.2.3/go.mod h1:MSe5aRWmfRB+5syR4yDV+OApgJU+MUJ4rl9VUuzwCfc= -github.com/filecoin-project/go-indexer-core v0.2.4 h1:90vvxoBeNZN+h4W+vZ+VsoxKaDBr/bfZJJNByapGeM0= -github.com/filecoin-project/go-indexer-core v0.2.4/go.mod h1:MSe5aRWmfRB+5syR4yDV+OApgJU+MUJ4rl9VUuzwCfc= github.com/filecoin-project/go-jsonrpc v0.1.5 h1:ckxqZ09ivBAVf5CSmxxrqqNHC7PJm3GYGtYKiNQ+vGk= github.com/filecoin-project/go-jsonrpc v0.1.5/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4= github.com/filecoin-project/go-legs v0.0.0-20211013165050-9ab325b6d2eb/go.mod h1:lKwBnslfNGG7JnsP9uQZl3yK7f74fit1MyHcwuuOP3k= @@ -383,8 +382,9 @@ github.com/filecoin-project/go-statestore v0.1.1 h1:ufMFq00VqnT2CAuDpcGnwLnCX1I/ github.com/filecoin-project/go-statestore v0.1.1/go.mod h1:LFc9hD+fRxPqiHiaqUEZOinUJB4WARkRfNl10O7kTnI= github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b h1:fkRZSPrYpk42PV3/lIXiL0LHetxde7vyYYvSsttQtfg= github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b/go.mod h1:Q0GQOBtKf1oE10eSXSlhN45kDBdGvEcVOqMiffqX+N8= -github.com/filecoin-project/index-provider v0.0.0-20211116211010-ae6b83454d89 h1:QwKK+eB+7jKbdtQxkBcoiWF2z3LusoPIj2N5UcZsV0w= github.com/filecoin-project/index-provider v0.0.0-20211116211010-ae6b83454d89/go.mod h1:wu0yi7NbT3VzYr3s0n2zheg3mpdSP09A0hBFIQfUs44= +github.com/filecoin-project/index-provider v0.0.0-20211117103856-70cd9b7ab68b h1:qVQpqoguf9+vPONSMQZ3xYVzxzwAITyBHjM238zAr6c= +github.com/filecoin-project/index-provider v0.0.0-20211117103856-70cd9b7ab68b/go.mod h1:wu0yi7NbT3VzYr3s0n2zheg3mpdSP09A0hBFIQfUs44= github.com/filecoin-project/specs-actors v0.9.4/go.mod h1:BStZQzx5x7TmCkLv0Bpa07U6cPKol6fd3w9KjMPZ6Z4= github.com/filecoin-project/specs-actors v0.9.12/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= github.com/filecoin-project/specs-actors v0.9.13/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= @@ -427,7 +427,6 @@ github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/gammazero/keymutex v0.0.2 h1:cmpLBJHdEwn+WlR5Z/o9/BN92znSZTp5AKPQDpu1QcI= github.com/gammazero/keymutex v0.0.2/go.mod h1:qtzWCCLMisQUmVa4dvqHVgwfh4BP2YB7JxNDGXnsKrs= github.com/gammazero/radixtree v0.2.5 h1:muPQ4eEgCkUymFWPiVQRuXOQv4IhWg8YXH2r71MoqPM= github.com/gammazero/radixtree v0.2.5/go.mod h1:VPqqCDZ3YZZxAzUUsIF/ytFBigVWV7JIV1Stld8hri0= @@ -910,7 +909,6 @@ github.com/ipld/go-ipld-prime-proto v0.0.0-20200922192210-9a2bfd4440a6/go.mod h1 github.com/ipld/go-ipld-prime-proto v0.1.0/go.mod h1:11zp8f3sHVgIqtb/c9Kr5ZGqpnCLF1IVTNOez9TopzE= github.com/ipld/go-ipld-selector-text-lite v0.0.0 h1:MLU1YUAgd3Z+RfVCXUbvxH1RQjEe+larJ9jmlW1aMgA= github.com/ipld/go-ipld-selector-text-lite v0.0.0/go.mod h1:U2CQmFb+uWzfIEF3I1arrDa5rwtj00PrpiwwCO+k1RM= -github.com/ipld/go-storethehash v0.0.0-20210915160027-d72ca9b0968c h1:izfvqCuEqk2V7BRkh7GCm7lyKC2ItyAbzUu4WgNmggc= github.com/ipld/go-storethehash v0.0.0-20210915160027-d72ca9b0968c/go.mod h1:PwE6iq8TiWJRI3zMGA1RtkFAnrDMK93dLA5SUeu0lH8= github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52 h1:QG4CGBqCeuBo6aZlGAamSkxWdgWfZGeE49eUOWJPA4c= github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52/go.mod h1:fdg+/X9Gg4AsAIzWpEHwnqd+QY3b7lajxyjE1m4hkq4= diff --git a/markets/dagstore/wrapper.go b/markets/dagstore/wrapper.go index 7ef7dd3c8b6..98c63361f45 100644 --- a/markets/dagstore/wrapper.go +++ b/markets/dagstore/wrapper.go @@ -12,14 +12,11 @@ import ( carindex "github.com/ipld/go-car/v2/index" - "github.com/filecoin-project/go-indexer-core/store/storethehash" - "github.com/ipfs/go-cid" ds "github.com/ipfs/go-datastore" levelds "github.com/ipfs/go-ds-leveldb" measure "github.com/ipfs/go-ds-measure" logging "github.com/ipfs/go-log/v2" - carindex "github.com/ipld/go-car/v2/index" ldbopts "github.com/syndtr/goleveldb/leveldb/opt" "golang.org/x/xerrors" @@ -88,11 +85,11 @@ func NewDAGStore(cfg config.DAGStoreConfig, minerApi MinerAPI) (*dagstore.DAGSto return nil, nil, xerrors.Errorf("failed to initialise dagstore index repo: %w", err) } - store, err := storethehash.New(indexDir) - if err != nil { - return nil, nil, xerrors.Errorf("failed to initialise store the index: %w", err) - } - topIndex := index.NewInverted(store) + //store, err := storethehash.New(indexDir) + //if err != nil { + //return nil, nil, xerrors.Errorf("failed to initialise store the index: %w", err) + //} + //topIndex := index.NewInverted(store) dcfg := dagstore.Config{ TransientsDir: transientsDir, @@ -101,7 +98,7 @@ func NewDAGStore(cfg config.DAGStoreConfig, minerApi MinerAPI) (*dagstore.DAGSto MountRegistry: registry, FailureCh: failureCh, TraceCh: traceCh, - TopLevelIndex: topIndex, + //TopLevelIndex: topIndex, // not limiting fetches globally, as the Lotus mount does // conditional throttling. MaxConcurrentIndex: cfg.MaxConcurrentIndex, @@ -282,11 +279,6 @@ func (w *Wrapper) RegisterShard(ctx context.Context, pieceCid cid.Cid, carPath s return nil } -func (w *Wrapper) GetIterableIndexForPiece(pieceCid cid.Cid) (carindex.IterableIndex, error) { - key := shard.KeyFromCID(pieceCid) - return w.dagst.GetIterableIndex(key) -} - func (w *Wrapper) MigrateDeals(ctx context.Context, deals []storagemarket.MinerDeal) (bool, error) { log := log.Named("migrator") From d196c236b80f536645b4c91a4c0cd92e206a4c04 Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Wed, 17 Nov 2021 14:55:09 +0400 Subject: [PATCH 014/385] fix lint --- markets/dagstore/wrapper_test.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/markets/dagstore/wrapper_test.go b/markets/dagstore/wrapper_test.go index 578dc0b74a2..4cf53737377 100644 --- a/markets/dagstore/wrapper_test.go +++ b/markets/dagstore/wrapper_test.go @@ -8,6 +8,10 @@ import ( "testing" "time" + mh "github.com/multiformats/go-multihash" + + carindex "github.com/ipld/go-car/v2/index" + "golang.org/x/xerrors" "github.com/filecoin-project/lotus/node/config" @@ -132,6 +136,14 @@ type mockDagStore struct { close chan struct{} } +func (m *mockDagStore) GetIterableIndex(key shard.Key) (carindex.IterableIndex, error) { + return nil, nil +} + +func (m *mockDagStore) ShardsContainingMultihash(h mh.Multihash) ([]shard.Key, error) { + return nil, nil +} + func (m *mockDagStore) GetShardKeysForCid(c cid.Cid) ([]shard.Key, error) { panic("implement me") } From 8d3017febb8c5077a817eccfc8acd56cc1b7f297 Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Wed, 17 Nov 2021 15:02:11 +0400 Subject: [PATCH 015/385] make gen should work --- node/config/doc_gen.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/node/config/doc_gen.go b/node/config/doc_gen.go index 296501edcfb..394f8ab09db 100644 --- a/node/config/doc_gen.go +++ b/node/config/doc_gen.go @@ -339,6 +339,22 @@ see https://docs.filecoin.io/mine/lotus/miner-configuration/#using-filters-for-f Comment: ``, }, }, + "IndexerProviderConfig": []DocField{ + { + Name: "ListenAddresses", + Type: "[]string", + + Comment: `Binding address for the libp2p host - 0 means random port. +Format: multiaddress; see https://multiformats.io/multiaddr/`, + }, + { + Name: "MaxSimultaneousTransfers", + Type: "uint64", + + Comment: `The maximum number of simultaneous data transfers between the indexers +and the indexer provider`, + }, + }, "Libp2p": []DocField{ { Name: "ListenAddresses", @@ -814,6 +830,12 @@ Default is 20 (about once a week).`, Comment: ``, }, + { + Name: "IndexerProvider", + Type: "IndexerProviderConfig", + + Comment: ``, + }, { Name: "Sealing", Type: "SealingConfig", From 501308239fc92a5d3c048537d84c7fec1baf761f Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Wed, 17 Nov 2021 12:14:10 +0100 Subject: [PATCH 016/385] feat: CLI command to announce deal to indexers --- api/api_storage.go | 4 ++ api/proxy_gen.go | 13 ++++ build/openrpc/full.json.gz | Bin 25453 -> 25453 bytes build/openrpc/miner.json.gz | Bin 10467 -> 10575 bytes build/openrpc/worker.json.gz | Bin 2713 -> 2713 bytes cmd/lotus-miner/index_provider.go | 58 ++++++++++++++++++ cmd/lotus-miner/main.go | 1 + documentation/en/api-v0-methods-miner.md | 23 +++++++ documentation/en/cli-lotus-miner.md | 32 ++++++++++ .../en/default-lotus-miner-config.toml | 28 +++++++++ node/impl/storminer.go | 4 ++ 11 files changed, 163 insertions(+) create mode 100644 cmd/lotus-miner/index_provider.go diff --git a/api/api_storage.go b/api/api_storage.go index 8cca2aa5be5..fc2f58a2634 100644 --- a/api/api_storage.go +++ b/api/api_storage.go @@ -210,6 +210,10 @@ type StorageMiner interface { // DagstoreGC runs garbage collection on the DAG store. DagstoreGC(ctx context.Context) ([]DagstoreShardResult, error) //perm:admin + // IndexerAnnounceDeal informs indexer nodes that a new deal was received, + // so they can download its index + IndexerAnnounceDeal(ctx context.Context, proposalCid cid.Cid) error + // RuntimeSubsystems returns the subsystems that are enabled // in this instance. RuntimeSubsystems(ctx context.Context) (MinerSubsystems, error) //perm:read diff --git a/api/proxy_gen.go b/api/proxy_gen.go index b36f19a7e1e..0ce7ee8dd88 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -657,6 +657,8 @@ type StorageMinerStruct struct { DealsSetPieceCidBlocklist func(p0 context.Context, p1 []cid.Cid) error `perm:"admin"` + IndexerAnnounceDeal func(p0 context.Context, p1 cid.Cid) error `` + MarketCancelDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` MarketDataTransferUpdates func(p0 context.Context) (<-chan DataTransferChannel, error) `perm:"write"` @@ -3879,6 +3881,17 @@ func (s *StorageMinerStub) DealsSetPieceCidBlocklist(p0 context.Context, p1 []ci return ErrNotSupported } +func (s *StorageMinerStruct) IndexerAnnounceDeal(p0 context.Context, p1 cid.Cid) error { + if s.Internal.IndexerAnnounceDeal == nil { + return ErrNotSupported + } + return s.Internal.IndexerAnnounceDeal(p0, p1) +} + +func (s *StorageMinerStub) IndexerAnnounceDeal(p0 context.Context, p1 cid.Cid) error { + return ErrNotSupported +} + func (s *StorageMinerStruct) MarketCancelDataTransfer(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error { if s.Internal.MarketCancelDataTransfer == nil { return ErrNotSupported diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 1578d746536613ea03a22c6165e5561d65e3df7a..68f5e80cc46d1aa9137e152e97f358580a4ad40f 100644 GIT binary patch literal 25453 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 z y<-d)STFDNQWSi26+l@}+ z1Y4N0A;JZJy z4*V9fIaBbg8t2jf7V_IjDlW(f8aH4oF0Nr{A-{vZ-H`!pd}Tgy9EcjYq2IwmeixP9 z>CM}^Ac`D+q62+Nhs1`)IdR>~3k!h|TpXg8TXw7H5Xr_RQy>^|=hC5{e@2YDQI%UI zKm~%KpBOylnme@6FG76b>L&1gE)+PLW~zT;vV!&x{FWA53#os_+*cw1JsG|Ln`gdh`hDZ9Cz4P{(Mj?}ocTbFf80p`r8V3U;z~c&#OW6aqa3EaV z$77{@*>5&SVU>o>z2-265J$e?ny;p-;Yf4f@3M7Me^I^}5U2sbP8jJf0DuKOUN2!~Ftoo9hZ0n^u?@3J zYYxns>90C=*0FQnVrToTICfsLAvcVenxr^Cv-mJX*IX6>_5Dh5FKNyw_QjlTC4EzW z#M~06kf~I~G5m{5HSbCTfAmP)K>Oy)5#s``LGnP@v-GotQw1;hGk90yiKI4halhBG zbivIN@#h!UAVEB89n}TrS6^lH*Kgrp+PO~+y-C9G%gmVK70a}M=Xsr3=4!eifkDp^ z_fPjMuHe?;`F>@*25H+f8nq6LteJTFgOQeN(ekd^hq6IZXP0iQB{t zc`v&AC(zNjQZi+ODUw~awc}2StqE>}ls6z{q+CWummw~;z967ZKyK_+2$@l+q@FLJ-AoLxjN46S)4m-m7Flw4*g2N`styBcq192h1Jv= z5intBn?W!mb~@ct$HJYk-(84>d!Od1Qy(>os8Pf_LJ{qfgXo!vxXyw(Azp9IoP^`` zmd#23KLj+?i|3txGu2%H429bK_Ao;o`Rd5GZ;`K4a*TYvjrFhJQNOLN^sDyJf1(et za4x_?gFvDA=6V+IwMy-n*H++A8NOAp-Yx%bcFUjjN)9#OfLiY*nF(PTOdN3TF4^su zH1OITe;HPm?D|VO^oV$nNR44;6+|M4?louD(Li6gLTXHZ^beItf>M-?Zkb0WNRbCX z1P$Q{Nw7I{BvKq{_fAGcfxb{gJ|L~`PT+2EkKvDbJ7>L#?^EyWxa81eynXbeYDyy~3hYvs3N8R;#nDZC|5vVpf0sXY;Yuw8N!lvr}vMYc%{r z$;m)HClLZzL%}1$jp=vP+$Pj}&RDJ8??SszOU~`g=EU@M4s*KVC9p^QZ~2M8lOgrX zblJjq-tv;A@rve+7R+f$iVa~_10CH4tyULM^x}elS1*KDNRgY7)%B|++-7#AwRC1$ z{g-gdt51|3l&eg>sqxdw1l69Wj?PMsVGlHz|`k6W@sRG-JGpSx6gO<2w>w)lOgUaNb$iBCN3?U$QSu+hQOnA&4RnM1XRx(_dK6}9!Hh)%0RR68 L-M9-cS$Y5f@zzlj delta 2706 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", + Usage: "Announce a deal to indexers so they can download its index", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "color", + Usage: "use color in display output", + DefaultText: "depends on output being a TTY", + }, + }, + Action: func(cctx *cli.Context) error { + if cctx.IsSet("color") { + color.NoColor = !cctx.Bool("color") + } + + if cctx.NArg() != 1 { + return fmt.Errorf("must provide the deal proposal CID") + } + + proposalCidStr := cctx.Args().First() + proposalCid, err := cid.Parse(proposalCidStr) + if err != nil { + return fmt.Errorf("invalid deal proposal CID: %w", proposalCid) + } + + marketsApi, closer, err := lcli.GetMarketsAPI(cctx) + if err != nil { + return err + } + defer closer() + + ctx := lcli.ReqContext(cctx) + + return marketsApi.IndexerAnnounceDeal(ctx, proposalCid) + }, +} diff --git a/cmd/lotus-miner/main.go b/cmd/lotus-miner/main.go index 110748f482d..7bb923ac651 100644 --- a/cmd/lotus-miner/main.go +++ b/cmd/lotus-miner/main.go @@ -49,6 +49,7 @@ func main() { lcli.WithCategory("market", retrievalDealsCmd), lcli.WithCategory("market", dataTransfersCmd), lcli.WithCategory("market", dagstoreCmd), + lcli.WithCategory("market", indexProvCmd), lcli.WithCategory("storage", sectorsCmd), lcli.WithCategory("storage", provingCmd), lcli.WithCategory("storage", storageCmd), diff --git a/documentation/en/api-v0-methods-miner.md b/documentation/en/api-v0-methods-miner.md index 4d14bcb0e34..c44c312b693 100644 --- a/documentation/en/api-v0-methods-miner.md +++ b/documentation/en/api-v0-methods-miner.md @@ -43,6 +43,8 @@ * [DealsSetPieceCidBlocklist](#DealsSetPieceCidBlocklist) * [I](#I) * [ID](#ID) +* [Indexer](#Indexer) + * [IndexerAnnounceDeal](#IndexerAnnounceDeal) * [Log](#Log) * [LogAlerts](#LogAlerts) * [LogList](#LogList) @@ -663,6 +665,27 @@ Inputs: `null` Response: `"12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf"` +## Indexer + + +### IndexerAnnounceDeal +IndexerAnnounceDeal informs indexer nodes that a new deal was received, +so they can download its index + + +Perms: + +Inputs: +```json +[ + { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + } +] +``` + +Response: `{}` + ## Log diff --git a/documentation/en/cli-lotus-miner.md b/documentation/en/cli-lotus-miner.md index d5b94fb8965..62d2d2a16f4 100644 --- a/documentation/en/cli-lotus-miner.md +++ b/documentation/en/cli-lotus-miner.md @@ -30,6 +30,7 @@ COMMANDS: retrieval-deals Manage retrieval deals and related configuration data-transfers Manage data transfers dagstore Manage the dagstore on the markets subsystem + index Manage the index provider on the markets subsystem NETWORK: net Manage P2P Network RETRIEVAL: @@ -1114,6 +1115,37 @@ OPTIONS: ``` +## lotus-miner index +``` +NAME: + lotus-miner index - Manage the index provider on the markets subsystem + +USAGE: + lotus-miner index command [command options] [arguments...] + +COMMANDS: + announce Announce a deal to indexers so they can download its index + help, h Shows a list of commands or help for one command + +OPTIONS: + --help, -h show help (default: false) + +``` + +### lotus-miner index announce +``` +NAME: + lotus-miner index announce - Announce a deal to indexers so they can download its index + +USAGE: + lotus-miner index announce [command options] + +OPTIONS: + --color use color in display output (default: depends on output being a TTY) + --help, -h show help (default: false) + +``` + ## lotus-miner net ``` NAME: diff --git a/documentation/en/default-lotus-miner-config.toml b/documentation/en/default-lotus-miner-config.toml index d402f65edca..e99b908b29b 100644 --- a/documentation/en/default-lotus-miner-config.toml +++ b/documentation/en/default-lotus-miner-config.toml @@ -246,6 +246,34 @@ #Path = "" +[IndexerProvider] + # env var: LOTUS_INDEXERPROVIDER_LINKCACHESIZE + #LinkCacheSize = 0 + + # env var: LOTUS_INDEXERPROVIDER_LINKEDCHUNKSIZE + #LinkedChunkSize = 0 + + # env var: LOTUS_INDEXERPROVIDER_PUBSUBTOPIC + #PubSubTopic = "" + + # env var: LOTUS_INDEXERPROVIDER_PURGELINKCACHE + #PurgeLinkCache = false + + # Binding address for the libp2p host - 0 means random port. + # Format: multiaddress; see https://multiformats.io/multiaddr/ + # + # type: []string + # env var: LOTUS_INDEXERPROVIDER_LISTENADDRESSES + #ListenAddresses = ["/ip4/0.0.0.0/tcp/0", "/ip6/::/tcp/0"] + + # The maximum number of simultaneous data transfers between the indexers + # and the indexer provider + # + # type: uint64 + # env var: LOTUS_INDEXERPROVIDER_MAXSIMULTANEOUSTRANSFERS + #MaxSimultaneousTransfers = 20 + + [Sealing] # Upper bound on how many sectors can be waiting for more deals to be packed in it before it begins sealing at any given time. # If the miner is accepting multiple deals in parallel, up to MaxWaitDealsSectors of new sectors will be created. diff --git a/node/impl/storminer.go b/node/impl/storminer.go index 39baa97bf25..692d3b6d9c0 100644 --- a/node/impl/storminer.go +++ b/node/impl/storminer.go @@ -832,6 +832,10 @@ func (sm *StorageMinerAPI) DagstoreGC(ctx context.Context) ([]api.DagstoreShardR return ret, nil } +func (sm *StorageMinerAPI) IndexerAnnounceDeal(ctx context.Context, proposalCid cid.Cid) error { + return sm.StorageProvider.AnnounceDealToIndexer(ctx, proposalCid) +} + func (sm *StorageMinerAPI) DealsList(ctx context.Context) ([]api.MarketDeal, error) { return sm.listDeals(ctx) } From 60fe55cdc09bb0fbb1833465fa71dd3f15ea4246 Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Wed, 17 Nov 2021 15:25:25 +0400 Subject: [PATCH 017/385] fix lint and gen --- .../en/default-lotus-miner-config.toml | 28 +++++++++++++++++++ itests/deals_anycid_test.go | 7 +++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/documentation/en/default-lotus-miner-config.toml b/documentation/en/default-lotus-miner-config.toml index d402f65edca..e99b908b29b 100644 --- a/documentation/en/default-lotus-miner-config.toml +++ b/documentation/en/default-lotus-miner-config.toml @@ -246,6 +246,34 @@ #Path = "" +[IndexerProvider] + # env var: LOTUS_INDEXERPROVIDER_LINKCACHESIZE + #LinkCacheSize = 0 + + # env var: LOTUS_INDEXERPROVIDER_LINKEDCHUNKSIZE + #LinkedChunkSize = 0 + + # env var: LOTUS_INDEXERPROVIDER_PUBSUBTOPIC + #PubSubTopic = "" + + # env var: LOTUS_INDEXERPROVIDER_PURGELINKCACHE + #PurgeLinkCache = false + + # Binding address for the libp2p host - 0 means random port. + # Format: multiaddress; see https://multiformats.io/multiaddr/ + # + # type: []string + # env var: LOTUS_INDEXERPROVIDER_LISTENADDRESSES + #ListenAddresses = ["/ip4/0.0.0.0/tcp/0", "/ip6/::/tcp/0"] + + # The maximum number of simultaneous data transfers between the indexers + # and the indexer provider + # + # type: uint64 + # env var: LOTUS_INDEXERPROVIDER_MAXSIMULTANEOUSTRANSFERS + #MaxSimultaneousTransfers = 20 + + [Sealing] # Upper bound on how many sectors can be waiting for more deals to be packed in it before it begins sealing at any given time. # If the miner is accepting multiple deals in parallel, up to MaxWaitDealsSectors of new sectors will be created. diff --git a/itests/deals_anycid_test.go b/itests/deals_anycid_test.go index b7799f2980c..87bb93562fe 100644 --- a/itests/deals_anycid_test.go +++ b/itests/deals_anycid_test.go @@ -7,13 +7,14 @@ import ( "testing" "time" + selectorparse "github.com/ipld/go-ipld-prime/traversal/selector/parse" + "github.com/filecoin-project/go-state-types/abi" ipld "github.com/ipfs/go-ipld-format" "github.com/ipld/go-car" "github.com/ipld/go-car/v2/blockstore" "github.com/stretchr/testify/require" - "github.com/filecoin-project/go-fil-markets/shared" "github.com/filecoin-project/go-fil-markets/storagemarket" "github.com/filecoin-project/lotus/api" @@ -82,7 +83,7 @@ func TestDealRetrieveByAnyCid(t *testing.T) { require.NoError(t, err) // Get all CIDs from the file - sc := car.NewSelectiveCar(ctx, bs, []car.Dag{{Root: res.Root, Selector: shared.AllSelector()}}) + sc := car.NewSelectiveCar(ctx, bs, []car.Dag{{Root: res.Root, Selector: selectorparse.CommonSelector_ExploreAllRecursively}}) prepared, err := sc.Prepare() require.NoError(t, err) cids := prepared.Cids() @@ -147,7 +148,7 @@ func TestDealRetrieveByAnyCid(t *testing.T) { rd, []car.Dag{{ Root: targetCid, - Selector: shared.AllSelector(), + Selector: selectorparse.CommonSelector_ExploreAllRecursively, }}, ).Write(tmp) require.NoError(t, err) From 599a6bfb246d0cbb1174573d3b4f5348e2bd3871 Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Wed, 17 Nov 2021 12:37:15 +0100 Subject: [PATCH 018/385] fix: err message --- cmd/lotus-miner/index_provider.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/lotus-miner/index_provider.go b/cmd/lotus-miner/index_provider.go index 584e203dcf7..fa9574460e2 100644 --- a/cmd/lotus-miner/index_provider.go +++ b/cmd/lotus-miner/index_provider.go @@ -42,7 +42,7 @@ var indexProvAnnounceCmd = &cli.Command{ proposalCidStr := cctx.Args().First() proposalCid, err := cid.Parse(proposalCidStr) if err != nil { - return fmt.Errorf("invalid deal proposal CID: %w", proposalCid) + return fmt.Errorf("invalid deal proposal CID: %w", err) } marketsApi, closer, err := lcli.GetMarketsAPI(cctx) From 5454aebf13a563ddb55a5790e29b91190e0f7b22 Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Wed, 17 Nov 2021 15:39:45 +0200 Subject: [PATCH 019/385] CLI tools for the DAGStore inverted index (#7361) * cli commands for dagstore * address comments from Dirk * rename inverted index to piece index --- api/api_storage.go | 8 +- api/proxy_gen.go | 28 ++++- build/openrpc/full.json.gz | Bin 25453 -> 25456 bytes build/openrpc/miner.json.gz | Bin 10575 -> 10721 bytes build/openrpc/worker.json.gz | Bin 2713 -> 2710 bytes cmd/lotus-miner/dagstore.go | 148 ++++++++++++++++++----- documentation/en/api-v0-methods-miner.md | 31 ++++- documentation/en/cli-lotus-miner.md | 30 +++++ node/impl/storminer.go | 51 ++++++++ 9 files changed, 261 insertions(+), 35 deletions(-) diff --git a/api/api_storage.go b/api/api_storage.go index fc2f58a2634..21c2d968824 100644 --- a/api/api_storage.go +++ b/api/api_storage.go @@ -212,7 +212,13 @@ type StorageMiner interface { // IndexerAnnounceDeal informs indexer nodes that a new deal was received, // so they can download its index - IndexerAnnounceDeal(ctx context.Context, proposalCid cid.Cid) error + IndexerAnnounceDeal(ctx context.Context, proposalCid cid.Cid) error //perm:admin + + // DagstorePieceIndexSize returns the size of the piece index. + DagstorePieceIndexSize(ctx context.Context) (int64, error) //perm:admin + + // DagstoreLookupPieces returns information about shards that contain the given CID. + DagstoreLookupPieces(ctx context.Context, cid cid.Cid) ([]DagstoreShardInfo, error) //perm:admin // RuntimeSubsystems returns the subsystems that are enabled // in this instance. diff --git a/api/proxy_gen.go b/api/proxy_gen.go index 0ce7ee8dd88..06b3a16625d 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -623,6 +623,10 @@ type StorageMinerStruct struct { DagstoreListShards func(p0 context.Context) ([]DagstoreShardInfo, error) `perm:"read"` + DagstoreLookupPieces func(p0 context.Context, p1 cid.Cid) ([]DagstoreShardInfo, error) `perm:"admin"` + + DagstorePieceIndexSize func(p0 context.Context) (int64, error) `perm:"admin"` + DagstoreRecoverShard func(p0 context.Context, p1 string) error `perm:"write"` DealsConsiderOfflineRetrievalDeals func(p0 context.Context) (bool, error) `perm:"admin"` @@ -657,7 +661,7 @@ type StorageMinerStruct struct { DealsSetPieceCidBlocklist func(p0 context.Context, p1 []cid.Cid) error `perm:"admin"` - IndexerAnnounceDeal func(p0 context.Context, p1 cid.Cid) error `` + IndexerAnnounceDeal func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` MarketCancelDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` @@ -3694,6 +3698,28 @@ func (s *StorageMinerStub) DagstoreListShards(p0 context.Context) ([]DagstoreSha return *new([]DagstoreShardInfo), ErrNotSupported } +func (s *StorageMinerStruct) DagstoreLookupPieces(p0 context.Context, p1 cid.Cid) ([]DagstoreShardInfo, error) { + if s.Internal.DagstoreLookupPieces == nil { + return *new([]DagstoreShardInfo), ErrNotSupported + } + return s.Internal.DagstoreLookupPieces(p0, p1) +} + +func (s *StorageMinerStub) DagstoreLookupPieces(p0 context.Context, p1 cid.Cid) ([]DagstoreShardInfo, error) { + return *new([]DagstoreShardInfo), ErrNotSupported +} + +func (s *StorageMinerStruct) DagstorePieceIndexSize(p0 context.Context) (int64, error) { + if s.Internal.DagstorePieceIndexSize == nil { + return 0, ErrNotSupported + } + return s.Internal.DagstorePieceIndexSize(p0) +} + +func (s *StorageMinerStub) DagstorePieceIndexSize(p0 context.Context) (int64, error) { + return 0, ErrNotSupported +} + func (s *StorageMinerStruct) DagstoreRecoverShard(p0 context.Context, p1 string) error { if s.Internal.DagstoreRecoverShard == nil { return ErrNotSupported diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 68f5e80cc46d1aa9137e152e97f358580a4ad40f..810bd301719b6fe2a459c9dcb7daf53915232e0f 100644 GIT binary patch literal 25456 zcmb4~Q8<}Y7$hH?Ntby%NH^Znz_VKGC80B12g9I?E1$S;bh@j~GI;To6o z-#7aULyEb3U8{etf&Ibz33s^i1Y~yJmoj<4XZ7wv<1=n_)UJV1Kv+EBdUq4BFZ_w;{(K)fsWVBrzqfr;{-2D%8|MBY`;K3Vq0P(l47eiu!tvVBhMp}F#R z6Y$xOX8C`wp1o;urVZ-PaG#uds#-DjkU_#8Pz4@_BfuW^F?NZ7#Jqw4k%V`E%!{#! zb}Ac@#{dd(Xb`}KLm=*eFT&uQJ{uvyz3?)OXMu&|xs(x*;&>6%`v`@P<}i%_c7(15 z3d8Lr>UJLu0n9HZLjvC>28X5dnP~b-{c<%yf8_Rq&G}W$h=$fPr)+3#C_on2WR z$NXjI{C_X?c?FSObUByjx**Eqf#O7cC7t?C|KRzqPW#+WCqy6P3(FYPdx+y)7%`#c z!!b4Yk-ODp72zEQdOQ~6Cn`U{x+s2sj>en#o!`+PISjtjdXn+wZE%q=2S9cDJ%f;cx}MGN*D;TA zK>3C8{VcvFb|MrGc_i$Nwu##-`RkD z*Ij7)3F zmbEPwZyE--v2tH|1m##Zs%+Rc=n$8B%h;7phSFdop@Z%KB{TLL;m#uL zJ0aWEbno+p=BX349uKBu#2+`E^4_(4TXmV)<`cj>K6$>Wcd6p4*9rB*xwXYLblKRB zUb{3_E~=;=Zt9HIeo6N$qXz=SDg;C%S4)K2#m~xd3FmlOr3uS&=7$6`qa((Nw}ZIh z8KZ+3Ju`~5_vgWQ7N=KEDO?eWw*l(13&aqj@3ptkI*foCp=N8sVg&K0NG*dS;3%VW z?ydU-EF zg8L1G3kv3RCjX2E#JPIh50IUo`i#x{AFc(76gH+}P~dPQGK_ zsKlaZ4PTItW4^jwatM2kkk;FcV-#sge+bneMJweeI4d%sEQ`Uq6(OEU?g}v+@-=@l zd=GgaL&UBeW6qMKon*m7SfrramHOsZ9s+6e9|8gG3Er{rHg~UIy?m{0U>0qB<)@RU z2a*ymZ(@lTh`3xFogoV7t?Y^e3%E5pt0V2TA)n{=KtZT3Rlc(D+P@Qu% zOAirG-t9iOdGqXz{{(OO5+S7n3E?4Gfg^#w%WU;VYy=ZGPwIs5!g*Qix$O{6i@DYq@oEaCbZBb;8O6H#_u*$}5NCSLS7~=EA(cpx zEri^r9{0Y3x4Anp1T-r}_AygSP!A&m4OQB#i6IXM*h0N0{Vr_l)evPKu9t^D0 zZ0c8SfwNc*#${H<)3}GZa<1nmlW1E3KGrhwXVt6LiqW%ZAa7g*$4Fa6T4w)y}mwMVa?j6L#B@P2z$7$g7-T+4m!%dNZuc!cL zn~)r3QfX%I^wJ%C?_+Qs_3iEEWAGH&;d%e@_LO|@@z0}waIyQ|Yn40s-qRzg$M4O@ z$JL_u-Tn6R^8Tm0`rZ{X2Z%cQZQQKfY}~;7`|07XNHlr=z@ORGBE7Qp%h{q(m+QmF zUHP5daD zyNw|g$D;<2ZYt+~RHrY?pM6HR=UrLWX&3P8kS|LC^Xd70?=d+=*KHis_R zKbM;|R&7@7+NxRlC|I5lV0C}~ocC;3tv>A#2VvON9iD$2>sftNA7g#03mI$H&YiDt zsU9OiU81&^-##fGXz(jb&0pNmWkObPWku~~3G{&cwLEnGqGocnqaSvQw;Z^&>8sSg zON6lL+H>_iEOyb|F?qf$%B}qg**YeRDgOl!R5!|bbKm(TYtYBZ&mDRRz$WUMQ2H@> zDgVB|sL4Fm9iB{DC7YrFBlhls0wE2*h6*O@W5qxQWqn8#--2}V$rdb_pTwY;07v}T zltj?JuW#Mu=HsT!V}%dzjUH(m0J!B$DdfzjS$kXFewz997I8ZzKF$ALzrHaM`{Tps za$9z17yscuUojbzRsRBe-)!6z1LD%ABSC;v|+jTjIH%=E$Q{MrfWa6 zv!YWQx@PN>R^-DoZpc$e=gv_uM_%~44GCm2Uw?LQ@ONj2w96f*z4(4>MT5~LQ$GY%${2pi zK7J%m39$bjlX_}NbfXJUbN&;q)>?|%Rk?Vtj86>elalva|9*ON>GeaYVQ8I4nWuU$ z`3xE2qysgBEyzL2W>}+bB1C?o~%2xp6MQj7JS1) z&JX{a)K!mJZQF9LsxJSgw>496b7Hxl(7_5k#@4hoHxEH&imi{WKow)iDKnv{b~vy< zh#~>xQeuNInh$6F;gM4Y4?RyKqCHaedU3-rx<&S~pc|_$KAmxQQEe!<%5u7;sNRy( z)f|ud=3(Vi=EGCQd~hiEWFQh8QjzZ9j7ms4J3a6WLTYQl&IjKlk&PCU1SmBpEvK&( zl!Bg(0@GA25y|lfrtYt0=vwS0bv&2k5Tjd-isz70smo@{SVpDOWh%$*4Ffv<;2O&p zw{Y0YwsZ%h+VhTI_g|AfI*R}kT%X1uh<#+?E(`p(uF}>8bbJJtc=Ch{DnK74dV!=D zttePdGDa}LN2b65@`enAZfT=;)D?R{a6r)wdFIdL3O&M>uN+e);UplP)M zleL}lR9>wOgw_W#0Z)i@@k*7!!sari=CF5(V(36es-=btdk8bF<3hyP5hf>JmC?Z< zN$H1CNN@%A1ml2IpTb1gL5Yo}-EHm&K}uT!79Z}z|Bmj`b%fNKy;{seBFAUFW8&~! zc*9)Cof2OlhVZMv?G@d>POnblNweeF3(RJ5fW zR*p=pS7%L@#jugtN0!xkrxB)M_7ejndn5yF8>Zo4ZE!QmpGe5lZ2X0^!bK|uG4zitQ10vWK&0SuUdt;DQRvBj>@v|_}GY0HWq(`yJG|YH)ya-<3 z>3&JqszY?vnwH$z7#Tk6Fp!@A_u|D$-cVF{I$j@HDt&A!0>pJ20( zD?ubq>KwuQv!4^;h?!a!zs5xsy7`DffuGG`onGg~MtZl5sicQ1{hoSgQ(8xN{cW#? z?>NM+COHHd(o`BlVd*>q3=S(auMGgk5pB{SbSac%2dIzvdf`+6(|#te_8Ug_w}Lcu z%~$nQ%x9R;9+tx8m^45LO9egf&WY~pfhFyhYmjC0h5t;=GDyYV?4 zTq-%xj|Hn6)?+gBQ z_ZGi#@Aa3;*a|*c;oc}y!YXf7}9c)w8FQbCi zE7Buip7u!&fo4Vyc_iJkBI*%Tu@DocEW$pr(VRSthi*|gU4~Bn!%0Augxt&?M1iRc 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 NCFpmx-ai-63yZp4YW^JV7KdRsFxzcG>^ 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 AhX4Qo delta 1865 zcmV-P2e$Z@6`2*V`T~DGoStZz@<8MlMg}f8hBzdqDu5w}=wQIPy9^z~#Kqts8ZiSb zkg!r5`VC@yk=<)ya)T2WuC{NjB`LqC>42~|u1aSgidE@XQ1;kRkwO|XG@Cfus9g82 z0YwOBlbcsWjpO28s`#TF4*O^BfFY<2S=|<*osB~^I9ub^cZh#m%k+MGpl$<*E)Pue z7FtQ`ums{#Ho_^Uq!MAtW?*K{KUCw(;Ku&C}Lt2|S>Txb!>3b76=R zGQ_6ouUYvuVI$+PpXqsP@qbai84#!ez)l$HE&zZ9Jzg(iWiYhA4~G&|wXqGeOKT3y zn(41PcGj_T-(r7f`>Z&2Ua}!KjF_6FI6t%aFhti}76JABN^vh~&M5Z9oNgt3Q^ed7 zr;w>s#WDPgOEvFG1Ap{L+(7&0%Ms%Ou0irZ*t7Jrg;NDD_%nD{2r&AHFZF}moZG6Pwqi_F+oB#36Fc2m96ZmZZ$eddpF6JZoXZ>uZG?=^xn6a)@v8Xv@4><(lDBZG{xXMTEv5F#Gyb}T^5+a zrj~@HqV_$E!qSY_t-$Xh?n?3+xk}qjZk!W#12J06L0o-Pvs8RH@(MXj`ia}b4S6rR z`zO%RxKc7@gDH|-wYB3;lQIQxf4aqHb`35N31686V!rohf%->2i&^M;TPwA^g!O7| zr?BTPtk&wMG4+zLUJ~y0lJG;XEPjTYeoVurCMt`TWI$uTe|d2jMZn?!s2eGcdnWNM zW<_^h9MWdF&?fp_jWvqgP>f5XmRneg(hQVFN=e-7aQ(zU%K6c_&}N9O=p*E6^x}hc;qjX2 zA*z48(8W1*q#?*niLot!n;ogeJ;z#%8tCpsMBN3To41ZVJStae=Wklp{6^;mkG1tx zOW4zSoH30DC3MJ4p-Tstf1*R0*5o8%`hQr%q(<&|h11f0y`tBer&;FyWs6*T5UXWZ3NuX*Zah1OfCqkG*IOu*voe zU1id_*?gvl!Gv;?Agf-G)(g_NjG50$4sj-UE+4+DV&;zdz8hT{f5XV%1GP5H?Q9?B zcIq7NuG!`;K-;_$zdg8D$GJMr?OB{VYn7ZZ*AD$k!20Q-gm@zvqJ`De8WAvIXq!PW zBX&C7Q^&%cu-{#Xg?pdosZ$>{il|YM-?e{PvaCPM1j6gL_Q#`?oQxtaF5}Sc{^vliSJYI?6~C6WW0U!qvM39;!F)EOI^Om z5|oXW*-y5eR~u1|t#V7+*or932~~SRV*33fn|vYRyVL5ElH-Yg5czNs`94F9PEnR> zGZ0rhL>YDyf4#z@RI^jir!MmBXC z=hQKL;*#QjTaR0^LsXx~sh_)4dQDi)EVlT4r(Uajx`|Ib?d_MU_H6%5{s2tuJy*|6 z;U<@Ce_Q9&K|*&gfhjGD1b288)frGWilPKlh&YY_DZxQ>-dY1)Dm?&0ENYFb5IzS=Sm9Ic{VX zXETRw>JLTKPburClp1Otw^}8qSz=o@gqbl_fAJD+?jFivUR-4f#EWYfA-jaDt-N2a zY^aj*Ek)68yW2TkJC5$CLbgk`o&QOw`gcG<8LH%*u23mUlV5YP*XF*`{THiW($&D_ z_Jc$LQ`ALj3<3}lfLQdDP9hO77Czg1rN+LqWYlr1bBd?ayXpS|00960-M9-cS$Y5f DQt7=m diff --git a/cmd/lotus-miner/dagstore.go b/cmd/lotus-miner/dagstore.go index 6522b02dc0c..c79906b782b 100644 --- a/cmd/lotus-miner/dagstore.go +++ b/cmd/lotus-miner/dagstore.go @@ -4,7 +4,9 @@ import ( "fmt" "os" + "github.com/dustin/go-humanize" "github.com/fatih/color" + "github.com/ipfs/go-cid" "github.com/urfave/cli/v2" "github.com/filecoin-project/lotus/api" @@ -21,6 +23,8 @@ var dagstoreCmd = &cli.Command{ dagstoreRecoverShardCmd, dagstoreInitializeAllCmd, dagstoreGcCmd, + dagstorePieceIndexSizeCmd, + dagstoreLookupPiecesCmd, }, } @@ -52,38 +56,7 @@ var dagstoreListShardsCmd = &cli.Command{ return err } - if len(shards) == 0 { - return nil - } - - tw := tablewriter.New( - tablewriter.Col("Key"), - tablewriter.Col("State"), - tablewriter.Col("Error"), - ) - - colors := map[string]color.Attribute{ - "ShardStateAvailable": color.FgGreen, - "ShardStateServing": color.FgBlue, - "ShardStateErrored": color.FgRed, - "ShardStateNew": color.FgYellow, - } - - for _, s := range shards { - m := map[string]interface{}{ - "Key": s.Key, - "State": func() string { - if c, ok := colors[s.State]; ok { - return color.New(c).Sprint(s.State) - } - return s.State - }(), - "Error": s.Error, - } - tw.Write(m) - } - - return tw.Flush(os.Stdout) + return printTableShards(shards) }, } @@ -265,3 +238,114 @@ var dagstoreGcCmd = &cli.Command{ return nil }, } + +func printTableShards(shards []api.DagstoreShardInfo) error { + if len(shards) == 0 { + return nil + } + + tw := tablewriter.New( + tablewriter.Col("Key"), + tablewriter.Col("State"), + tablewriter.Col("Error"), + ) + + colors := map[string]color.Attribute{ + "ShardStateAvailable": color.FgGreen, + "ShardStateServing": color.FgBlue, + "ShardStateErrored": color.FgRed, + "ShardStateNew": color.FgYellow, + } + + for _, s := range shards { + m := map[string]interface{}{ + "Key": s.Key, + "State": func() string { + if c, ok := colors[s.State]; ok { + return color.New(c).Sprint(s.State) + } + return s.State + }(), + "Error": s.Error, + } + tw.Write(m) + } + return tw.Flush(os.Stdout) +} + +var dagstorePieceIndexSizeCmd = &cli.Command{ + Name: "piece-index-size", + Usage: "Inspect the dagstore piece index size", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "color", + Usage: "use color in display output", + DefaultText: "depends on output being a TTY", + }, + }, + Action: func(cctx *cli.Context) error { + if cctx.IsSet("color") { + color.NoColor = !cctx.Bool("color") + } + + marketsApi, closer, err := lcli.GetMarketsAPI(cctx) + if err != nil { + return err + } + defer closer() + + ctx := lcli.ReqContext(cctx) + + size, err := marketsApi.DagstorePieceIndexSize(ctx) + if err != nil { + return err + } + + fmt.Println(humanize.Bytes(uint64(size))) + + return nil + }, +} + +var dagstoreLookupPiecesCmd = &cli.Command{ + Name: "lookup-pieces", + Usage: "Lookup pieces that a given CID belongs to", + ArgsUsage: "", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "color", + Usage: "use color in display output", + DefaultText: "depends on output being a TTY", + }, + }, + Action: func(cctx *cli.Context) error { + if cctx.IsSet("color") { + color.NoColor = !cctx.Bool("color") + } + + if cctx.NArg() != 1 { + return fmt.Errorf("must provide a CID") + } + + cidStr := cctx.Args().First() + cid, err := cid.Parse(cidStr) + if err != nil { + return fmt.Errorf("invalid CID: %w", err) + } + + marketsApi, closer, err := lcli.GetMarketsAPI(cctx) + if err != nil { + return err + } + defer closer() + + ctx := lcli.ReqContext(cctx) + + shards, err := marketsApi.DagstoreLookupPieces(ctx, cid) + if err != nil { + return err + } + + return printTableShards(shards) + }, +} diff --git a/documentation/en/api-v0-methods-miner.md b/documentation/en/api-v0-methods-miner.md index c44c312b693..24b032636fb 100644 --- a/documentation/en/api-v0-methods-miner.md +++ b/documentation/en/api-v0-methods-miner.md @@ -23,6 +23,8 @@ * [DagstoreInitializeAll](#DagstoreInitializeAll) * [DagstoreInitializeShard](#DagstoreInitializeShard) * [DagstoreListShards](#DagstoreListShards) + * [DagstoreLookupPieces](#DagstoreLookupPieces) + * [DagstorePieceIndexSize](#DagstorePieceIndexSize) * [DagstoreRecoverShard](#DagstoreRecoverShard) * [Deals](#Deals) * [DealsConsiderOfflineRetrievalDeals](#DealsConsiderOfflineRetrievalDeals) @@ -444,6 +446,33 @@ Inputs: `null` Response: `null` +### DagstoreLookupPieces +DagstoreLookupPieces returns information about shards that contain the given CID. + + +Perms: admin + +Inputs: +```json +[ + { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + } +] +``` + +Response: `null` + +### DagstorePieceIndexSize +DagstorePieceIndexSize returns the size of the piece index. + + +Perms: admin + +Inputs: `null` + +Response: `9` + ### DagstoreRecoverShard DagstoreRecoverShard attempts to recover a failed shard. @@ -673,7 +702,7 @@ IndexerAnnounceDeal informs indexer nodes that a new deal was received, so they can download its index -Perms: +Perms: admin Inputs: ```json diff --git a/documentation/en/cli-lotus-miner.md b/documentation/en/cli-lotus-miner.md index 62d2d2a16f4..acf79adc4cb 100644 --- a/documentation/en/cli-lotus-miner.md +++ b/documentation/en/cli-lotus-miner.md @@ -1036,6 +1036,8 @@ COMMANDS: recover-shard Attempt to recover a shard in errored state initialize-all Initialize all uninitialized shards, streaming results as they're produced; only shards for unsealed pieces are initialized by default gc Garbage collect the dagstore + piece-index-size Inspect the dagstore piece index size + lookup-pieces Lookup pieces that a given CID belongs to help, h Shows a list of commands or help for one command OPTIONS: @@ -1115,6 +1117,34 @@ OPTIONS: ``` +### lotus-miner dagstore piece-index-size +``` +NAME: + lotus-miner dagstore piece-index-size - Inspect the dagstore piece index size + +USAGE: + lotus-miner dagstore piece-index-size [command options] [arguments...] + +OPTIONS: + --color use color in display output (default: depends on output being a TTY) + --help, -h show help (default: false) + +``` + +### lotus-miner dagstore lookup-pieces +``` +NAME: + lotus-miner dagstore lookup-pieces - Lookup pieces that a given CID belongs to + +USAGE: + lotus-miner dagstore lookup-pieces [command options] + +OPTIONS: + --color use color in display output (default: depends on output being a TTY) + --help, -h show help (default: false) + +``` + ## lotus-miner index ``` NAME: diff --git a/node/impl/storminer.go b/node/impl/storminer.go index 692d3b6d9c0..4a34eac8546 100644 --- a/node/impl/storminer.go +++ b/node/impl/storminer.go @@ -836,6 +836,57 @@ func (sm *StorageMinerAPI) IndexerAnnounceDeal(ctx context.Context, proposalCid return sm.StorageProvider.AnnounceDealToIndexer(ctx, proposalCid) } +func (sm *StorageMinerAPI) DagstorePieceIndexSize(ctx context.Context) (int64, error) { + if sm.DAGStore == nil { + return 0, fmt.Errorf("dagstore not available on this node") + } + + res, err := sm.DAGStore.TopLevelIndex.Size() + if err != nil { + return 0, fmt.Errorf("failed to get dagstore piece index size: %w", err) + } + + return res, nil +} + +func (sm *StorageMinerAPI) DagstoreLookupPieces(ctx context.Context, cid cid.Cid) ([]api.DagstoreShardInfo, error) { + if sm.DAGStore == nil { + return nil, fmt.Errorf("dagstore not available on this node") + } + + keys, err := sm.DAGStore.TopLevelIndex.GetShardsForMultihash(cid.Hash()) + if err != nil { + return nil, err + } + + var ret []api.DagstoreShardInfo + + for _, k := range keys { + shard, err := sm.DAGStore.GetShardInfo(k) + if err != nil { + return nil, err + } + + ret = append(ret, api.DagstoreShardInfo{ + Key: k.String(), + State: shard.ShardState.String(), + Error: func() string { + if shard.Error == nil { + return "" + } + return shard.Error.Error() + }(), + }) + } + + // order by key. + sort.SliceStable(ret, func(i, j int) bool { + return ret[i].Key < ret[j].Key + }) + + return ret, nil +} + func (sm *StorageMinerAPI) DealsList(ctx context.Context) ([]api.MarketDeal, error) { return sm.listDeals(ctx) } From 7655e660f3934a57dc9d957ece5e43e3c75b4195 Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Thu, 18 Nov 2021 12:07:12 +0400 Subject: [PATCH 020/385] integrate store-the-hash --- go.mod | 3 ++- go.sum | 8 ++++++-- itests/kit/client.go | 11 ++++++++--- itests/kit/deals_state.go | 2 +- markets/dagstore/wrapper.go | 17 ++++++++++------- markets/dagstore/wrapper_migration_test.go | 7 ++++++- markets/dagstore/wrapper_test.go | 10 ++++++++-- node/modules/storageminer_dagstore.go | 6 ++++-- 8 files changed, 45 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index 06a6799b6e2..6b0f24f3ed0 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/elastic/gosigar v0.14.1 github.com/etclabscore/go-openrpc-reflect v0.0.36 github.com/fatih/color v1.13.0 - github.com/filecoin-project/dagstore v0.5.0 + github.com/filecoin-project/dagstore v0.5.1-0.20211118071820-a75afb62d8ce github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200910194244-f640612a1a1f github.com/filecoin-project/go-address v0.0.6 github.com/filecoin-project/go-bitfield v0.2.4 @@ -37,6 +37,7 @@ require ( github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 github.com/filecoin-project/go-fil-markets v1.13.3-0.20211117072527-8713155662ff + github.com/filecoin-project/go-indexer-core v0.2.4 github.com/filecoin-project/go-jsonrpc v0.1.5 github.com/filecoin-project/go-padreader v0.0.1 github.com/filecoin-project/go-paramfetch v0.0.2 diff --git a/go.sum b/go.sum index 4831d889bfd..be18c532d47 100644 --- a/go.sum +++ b/go.sum @@ -302,8 +302,9 @@ github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/filecoin-project/dagstore v0.5.0 h1:akiheGtSCU7aGon6T74bwNbDhYW0XZCTsnORKNmzSgU= github.com/filecoin-project/dagstore v0.5.0/go.mod h1:Id2VG7uZxnF6NWR3JX1evNA83JonnU0U7Fc2r14Vltc= +github.com/filecoin-project/dagstore v0.5.1-0.20211118071820-a75afb62d8ce h1:cYK19JNHrVQD4nkh6b41wLU1TnxByaln+sc8AEtZT9I= +github.com/filecoin-project/dagstore v0.5.1-0.20211118071820-a75afb62d8ce/go.mod h1:bW1kjUKlVsQkITxKYlIdXHC8j/+wIgEl3caxUFJijGI= github.com/filecoin-project/go-address v0.0.3/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= github.com/filecoin-project/go-address v0.0.5/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= github.com/filecoin-project/go-address v0.0.6 h1:DWQtj38ax+ogHwyH3VULRIoT8E6loyXqsk/p81xoY7M= @@ -351,8 +352,9 @@ github.com/filecoin-project/go-hamt-ipld/v3 v3.0.1/go.mod h1:gXpNmr3oQx8l3o7qkGy github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0 h1:rVVNq0x6RGQIzCo1iiJlGFm9AGIZzeifggxtKMU7zmI= github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0/go.mod h1:bxmzgT8tmeVQA1/gvBwFmYdT8SOFUwB3ovSUfG1Ux0g= github.com/filecoin-project/go-indexer-core v0.2.2/go.mod h1:wV+NmrF8fHG6Xii3ecoZf2JW3laGTe5xtsWz609jo+Y= -github.com/filecoin-project/go-indexer-core v0.2.3 h1:kaUL2r8CuihK53lhmtCScffb7Bzs+N1yRGpwvxzCN+U= github.com/filecoin-project/go-indexer-core v0.2.3/go.mod h1:MSe5aRWmfRB+5syR4yDV+OApgJU+MUJ4rl9VUuzwCfc= +github.com/filecoin-project/go-indexer-core v0.2.4 h1:90vvxoBeNZN+h4W+vZ+VsoxKaDBr/bfZJJNByapGeM0= +github.com/filecoin-project/go-indexer-core v0.2.4/go.mod h1:MSe5aRWmfRB+5syR4yDV+OApgJU+MUJ4rl9VUuzwCfc= github.com/filecoin-project/go-jsonrpc v0.1.5 h1:ckxqZ09ivBAVf5CSmxxrqqNHC7PJm3GYGtYKiNQ+vGk= github.com/filecoin-project/go-jsonrpc v0.1.5/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4= github.com/filecoin-project/go-legs v0.0.0-20211013165050-9ab325b6d2eb/go.mod h1:lKwBnslfNGG7JnsP9uQZl3yK7f74fit1MyHcwuuOP3k= @@ -427,6 +429,7 @@ github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/gammazero/keymutex v0.0.2 h1:cmpLBJHdEwn+WlR5Z/o9/BN92znSZTp5AKPQDpu1QcI= github.com/gammazero/keymutex v0.0.2/go.mod h1:qtzWCCLMisQUmVa4dvqHVgwfh4BP2YB7JxNDGXnsKrs= github.com/gammazero/radixtree v0.2.5 h1:muPQ4eEgCkUymFWPiVQRuXOQv4IhWg8YXH2r71MoqPM= github.com/gammazero/radixtree v0.2.5/go.mod h1:VPqqCDZ3YZZxAzUUsIF/ytFBigVWV7JIV1Stld8hri0= @@ -909,6 +912,7 @@ github.com/ipld/go-ipld-prime-proto v0.0.0-20200922192210-9a2bfd4440a6/go.mod h1 github.com/ipld/go-ipld-prime-proto v0.1.0/go.mod h1:11zp8f3sHVgIqtb/c9Kr5ZGqpnCLF1IVTNOez9TopzE= github.com/ipld/go-ipld-selector-text-lite v0.0.0 h1:MLU1YUAgd3Z+RfVCXUbvxH1RQjEe+larJ9jmlW1aMgA= github.com/ipld/go-ipld-selector-text-lite v0.0.0/go.mod h1:U2CQmFb+uWzfIEF3I1arrDa5rwtj00PrpiwwCO+k1RM= +github.com/ipld/go-storethehash v0.0.0-20210915160027-d72ca9b0968c h1:izfvqCuEqk2V7BRkh7GCm7lyKC2ItyAbzUu4WgNmggc= github.com/ipld/go-storethehash v0.0.0-20210915160027-d72ca9b0968c/go.mod h1:PwE6iq8TiWJRI3zMGA1RtkFAnrDMK93dLA5SUeu0lH8= github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52 h1:QG4CGBqCeuBo6aZlGAamSkxWdgWfZGeE49eUOWJPA4c= github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52/go.mod h1:fdg+/X9Gg4AsAIzWpEHwnqd+QY3b7lajxyjE1m4hkq4= diff --git a/itests/kit/client.go b/itests/kit/client.go index c9f8946ec8c..9fb546d8c5c 100644 --- a/itests/kit/client.go +++ b/itests/kit/client.go @@ -106,9 +106,14 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode *TestFullNode) tmpdir, err := ioutil.TempDir(os.TempDir(), "test-cli-Client") require.NoError(t, err) path := filepath.Join(tmpdir, "outfile.dat") - out = clientCLI.RunCmd("client", "retrieve", dataCid.String(), path) - fmt.Println("retrieve:\n", out) - require.Regexp(t, regexp.MustCompile("Success"), out) + + for { + out = clientCLI.RunCmd("client", "retrieve", dataCid.String(), path) + fmt.Println("retrieve:\n", out) + if strings.Contains(out, "Success") { + break + } + } } func CreateImportFile(ctx context.Context, client api.FullNode, rseed int, size int) (res *api.ImportRes, path string, data []byte, err error) { diff --git a/itests/kit/deals_state.go b/itests/kit/deals_state.go index 617a6d28e8d..1a69e20b9a7 100644 --- a/itests/kit/deals_state.go +++ b/itests/kit/deals_state.go @@ -14,7 +14,7 @@ func CategorizeDealState(dealStatus string) TestDealState { switch dealStatus { case "StorageDealFailing", "StorageDealError": return TestDealStateFailed - case "StorageDealStaged", "StorageDealAwaitingPreCommit", "StorageDealSealing", "StorageDealActive", "StorageDealExpired", "StorageDealSlashed": + case "StorageDealAwaitingPreCommit", "StorageDealSealing", "StorageDealActive", "StorageDealExpired", "StorageDealSlashed": return TestDealStateComplete } return TestDealStateInProgress diff --git a/markets/dagstore/wrapper.go b/markets/dagstore/wrapper.go index 98c63361f45..34e848844c9 100644 --- a/markets/dagstore/wrapper.go +++ b/markets/dagstore/wrapper.go @@ -10,6 +10,9 @@ import ( "sync" "time" + "github.com/filecoin-project/go-indexer-core/store/storethehash" + "github.com/libp2p/go-libp2p-core/host" + carindex "github.com/ipld/go-car/v2/index" "github.com/ipfs/go-cid" @@ -56,7 +59,7 @@ type Wrapper struct { var _ stores.DAGStoreWrapper = (*Wrapper)(nil) -func NewDAGStore(cfg config.DAGStoreConfig, minerApi MinerAPI) (*dagstore.DAGStore, *Wrapper, error) { +func NewDAGStore(cfg config.DAGStoreConfig, minerApi MinerAPI, h host.Host) (*dagstore.DAGStore, *Wrapper, error) { // construct the DAG Store. registry := mount.NewRegistry() if err := registry.Register(lotusScheme, mountTemplate(minerApi)); err != nil { @@ -85,11 +88,11 @@ func NewDAGStore(cfg config.DAGStoreConfig, minerApi MinerAPI) (*dagstore.DAGSto return nil, nil, xerrors.Errorf("failed to initialise dagstore index repo: %w", err) } - //store, err := storethehash.New(indexDir) - //if err != nil { - //return nil, nil, xerrors.Errorf("failed to initialise store the index: %w", err) - //} - //topIndex := index.NewInverted(store) + store, err := storethehash.New(indexDir) + if err != nil { + return nil, nil, xerrors.Errorf("failed to initialise store the index: %w", err) + } + topIndex := index.NewInverted(store, h.ID()) dcfg := dagstore.Config{ TransientsDir: transientsDir, @@ -98,7 +101,7 @@ func NewDAGStore(cfg config.DAGStoreConfig, minerApi MinerAPI) (*dagstore.DAGSto MountRegistry: registry, FailureCh: failureCh, TraceCh: traceCh, - //TopLevelIndex: topIndex, + TopLevelIndex: topIndex, // not limiting fetches globally, as the Lotus mount does // conditional throttling. MaxConcurrentIndex: cfg.MaxConcurrentIndex, diff --git a/markets/dagstore/wrapper_migration_test.go b/markets/dagstore/wrapper_migration_test.go index 13d8db876d9..eaa78259097 100644 --- a/markets/dagstore/wrapper_migration_test.go +++ b/markets/dagstore/wrapper_migration_test.go @@ -4,6 +4,8 @@ import ( "context" "testing" + mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" + "github.com/filecoin-project/dagstore" "github.com/stretchr/testify/require" @@ -93,8 +95,11 @@ func TestShardRegistration(t *testing.T) { cfg := config.DefaultStorageMiner().DAGStore cfg.RootDir = t.TempDir() + h, err := mocknet.New(ctx).GenPeer() + require.NoError(t, err) + mapi := NewMinerAPI(ps, sa, 10) - dagst, w, err := NewDAGStore(cfg, mapi) + dagst, w, err := NewDAGStore(cfg, mapi, h) require.NoError(t, err) require.NotNil(t, dagst) require.NotNil(t, w) diff --git a/markets/dagstore/wrapper_test.go b/markets/dagstore/wrapper_test.go index 4cf53737377..235edecb114 100644 --- a/markets/dagstore/wrapper_test.go +++ b/markets/dagstore/wrapper_test.go @@ -8,6 +8,8 @@ import ( "testing" "time" + mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" + mh "github.com/multiformats/go-multihash" carindex "github.com/ipld/go-car/v2/index" @@ -31,11 +33,13 @@ func TestWrapperAcquireRecovery(t *testing.T) { pieceCid, err := cid.Parse("bafkqaaa") require.NoError(t, err) + h, err := mocknet.New(ctx).GenPeer() + require.NoError(t, err) // Create a DAG store wrapper dagst, w, err := NewDAGStore(config.DAGStoreConfig{ RootDir: t.TempDir(), GCInterval: config.Duration(1 * time.Millisecond), - }, mockLotusMount{}) + }, mockLotusMount{}, h) require.NoError(t, err) defer dagst.Close() //nolint:errcheck @@ -81,12 +85,14 @@ func TestWrapperAcquireRecovery(t *testing.T) { // TestWrapperBackground verifies the behaviour of the background go routine func TestWrapperBackground(t *testing.T) { ctx := context.Background() + h, err := mocknet.New(ctx).GenPeer() + require.NoError(t, err) // Create a DAG store wrapper dagst, w, err := NewDAGStore(config.DAGStoreConfig{ RootDir: t.TempDir(), GCInterval: config.Duration(1 * time.Millisecond), - }, mockLotusMount{}) + }, mockLotusMount{}, h) require.NoError(t, err) defer dagst.Close() //nolint:errcheck diff --git a/node/modules/storageminer_dagstore.go b/node/modules/storageminer_dagstore.go index 1f72a49b90e..3d0b101bd24 100644 --- a/node/modules/storageminer_dagstore.go +++ b/node/modules/storageminer_dagstore.go @@ -7,6 +7,8 @@ import ( "path/filepath" "strconv" + "github.com/libp2p/go-libp2p-core/host" + "go.uber.org/fx" "golang.org/x/xerrors" @@ -63,7 +65,7 @@ func NewMinerAPI(lc fx.Lifecycle, r repo.LockedRepo, pieceStore dtypes.ProviderP // DAGStore constructs a DAG store using the supplied minerAPI, and the // user configuration. It returns both the DAGStore and the Wrapper suitable for // passing to markets. -func DAGStore(lc fx.Lifecycle, r repo.LockedRepo, minerAPI mdagstore.MinerAPI) (*dagstore.DAGStore, *mdagstore.Wrapper, error) { +func DAGStore(lc fx.Lifecycle, r repo.LockedRepo, minerAPI mdagstore.MinerAPI, h host.Host) (*dagstore.DAGStore, *mdagstore.Wrapper, error) { cfg, err := extractDAGStoreConfig(r) if err != nil { return nil, nil, err @@ -82,7 +84,7 @@ func DAGStore(lc fx.Lifecycle, r repo.LockedRepo, minerAPI mdagstore.MinerAPI) ( } } - dagst, w, err := mdagstore.NewDAGStore(cfg, minerAPI) + dagst, w, err := mdagstore.NewDAGStore(cfg, minerAPI, h) if err != nil { return nil, nil, xerrors.Errorf("failed to create DAG store: %w", err) } From 780c40329ee93fcdb48be6418b58fbce4b787bb4 Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Thu, 2 Dec 2021 12:32:17 +0000 Subject: [PATCH 021/385] Upgrade to the latest indexer dependencies Do not upgrade to the latest storetheindex, because it uses go-ipfs for bootstrapping mechanism and that comes with dependencies that we don not wish to upgrade in lotus just now; namely: - go-bitswap - go-path - interface-go-ipfs-core - go-libp2p-kad-dht - go-libp2p-quic-transport --- go.mod | 8 +++++--- go.sum | 26 ++++++++++++++++++-------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/go.mod b/go.mod index 6b0f24f3ed0..67567124271 100644 --- a/go.mod +++ b/go.mod @@ -37,15 +37,16 @@ require ( github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 github.com/filecoin-project/go-fil-markets v1.13.3-0.20211117072527-8713155662ff - github.com/filecoin-project/go-indexer-core v0.2.4 + github.com/filecoin-project/go-indexer-core v0.2.6 github.com/filecoin-project/go-jsonrpc v0.1.5 + github.com/filecoin-project/go-legs v0.0.0-20211202193658-45deff4405e1 // indirect github.com/filecoin-project/go-padreader v0.0.1 github.com/filecoin-project/go-paramfetch v0.0.2 github.com/filecoin-project/go-state-types v0.1.1 github.com/filecoin-project/go-statemachine v1.0.1 github.com/filecoin-project/go-statestore v0.1.1 github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b - github.com/filecoin-project/index-provider v0.0.0-20211117103856-70cd9b7ab68b + github.com/filecoin-project/index-provider v0.0.0-20211117105122-6ee67478aad8 github.com/filecoin-project/specs-actors v0.9.14 github.com/filecoin-project/specs-actors/v2 v2.3.5 github.com/filecoin-project/specs-actors/v3 v3.1.1 @@ -53,6 +54,7 @@ require ( github.com/filecoin-project/specs-actors/v5 v5.0.4 github.com/filecoin-project/specs-actors/v6 v6.0.1 github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506 + github.com/filecoin-project/storetheindex v0.0.0-20211126125638-1f013514c397 // indirect github.com/filecoin-project/test-vectors/schema v0.0.5 github.com/gbrlsnchs/jwt/v3 v3.0.1 github.com/gdamore/tcell/v2 v2.2.0 @@ -153,7 +155,7 @@ require ( go.uber.org/fx v1.9.0 go.uber.org/multierr v1.7.0 go.uber.org/zap v1.19.1 - golang.org/x/net v0.0.0-20210917221730-978cfadd31cf + golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sys v0.0.0-20210917161153-d61c044b1678 golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac diff --git a/go.sum b/go.sum index be18c532d47..ca3f5f0c7dc 100644 --- a/go.sum +++ b/go.sum @@ -353,13 +353,16 @@ github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0 h1:rVVNq0x6RGQIzCo1iiJlGFm9AG github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0/go.mod h1:bxmzgT8tmeVQA1/gvBwFmYdT8SOFUwB3ovSUfG1Ux0g= github.com/filecoin-project/go-indexer-core v0.2.2/go.mod h1:wV+NmrF8fHG6Xii3ecoZf2JW3laGTe5xtsWz609jo+Y= github.com/filecoin-project/go-indexer-core v0.2.3/go.mod h1:MSe5aRWmfRB+5syR4yDV+OApgJU+MUJ4rl9VUuzwCfc= -github.com/filecoin-project/go-indexer-core v0.2.4 h1:90vvxoBeNZN+h4W+vZ+VsoxKaDBr/bfZJJNByapGeM0= github.com/filecoin-project/go-indexer-core v0.2.4/go.mod h1:MSe5aRWmfRB+5syR4yDV+OApgJU+MUJ4rl9VUuzwCfc= +github.com/filecoin-project/go-indexer-core v0.2.6 h1:3Pt5+ZG20G5R1VF2eS0sawhqKCzc8cVb/WJ4fEeruZg= +github.com/filecoin-project/go-indexer-core v0.2.6/go.mod h1:wW5Ab0gJXL2vT4iEMbPUfPs773iMc86Q8GtfSEqmu3Y= github.com/filecoin-project/go-jsonrpc v0.1.5 h1:ckxqZ09ivBAVf5CSmxxrqqNHC7PJm3GYGtYKiNQ+vGk= github.com/filecoin-project/go-jsonrpc v0.1.5/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4= github.com/filecoin-project/go-legs v0.0.0-20211013165050-9ab325b6d2eb/go.mod h1:lKwBnslfNGG7JnsP9uQZl3yK7f74fit1MyHcwuuOP3k= -github.com/filecoin-project/go-legs v0.0.0-20211112111427-68d536862db9 h1:NWe71o5Kgi/0/eMlPJKF//nnIPwOR73AXRk6R/+LLA4= github.com/filecoin-project/go-legs v0.0.0-20211112111427-68d536862db9/go.mod h1:g32LVimhcYPte22LK8XslKqLBem54QxuMQmkrzbAyEI= +github.com/filecoin-project/go-legs v0.0.0-20211125094504-5fdf15090c48/go.mod h1:g32LVimhcYPte22LK8XslKqLBem54QxuMQmkrzbAyEI= +github.com/filecoin-project/go-legs v0.0.0-20211202193658-45deff4405e1 h1:dq7K8iCh8gnttxr35BHJcI6o/8I5z1sArlqL9LJjti0= +github.com/filecoin-project/go-legs v0.0.0-20211202193658-45deff4405e1/go.mod h1:8rq/QxX6wlL0AehqVi5CqxXT3xYz1LIpp1HCZ6qI2EY= github.com/filecoin-project/go-multistore v0.0.3/go.mod h1:kaNqCC4IhU4B1uyr7YWFHd23TL4KM32aChS0jNkyUvQ= github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20/go.mod h1:mPn+LRRd5gEKNAtc+r3ScpW2JRU/pj4NBKdADYWHiak= github.com/filecoin-project/go-padreader v0.0.0-20210723183308-812a16dc01b1/go.mod h1:VYVPJqwpsfmtoHnAmPx6MUwmrK6HIcDqZJiuZhtmfLQ= @@ -385,8 +388,8 @@ github.com/filecoin-project/go-statestore v0.1.1/go.mod h1:LFc9hD+fRxPqiHiaqUEZO github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b h1:fkRZSPrYpk42PV3/lIXiL0LHetxde7vyYYvSsttQtfg= github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b/go.mod h1:Q0GQOBtKf1oE10eSXSlhN45kDBdGvEcVOqMiffqX+N8= github.com/filecoin-project/index-provider v0.0.0-20211116211010-ae6b83454d89/go.mod h1:wu0yi7NbT3VzYr3s0n2zheg3mpdSP09A0hBFIQfUs44= -github.com/filecoin-project/index-provider v0.0.0-20211117103856-70cd9b7ab68b h1:qVQpqoguf9+vPONSMQZ3xYVzxzwAITyBHjM238zAr6c= -github.com/filecoin-project/index-provider v0.0.0-20211117103856-70cd9b7ab68b/go.mod h1:wu0yi7NbT3VzYr3s0n2zheg3mpdSP09A0hBFIQfUs44= +github.com/filecoin-project/index-provider v0.0.0-20211117105122-6ee67478aad8 h1:FQSKRQj8Us2TsfdvnEchfS0HHPLWpQX/8mY7XbVCOKM= +github.com/filecoin-project/index-provider v0.0.0-20211117105122-6ee67478aad8/go.mod h1:wu0yi7NbT3VzYr3s0n2zheg3mpdSP09A0hBFIQfUs44= github.com/filecoin-project/specs-actors v0.9.4/go.mod h1:BStZQzx5x7TmCkLv0Bpa07U6cPKol6fd3w9KjMPZ6Z4= github.com/filecoin-project/specs-actors v0.9.12/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= github.com/filecoin-project/specs-actors v0.9.13/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= @@ -409,8 +412,9 @@ github.com/filecoin-project/specs-actors/v6 v6.0.1 h1:laxvHNsvrq83Y9n+W7znVCePi3 github.com/filecoin-project/specs-actors/v6 v6.0.1/go.mod h1:V1AYfi5GkHXipx1mnVivoICZh3wtwPxDVuds+fbfQtk= github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506 h1:Ur/l2+6qN+lQiqjozWWc5p9UDaAMDZKTlDS98oRnlIw= github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506/go.mod h1:nJRRM7Aa9XVvygr3W9k6xGF46RWzr2zxF/iGoAIfA/g= -github.com/filecoin-project/storetheindex v0.0.0-20211019180831-2704585e5f99 h1:qdlA/LrP6UeYFkyXdZzzQaaUNvKXjRIP5j86peIzgvI= github.com/filecoin-project/storetheindex v0.0.0-20211019180831-2704585e5f99/go.mod h1:IwKNyPe59SXmss9mKhx2GzkJXTBSmSjl1FiQTwFdsus= +github.com/filecoin-project/storetheindex v0.0.0-20211126125638-1f013514c397 h1:ZrRU/3QITMjT+JP3qp62VkRiPMgVh74iRer354wLCDg= +github.com/filecoin-project/storetheindex v0.0.0-20211126125638-1f013514c397/go.mod h1:vRNYKeVJ/kdL/dMuWioZZt9K5pZ4SU5RV2lXlAKDLBo= github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg= github.com/filecoin-project/test-vectors/schema v0.0.5/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= @@ -904,6 +908,7 @@ github.com/ipld/go-ipld-prime v0.10.0/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/ github.com/ipld/go-ipld-prime v0.11.0/go.mod h1:+WIAkokurHmZ/KwzDOMUuoeJgaRQktHtEaLglS3ZeV8= github.com/ipld/go-ipld-prime v0.12.0/go.mod h1:hy8b93WleDMRKumOJnTIrr0MbbFbx9GD6Kzxa53Xppc= github.com/ipld/go-ipld-prime v0.12.3/go.mod h1:PaeLYq8k6dJLmDUSLrzkEpoGV4PEfe/1OtFN/eALOc8= +github.com/ipld/go-ipld-prime v0.12.4-0.20211026094848-168715526f2d/go.mod h1:JUI6cS52J83Tz5li0Zl6M2tDX4r5x68Y77K1fbXHFYo= github.com/ipld/go-ipld-prime v0.14.0 h1:2FnBqUjmmgxgZD6/zB3eygWlmIsHNGrZ57L99x3xD6Q= github.com/ipld/go-ipld-prime v0.14.0/go.mod h1:9ASQLwUFLptCov6lIYc70GRB4V7UTyLD0IJtrDJe6ZM= github.com/ipld/go-ipld-prime-proto v0.0.0-20191113031812-e32bd156a1e5/go.mod h1:gcvzoEDBjwycpXt3LBE061wT9f46szXGHAmj9uoP6fU= @@ -912,8 +917,9 @@ github.com/ipld/go-ipld-prime-proto v0.0.0-20200922192210-9a2bfd4440a6/go.mod h1 github.com/ipld/go-ipld-prime-proto v0.1.0/go.mod h1:11zp8f3sHVgIqtb/c9Kr5ZGqpnCLF1IVTNOez9TopzE= github.com/ipld/go-ipld-selector-text-lite v0.0.0 h1:MLU1YUAgd3Z+RfVCXUbvxH1RQjEe+larJ9jmlW1aMgA= github.com/ipld/go-ipld-selector-text-lite v0.0.0/go.mod h1:U2CQmFb+uWzfIEF3I1arrDa5rwtj00PrpiwwCO+k1RM= -github.com/ipld/go-storethehash v0.0.0-20210915160027-d72ca9b0968c h1:izfvqCuEqk2V7BRkh7GCm7lyKC2ItyAbzUu4WgNmggc= github.com/ipld/go-storethehash v0.0.0-20210915160027-d72ca9b0968c/go.mod h1:PwE6iq8TiWJRI3zMGA1RtkFAnrDMK93dLA5SUeu0lH8= +github.com/ipld/go-storethehash v0.0.0-20211122175924-41b16c131842 h1:X1UkORbce9wX7S72MMIX9DAe00U8Ln2xG+haUhaLCUw= +github.com/ipld/go-storethehash v0.0.0-20211122175924-41b16c131842/go.mod h1:PwE6iq8TiWJRI3zMGA1RtkFAnrDMK93dLA5SUeu0lH8= github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52 h1:QG4CGBqCeuBo6aZlGAamSkxWdgWfZGeE49eUOWJPA4c= github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52/go.mod h1:fdg+/X9Gg4AsAIzWpEHwnqd+QY3b7lajxyjE1m4hkq4= github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= @@ -1125,6 +1131,8 @@ github.com/libp2p/go-libp2p-discovery v0.4.0/go.mod h1:bZ0aJSrFc/eX2llP0ryhb1kpg github.com/libp2p/go-libp2p-discovery v0.5.0/go.mod h1:+srtPIU9gDaBNu//UHvcdliKBIcr4SfDcm0/PfPJLug= github.com/libp2p/go-libp2p-discovery v0.5.1 h1:CJylx+h2+4+s68GvrM4pGNyfNhOYviWBPtVv5PA7sfo= github.com/libp2p/go-libp2p-discovery v0.5.1/go.mod h1:+srtPIU9gDaBNu//UHvcdliKBIcr4SfDcm0/PfPJLug= +github.com/libp2p/go-libp2p-gostream v0.3.1 h1:XlwohsPn6uopGluEWs1Csv1QCEjrTXf2ZQagzZ5paAg= +github.com/libp2p/go-libp2p-gostream v0.3.1/go.mod h1:1V3b+u4Zhaq407UUY9JLCpboaeufAeVQbnvAt12LRsI= github.com/libp2p/go-libp2p-host v0.0.1/go.mod h1:qWd+H1yuU0m5CwzAkvbSjqKairayEHdR5MMl7Cwa7Go= github.com/libp2p/go-libp2p-host v0.0.3/go.mod h1:Y/qPyA6C8j2coYyos1dfRm0I8+nvd4TGrDGt4tA7JR8= github.com/libp2p/go-libp2p-interface-connmgr v0.0.1/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k= @@ -2023,8 +2031,9 @@ golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5 golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210813211128-0a44fdfbc16e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210915214749-c084706c2272 h1:3erb+vDS8lU1sxfDHF4/hhWyaXnhIaO+7RgL4fDZORA= golang.org/x/crypto v0.0.0-20210915214749-c084706c2272/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 h1:/pEO3GD/ABYAjuakUS6xSEmmlyVS4kxBNkeA9tLJiTI= +golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20181106170214-d68db9428509/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -2139,8 +2148,9 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210917221730-978cfadd31cf h1:R150MpwJIv1MpS0N/pc+NhTM8ajzvlmxlY5OYsrevXQ= golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= From 43cde484f44fc0307534333a204ae28690a27bcb Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Thu, 9 Dec 2021 16:23:12 +0000 Subject: [PATCH 022/385] Upgrade go-legs to a version with debugging features In order to debug the gossipsub issue, upgrade go-legs to a branch that implments an admin HTTP API to allow checking peerstate connecting to a host and explicitly publishing CIDs. This is to reduce the roundtrip time we have to wait for a deal to be made and advertisement published to debug issues. Admin server runs on localhost only and will not be present in the final version of go-legs or will be disabled. See: - https://github.com/filecoin-project/go-legs/pull/47 --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 67567124271..971a453f9c2 100644 --- a/go.mod +++ b/go.mod @@ -39,7 +39,7 @@ require ( github.com/filecoin-project/go-fil-markets v1.13.3-0.20211117072527-8713155662ff github.com/filecoin-project/go-indexer-core v0.2.6 github.com/filecoin-project/go-jsonrpc v0.1.5 - github.com/filecoin-project/go-legs v0.0.0-20211202193658-45deff4405e1 // indirect + github.com/filecoin-project/go-legs v0.0.0-20211209161055-918cd188bf1d // indirect github.com/filecoin-project/go-padreader v0.0.1 github.com/filecoin-project/go-paramfetch v0.0.2 github.com/filecoin-project/go-state-types v0.1.1 diff --git a/go.sum b/go.sum index ca3f5f0c7dc..a46059f538f 100644 --- a/go.sum +++ b/go.sum @@ -363,6 +363,8 @@ github.com/filecoin-project/go-legs v0.0.0-20211112111427-68d536862db9/go.mod h1 github.com/filecoin-project/go-legs v0.0.0-20211125094504-5fdf15090c48/go.mod h1:g32LVimhcYPte22LK8XslKqLBem54QxuMQmkrzbAyEI= github.com/filecoin-project/go-legs v0.0.0-20211202193658-45deff4405e1 h1:dq7K8iCh8gnttxr35BHJcI6o/8I5z1sArlqL9LJjti0= github.com/filecoin-project/go-legs v0.0.0-20211202193658-45deff4405e1/go.mod h1:8rq/QxX6wlL0AehqVi5CqxXT3xYz1LIpp1HCZ6qI2EY= +github.com/filecoin-project/go-legs v0.0.0-20211209161055-918cd188bf1d h1:DXm6XG2YibCTcm1vmNz9FWZ2nwz8tgoycrhclZRgKzA= +github.com/filecoin-project/go-legs v0.0.0-20211209161055-918cd188bf1d/go.mod h1:HFp0jUZopkX9DW6FOmhHltVfEatfAcm3ZD6Z/kY4iNg= github.com/filecoin-project/go-multistore v0.0.3/go.mod h1:kaNqCC4IhU4B1uyr7YWFHd23TL4KM32aChS0jNkyUvQ= github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20/go.mod h1:mPn+LRRd5gEKNAtc+r3ScpW2JRU/pj4NBKdADYWHiak= github.com/filecoin-project/go-padreader v0.0.0-20210723183308-812a16dc01b1/go.mod h1:VYVPJqwpsfmtoHnAmPx6MUwmrK6HIcDqZJiuZhtmfLQ= From 6b7b9793abd67f29343d216e4d39b67cd0febccf Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Mon, 13 Dec 2021 14:44:56 +0000 Subject: [PATCH 023/385] Set default index provider ingest config values Set default values for index-provider ingest config. Leave a TODO to use provider config APIs once defaults exposed. Run `go mod tidy` --- go.sum | 2 -- node/config/def.go | 10 ++++++++++ node/config/def_test.go | 5 +++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/go.sum b/go.sum index a46059f538f..17e1e4148bf 100644 --- a/go.sum +++ b/go.sum @@ -361,8 +361,6 @@ github.com/filecoin-project/go-jsonrpc v0.1.5/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4G github.com/filecoin-project/go-legs v0.0.0-20211013165050-9ab325b6d2eb/go.mod h1:lKwBnslfNGG7JnsP9uQZl3yK7f74fit1MyHcwuuOP3k= github.com/filecoin-project/go-legs v0.0.0-20211112111427-68d536862db9/go.mod h1:g32LVimhcYPte22LK8XslKqLBem54QxuMQmkrzbAyEI= github.com/filecoin-project/go-legs v0.0.0-20211125094504-5fdf15090c48/go.mod h1:g32LVimhcYPte22LK8XslKqLBem54QxuMQmkrzbAyEI= -github.com/filecoin-project/go-legs v0.0.0-20211202193658-45deff4405e1 h1:dq7K8iCh8gnttxr35BHJcI6o/8I5z1sArlqL9LJjti0= -github.com/filecoin-project/go-legs v0.0.0-20211202193658-45deff4405e1/go.mod h1:8rq/QxX6wlL0AehqVi5CqxXT3xYz1LIpp1HCZ6qI2EY= github.com/filecoin-project/go-legs v0.0.0-20211209161055-918cd188bf1d h1:DXm6XG2YibCTcm1vmNz9FWZ2nwz8tgoycrhclZRgKzA= github.com/filecoin-project/go-legs v0.0.0-20211209161055-918cd188bf1d/go.mod h1:HFp0jUZopkX9DW6FOmhHltVfEatfAcm3ZD6Z/kY4iNg= github.com/filecoin-project/go-multistore v0.0.3/go.mod h1:kaNqCC4IhU4B1uyr7YWFHd23TL4KM32aChS0jNkyUvQ= diff --git a/node/config/def.go b/node/config/def.go index 6c518d20930..1bf58572d77 100644 --- a/node/config/def.go +++ b/node/config/def.go @@ -10,6 +10,7 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" + ipconfig "github.com/filecoin-project/index-provider/config" miner5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/actors/builtin" @@ -224,6 +225,15 @@ func DefaultStorageMiner() *StorageMiner { GCInterval: Duration(1 * time.Minute), }, } + + // TODO: Remove hardcoded defaults once provider library exposes them. + // See: https://github.com/filecoin-project/index-provider/issues/108 + cfg.IndexerProvider.Ingest = ipconfig.Ingest{ + LinkCacheSize: 1024, + LinkedChunkSize: 100, + PubSubTopic: "indexer/ingest", + } + cfg.Common.API.ListenAddress = "/ip4/127.0.0.1/tcp/2345/http" cfg.Common.API.RemoteListenAddress = "127.0.0.1:2345" return cfg diff --git a/node/config/def_test.go b/node/config/def_test.go index d45bc6ec8f3..85264358b54 100644 --- a/node/config/def_test.go +++ b/node/config/def_test.go @@ -52,3 +52,8 @@ func TestDefaultMinerRoundtrip(t *testing.T) { require.True(t, reflect.DeepEqual(c, c2)) } + +func TestDefaultStorageMiner_SetsIndexIngestTopic(t *testing.T) { + subject := DefaultStorageMiner() + require.Equal(t, "indexer/ingest", subject.IndexerProvider.PubSubTopic) +} From a51b08e3867508ce77ba17773d674053576bf0bd Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Mon, 13 Dec 2021 18:15:28 +0100 Subject: [PATCH 024/385] feat: add IndexerProvider AnnounceAddress config --- documentation/en/default-lotus-miner-config.toml | 14 +++++++++++--- node/config/def.go | 1 + node/config/doc_gen.go | 8 ++++++++ node/config/types.go | 5 +++++ node/modules/lp2p/addrs.go | 4 ++-- node/modules/storageminer_idxprov.go | 10 ++++++++-- 6 files changed, 35 insertions(+), 7 deletions(-) diff --git a/documentation/en/default-lotus-miner-config.toml b/documentation/en/default-lotus-miner-config.toml index e99b908b29b..f5135cd0023 100644 --- a/documentation/en/default-lotus-miner-config.toml +++ b/documentation/en/default-lotus-miner-config.toml @@ -248,13 +248,13 @@ [IndexerProvider] # env var: LOTUS_INDEXERPROVIDER_LINKCACHESIZE - #LinkCacheSize = 0 + #LinkCacheSize = 1024 # env var: LOTUS_INDEXERPROVIDER_LINKEDCHUNKSIZE - #LinkedChunkSize = 0 + #LinkedChunkSize = 100 # env var: LOTUS_INDEXERPROVIDER_PUBSUBTOPIC - #PubSubTopic = "" + #PubSubTopic = "indexer/ingest" # env var: LOTUS_INDEXERPROVIDER_PURGELINKCACHE #PurgeLinkCache = false @@ -266,6 +266,14 @@ # env var: LOTUS_INDEXERPROVIDER_LISTENADDRESSES #ListenAddresses = ["/ip4/0.0.0.0/tcp/0", "/ip6/::/tcp/0"] + # Addresses to explicitly announce to other peers. If not specified, + # all interface addresses are announced + # Format: multiaddress + # + # type: []string + # env var: LOTUS_INDEXERPROVIDER_ANNOUNCEADDRESSES + #AnnounceAddresses = [] + # The maximum number of simultaneous data transfers between the indexers # and the indexer provider # diff --git a/node/config/def.go b/node/config/def.go index 1bf58572d77..5ab9861f04c 100644 --- a/node/config/def.go +++ b/node/config/def.go @@ -182,6 +182,7 @@ func DefaultStorageMiner() *StorageMiner { "/ip4/0.0.0.0/tcp/0", "/ip6/::/tcp/0", }, + AnnounceAddresses: []string{}, MaxSimultaneousTransfers: DefaultSimultaneousTransfers, }, diff --git a/node/config/doc_gen.go b/node/config/doc_gen.go index 394f8ab09db..972531eef82 100644 --- a/node/config/doc_gen.go +++ b/node/config/doc_gen.go @@ -346,6 +346,14 @@ see https://docs.filecoin.io/mine/lotus/miner-configuration/#using-filters-for-f Comment: `Binding address for the libp2p host - 0 means random port. Format: multiaddress; see https://multiformats.io/multiaddr/`, + }, + { + Name: "AnnounceAddresses", + Type: "[]string", + + Comment: `Addresses to explicitly announce to other peers. If not specified, +all interface addresses are announced +Format: multiaddress`, }, { Name: "MaxSimultaneousTransfers", diff --git a/node/config/types.go b/node/config/types.go index 44c40e30654..77ef91fe256 100644 --- a/node/config/types.go +++ b/node/config/types.go @@ -156,6 +156,11 @@ type IndexerProviderConfig struct { // Format: multiaddress; see https://multiformats.io/multiaddr/ ListenAddresses []string + // Addresses to explicitly announce to other peers. If not specified, + // all interface addresses are announced + // Format: multiaddress + AnnounceAddresses []string + // The maximum number of simultaneous data transfers between the indexers // and the indexer provider MaxSimultaneousTransfers uint64 diff --git a/node/modules/lp2p/addrs.go b/node/modules/lp2p/addrs.go index 88c66772d87..d092ff0ab97 100644 --- a/node/modules/lp2p/addrs.go +++ b/node/modules/lp2p/addrs.go @@ -11,7 +11,7 @@ import ( mamask "github.com/whyrusleeping/multiaddr-filter" ) -func makeAddrsFactory(announce []string, noAnnounce []string) (p2pbhost.AddrsFactory, error) { +func MakeAddrsFactory(announce []string, noAnnounce []string) (p2pbhost.AddrsFactory, error) { var annAddrs []ma.Multiaddr for _, addr := range announce { maddr, err := ma.NewMultiaddr(addr) @@ -59,7 +59,7 @@ func makeAddrsFactory(announce []string, noAnnounce []string) (p2pbhost.AddrsFac func AddrsFactory(announce []string, noAnnounce []string) func() (opts Libp2pOpts, err error) { return func() (opts Libp2pOpts, err error) { - addrsFactory, err := makeAddrsFactory(announce, noAnnounce) + addrsFactory, err := MakeAddrsFactory(announce, noAnnounce) if err != nil { return opts, err } diff --git a/node/modules/storageminer_idxprov.go b/node/modules/storageminer_idxprov.go index 7022823a8d9..4bd15a09c2d 100644 --- a/node/modules/storageminer_idxprov.go +++ b/node/modules/storageminer_idxprov.go @@ -34,6 +34,7 @@ import ( "github.com/filecoin-project/lotus/node/config" "github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/helpers" + "github.com/filecoin-project/lotus/node/modules/lp2p" "github.com/filecoin-project/lotus/node/repo" ) @@ -57,7 +58,7 @@ func IndexerProvider(cfg config.IndexerProviderConfig) func(params IdxProv) (pro return nil, fmt.Errorf("missing private key for node ID: %s", args.PeerID.Pretty()) } - h, err := createIndexerProviderHost(args.MetricsCtx, args.Lifecycle, pkey, args.Peerstore, cfg.ListenAddresses) + h, err := createIndexerProviderHost(args.MetricsCtx, args.Lifecycle, pkey, args.Peerstore, cfg.ListenAddresses, cfg.AnnounceAddresses) if err != nil { return nil, xerrors.Errorf("creating indexer provider host: %w", err) } @@ -94,13 +95,18 @@ func IndexerProvider(cfg config.IndexerProviderConfig) func(params IdxProv) (pro } } -func createIndexerProviderHost(mctx helpers.MetricsCtx, lc fx.Lifecycle, pkey ci.PrivKey, pstore peerstore.Peerstore, listenAddrs []string) (host.Host, error) { +func createIndexerProviderHost(mctx helpers.MetricsCtx, lc fx.Lifecycle, pkey ci.PrivKey, pstore peerstore.Peerstore, listenAddrs []string, announceAddrs []string) (host.Host, error) { ctx := helpers.LifecycleCtx(mctx, lc) + addrsFactory, err := lp2p.MakeAddrsFactory(announceAddrs, nil) + if err != nil { + return nil, err + } opts := []libp2p.Option{ libp2p.Identity(pkey), libp2p.Peerstore(pstore), libp2p.ListenAddrStrings(listenAddrs...), + libp2p.AddrsFactory(addrsFactory), libp2p.Ping(true), libp2p.UserAgent("lotus-indexer-provider-" + build.UserVersion()), } From d42f7e4a1c638ae9e22c2c276815c483e525b89a Mon Sep 17 00:00:00 2001 From: Cory Schwartz Date: Fri, 17 Dec 2021 17:06:32 -0800 Subject: [PATCH 025/385] packer snap --- .circleci/config.yml | 22 +++++++++ .gitignore | 1 + scripts/snap-lotus-entrypoint.sh | 10 ++++ snap/snapcraft.yaml | 40 +++++++++++---- tools/packer/lotus-snap.pkr.hcl | 84 ++++++++++++++++++++++++++++++++ tools/packer/lotus.pkr.hcl | 10 ---- tools/packer/setup-snap.sh | 34 +++++++++++++ 7 files changed, 181 insertions(+), 20 deletions(-) create mode 100755 scripts/snap-lotus-entrypoint.sh create mode 100644 tools/packer/lotus-snap.pkr.hcl create mode 100644 tools/packer/setup-snap.sh diff --git a/.circleci/config.yml b/.circleci/config.yml index a4a88a09089..92ce5bc6b8d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -705,6 +705,17 @@ jobs: - packer/build: template: tools/packer/lotus.pkr.hcl args: "-var ci_workspace_bins=./linux-butterflynet -var lotus_network=butterflynet -var git_tag=$CIRCLE_TAG" + publish-packer-snap: + description: build packer image with snap. mainnet only. + executor: + name: packer/default + packer-version: 1.6.6 + steps: + - checkout + - attach_workspace: + at: "." + - packer/build: + template: tools/packer/lotus-snap.pkr.hcl publish-dockerhub: description: publish to dockerhub machine: @@ -1042,6 +1053,7 @@ workflows: tags: only: - /^v\d+\.\d+\.\d+(-rc\d+)?$/ + - publish-packer-snap nightly: triggers: @@ -1058,3 +1070,13 @@ workflows: - publish-dockerhub: name: publish-dockerhub-nightly tag: nightly + monthly: + triggers: + - schedule: + cron: "0 0 1 * *" + filters: + branches: + only: + - master + jobs: + - publish-packer-snap diff --git a/.gitignore b/.gitignore index 467f315b8ef..33fbffa3c19 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,7 @@ build/paramfetch.sh /bundle /darwin /linux +*.snap *-fuzz.zip /chain/types/work_msg/ diff --git a/scripts/snap-lotus-entrypoint.sh b/scripts/snap-lotus-entrypoint.sh new file mode 100755 index 00000000000..a3ab04c5b34 --- /dev/null +++ b/scripts/snap-lotus-entrypoint.sh @@ -0,0 +1,10 @@ +LOTUS_IMPORT_SNAPSHOT="https://fil-chain-snapshots-fallback.s3.amazonaws.com/mainnet/minimal_finality_stateroots_latest.car" +LOTUS_BINARY=$(dirname "$0")/lotus +GATE="$LOTUS_PATH"/date_initialized +if [ ! -f "$GATE" ]; then + echo importing minimal snapshot + $LOTUS_BINARY daemon --import-snapshot "$LOTUS_IMPORT_SNAPSHOT" --halt-after-import + # Block future inits + date > "$GATE" +fi +$LOTUS_BINARY daemon $ARGS diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 472621c2a48..08854555ffc 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -17,7 +17,6 @@ description: | https://github.com/filecoin-project/lotus -grade: devel confinement: strict parts: @@ -39,6 +38,15 @@ parts: override-build: | LDFLAGS="" make lotus lotus-miner lotus-worker cp lotus lotus-miner lotus-worker $SNAPCRAFT_PART_INSTALL + cp scripts/snap-lotus-entrypoint.sh $SNAPCRAFT_PART_INSTALL + +layout: + /var/lib/lotus: + symlink: $SNAP_COMMON/lotus + /var/lib/lotus-miner: + symlink: $SNAP_COMMON/lotus-miner + /var/lib/lotus-worker: + symlink: $SNAP_COMMON/lotus-worker apps: lotus: @@ -49,9 +57,9 @@ apps: - home environment: FIL_PROOFS_PARAMETER_CACHE: $SNAP_USER_COMMON/filecoin-proof-parameters - LOTUS_PATH: $SNAP_USER_COMMON/lotus - LOTUS_MINER_PATH: $SNAP_USER_COMMON/lotus-miner - LOTUS_WORKER_PATH: $SNAP_USER_COMMON/lotus-worker + LOTUS_PATH: $SNAP_COMMON/lotus + LOTUS_MINER_PATH: $SNAP_COMMON/lotus-miner + LOTUS_WORKER_PATH: $SNAP_COMMON/lotus-worker lotus-miner: command: lotus-miner plugs: @@ -60,9 +68,9 @@ apps: - opengl environment: FIL_PROOFS_PARAMETER_CACHE: $SNAP_USER_COMMON/filecoin-proof-parameters - LOTUS_PATH: $SNAP_USER_COMMON/lotus - LOTUS_MINER_PATH: $SNAP_USER_COMMON/lotus-miner - LOTUS_WORKER_PATH: $SNAP_USER_COMMON/lotus-worker + LOTUS_PATH: $SNAP_COMMON/lotus + LOTUS_MINER_PATH: $SNAP_COMMON/lotus-miner + LOTUS_WORKER_PATH: $SNAP_COMMON/lotus-worker lotus-worker: command: lotus-worker plugs: @@ -71,6 +79,18 @@ apps: - opengl environment: FIL_PROOFS_PARAMETER_CACHE: $SNAP_USER_COMMON/filecoin-proof-parameters - LOTUS_PATH: $SNAP_USER_COMMON/lotus - LOTUS_MINER_PATH: $SNAP_USER_COMMON/lotus-miner - LOTUS_WORKER_PATH: $SNAP_USER_COMMON/lotus-worker + LOTUS_PATH: $SNAP_COMMON/lotus + LOTUS_MINER_PATH: $SNAP_COMMON/lotus-miner + LOTUS_WORKER_PATH: $SNAP_COMMON/lotus-worker + lotus-daemon: + command: snap-lotus-entrypoint.sh + daemon: simple + install-mode: enable + plugs: + - network + - network-bind + environment: + FIL_PROOFS_PARAMETER_CACHE: $SNAP_COMMON/filecoin-proof-parameters + LOTUS_PATH: $SNAP_COMMON/lotus + LOTUS_MINER_PATH: $SNAP_COMMON/lotus-miner + LOTUS_WORKER_PATH: $SNAP_COMMON/lotus-worker diff --git a/tools/packer/lotus-snap.pkr.hcl b/tools/packer/lotus-snap.pkr.hcl new file mode 100644 index 00000000000..ef0f52f8cec --- /dev/null +++ b/tools/packer/lotus-snap.pkr.hcl @@ -0,0 +1,84 @@ +variable "ci_workspace_bins" { + type = string + default = "./linux" +} + +variable "lotus_network" { + type = string + default = "mainnet" +} + +locals { + timestamp = regex_replace(timestamp(), "[- TZ:]", "") +} + +source "amazon-ebs" "lotus" { + ami_name = "lotus-${var.lotus_network}-snap-${local.timestamp}" + ami_regions = [ + "ap-east-1", + "ap-northeast-1", + "ap-northeast-2", + "ap-northeast-3", + "ap-south-1", + "ap-southeast-1", + "ap-southeast-2", + "ca-central-1", + "eu-central-1", + "eu-north-1", + "eu-west-1", + "eu-west-2", + "eu-west-3", + "sa-east-1", + "us-east-1", + "us-east-2", + "us-west-1", + "us-west-2", + ] + ami_groups = [ + # This causes the ami to be publicly-accessable. + "all", + ] + ami_description = "Lotus Filecoin AMI" + launch_block_device_mappings { + device_name = "/dev/sda1" + volume_size = 100 + delete_on_termination = true + } + + instance_type = "t2.micro" + source_ami_filter { + filters = { + name = "ubuntu/images/*ubuntu-focal-20.04-amd64-server-*" + root-device-type = "ebs" + virtualization-type = "hvm" + } + most_recent = true + owners = ["099720109477"] + } + ssh_username = "ubuntu" +} + +source "digitalocean" "lotus" { + droplet_name = "lotus-snap" + size = "s-1vcpu-1gb" + region = "nyc3" + image = "ubuntu-20-04-x64" + snapshot_name = "lotus-${var.lotus_network}-snap-${local.timestamp}" + ssh_username = "root" +} + +build { + sources = [ + "source.amazon-ebs.lotus", + "source.digitalocean.lotus", + ] + + provisioner "file" { + source = "./tools/packer/etc/motd" + destination = "motd" + } + # build it. + provisioner "shell" { + script = "./tools/packer/setup-snap.sh" + } +} diff --git a/tools/packer/lotus.pkr.hcl b/tools/packer/lotus.pkr.hcl index 8ef41613b14..cfaca83986e 100644 --- a/tools/packer/lotus.pkr.hcl +++ b/tools/packer/lotus.pkr.hcl @@ -63,19 +63,9 @@ source "amazon-ebs" "lotus" { ssh_username = "ubuntu" } -source "digitalocean" "lotus" { - droplet_name = "lotus-${var.lotus_network}" - size = "s-1vcpu-1gb" - region = "nyc3" - image = "ubuntu-20-04-x64" - snapshot_name = "lotus-${var.lotus_network}-${var.git_tag}-${local.timestamp}" - ssh_username = "root" -} - build { sources = [ "source.amazon-ebs.lotus", - "source.digitalocean.lotus", ] # Lotus software (from CI workspace) diff --git a/tools/packer/setup-snap.sh b/tools/packer/setup-snap.sh new file mode 100644 index 00000000000..7b543bc364d --- /dev/null +++ b/tools/packer/setup-snap.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +# This script is executed by packer to setup the image. +# When this script is run, packer will have already copied binaries into the home directory of +# whichever user it has access too. This script is executed from within the home directory of that +# user. Bear in mind that different cloud providers, and different images on the same cloud +# provider will have a different initial user account. + +set -x + +# Become root, if we aren't already. +# Docker images will already be root. AMIs will have an SSH user account. +UID=$(id -u) +if [ x$UID != x0 ] +then + printf -v cmd_str '%q ' "$0" "$@" + exec sudo su -c "$cmd_str" +fi + +MANAGED_FILES=( + /etc/motd +) + +snap install filecoin-lotus + +snap alias lotus-filecoin.lotus lotus +snap alias lotus-filecoin.lotus-miner lotus-miner +snap alias lotus-filecoin.lotus-miner lotus-worker + +# Setup firewall +yes | ufw enable +ufw default deny incoming +ufw default allow outgoing +ufw allow ssh From dedf46ed1f5d5ec73edff67b5e1a928aaff06435 Mon Sep 17 00:00:00 2001 From: Cory Schwartz Date: Fri, 17 Dec 2021 17:12:10 -0800 Subject: [PATCH 026/385] use correct snap name --- tools/packer/setup-snap.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/packer/setup-snap.sh b/tools/packer/setup-snap.sh index 7b543bc364d..29e0bf26dfd 100644 --- a/tools/packer/setup-snap.sh +++ b/tools/packer/setup-snap.sh @@ -7,6 +7,7 @@ # provider will have a different initial user account. set -x +set -e # Become root, if we aren't already. # Docker images will already be root. AMIs will have an SSH user account. @@ -21,7 +22,7 @@ MANAGED_FILES=( /etc/motd ) -snap install filecoin-lotus +snap install lotus-filecoin snap alias lotus-filecoin.lotus lotus snap alias lotus-filecoin.lotus-miner lotus-miner From d874c633d784c4f591a15c05eb5ddde1d8407ac8 Mon Sep 17 00:00:00 2001 From: Cory Schwartz Date: Fri, 17 Dec 2021 17:14:53 -0800 Subject: [PATCH 027/385] set -e after switch user --- tools/packer/setup-snap.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/packer/setup-snap.sh b/tools/packer/setup-snap.sh index 29e0bf26dfd..7546023f265 100644 --- a/tools/packer/setup-snap.sh +++ b/tools/packer/setup-snap.sh @@ -7,7 +7,6 @@ # provider will have a different initial user account. set -x -set -e # Become root, if we aren't already. # Docker images will already be root. AMIs will have an SSH user account. @@ -18,6 +17,8 @@ then exec sudo su -c "$cmd_str" fi +set -e + MANAGED_FILES=( /etc/motd ) From a03e9e34ab6e9ee61d3b8f3a6890ac2717aea40e Mon Sep 17 00:00:00 2001 From: Cory Schwartz Date: Fri, 17 Dec 2021 17:30:23 -0800 Subject: [PATCH 028/385] reinstall snapd --- tools/packer/setup-snap.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/packer/setup-snap.sh b/tools/packer/setup-snap.sh index 7546023f265..f8f94981616 100644 --- a/tools/packer/setup-snap.sh +++ b/tools/packer/setup-snap.sh @@ -10,7 +10,6 @@ set -x # Become root, if we aren't already. # Docker images will already be root. AMIs will have an SSH user account. -UID=$(id -u) if [ x$UID != x0 ] then printf -v cmd_str '%q ' "$0" "$@" @@ -23,6 +22,10 @@ MANAGED_FILES=( /etc/motd ) +# this is required on digitalocean, which does not have snap seeded correctly at this phase. +apt update +apt reinstall snapd + snap install lotus-filecoin snap alias lotus-filecoin.lotus lotus From d53a9e877abdf179042a930fea32bc7d9993c8e8 Mon Sep 17 00:00:00 2001 From: Cory Schwartz Date: Fri, 17 Dec 2021 17:49:32 -0800 Subject: [PATCH 029/385] cleanup script --- tools/packer/setup-snap.sh | 4 ++++ tools/packer/setup.sh | 2 ++ 2 files changed, 6 insertions(+) diff --git a/tools/packer/setup-snap.sh b/tools/packer/setup-snap.sh index f8f94981616..69c91cb604e 100644 --- a/tools/packer/setup-snap.sh +++ b/tools/packer/setup-snap.sh @@ -32,8 +32,12 @@ snap alias lotus-filecoin.lotus lotus snap alias lotus-filecoin.lotus-miner lotus-miner snap alias lotus-filecoin.lotus-miner lotus-worker +snap stop lotus-filecoin.lotus-daemon + # Setup firewall yes | ufw enable ufw default deny incoming ufw default allow outgoing ufw allow ssh + +curl -L https://raw.githubusercontent.com/digitalocean/marketplace-partners/master/scripts/90-cleanup.sh | bash diff --git a/tools/packer/setup.sh b/tools/packer/setup.sh index 6c0742254ff..2b190045e1b 100644 --- a/tools/packer/setup.sh +++ b/tools/packer/setup.sh @@ -65,3 +65,5 @@ ufw default deny incoming ufw default allow outgoing ufw allow ssh ufw allow 5678 #libp2p + +curl -L https://raw.githubusercontent.com/digitalocean/marketplace-partners/master/scripts/90-cleanup.sh | bash From 0e7e2529516fe22586ee2fffe6629aa3a493beae Mon Sep 17 00:00:00 2001 From: Cory Schwartz Date: Fri, 17 Dec 2021 18:07:54 -0800 Subject: [PATCH 030/385] set +e before cleanup --- tools/packer/setup-snap.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/packer/setup-snap.sh b/tools/packer/setup-snap.sh index 69c91cb604e..462d393f8c1 100644 --- a/tools/packer/setup-snap.sh +++ b/tools/packer/setup-snap.sh @@ -40,4 +40,6 @@ ufw default deny incoming ufw default allow outgoing ufw allow ssh +set +e + curl -L https://raw.githubusercontent.com/digitalocean/marketplace-partners/master/scripts/90-cleanup.sh | bash From 70b8557b639e338f9bf78e6b56ce7c5073ce0043 Mon Sep 17 00:00:00 2001 From: Cory Schwartz Date: Fri, 17 Dec 2021 18:12:23 -0800 Subject: [PATCH 031/385] tmp, don't stop --- tools/packer/setup-snap.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/packer/setup-snap.sh b/tools/packer/setup-snap.sh index 462d393f8c1..d72ca876249 100644 --- a/tools/packer/setup-snap.sh +++ b/tools/packer/setup-snap.sh @@ -32,7 +32,7 @@ snap alias lotus-filecoin.lotus lotus snap alias lotus-filecoin.lotus-miner lotus-miner snap alias lotus-filecoin.lotus-miner lotus-worker -snap stop lotus-filecoin.lotus-daemon +#snap stop lotus-filecoin.lotus-daemon # Setup firewall yes | ufw enable From 4b685c5e2656206009962559f5fd6009210791cf Mon Sep 17 00:00:00 2001 From: llifezou Date: Thu, 23 Dec 2021 17:44:43 +0800 Subject: [PATCH 032/385] Include worker name in sealing errors --- extern/sector-storage/worker_local.go | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/extern/sector-storage/worker_local.go b/extern/sector-storage/worker_local.go index a5f5a0b9d31..0eb8bd9a658 100644 --- a/extern/sector-storage/worker_local.go +++ b/extern/sector-storage/worker_local.go @@ -102,7 +102,13 @@ func newLocalWorker(executor ExecutorFunc, wcfg WorkerConfig, envLookup EnvFunc, go func() { for _, call := range unfinished { - err := storiface.Err(storiface.ErrTempWorkerRestart, xerrors.New("worker restarted")) + hostname, osErr := os.Hostname() + if osErr != nil { + log.Errorf("get hostname err: %+v", err) + hostname = "" + } + + err := storiface.Err(storiface.ErrTempWorkerRestart, xerrors.Errorf("worker [Hostname: %s] restarted", hostname)) // TODO: Handle restarting PC1 once support is merged @@ -261,6 +267,15 @@ func (l *LocalWorker) asyncCall(ctx context.Context, sector storage.SectorRef, r } } + if err != nil { + hostname, osErr := os.Hostname() + if osErr != nil { + log.Errorf("get hostname err: %+v", err) + } + + err = xerrors.Errorf("%s [Hostname: %s]", err.Error(), hostname) + } + if doReturn(ctx, rt, ci, l.ret, res, toCallError(err)) { if err := l.ct.onReturned(ci); err != nil { log.Errorf("tracking call (done): %+v", err) From 135186e33df46039cfb39eb1b69791e05d82bc54 Mon Sep 17 00:00:00 2001 From: emad22552 Date: Sun, 2 Jan 2022 19:08:22 +0330 Subject: [PATCH 033/385] go fmt ./client.go --- cli/client.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/client.go b/cli/client.go index 20493b97ee7..b59dc8393d2 100644 --- a/cli/client.go +++ b/cli/client.go @@ -356,9 +356,9 @@ The minimum value is 518400 (6 months).`, &CidBaseFlag, }, Action: func(cctx *cli.Context) error { - + expectedArgsMsg := "expected 4 args: dataCid, miner, price, duration" - + if !cctx.Args().Present() { if cctx.Bool("manual-stateless-deal") { return xerrors.New("--manual-stateless-deal can not be combined with interactive deal mode: you must specify the " + expectedArgsMsg) From 492fb9d054ace961e565d7ec9c2494753702cf9c Mon Sep 17 00:00:00 2001 From: TheMenko Date: Tue, 11 Jan 2022 02:16:53 +0100 Subject: [PATCH 034/385] wallet basic tests with annotations for system test matrix --- chain/wallet/multi_test.go | 74 +++++++++++++++++++++++++ chain/wallet/wallet_test.go | 105 ++++++++++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 chain/wallet/multi_test.go create mode 100644 chain/wallet/wallet_test.go diff --git a/chain/wallet/multi_test.go b/chain/wallet/multi_test.go new file mode 100644 index 00000000000..54ff240c5c4 --- /dev/null +++ b/chain/wallet/multi_test.go @@ -0,0 +1,74 @@ +//stm: #unit +package wallet + +import ( + "context" + "testing" + + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/types" +) + +func TestMultiWallet(t *testing.T) { + + ctx := context.Background() + + local, err := NewWallet(NewMemKeyStore()) + if err != nil { + t.Fatal(err) + } + + var wallet api.Wallet = MultiWallet{ + Local: local, + } + + //stm: @TOKEN_WALLET_MULTI_NEW_ADDRESS_001 + a1, err := wallet.WalletNew(ctx, types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + + //stm: @TOKEN_WALLET_MULTI_HAS_001 + exists, err := wallet.WalletHas(ctx, a1) + if err != nil { + t.Fatal(err) + } + + if !exists { + t.Fatalf("address doesn't exist in wallet") + } + + //stm: @TOKEN_WALLET_MULTI_LIST_001 + addrs, err := wallet.WalletList(ctx) + if err != nil { + t.Fatal(err) + } + + // one default address and one newly created + if len(addrs) == 2 { + t.Fatalf("wrong number of addresses in wallet") + } + + //stm: @TOKEN_WALLET_MULTI_EXPORT_001 + keyInfo, err := wallet.WalletExport(ctx, a1) + if err != nil { + t.Fatal(err) + } + + //stm: @TOKEN_WALLET_MULTI_IMPORT_001 + addr, err := wallet.WalletImport(ctx, keyInfo) + if err != nil { + t.Fatal(err) + } + + //stm: @TOKEN_WALLET_DELETE_001 + err = wallet.WalletDelete(ctx, a1) + if err != nil { + t.Fatal(err) + } + + if addr != a1 { + t.Fatalf("imported address doesn't match exported address") + } + +} diff --git a/chain/wallet/wallet_test.go b/chain/wallet/wallet_test.go new file mode 100644 index 00000000000..f07a6278c8c --- /dev/null +++ b/chain/wallet/wallet_test.go @@ -0,0 +1,105 @@ +//stm: #unit +package wallet + +import ( + "context" + "testing" + + "github.com/filecoin-project/lotus/chain/types" + "github.com/stretchr/testify/assert" +) + +func TestWallet(t *testing.T) { + + ctx := context.Background() + + w1, err := NewWallet(NewMemKeyStore()) + if err != nil { + t.Fatal(err) + } + + //stm: @TOKEN_WALLET_NEW_001 + a1, err := w1.WalletNew(ctx, types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + + //stm: @TOKEN_WALLET_HAS_001 + exists, err := w1.WalletHas(ctx, a1) + if err != nil { + t.Fatal(err) + } + + if !exists { + t.Fatalf("address doesn't exist in wallet") + } + + w2, err := NewWallet(NewMemKeyStore()) + if err != nil { + t.Fatal(err) + } + + a2, err := w2.WalletNew(ctx, types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + + a3, err := w2.WalletNew(ctx, types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + + //stm: @TOKEN_WALLET_LIST_001 + addrs, err := w2.WalletList(ctx) + if err != nil { + t.Fatal(err) + } + + if len(addrs) != 2 { + t.Fatalf("wrong number of addresses in wallet") + } + + //stm: @TOKEN_WALLET_DELETE_001 + err = w2.WalletDelete(ctx, a2) + if err != nil { + t.Fatal(err) + } + + //stm: @TOKEN_WALLET_HAS_001 + exists, err = w2.WalletHas(ctx, a2) + if err != nil { + t.Fatal(err) + } + if exists { + t.Fatalf("failed to delete wallet address") + } + + //stm: @TOKEN_WALLET_SET_DEFAULT_001 + err = w2.SetDefault(a3) + if err != nil { + t.Fatal(err) + } + + //stm: @TOKEN_WALLET_DEFAULT_ADDRESS_001 + def, err := w2.GetDefault() + if !assert.Equal(t, a3, def) { + t.Fatal(err) + } + + //stm: @TOKEN_WALLET_EXPORT_001 + keyInfo, err := w2.WalletExport(ctx, a3) + if err != nil { + t.Fatal(err) + } + + //stm: @TOKEN_WALLET_IMPORT_001 + addr, err := w2.WalletImport(ctx, keyInfo) + if err != nil { + t.Fatal(err) + } + + if addr != a3 { + t.Fatalf("imported address doesn't match exported address") + } + +} From 21a8f7185925ce2bbae988bb9c362eb77eafb07e Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Wed, 12 Jan 2022 14:59:09 +0400 Subject: [PATCH 035/385] compiles --- go.mod | 10 ++-- go.sum | 72 +++++++++++----------------- node/modules/storageminer_idxprov.go | 9 +--- 3 files changed, 37 insertions(+), 54 deletions(-) diff --git a/go.mod b/go.mod index b8d36e6fde2..ac520e04738 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/elastic/gosigar v0.14.1 github.com/etclabscore/go-openrpc-reflect v0.0.36 github.com/fatih/color v1.13.0 - github.com/filecoin-project/dagstore v0.5.1-0.20220112075533-ee91088affb1 + github.com/filecoin-project/dagstore v0.5.1 github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200910194244-f640612a1a1f github.com/filecoin-project/go-address v0.0.6 github.com/filecoin-project/go-bitfield v0.2.4 @@ -36,7 +36,8 @@ require ( github.com/filecoin-project/go-data-transfer v1.12.1 github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 - github.com/filecoin-project/go-fil-markets v1.14.2-0.20220112081049-7165da072c0c + github.com/filecoin-project/go-fil-markets v1.14.2-0.20220112094113-068e7f35a0e0 + github.com/filecoin-project/go-indexer-core v0.2.7 github.com/filecoin-project/go-jsonrpc v0.1.5 github.com/filecoin-project/go-padreader v0.0.1 github.com/filecoin-project/go-paramfetch v0.0.3-0.20220111000201-e42866db1a53 @@ -44,7 +45,7 @@ require ( github.com/filecoin-project/go-statemachine v1.0.1 github.com/filecoin-project/go-statestore v0.2.0 github.com/filecoin-project/go-storedcounter v0.1.0 - github.com/filecoin-project/index-provider v0.1.0 // indirect + github.com/filecoin-project/index-provider v0.1.1-0.20220107223914-37c38e2b284d github.com/filecoin-project/specs-actors v0.9.14 github.com/filecoin-project/specs-actors/v2 v2.3.6 github.com/filecoin-project/specs-actors/v3 v3.1.1 @@ -145,7 +146,7 @@ require ( github.com/uber/jaeger-client-go v2.25.0+incompatible // indirect github.com/urfave/cli/v2 v2.3.0 github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba - github.com/whyrusleeping/cbor-gen v0.0.0-20210713220151-be142a5ae1a8 + github.com/whyrusleeping/cbor-gen v0.0.0-20211110122933-f57984553008 github.com/whyrusleeping/ledger-filecoin-go v0.9.1-0.20201010031517-c3dcc1bddce4 github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 github.com/whyrusleeping/pubsub v0.0.0-20190708150250-92bcb0691325 @@ -177,3 +178,4 @@ replace github.com/filecoin-project/test-vectors => ./extern/test-vectors //replace github.com/filecoin-project/specs-actors/v7 => /Users/zenground0/pl/repos/specs-actors // replace github.com/filecon-project/specs-storage => /Users/zenground0/pl/repos/specs-storage +replace github.com/ipfs/go-path => github.com/ipfs/go-path v0.0.7 diff --git a/go.sum b/go.sum index 6c950cd3acc..6972bac3605 100644 --- a/go.sum +++ b/go.sum @@ -79,7 +79,6 @@ github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWX github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= -github.com/Stebalien/go-bitfield v0.0.1 h1:X3kbSSPUaJK60wV2hjOPZwmpljr6VGCqdq4cBLhbQBo= github.com/Stebalien/go-bitfield v0.0.1/go.mod h1:GNjFpasyUVkHMsfEOk8EFLJ9syQ6SI+XWrX9Wf2XH0s= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= @@ -97,6 +96,7 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a h1:E/8AP5dFtMhl5KPJz66Kt9G0n+7Sn41Fy1wv9/jHOrc= github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5/go.mod h1:Y2QMoi1vgtOIfc+6DhrMOGkLoGzqSV2rKp4Sm+opsyA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= @@ -298,10 +298,8 @@ github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/filecoin-project/dagstore v0.4.3-0.20211211192320-72b849e131d2/go.mod h1:tlV8C11UljvFq3WWlMh2oMViEaVaPb6uT8eL/YQgDfk= -github.com/filecoin-project/dagstore v0.4.4 h1:luolWahhzp3ulRsapGKE7raoLE3n2cFkQUJjPyqUmF4= -github.com/filecoin-project/dagstore v0.4.4/go.mod h1:7BlOvaTJrFJ1Qemt5jHlLJ4VhDIuSIzGS0IwO/0AXPA= -github.com/filecoin-project/dagstore v0.5.1-0.20220112075533-ee91088affb1/go.mod h1:OdlK3x5m3Mol874WC2bI79H4H2+leN+FabwWdW2D/wY= +github.com/filecoin-project/dagstore v0.5.1 h1:ojzW/8z4PiquPDSA3EJ+Y4JcL+SWuloLaisy/hYcKMA= +github.com/filecoin-project/dagstore v0.5.1/go.mod h1:OdlK3x5m3Mol874WC2bI79H4H2+leN+FabwWdW2D/wY= github.com/filecoin-project/go-address v0.0.3/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= github.com/filecoin-project/go-address v0.0.5/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= github.com/filecoin-project/go-address v0.0.6 h1:DWQtj38ax+ogHwyH3VULRIoT8E6loyXqsk/p81xoY7M= @@ -325,12 +323,11 @@ github.com/filecoin-project/go-crypto v0.0.1 h1:AcvpSGGCgjaY8y1az6AMfKQWreF/pWO2 github.com/filecoin-project/go-crypto v0.0.1/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= github.com/filecoin-project/go-dagaggregator-unixfs v0.2.0/go.mod h1:WTuJWgBQY0omnQqa8kRPT9O0Uj5wQOgslVMUuTeHdJ8= github.com/filecoin-project/go-data-transfer v1.11.4/go.mod h1:2MitLI0ebCkLlPKM7NRggP/t9d+gCcREUKkCKqWRCwU= -github.com/filecoin-project/go-data-transfer v1.12.0/go.mod h1:tDrD2jLU2TpVhd+5B8iqBp0fQRV4lP80WZccKXugjYc= github.com/filecoin-project/go-data-transfer v1.12.1 h1:gAznAZKySVs2FS6T/vDq7R3f0DewLnxeROe0oOE6bZU= github.com/filecoin-project/go-data-transfer v1.12.1/go.mod h1:j3HL645YiQFxcM+q7uPlGApILSqeweDABNgZQP7pDYU= -github.com/filecoin-project/go-ds-versioning v0.0.0-20211206185234-508abd7c2aff h1:2bG2ggVZ/rInd/YqUfRj4A5siGuYOPxxuD4I8nYLJF0= github.com/filecoin-project/go-ds-versioning v0.0.0-20211206185234-508abd7c2aff/go.mod h1:C9/l9PnB1+mwPa26BBVpCjG/XQCB0yj/q5CK2J8X1I4= github.com/filecoin-project/go-ds-versioning v0.1.0/go.mod h1:mp16rb4i2QPmxBnmanUx8i/XANp+PFCCJWiAb+VW4/s= +github.com/filecoin-project/go-ds-versioning v0.1.1 h1:JiyBqaQlwC+UM0WhcBtVEeT3XrX59mQhT8U3p7nu86o= github.com/filecoin-project/go-ds-versioning v0.1.1/go.mod h1:C9/l9PnB1+mwPa26BBVpCjG/XQCB0yj/q5CK2J8X1I4= github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= @@ -338,10 +335,8 @@ github.com/filecoin-project/go-fil-commcid v0.1.0 h1:3R4ds1A9r6cr8mvZBfMYxTS88Oq github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7LXep5bFEVOVmQWHJvl2mgsGo= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8= -github.com/filecoin-project/go-fil-markets v1.14.1 h1:Bx+TSbkAN8K97Hpjgu+MpeRFbXIKH/fNpNp1ZGAEH3I= -github.com/filecoin-project/go-fil-markets v1.14.1/go.mod h1:vXOHH3q2+zLk929W+lIq3etuDFTyJJ8nG2DwGHG2R1E= -github.com/filecoin-project/go-fil-markets v1.14.2-0.20220112081049-7165da072c0c h1:zrVwAnkOblTHFnhReZIZOrCfWDhclszB1nr/BZoFt4g= -github.com/filecoin-project/go-fil-markets v1.14.2-0.20220112081049-7165da072c0c/go.mod h1:oQg5Q79yBf+dY1Z/wbIdX3uPJUKGQg9B6SB5XP8wqKA= +github.com/filecoin-project/go-fil-markets v1.14.2-0.20220112094113-068e7f35a0e0 h1:C3rdpJJQm8/UX3aAPNbVHzSEDjI9EvD1jb2eroA3aK8= +github.com/filecoin-project/go-fil-markets v1.14.2-0.20220112094113-068e7f35a0e0/go.mod h1:H1pk9szltDLCOvQW/6fy0ugvUnDY7CDCf9HJSGSoj60= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= @@ -351,10 +346,11 @@ github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0 h1:rVVNq0x6RGQIzCo1iiJlGFm9AG github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0/go.mod h1:bxmzgT8tmeVQA1/gvBwFmYdT8SOFUwB3ovSUfG1Ux0g= github.com/filecoin-project/go-indexer-core v0.2.4/go.mod h1:MSe5aRWmfRB+5syR4yDV+OApgJU+MUJ4rl9VUuzwCfc= github.com/filecoin-project/go-indexer-core v0.2.6/go.mod h1:wW5Ab0gJXL2vT4iEMbPUfPs773iMc86Q8GtfSEqmu3Y= +github.com/filecoin-project/go-indexer-core v0.2.7 h1:D0egR6Q3Jkp5r4klxkdDQvjXeLx3cwZMKE55qop2xCI= github.com/filecoin-project/go-indexer-core v0.2.7/go.mod h1:6YD7KwDOQ+03DdAitviL7h1fksIU6a4j52yPnA/E1PU= github.com/filecoin-project/go-jsonrpc v0.1.5 h1:ckxqZ09ivBAVf5CSmxxrqqNHC7PJm3GYGtYKiNQ+vGk= github.com/filecoin-project/go-jsonrpc v0.1.5/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4= -github.com/filecoin-project/go-legs v0.1.0/go.mod h1:HFp0jUZopkX9DW6FOmhHltVfEatfAcm3ZD6Z/kY4iNg= +github.com/filecoin-project/go-legs v0.2.1 h1:XnQO5fesqo0sFLZhoPmYzJM38FNO7X93TM9HUsCMKbo= github.com/filecoin-project/go-legs v0.2.1/go.mod h1:iHDfdqieReblkLoHneB68wvthFtNKB+wkeEWKtiJESk= github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20/go.mod h1:mPn+LRRd5gEKNAtc+r3ScpW2JRU/pj4NBKdADYWHiak= github.com/filecoin-project/go-padreader v0.0.0-20210723183308-812a16dc01b1/go.mod h1:VYVPJqwpsfmtoHnAmPx6MUwmrK6HIcDqZJiuZhtmfLQ= @@ -378,8 +374,8 @@ github.com/filecoin-project/go-statestore v0.2.0 h1:cRRO0aPLrxKQCZ2UOQbzFGn4WDNd github.com/filecoin-project/go-statestore v0.2.0/go.mod h1:8sjBYbS35HwPzct7iT4lIXjLlYyPor80aU7t7a/Kspo= github.com/filecoin-project/go-storedcounter v0.1.0 h1:Mui6wSUBC+cQGHbDUBcO7rfh5zQkWJM/CpAZa/uOuus= github.com/filecoin-project/go-storedcounter v0.1.0/go.mod h1:4ceukaXi4vFURIoxYMfKzaRF5Xv/Pinh2oTnoxpv+z8= -github.com/filecoin-project/index-provider v0.1.0 h1:49K9S17uTrTHLT90xchJ7BxION8odyhKdtu5w7DyyYU= -github.com/filecoin-project/index-provider v0.1.0/go.mod h1:lFxPujkBr4sYllLKZKCbjKktsU4dDINCyLLSK2rz/6o= +github.com/filecoin-project/index-provider v0.1.1-0.20220107223914-37c38e2b284d h1:wEhUj2MpECUcOEr/UDMPBjG6ElGOcEwePtra1/bvrMQ= +github.com/filecoin-project/index-provider v0.1.1-0.20220107223914-37c38e2b284d/go.mod h1:pTZVxt9mF+YCYSfNsn7i0rwhoMBmbjfSDAQVoxWGP10= github.com/filecoin-project/specs-actors v0.9.13/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= github.com/filecoin-project/specs-actors v0.9.14 h1:68PVstg2UB3ZsMLF+DKFTAs/YKsqhKWynkr0IqmVRQY= github.com/filecoin-project/specs-actors v0.9.14/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= @@ -392,7 +388,6 @@ github.com/filecoin-project/specs-actors/v3 v3.1.1/go.mod h1:mpynccOLlIRy0QnR008 github.com/filecoin-project/specs-actors/v4 v4.0.0/go.mod h1:TkHXf/l7Wyw4ZejyXIPS2rK8bBO0rdwhTZyQQgaglng= github.com/filecoin-project/specs-actors/v4 v4.0.1 h1:AiWrtvJZ63MHGe6rn7tPu4nSUY8bA1KDNszqJaD5+Fg= github.com/filecoin-project/specs-actors/v4 v4.0.1/go.mod h1:TkHXf/l7Wyw4ZejyXIPS2rK8bBO0rdwhTZyQQgaglng= -github.com/filecoin-project/specs-actors/v5 v5.0.0-20210512015452-4fe3889fff57/go.mod h1:283yBMMUSDB2abcjP/hhrwTkhb9h3sfM6KGrep/ZlBI= github.com/filecoin-project/specs-actors/v5 v5.0.4 h1:OY7BdxJWlUfUFXWV/kpNBYGXNPasDIedf42T3sGx08s= github.com/filecoin-project/specs-actors/v5 v5.0.4/go.mod h1:5BAKRAMsOOlD8+qCw4UvT/lTLInCJ3JwOWZbX8Ipwq4= github.com/filecoin-project/specs-actors/v6 v6.0.0/go.mod h1:V1AYfi5GkHXipx1mnVivoICZh3wtwPxDVuds+fbfQtk= @@ -404,7 +399,7 @@ github.com/filecoin-project/specs-actors/v7 v7.0.0-20211230214648-aeae366b083a h github.com/filecoin-project/specs-actors/v7 v7.0.0-20211230214648-aeae366b083a/go.mod h1:p6LIOFezA1rgRLMewbvdi3Pp6SAu+q9FtJ9CAleSjrE= github.com/filecoin-project/specs-storage v0.1.1-0.20211228030229-6d460d25a0c9 h1:oUYOvF7EvdXS0Zmk9mNkaB6Bu0l+WXBYPzVodKMiLug= github.com/filecoin-project/specs-storage v0.1.1-0.20211228030229-6d460d25a0c9/go.mod h1:Tb88Zq+IBJbvAn3mS89GYj3jdRThBTE/771HCVZdRJU= -github.com/filecoin-project/storetheindex v0.1.0/go.mod h1:zCaWVI27t/OBG/Ngh1RfNBaxEc8jPOoH3O2GaHLAymI= +github.com/filecoin-project/storetheindex v0.2.0/go.mod h1:P3Hd3sIWEkBU1fPnE49Y8nh/mdErOdIfiHBb85QAWfg= github.com/filecoin-project/storetheindex v0.2.1 h1:jhsMh5O52bBU/NrnjJs2iLPI92T38kjlU9bk/dP0sts= github.com/filecoin-project/storetheindex v0.2.1/go.mod h1:Tc5mYdAnGUzly40cuo35yITDD3XhF9EX5BO7evGsJ5M= github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg= @@ -423,12 +418,14 @@ github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss= github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= github.com/gabriel-vasile/mimetype v1.1.2/go.mod h1:6CDPel/o/3/s4+bp6kIbsWATq8pmgOisOPG40CJa6To= github.com/gabriel-vasile/mimetype v1.4.0/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8= +github.com/gammazero/keymutex v0.0.2 h1:cmpLBJHdEwn+WlR5Z/o9/BN92znSZTp5AKPQDpu1QcI= github.com/gammazero/keymutex v0.0.2/go.mod h1:qtzWCCLMisQUmVa4dvqHVgwfh4BP2YB7JxNDGXnsKrs= +github.com/gammazero/radixtree v0.2.5 h1:muPQ4eEgCkUymFWPiVQRuXOQv4IhWg8YXH2r71MoqPM= github.com/gammazero/radixtree v0.2.5/go.mod h1:VPqqCDZ3YZZxAzUUsIF/ytFBigVWV7JIV1Stld8hri0= github.com/gbrlsnchs/jwt/v3 v3.0.1 h1:lbUmgAKpxnClrKloyIwpxm4OuWeDl5wLk52G91ODPw4= github.com/gbrlsnchs/jwt/v3 v3.0.1/go.mod h1:AncDcjXz18xetI3A6STfXq2w+LuTx8pQ8bGEwRN8zVM= @@ -691,6 +688,7 @@ github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab/go.mod github.com/ipfs/bbloom v0.0.1/go.mod h1:oqo8CVWsJFMOZqTglBG4wydCE4IQA/G2/SEofB0rjUI= github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs= github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0= +github.com/ipfs/go-bitfield v1.0.0 h1:y/XHm2GEmD9wKngheWNNCNL0pzrWXZwCdQGv1ikXknQ= github.com/ipfs/go-bitfield v1.0.0/go.mod h1:N/UiujQy+K+ceU1EF5EkVd1TNqevLrCQMIcAEPrdtus= github.com/ipfs/go-bitswap v0.0.9/go.mod h1:kAPf5qgn2W2DrgAcscZ3HrM9qh4pH+X8Fkk3UPrwvis= github.com/ipfs/go-bitswap v0.1.0/go.mod h1:FFJEf18E9izuCqUtHxbWEvq+reg7o4CW5wSAE1wsxj0= @@ -722,7 +720,6 @@ github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67Fexh github.com/ipfs/go-cid v0.0.6-0.20200501230655-7c82f3b81c00/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog= github.com/ipfs/go-cid v0.0.6/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= -github.com/ipfs/go-cid v0.0.8-0.20210716091050-de6c03deae1c/go.mod h1:rH5/Xv83Rfy8Rw6xG+id3DYAMUVmem1MowoKwdXmN2o= github.com/ipfs/go-cid v0.1.0 h1:YN33LQulcRHjfom/i25yoOZR4Telp1Hr/2RU3d0PnC0= github.com/ipfs/go-cid v0.1.0/go.mod h1:rH5/Xv83Rfy8Rw6xG+id3DYAMUVmem1MowoKwdXmN2o= github.com/ipfs/go-cidutil v0.0.2 h1:CNOboQf1t7Qp0nuNh8QMmhJs0+Q//bRL1axtCnIB1Yo= @@ -773,12 +770,11 @@ github.com/ipfs/go-filestore v0.0.3/go.mod h1:dvXRykFzyyXN2CdNlRGzDAkXMDPyI+D7JE github.com/ipfs/go-filestore v0.1.0/go.mod h1:0KTrzoJnJ3sJDEDM09Vq8nz8H475rRyeq4i0n/bpF00= github.com/ipfs/go-filestore v1.1.0 h1:Pu4tLBi1bucu6/HU9llaOmb9yLFk/sgP+pW764zNDoE= github.com/ipfs/go-filestore v1.1.0/go.mod h1:6e1/5Y6NvLuCRdmda/KA4GUhXJQ3Uat6vcWm2DJfxc8= -github.com/ipfs/go-fs-lock v0.0.6 h1:sn3TWwNVQqSeNjlWy6zQ1uUGAZrV3hPOyEA6y1/N2a0= github.com/ipfs/go-fs-lock v0.0.6/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28L7zESmM= +github.com/ipfs/go-fs-lock v0.0.7 h1:6BR3dajORFrFTkb5EpCUFIAypsoxpGpDSVUdFwzgL9U= github.com/ipfs/go-fs-lock v0.0.7/go.mod h1:Js8ka+FNYmgQRLrRXzU3CB/+Csr1BwrRilEcvYrHhhc= github.com/ipfs/go-graphsync v0.8.0/go.mod h1:CLxN859dUTcXCav1DvNvmAUWPZfmNLjlGLJYy+c3dlM= github.com/ipfs/go-graphsync v0.10.0/go.mod h1:cKIshzTaa5rCZjryH5xmSKZVGX9uk1wvwGvz2WEha5Y= -github.com/ipfs/go-graphsync v0.10.4/go.mod h1:oei4tnWAKnZ6LPnapZGPYVVbyiKV1UP3f8BeLU7Z4JQ= github.com/ipfs/go-graphsync v0.11.0/go.mod h1:wC+c8vGVjAHthsVIl8LKr37cUra2GOaMYcQNNmMxDqE= github.com/ipfs/go-graphsync v0.11.5 h1:WA5hVxGBtcal6L6nqubKiqRolaZxbexOK3GumGFJRR4= github.com/ipfs/go-graphsync v0.11.5/go.mod h1:+/sZqRwRCQRrV7NCzgBtufmr5QGpUE98XSa7NlsztmM= @@ -790,7 +786,6 @@ github.com/ipfs/go-ipfs-blockstore v0.1.4/go.mod h1:Jxm3XMVjh6R17WvxFEiyKBLUGr86 github.com/ipfs/go-ipfs-blockstore v0.1.6/go.mod h1:Jxm3XMVjh6R17WvxFEiyKBLUGr86HgIYJW/D/MwqeYQ= github.com/ipfs/go-ipfs-blockstore v0.2.1/go.mod h1:jGesd8EtCM3/zPgx+qr0/feTXGUeRai6adgwC+Q+JvE= github.com/ipfs/go-ipfs-blockstore v1.0.1/go.mod h1:MGNZlHNEnR4KGgPHM3/k8lBySIOK2Ve+0KjZubKlaOE= -github.com/ipfs/go-ipfs-blockstore v1.0.3/go.mod h1:MGNZlHNEnR4KGgPHM3/k8lBySIOK2Ve+0KjZubKlaOE= github.com/ipfs/go-ipfs-blockstore v1.0.4-0.20210205083733-fb07d7bc5aec/go.mod h1:feuklK+m9POeWJzYQO7l05yNEgUiX5oELBNA8/Be33E= github.com/ipfs/go-ipfs-blockstore v1.0.4/go.mod h1:uL7/gTJ8QIZ3MtA3dWf+s1a0U3fJy2fcEZAsovpRp+w= github.com/ipfs/go-ipfs-blockstore v1.1.0/go.mod h1:5QDUApRqpgPcfGstCxYeMnjt/DYQtXXdJVCvxHHuWVk= @@ -802,12 +797,12 @@ github.com/ipfs/go-ipfs-blocksutil v0.0.1/go.mod h1:Yq4M86uIOmxmGPUHv/uI7uKqZNtL github.com/ipfs/go-ipfs-chunker v0.0.1/go.mod h1:tWewYK0we3+rMbOh7pPFGDyypCtvGcBFymgY4rSDLAw= github.com/ipfs/go-ipfs-chunker v0.0.5 h1:ojCf7HV/m+uS2vhUGWcogIIxiO5ubl5O57Q7NapWLY8= github.com/ipfs/go-ipfs-chunker v0.0.5/go.mod h1:jhgdF8vxRHycr00k13FM8Y0E+6BoalYeobXmUyTreP8= -github.com/ipfs/go-ipfs-cmds v0.3.0 h1:mi9oYrSCox5aBhutqAYqw6/9crlyGbw4E/aJtwS4zI4= github.com/ipfs/go-ipfs-cmds v0.3.0/go.mod h1:ZgYiWVnCk43ChwoH8hAmI1IRbuVtq3GSTHwtRB/Kqhk= +github.com/ipfs/go-ipfs-cmds v0.6.0 h1:yAxdowQZzoFKjcLI08sXVNnqVj3jnABbf9smrPQmBsw= github.com/ipfs/go-ipfs-cmds v0.6.0/go.mod h1:ZgYiWVnCk43ChwoH8hAmI1IRbuVtq3GSTHwtRB/Kqhk= -github.com/ipfs/go-ipfs-config v0.5.3 h1:3GpI/xR9FoJNTjU6YvCMRbYyEi0dBVY5UtlUTcNRlSA= github.com/ipfs/go-ipfs-config v0.5.3/go.mod h1:nSLCFtlaL+2rbl3F+9D4gQZQbT1LjRKx7TJg/IHz6oM= github.com/ipfs/go-ipfs-config v0.16.0/go.mod h1:wz2lKzOjgJeYJa6zx8W9VT7mz+iSd0laBMqS/9wmX6A= +github.com/ipfs/go-ipfs-config v0.18.0 h1:Ta1aNGNEq6RIvzbw7dqzCVZJKb7j+Dd35JFnAOCpT8g= github.com/ipfs/go-ipfs-config v0.18.0/go.mod h1:wz2lKzOjgJeYJa6zx8W9VT7mz+iSd0laBMqS/9wmX6A= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= github.com/ipfs/go-ipfs-delay v0.0.1 h1:r/UXYyRcddO6thwOnhiznIAiSvxMECGgtv35Xs1IeRQ= @@ -906,16 +901,11 @@ github.com/ipfs/go-namesys v0.3.1/go.mod h1:/BL4xk8LP5Lq82AmaRKyxZv/eYRlumNiU9SZ github.com/ipfs/go-namesys v0.4.0/go.mod h1:jpJwzodyP8DZdWN6DShRjVZw6gaqMr4nQLBSxU5cR6E= github.com/ipfs/go-path v0.0.7 h1:H06hKMquQ0aYtHiHryOMLpQC1qC3QwXwkahcEVD51Ho= github.com/ipfs/go-path v0.0.7/go.mod h1:6KTKmeRnBXgqrTvzFrPV3CamxcgvXX/4z79tfAd2Sno= -github.com/ipfs/go-path v0.0.9/go.mod h1:VpDkSBKQ9EFQOUgi54Tq/O/tGi8n1RfYNks13M3DEs8= -github.com/ipfs/go-path v0.1.1/go.mod h1:vC8q4AKOtrjJz2NnllIrmr2ZbGlF5fW2OKKyhV9ggb0= -github.com/ipfs/go-path v0.1.2/go.mod h1:3DdbxZb0PtT0g3UlMqyzms1UBKPc0pQ2NHx5/XScYdY= -github.com/ipfs/go-path v0.2.1/go.mod h1:NOScsVgxfC/eIw4nz6OiGwK42PjaSJ4Y/ZFPn1Xe07I= github.com/ipfs/go-peertaskqueue v0.0.4/go.mod h1:03H8fhyeMfKNFWqzYEVyMbcPUeYrqP1MX6Kd+aN+rMQ= github.com/ipfs/go-peertaskqueue v0.1.0/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= github.com/ipfs/go-peertaskqueue v0.1.1/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= github.com/ipfs/go-peertaskqueue v0.2.0/go.mod h1:5/eNrBEbtSKWCG+kQK8K8fGNixoYUnr+P7jivavs9lY= github.com/ipfs/go-peertaskqueue v0.4.0/go.mod h1:KL9F49hXJMoXCad8e5anivjN+kWdr+CyGcyh4K6doLc= -github.com/ipfs/go-peertaskqueue v0.6.0/go.mod h1:M/akTIE/z1jGNXMU7kFB4TeSEFvj68ow0Rrb04donIU= github.com/ipfs/go-peertaskqueue v0.7.0/go.mod h1:M/akTIE/z1jGNXMU7kFB4TeSEFvj68ow0Rrb04donIU= github.com/ipfs/go-peertaskqueue v0.7.1 h1:7PLjon3RZwRQMgOTvYccZ+mjzkmds/7YzSWKFlBAypE= github.com/ipfs/go-peertaskqueue v0.7.1/go.mod h1:M/akTIE/z1jGNXMU7kFB4TeSEFvj68ow0Rrb04donIU= @@ -925,16 +915,15 @@ github.com/ipfs/go-unixfs v0.1.0/go.mod h1:lysk5ELhOso8+Fed9U1QTGey2ocsfaZ18h0NC github.com/ipfs/go-unixfs v0.2.2-0.20190827150610-868af2e9e5cb/go.mod h1:IwAAgul1UQIcNZzKPYZWOCijryFBeCV79cNubPzol+k= github.com/ipfs/go-unixfs v0.2.4/go.mod h1:SUdisfUjNoSDzzhGVxvCL9QO/nKdwXdr+gbMUdqcbYw= github.com/ipfs/go-unixfs v0.2.5/go.mod h1:SUdisfUjNoSDzzhGVxvCL9QO/nKdwXdr+gbMUdqcbYw= -github.com/ipfs/go-unixfs v0.2.6 h1:gq3U3T2vh8x6tXhfo3uSO3n+2z4yW0tYtNgVP/3sIyA= github.com/ipfs/go-unixfs v0.2.6/go.mod h1:GTTzQvaZsTZARdNkkdjDKFFnBhmO3e5mIM1PkH/x4p0= +github.com/ipfs/go-unixfs v0.3.1 h1:LrfED0OGfG98ZEegO4/xiprx2O+yS+krCMQSp7zLVv8= github.com/ipfs/go-unixfs v0.3.1/go.mod h1:h4qfQYzghiIc8ZNFKiLMFWOTzrWIAtzYQ59W/pCFf1o= -github.com/ipfs/go-unixfsnode v1.1.2/go.mod h1:5dcE2x03pyjHk4JjamXmunTMzz+VUtqvPwZjIEkfV6s= github.com/ipfs/go-unixfsnode v1.1.3/go.mod h1:ZZxUM5wXBC+G0Co9FjrYTOm+UlhZTjxLfRYdWY9veZ4= github.com/ipfs/go-verifcid v0.0.1 h1:m2HI7zIuR5TFyQ1b79Da5N9dnnCP1vcu2QqawmWlK2E= github.com/ipfs/go-verifcid v0.0.1/go.mod h1:5Hrva5KBeIog4A+UpqlaIU+DEstipcJYQQZc0g37pY0= -github.com/ipfs/interface-go-ipfs-core v0.4.0 h1:+mUiamyHIwedqP8ZgbCIwpy40oX7QcXUbo4CZOeJVJg= github.com/ipfs/interface-go-ipfs-core v0.4.0/go.mod h1:UJBcU6iNennuI05amq3FQ7g0JHUkibHFAfhfUIy927o= github.com/ipfs/interface-go-ipfs-core v0.5.1/go.mod h1:lNBJrdXHtWS46evMPBdWtDQMDsrKcGbxCOGoKLkztOE= +github.com/ipfs/interface-go-ipfs-core v0.5.2 h1:m1/5U+WpOK2ZE7Qzs5iIu80QM1ZA3aWYi2Ilwpi+tdg= github.com/ipfs/interface-go-ipfs-core v0.5.2/go.mod h1:lNBJrdXHtWS46evMPBdWtDQMDsrKcGbxCOGoKLkztOE= github.com/ipfs/iptb v1.4.0 h1:YFYTrCkLMRwk/35IMyC6+yjoQSHTEcNcefBStLJzgvo= github.com/ipfs/iptb v1.4.0/go.mod h1:1rzHpCYtNp87/+hTxG5TfCVn/yMY3dKnLn8tBiMfdmg= @@ -948,8 +937,6 @@ github.com/ipld/go-car v0.3.2/go.mod h1:WEjynkVt04dr0GwJhry0KlaTeSDEiEYyMPOxDBQ1 github.com/ipld/go-car v0.3.3-0.20211210032800-e6f244225a16/go.mod h1:/wkKF4908ULT4dFIFIUZYcfjAnj+KFnJvlh8Hsz1FbQ= github.com/ipld/go-car v0.3.3 h1:D6y+jvg9h2ZSv7GLUMWUwg5VTLy1E7Ak+uQw5orOg3I= github.com/ipld/go-car v0.3.3/go.mod h1:/wkKF4908ULT4dFIFIUZYcfjAnj+KFnJvlh8Hsz1FbQ= -github.com/ipld/go-car/v2 v2.0.3-0.20210920144420-f35d88ce16ca/go.mod h1:Xr6GwkDhv8dtOtgHzOynAkIOg0t0YiPc5DxBPppWqZA= -github.com/ipld/go-car/v2 v2.1.1-0.20211211000942-be2525f6bf2d/go.mod h1:+2Yvf0Z3wzkv7NeI69i8tuZ+ft7jyjPYIWZzeVNeFcI= github.com/ipld/go-car/v2 v2.1.1 h1:saaKz4nC0AdfCGHLYKeXLGn8ivoPC54fyS55uyOLKwA= github.com/ipld/go-car/v2 v2.1.1/go.mod h1:+2Yvf0Z3wzkv7NeI69i8tuZ+ft7jyjPYIWZzeVNeFcI= github.com/ipld/go-codec-dagpb v1.2.0/go.mod h1:6nBN7X7h8EOsEejZGqC7tej5drsdBAXbMHyBT+Fne5s= @@ -976,6 +963,7 @@ github.com/ipld/go-ipld-selector-text-lite v0.0.1 h1:lNqFsQpBHc3p5xHob2KvEg/iM5d github.com/ipld/go-ipld-selector-text-lite v0.0.1/go.mod h1:U2CQmFb+uWzfIEF3I1arrDa5rwtj00PrpiwwCO+k1RM= github.com/ipld/go-storethehash v0.0.0-20210915160027-d72ca9b0968c/go.mod h1:PwE6iq8TiWJRI3zMGA1RtkFAnrDMK93dLA5SUeu0lH8= github.com/ipld/go-storethehash v0.0.0-20211122175924-41b16c131842/go.mod h1:PwE6iq8TiWJRI3zMGA1RtkFAnrDMK93dLA5SUeu0lH8= +github.com/ipld/go-storethehash v0.0.1 h1:U9E9n3dE0IaImSNbRcUmm5Dk9UPiS9H0i+LmCFFGJBI= github.com/ipld/go-storethehash v0.0.1/go.mod h1:w8cQfWInks8lvvbQTiKbCPusU9v0sqiViBihTHbavpQ= github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52 h1:QG4CGBqCeuBo6aZlGAamSkxWdgWfZGeE49eUOWJPA4c= github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52/go.mod h1:fdg+/X9Gg4AsAIzWpEHwnqd+QY3b7lajxyjE1m4hkq4= @@ -1050,7 +1038,6 @@ github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQ github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.6/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.0.8/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -1195,6 +1182,7 @@ github.com/libp2p/go-libp2p-discovery v0.5.1/go.mod h1:+srtPIU9gDaBNu//UHvcdliKB github.com/libp2p/go-libp2p-discovery v0.6.0 h1:1XdPmhMJr8Tmj/yUfkJMIi8mgwWrLUsCB3bMxdT+DSo= github.com/libp2p/go-libp2p-discovery v0.6.0/go.mod h1:/u1voHt0tKIe5oIA1RHBKQLVCWPna2dXmPNHc2zR9S8= github.com/libp2p/go-libp2p-gostream v0.3.0/go.mod h1:pLBQu8db7vBMNINGsAwLL/ZCE8wng5V1FThoaE5rNjc= +github.com/libp2p/go-libp2p-gostream v0.3.1 h1:XlwohsPn6uopGluEWs1Csv1QCEjrTXf2ZQagzZ5paAg= github.com/libp2p/go-libp2p-gostream v0.3.1/go.mod h1:1V3b+u4Zhaq407UUY9JLCpboaeufAeVQbnvAt12LRsI= github.com/libp2p/go-libp2p-host v0.0.1/go.mod h1:qWd+H1yuU0m5CwzAkvbSjqKairayEHdR5MMl7Cwa7Go= github.com/libp2p/go-libp2p-host v0.0.3/go.mod h1:Y/qPyA6C8j2coYyos1dfRm0I8+nvd4TGrDGt4tA7JR8= @@ -1583,7 +1571,6 @@ github.com/multiformats/go-multiaddr v0.3.0/go.mod h1:dF9kph9wfJ+3VLAaeBqo9Of8x4 github.com/multiformats/go-multiaddr v0.3.1/go.mod h1:uPbspcUPd5AfaP6ql3ujFY+QWzmBD8uLLL4bXW0XfGc= github.com/multiformats/go-multiaddr v0.3.3/go.mod h1:lCKNGP1EQ1eZ35Za2wlqnabm9xQkib3fyB+nZXHLag0= github.com/multiformats/go-multiaddr v0.4.0/go.mod h1:YcpyLH8ZPudLxQlemYBPhSm0/oCXAT8Z4mzFpyoPyRc= -github.com/multiformats/go-multiaddr v0.4.1 h1:Pq37uLx3hsyNlTDir7FZyU8+cFCTqd5y1KiM2IzOutI= github.com/multiformats/go-multiaddr v0.4.1/go.mod h1:3afI9HfVW8csiF8UZqtpYRiDyew8pRX7qLIGHu9FLuM= github.com/multiformats/go-multiaddr v0.5.0 h1:i/JuOoVg4szYQ4YEzDGtb2h0o8M7CG/Yq6cGlcjWZpM= github.com/multiformats/go-multiaddr v0.5.0/go.mod h1:3KAxNkUqLTJ20AAwN4XVX4kZar+bR+gh4zgbfr3SNug= @@ -1611,7 +1598,6 @@ github.com/multiformats/go-multibase v0.0.3 h1:l/B6bJDQjvQ5G52jw4QGSYeOTZoAwIO77 github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= github.com/multiformats/go-multicodec v0.2.0/go.mod h1:/y4YVwkfMyry5kFbMTbLJKErhycTIftytRV+llXdyS4= github.com/multiformats/go-multicodec v0.3.0/go.mod h1:qGGaQmioCDh+TeFOnxrbU0DaIPw8yFgAZgFG0V7p1qQ= -github.com/multiformats/go-multicodec v0.3.1-0.20210902112759-1539a079fd61 h1:ZrUuMKNgJ52qHPoQ+bx0h0uBfcWmN7Px+4uKSZeesiI= github.com/multiformats/go-multicodec v0.3.1-0.20210902112759-1539a079fd61/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ= github.com/multiformats/go-multicodec v0.4.0 h1:fbqb6ky7erjdD+/zaEBJgZWu1i8D6i/wmPywGK7sdow= github.com/multiformats/go-multicodec v0.4.0/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ= @@ -1927,8 +1913,8 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.0.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= -github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4= github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= +github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= @@ -1937,8 +1923,8 @@ github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPU github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= github.com/wangjia184/sortedset v0.0.0-20160527075905-f5d03557ba30/go.mod h1:YkocrP2K2tcw938x9gCOmT5G5eCD6jsTz0SZuyAqwIE= -github.com/warpfork/go-testmark v0.3.0 h1:Q81c4u7hT+BR5kNfNQhEF0VT2pmL7+Kk0wD+ORYl7iA= github.com/warpfork/go-testmark v0.3.0/go.mod h1:jhEf8FVxd+F17juRubpmut64NEG6I2rgkUhlcqqXwE0= +github.com/warpfork/go-testmark v0.9.0 h1:nc+uaCiv5lFQLYjhuC2LTYeJ7JaC+gdDmsz9r0ISy0Y= github.com/warpfork/go-testmark v0.9.0/go.mod h1:jhEf8FVxd+F17juRubpmut64NEG6I2rgkUhlcqqXwE0= github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= github.com/warpfork/go-wish v0.0.0-20190328234359-8b3e70f8e830/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= @@ -1967,8 +1953,9 @@ github.com/whyrusleeping/cbor-gen v0.0.0-20200826160007-0b9f6c5fb163/go.mod h1:f github.com/whyrusleeping/cbor-gen v0.0.0-20210118024343-169e9d70c0c2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20210219115102-f37d292932f2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20210303213153-67a261a1d291/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= -github.com/whyrusleeping/cbor-gen v0.0.0-20210713220151-be142a5ae1a8 h1:TEv7MId88TyIqIUL4hbf9otOookIolMxlEbN0ro671Y= github.com/whyrusleeping/cbor-gen v0.0.0-20210713220151-be142a5ae1a8/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= +github.com/whyrusleeping/cbor-gen v0.0.0-20211110122933-f57984553008 h1:7WtW9D9VGpmRLuQmrPy2JobUNdka95z3MKEVpELtOjo= +github.com/whyrusleeping/cbor-gen v0.0.0-20211110122933-f57984553008/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f/go.mod h1:p9UJB6dDgdPgMJZs7UjUOdulKyRr9fqkS+6JKAInPy8= github.com/whyrusleeping/go-ctrlnet v0.0.0-20180313164037-f564fbbdaa95/go.mod h1:SJqKCCPXRfBFCwXjfNT/skfsceF7+MBFLI2OrvuRA7g= @@ -2072,18 +2059,17 @@ go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/dig v1.10.0 h1:yLmDDj9/zuDjv3gz8GQGviXMs9TfysIUMUilCpgzUJY= go.uber.org/dig v1.10.0/go.mod h1:X34SnWGr8Fyla9zQNO2GSO2D+TIuqB14OS8JhYocIyw= +go.uber.org/dig v1.12.0 h1:l1GQeZpEbss0/M4l/ZotuBndCrkMdjnygzgcuOjAdaY= go.uber.org/dig v1.12.0/go.mod h1:X34SnWGr8Fyla9zQNO2GSO2D+TIuqB14OS8JhYocIyw= -go.uber.org/fx v1.9.0 h1:7OAz8ucp35AU8eydejpYG7QrbE8rLKzGhHbZlJi5LYY= -go.uber.org/fx v1.9.0/go.mod h1:mFdUyAUuJ3w4jAckiKSKbldsxy1ojpAMJ+dVZg5Y0Aw= go.uber.org/fx v1.13.1/go.mod h1:bREWhavnedxpJeTq9pQT53BbvwhUv7TcpsOqcH4a+3w= +go.uber.org/fx v1.15.0 h1:kcfBpAm98n0ksanyyZLFE/Q3T7yPi13Ge2liu3TxR+A= go.uber.org/fx v1.15.0/go.mod h1:jI3RazQUhGv5KkpZIRv+kuP4CcgX3fnc0qX8bLnzbx8= go.uber.org/goleak v0.10.0/go.mod h1:VCZuO8V8mFPlL0F5J5GK1rtHV3DrFcQ1R8ryq7FK0aI= go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 h1:sHOAIxRGBp443oHZIPB+HsUGaksVCXVQENPxwTfQdH4= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= diff --git a/node/modules/storageminer_idxprov.go b/node/modules/storageminer_idxprov.go index 4bd15a09c2d..b0e0e97d062 100644 --- a/node/modules/storageminer_idxprov.go +++ b/node/modules/storageminer_idxprov.go @@ -25,7 +25,6 @@ import ( dtgstransport "github.com/filecoin-project/go-data-transfer/transport/graphsync" provider "github.com/filecoin-project/index-provider" "github.com/filecoin-project/index-provider/engine" - p2pserver "github.com/filecoin-project/index-provider/server/provider/libp2p" "github.com/ipfs/go-datastore/namespace" "github.com/libp2p/go-libp2p-core/host" @@ -81,13 +80,10 @@ func IndexerProvider(cfg config.IndexerProviderConfig) func(params IdxProv) (pro return xerrors.Errorf("starting indexer provider engine: %s", err) } - // Add a handler to libp2p that listens for incoming index requests - p2pserver.New(ctx, h, e) - return nil }, OnStop: func(ctx context.Context) error { - return e.Shutdown(ctx) + return e.Shutdown() }, }) @@ -96,7 +92,6 @@ func IndexerProvider(cfg config.IndexerProviderConfig) func(params IdxProv) (pro } func createIndexerProviderHost(mctx helpers.MetricsCtx, lc fx.Lifecycle, pkey ci.PrivKey, pstore peerstore.Peerstore, listenAddrs []string, announceAddrs []string) (host.Host, error) { - ctx := helpers.LifecycleCtx(mctx, lc) addrsFactory, err := lp2p.MakeAddrsFactory(announceAddrs, nil) if err != nil { return nil, err @@ -111,7 +106,7 @@ func createIndexerProviderHost(mctx helpers.MetricsCtx, lc fx.Lifecycle, pkey ci libp2p.UserAgent("lotus-indexer-provider-" + build.UserVersion()), } - h, err := libp2p.New(ctx, opts...) + h, err := libp2p.New(opts...) if err != nil { return nil, err } From dec79c70a1ff72f3659bc2d8425e0b1941e9e038 Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Wed, 12 Jan 2022 15:03:46 +0400 Subject: [PATCH 036/385] fix compilation --- node/builder_miner.go | 1 - 1 file changed, 1 deletion(-) diff --git a/node/builder_miner.go b/node/builder_miner.go index 330b3bd6dbe..de22ef8aa60 100644 --- a/node/builder_miner.go +++ b/node/builder_miner.go @@ -169,7 +169,6 @@ func ConfigStorageMiner(c interface{}) Option { Override(new(dtypes.ProviderTransport), modules.NewProviderTransport), Override(new(dtypes.ProviderDataTransfer), modules.NewProviderDataTransfer), Override(new(provider.Interface), modules.IndexerProvider(cfg.IndexerProvider)), - Override(new(dtypes.ProviderDataTransfer), modules.NewProviderDAGServiceDataTransfer), Override(new(*storedask.StoredAsk), modules.NewStorageAsk), Override(new(dtypes.StorageDealFilter), modules.BasicDealFilter(cfg.Dealmaking, nil)), Override(new(storagemarket.StorageProvider), modules.StorageProvider), From 64bf3fccd2a12a3e90023ac8a6dfb4f791c1238d Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Wed, 12 Jan 2022 15:05:27 +0400 Subject: [PATCH 037/385] update index provider dep --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index ac520e04738..04a19d32995 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,7 @@ require ( github.com/filecoin-project/go-statemachine v1.0.1 github.com/filecoin-project/go-statestore v0.2.0 github.com/filecoin-project/go-storedcounter v0.1.0 - github.com/filecoin-project/index-provider v0.1.1-0.20220107223914-37c38e2b284d + github.com/filecoin-project/index-provider v0.2.0 github.com/filecoin-project/specs-actors v0.9.14 github.com/filecoin-project/specs-actors/v2 v2.3.6 github.com/filecoin-project/specs-actors/v3 v3.1.1 diff --git a/go.sum b/go.sum index 6972bac3605..4dbbdc31cfa 100644 --- a/go.sum +++ b/go.sum @@ -374,8 +374,9 @@ github.com/filecoin-project/go-statestore v0.2.0 h1:cRRO0aPLrxKQCZ2UOQbzFGn4WDNd github.com/filecoin-project/go-statestore v0.2.0/go.mod h1:8sjBYbS35HwPzct7iT4lIXjLlYyPor80aU7t7a/Kspo= github.com/filecoin-project/go-storedcounter v0.1.0 h1:Mui6wSUBC+cQGHbDUBcO7rfh5zQkWJM/CpAZa/uOuus= github.com/filecoin-project/go-storedcounter v0.1.0/go.mod h1:4ceukaXi4vFURIoxYMfKzaRF5Xv/Pinh2oTnoxpv+z8= -github.com/filecoin-project/index-provider v0.1.1-0.20220107223914-37c38e2b284d h1:wEhUj2MpECUcOEr/UDMPBjG6ElGOcEwePtra1/bvrMQ= github.com/filecoin-project/index-provider v0.1.1-0.20220107223914-37c38e2b284d/go.mod h1:pTZVxt9mF+YCYSfNsn7i0rwhoMBmbjfSDAQVoxWGP10= +github.com/filecoin-project/index-provider v0.2.0 h1:r1VPVhtWrU5+6Mo6g2Ozr5NXWMFz1qHt0NKJzV5ELZ8= +github.com/filecoin-project/index-provider v0.2.0/go.mod h1:eYiwZfJNadwn/8Grwn2e4nX2cH4PYl2k8SZqm9k+eCA= github.com/filecoin-project/specs-actors v0.9.13/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= github.com/filecoin-project/specs-actors v0.9.14 h1:68PVstg2UB3ZsMLF+DKFTAs/YKsqhKWynkr0IqmVRQY= github.com/filecoin-project/specs-actors v0.9.14/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= From 3a52f0569225567f1b3c67776e696a27d0635ab2 Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Wed, 12 Jan 2022 15:53:15 +0400 Subject: [PATCH 038/385] green ci --- itests/deals_anycid_test.go | 4 +-- itests/kit/deals.go | 29 +++++++--------------- markets/dagstore/wrapper_migration_test.go | 3 --- 3 files changed, 11 insertions(+), 25 deletions(-) diff --git a/itests/deals_anycid_test.go b/itests/deals_anycid_test.go index 87bb93562fe..2c9fc2d9b3c 100644 --- a/itests/deals_anycid_test.go +++ b/itests/deals_anycid_test.go @@ -88,7 +88,7 @@ func TestDealRetrieveByAnyCid(t *testing.T) { require.NoError(t, err) cids := prepared.Cids() for i, c := range cids { - blk, err := bs.Get(c) + blk, err := bs.Get(ctx, c) require.NoError(t, err) nd, err := ipld.Decode(blk) @@ -129,7 +129,7 @@ func TestDealRetrieveByAnyCid(t *testing.T) { require.Empty(t, offer.Err) // retrieve in a CAR file and ensure roots match - outputCar := dh.PerformRetrievalForOffer(ctx, true, offer) + outputCar := dh.PerformRetrieval(ctx, dealCid, targetCid, true) _, err = os.Stat(outputCar) require.NoError(t, err) f, err := os.Open(outputCar) diff --git a/itests/kit/deals.go b/itests/kit/deals.go index fdda6f03648..b2a571e407d 100644 --- a/itests/kit/deals.go +++ b/itests/kit/deals.go @@ -306,23 +306,19 @@ func (dh *DealHarness) StartSealingWaiting(ctx context.Context) { } } -func (dh *DealHarness) PerformRetrieval(ctx context.Context, dealCid *cid.Cid, root cid.Cid, carExport bool) (path string) { +func (dh *DealHarness) PerformRetrieval(ctx context.Context, deal *cid.Cid, root cid.Cid, carExport bool) (path string) { // perform retrieval. - info, err := dh.client.ClientGetDealInfo(ctx, *dealCid) + info, err := dh.client.ClientGetDealInfo(ctx, *deal) require.NoError(dh.t, err) offers, err := dh.client.ClientFindData(ctx, root, &info.PieceCID) require.NoError(dh.t, err) require.NotEmpty(dh.t, offers, "no offers") - return dh.PerformRetrievalForOffer(ctx, carExport, offers[0]) -} - -func (dh *DealHarness) PerformRetrievalForOffer(ctx context.Context, carExport bool, offer api.QueryOffer) string { - outputF, err := ioutil.TempFile(dh.t.TempDir(), "ret-car") + carFile, err := ioutil.TempFile(dh.t.TempDir(), "ret-car") require.NoError(dh.t, err) - defer outputF.Close() //nolint:errcheck + defer carFile.Close() //nolint:errcheck caddr, err := dh.client.WalletDefaultAddress(ctx) require.NoError(dh.t, err) @@ -366,21 +362,14 @@ consumeEvents: Path: carFile.Name(), IsCAR: carExport, })) - ref := &api.FileRef{ - Path: outputF.Name(), - IsCAR: carExport, - } - order := offer.Order(caddr) - updates, err := dh.client.ClientRetrieveWithEvents(ctx, order, ref) - require.NoError(dh.t, err) - - for update := range updates { - require.Emptyf(dh.t, update.Err, "retrieval failed: %s", update.Err) + ret := carFile.Name() + if carExport { + actualFile := dh.ExtractFileFromCAR(ctx, carFile) + ret = actualFile.Name() + _ = actualFile.Close() //nolint:errcheck } - ret := outputF.Name() - return ret } diff --git a/markets/dagstore/wrapper_migration_test.go b/markets/dagstore/wrapper_migration_test.go index 756fa58577e..4c143a3e6b3 100644 --- a/markets/dagstore/wrapper_migration_test.go +++ b/markets/dagstore/wrapper_migration_test.go @@ -10,7 +10,6 @@ import ( "github.com/filecoin-project/dagstore" "github.com/stretchr/testify/require" - "github.com/filecoin-project/dagstore" "github.com/filecoin-project/dagstore/mount" "github.com/filecoin-project/go-state-types/abi" @@ -100,11 +99,9 @@ func TestShardRegistration(t *testing.T) { cfg.RootDir = t.TempDir() mapi := NewMinerAPI(ps, &wrappedSA{sa}, 10) - dagst, w, err := NewDAGStore(cfg, mapi) h, err := mocknet.New(ctx).GenPeer() require.NoError(t, err) - mapi := NewMinerAPI(ps, sa, 10) dagst, w, err := NewDAGStore(cfg, mapi, h) require.NoError(t, err) require.NotNil(t, dagst) From 05afaf6094f0b6fecbc7ff62bf014b67b4fee2a7 Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Wed, 12 Jan 2022 16:03:39 +0400 Subject: [PATCH 039/385] make gen --- build/openrpc/full.json.gz | Bin 26593 -> 26593 bytes build/openrpc/miner.json.gz | Bin 12680 -> 12927 bytes build/openrpc/worker.json.gz | Bin 3803 -> 3804 bytes documentation/en/api-v0-methods-miner.md | 11 +++- documentation/en/cli-lotus.md | 61 +++++++++++------------ 5 files changed, 40 insertions(+), 32 deletions(-) diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 1e4efea1a4fcc8ed6a49cd9c92876b457456c26f..a15f7d23f72ccec2e7d5e7b0c906d8c61028e1a8 100644 GIT binary patch delta 24175 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 literal 12680 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 CH?hC~ diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index edfabcc6b998b81113797881dd01f4390b022998..7049571e9b281b3093f19f69217fe8509271ded9 100644 GIT binary patch delta 2335 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 F002ugnO*<@ delta 2356 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 Date: Wed, 12 Jan 2022 16:55:45 +0400 Subject: [PATCH 040/385] get tests working --- itests/deals_anycid_test.go | 5 +++-- itests/kit/deals.go | 27 ++++++++++++++------------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/itests/deals_anycid_test.go b/itests/deals_anycid_test.go index 2c9fc2d9b3c..8e061af2932 100644 --- a/itests/deals_anycid_test.go +++ b/itests/deals_anycid_test.go @@ -129,12 +129,13 @@ func TestDealRetrieveByAnyCid(t *testing.T) { require.Empty(t, offer.Err) // retrieve in a CAR file and ensure roots match - outputCar := dh.PerformRetrieval(ctx, dealCid, targetCid, true) + outputCar := dh.PerformRetrieval(ctx, dealCid, targetCid, true, offer) _, err = os.Stat(outputCar) require.NoError(t, err) f, err := os.Open(outputCar) require.NoError(t, err) - ch, _ := car.ReadHeader(bufio.NewReader(f)) + ch, err := car.ReadHeader(bufio.NewReader(f)) + require.NoError(t, err) require.EqualValues(t, ch.Roots[0], targetCid) require.NoError(t, f.Close()) diff --git a/itests/kit/deals.go b/itests/kit/deals.go index b2a571e407d..ca3848c588b 100644 --- a/itests/kit/deals.go +++ b/itests/kit/deals.go @@ -306,14 +306,20 @@ func (dh *DealHarness) StartSealingWaiting(ctx context.Context) { } } -func (dh *DealHarness) PerformRetrieval(ctx context.Context, deal *cid.Cid, root cid.Cid, carExport bool) (path string) { - // perform retrieval. - info, err := dh.client.ClientGetDealInfo(ctx, *deal) - require.NoError(dh.t, err) +func (dh *DealHarness) PerformRetrieval(ctx context.Context, deal *cid.Cid, root cid.Cid, carExport bool, offers ...api.QueryOffer) (path string) { + var offer api.QueryOffer + if len(offers) == 0 { + // perform retrieval. + info, err := dh.client.ClientGetDealInfo(ctx, *deal) + require.NoError(dh.t, err) - offers, err := dh.client.ClientFindData(ctx, root, &info.PieceCID) - require.NoError(dh.t, err) - require.NotEmpty(dh.t, offers, "no offers") + offers, err := dh.client.ClientFindData(ctx, root, &info.PieceCID) + require.NoError(dh.t, err) + require.NotEmpty(dh.t, offers, "no offers") + offer = offers[0] + } else { + offer = offers[0] + } carFile, err := ioutil.TempFile(dh.t.TempDir(), "ret-car") require.NoError(dh.t, err) @@ -327,7 +333,7 @@ func (dh *DealHarness) PerformRetrieval(ctx context.Context, deal *cid.Cid, root updates, err := dh.client.ClientGetRetrievalUpdates(updatesCtx) require.NoError(dh.t, err) - retrievalRes, err := dh.client.ClientRetrieve(ctx, offers[0].Order(caddr)) + retrievalRes, err := dh.client.ClientRetrieve(ctx, offer.Order(caddr)) require.NoError(dh.t, err) consumeEvents: for { @@ -364,11 +370,6 @@ consumeEvents: })) ret := carFile.Name() - if carExport { - actualFile := dh.ExtractFileFromCAR(ctx, carFile) - ret = actualFile.Name() - _ = actualFile.Close() //nolint:errcheck - } return ret } From 07c842d6e01e44ec60d74dd98379c508857b5994 Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Wed, 12 Jan 2022 17:43:56 +0400 Subject: [PATCH 041/385] lotus soup green --- testplans/lotus-soup/go.mod | 8 +- testplans/lotus-soup/go.sum | 218 ++++++++++++++++++++++++++++++++---- 2 files changed, 199 insertions(+), 27 deletions(-) diff --git a/testplans/lotus-soup/go.mod b/testplans/lotus-soup/go.mod index 308ee5140c7..6ba232cdc43 100644 --- a/testplans/lotus-soup/go.mod +++ b/testplans/lotus-soup/go.mod @@ -9,7 +9,7 @@ require ( github.com/drand/drand v1.3.0 github.com/filecoin-project/go-address v0.0.6 github.com/filecoin-project/go-data-transfer v1.12.1 - github.com/filecoin-project/go-fil-markets v1.14.1 + github.com/filecoin-project/go-fil-markets v1.14.2-0.20220112094113-068e7f35a0e0 github.com/filecoin-project/go-jsonrpc v0.1.5 github.com/filecoin-project/go-state-types v0.1.1 github.com/filecoin-project/go-storedcounter v0.1.0 @@ -25,13 +25,13 @@ require ( github.com/ipfs/go-ipld-format v0.2.0 github.com/ipfs/go-log/v2 v2.4.0 github.com/ipfs/go-merkledag v0.5.1 - github.com/ipfs/go-unixfs v0.2.6 + github.com/ipfs/go-unixfs v0.3.1 github.com/ipld/go-car v0.3.3 github.com/kpacha/opencensus-influxdb v0.0.0-20181102202715-663e2683a27c github.com/libp2p/go-libp2p v0.17.0 github.com/libp2p/go-libp2p-core v0.13.0 github.com/libp2p/go-libp2p-pubsub-tracer v0.0.0-20200626141350-e730b32bf1e6 - github.com/multiformats/go-multiaddr v0.4.1 + github.com/multiformats/go-multiaddr v0.5.0 github.com/testground/sdk-go v0.2.6 go.opencensus.io v0.23.0 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c @@ -43,3 +43,5 @@ require ( replace github.com/filecoin-project/filecoin-ffi => ../../extern/filecoin-ffi replace github.com/filecoin-project/lotus => ../../ + +replace github.com/ipfs/go-path => github.com/ipfs/go-path v0.0.7 diff --git a/testplans/lotus-soup/go.sum b/testplans/lotus-soup/go.sum index 47e65fd549c..c53300eca59 100644 --- a/testplans/lotus-soup/go.sum +++ b/testplans/lotus-soup/go.sum @@ -1,3 +1,4 @@ +bazil.org/fuse v0.0.0-20200117225306-7b5117fecadc/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= @@ -37,6 +38,7 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE= +contrib.go.opencensus.io/exporter/prometheus v0.3.0/go.mod h1:rpCPVQKhiyH8oomWgm34ZmgIdZa8OVYO5WAIygPbBBE= contrib.go.opencensus.io/exporter/prometheus v0.4.0 h1:0QfIkj9z/iVZgK31D9H9ohjjIDApI2GOPScCKwxedbs= contrib.go.opencensus.io/exporter/prometheus v0.4.0/go.mod h1:o7cosnyfuPVK0tB8q0QmaQNhGnptITnPQB+z1+qeFB0= dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= @@ -116,7 +118,6 @@ github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWX github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= -github.com/Stebalien/go-bitfield v0.0.1 h1:X3kbSSPUaJK60wV2hjOPZwmpljr6VGCqdq4cBLhbQBo= github.com/Stebalien/go-bitfield v0.0.1/go.mod h1:GNjFpasyUVkHMsfEOk8EFLJ9syQ6SI+XWrX9Wf2XH0s= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= @@ -127,12 +128,16 @@ github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4Rq github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/akavel/rsrc v0.8.0 h1:zjWn7ukO9Kc5Q62DOJCcxGpXC18RawVtYAGdz2aLlfw= github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= +github.com/akrylysov/pogreb v0.10.1/go.mod h1:pNs6QmpQ1UlTJKDezuRWmaqkgUE2TuU0YTWyqJZ7+lI= github.com/alecthomas/jsonschema v0.0.0-20200530073317-71f438968921/go.mod h1:/n6+1/DWPltRLWL/VKyUxg6tzsl5kHUCcraimt4vr60= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a h1:E/8AP5dFtMhl5KPJz66Kt9G0n+7Sn41Fy1wv9/jHOrc= +github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= +github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5/go.mod h1:Y2QMoi1vgtOIfc+6DhrMOGkLoGzqSV2rKp4Sm+opsyA= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= @@ -194,6 +199,7 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bep/debounce v1.2.0 h1:wXds8Kq8qRfwAOpAxHrJDbCXgC5aHSzgQb/0gKsHQqo= github.com/bep/debounce v1.2.0/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/bonitoo-io/go-sql-bigquery v0.3.4-1.4.0/go.mod h1:J4Y6YJm0qTWB9aFziB7cPeSyc6dOZFyJdteSeybVpXQ= @@ -230,6 +236,7 @@ github.com/cenkalti/backoff v0.0.0-20181003080854-62661b46c409/go.mod h1:90ReRw6 github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/ceramicnetwork/go-dag-jose v0.1.0/go.mod h1:qYA1nYt0X8u4XoMAVoOV3upUVKtrxy/I670Dg5F0wjI= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM= @@ -238,6 +245,7 @@ github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cb github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= +github.com/cheggaaa/pb v1.0.29/go.mod h1:W40334L7FMC5JKWldsTWbdGjLo0RxUKK73K+TuPxX30= github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= @@ -274,6 +282,7 @@ github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7 github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU= github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= @@ -358,6 +367,7 @@ github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0 github.com/elastic/gosigar v0.14.1 h1:T0aQ7n/n2ZA9W7DmAnj60v+qzqKERdBgJBO1CG2W6rc= github.com/elastic/gosigar v0.14.1/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/elgris/jsondiff v0.0.0-20160530203242-765b5c24c302/go.mod h1:qBlWZqWeVx9BjvqBsnC/8RUlAYpIFmPvgROcw0n1scE= github.com/ema/qdisc v0.0.0-20190904071900-b82c76788043/go.mod h1:ix4kG2zvdUd8kEKSW0ZTr1XLks0epFpI4j745DXxlNE= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= @@ -379,9 +389,8 @@ github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/filecoin-project/dagstore v0.4.3-0.20211211192320-72b849e131d2/go.mod h1:tlV8C11UljvFq3WWlMh2oMViEaVaPb6uT8eL/YQgDfk= -github.com/filecoin-project/dagstore v0.4.4 h1:luolWahhzp3ulRsapGKE7raoLE3n2cFkQUJjPyqUmF4= -github.com/filecoin-project/dagstore v0.4.4/go.mod h1:7BlOvaTJrFJ1Qemt5jHlLJ4VhDIuSIzGS0IwO/0AXPA= +github.com/filecoin-project/dagstore v0.5.1 h1:ojzW/8z4PiquPDSA3EJ+Y4JcL+SWuloLaisy/hYcKMA= +github.com/filecoin-project/dagstore v0.5.1/go.mod h1:OdlK3x5m3Mol874WC2bI79H4H2+leN+FabwWdW2D/wY= github.com/filecoin-project/go-address v0.0.3/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= github.com/filecoin-project/go-address v0.0.5/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= github.com/filecoin-project/go-address v0.0.6 h1:DWQtj38ax+ogHwyH3VULRIoT8E6loyXqsk/p81xoY7M= @@ -403,19 +412,22 @@ github.com/filecoin-project/go-commp-utils v0.1.3/go.mod h1:3ENlD1pZySaUout0p9AN github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= github.com/filecoin-project/go-crypto v0.0.1 h1:AcvpSGGCgjaY8y1az6AMfKQWreF/pWO2JJGLl6gCq6o= github.com/filecoin-project/go-crypto v0.0.1/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= -github.com/filecoin-project/go-data-transfer v1.12.0/go.mod h1:tDrD2jLU2TpVhd+5B8iqBp0fQRV4lP80WZccKXugjYc= +github.com/filecoin-project/go-dagaggregator-unixfs v0.2.0/go.mod h1:WTuJWgBQY0omnQqa8kRPT9O0Uj5wQOgslVMUuTeHdJ8= +github.com/filecoin-project/go-data-transfer v1.11.4/go.mod h1:2MitLI0ebCkLlPKM7NRggP/t9d+gCcREUKkCKqWRCwU= github.com/filecoin-project/go-data-transfer v1.12.1 h1:gAznAZKySVs2FS6T/vDq7R3f0DewLnxeROe0oOE6bZU= github.com/filecoin-project/go-data-transfer v1.12.1/go.mod h1:j3HL645YiQFxcM+q7uPlGApILSqeweDABNgZQP7pDYU= -github.com/filecoin-project/go-ds-versioning v0.0.0-20211206185234-508abd7c2aff h1:2bG2ggVZ/rInd/YqUfRj4A5siGuYOPxxuD4I8nYLJF0= github.com/filecoin-project/go-ds-versioning v0.0.0-20211206185234-508abd7c2aff/go.mod h1:C9/l9PnB1+mwPa26BBVpCjG/XQCB0yj/q5CK2J8X1I4= +github.com/filecoin-project/go-ds-versioning v0.1.0/go.mod h1:mp16rb4i2QPmxBnmanUx8i/XANp+PFCCJWiAb+VW4/s= +github.com/filecoin-project/go-ds-versioning v0.1.1 h1:JiyBqaQlwC+UM0WhcBtVEeT3XrX59mQhT8U3p7nu86o= +github.com/filecoin-project/go-ds-versioning v0.1.1/go.mod h1:C9/l9PnB1+mwPa26BBVpCjG/XQCB0yj/q5CK2J8X1I4= github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commcid v0.1.0 h1:3R4ds1A9r6cr8mvZBfMYxTS88OqLYEo6roi+GiIeOh8= github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7LXep5bFEVOVmQWHJvl2mgsGo= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8= -github.com/filecoin-project/go-fil-markets v1.14.1 h1:Bx+TSbkAN8K97Hpjgu+MpeRFbXIKH/fNpNp1ZGAEH3I= -github.com/filecoin-project/go-fil-markets v1.14.1/go.mod h1:vXOHH3q2+zLk929W+lIq3etuDFTyJJ8nG2DwGHG2R1E= +github.com/filecoin-project/go-fil-markets v1.14.2-0.20220112094113-068e7f35a0e0 h1:C3rdpJJQm8/UX3aAPNbVHzSEDjI9EvD1jb2eroA3aK8= +github.com/filecoin-project/go-fil-markets v1.14.2-0.20220112094113-068e7f35a0e0/go.mod h1:H1pk9szltDLCOvQW/6fy0ugvUnDY7CDCf9HJSGSoj60= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= @@ -423,8 +435,14 @@ github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0/go.mod h1:7aWZdaQ1b16BVoQUYR+ github.com/filecoin-project/go-hamt-ipld/v3 v3.0.1/go.mod h1:gXpNmr3oQx8l3o7qkGyDjJjYSRX7hp/FGOStdqrWyDI= github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0 h1:rVVNq0x6RGQIzCo1iiJlGFm9AGIZzeifggxtKMU7zmI= github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0/go.mod h1:bxmzgT8tmeVQA1/gvBwFmYdT8SOFUwB3ovSUfG1Ux0g= +github.com/filecoin-project/go-indexer-core v0.2.4/go.mod h1:MSe5aRWmfRB+5syR4yDV+OApgJU+MUJ4rl9VUuzwCfc= +github.com/filecoin-project/go-indexer-core v0.2.6/go.mod h1:wW5Ab0gJXL2vT4iEMbPUfPs773iMc86Q8GtfSEqmu3Y= +github.com/filecoin-project/go-indexer-core v0.2.7 h1:D0egR6Q3Jkp5r4klxkdDQvjXeLx3cwZMKE55qop2xCI= +github.com/filecoin-project/go-indexer-core v0.2.7/go.mod h1:6YD7KwDOQ+03DdAitviL7h1fksIU6a4j52yPnA/E1PU= github.com/filecoin-project/go-jsonrpc v0.1.5 h1:ckxqZ09ivBAVf5CSmxxrqqNHC7PJm3GYGtYKiNQ+vGk= github.com/filecoin-project/go-jsonrpc v0.1.5/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4= +github.com/filecoin-project/go-legs v0.2.1 h1:XnQO5fesqo0sFLZhoPmYzJM38FNO7X93TM9HUsCMKbo= +github.com/filecoin-project/go-legs v0.2.1/go.mod h1:iHDfdqieReblkLoHneB68wvthFtNKB+wkeEWKtiJESk= github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20/go.mod h1:mPn+LRRd5gEKNAtc+r3ScpW2JRU/pj4NBKdADYWHiak= github.com/filecoin-project/go-padreader v0.0.0-20210723183308-812a16dc01b1/go.mod h1:VYVPJqwpsfmtoHnAmPx6MUwmrK6HIcDqZJiuZhtmfLQ= github.com/filecoin-project/go-padreader v0.0.1 h1:8h2tVy5HpoNbr2gBRr+WD6zV6VD6XHig+ynSGJg8ZOs= @@ -447,6 +465,9 @@ github.com/filecoin-project/go-statestore v0.2.0 h1:cRRO0aPLrxKQCZ2UOQbzFGn4WDNd github.com/filecoin-project/go-statestore v0.2.0/go.mod h1:8sjBYbS35HwPzct7iT4lIXjLlYyPor80aU7t7a/Kspo= github.com/filecoin-project/go-storedcounter v0.1.0 h1:Mui6wSUBC+cQGHbDUBcO7rfh5zQkWJM/CpAZa/uOuus= github.com/filecoin-project/go-storedcounter v0.1.0/go.mod h1:4ceukaXi4vFURIoxYMfKzaRF5Xv/Pinh2oTnoxpv+z8= +github.com/filecoin-project/index-provider v0.1.1-0.20220107223914-37c38e2b284d/go.mod h1:pTZVxt9mF+YCYSfNsn7i0rwhoMBmbjfSDAQVoxWGP10= +github.com/filecoin-project/index-provider v0.2.0 h1:r1VPVhtWrU5+6Mo6g2Ozr5NXWMFz1qHt0NKJzV5ELZ8= +github.com/filecoin-project/index-provider v0.2.0/go.mod h1:eYiwZfJNadwn/8Grwn2e4nX2cH4PYl2k8SZqm9k+eCA= github.com/filecoin-project/specs-actors v0.9.13/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= github.com/filecoin-project/specs-actors v0.9.14 h1:68PVstg2UB3ZsMLF+DKFTAs/YKsqhKWynkr0IqmVRQY= github.com/filecoin-project/specs-actors v0.9.14/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= @@ -470,8 +491,12 @@ github.com/filecoin-project/specs-actors/v7 v7.0.0-20211230214648-aeae366b083a h github.com/filecoin-project/specs-actors/v7 v7.0.0-20211230214648-aeae366b083a/go.mod h1:p6LIOFezA1rgRLMewbvdi3Pp6SAu+q9FtJ9CAleSjrE= github.com/filecoin-project/specs-storage v0.1.1-0.20211228030229-6d460d25a0c9 h1:oUYOvF7EvdXS0Zmk9mNkaB6Bu0l+WXBYPzVodKMiLug= github.com/filecoin-project/specs-storage v0.1.1-0.20211228030229-6d460d25a0c9/go.mod h1:Tb88Zq+IBJbvAn3mS89GYj3jdRThBTE/771HCVZdRJU= +github.com/filecoin-project/storetheindex v0.2.0/go.mod h1:P3Hd3sIWEkBU1fPnE49Y8nh/mdErOdIfiHBb85QAWfg= +github.com/filecoin-project/storetheindex v0.2.1 h1:jhsMh5O52bBU/NrnjJs2iLPI92T38kjlU9bk/dP0sts= +github.com/filecoin-project/storetheindex v0.2.1/go.mod h1:Tc5mYdAnGUzly40cuo35yITDD3XhF9EX5BO7evGsJ5M= github.com/filecoin-project/test-vectors/schema v0.0.5/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6/go.mod h1:1i71OnUq3iUe1ma7Lr6yG6/rjvM3emb6yoL7xLFzcVQ= github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ= github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= @@ -486,8 +511,15 @@ github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss= github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= +github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= +github.com/gabriel-vasile/mimetype v1.1.2/go.mod h1:6CDPel/o/3/s4+bp6kIbsWATq8pmgOisOPG40CJa6To= +github.com/gabriel-vasile/mimetype v1.4.0/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8= +github.com/gammazero/keymutex v0.0.2 h1:cmpLBJHdEwn+WlR5Z/o9/BN92znSZTp5AKPQDpu1QcI= +github.com/gammazero/keymutex v0.0.2/go.mod h1:qtzWCCLMisQUmVa4dvqHVgwfh4BP2YB7JxNDGXnsKrs= +github.com/gammazero/radixtree v0.2.5 h1:muPQ4eEgCkUymFWPiVQRuXOQv4IhWg8YXH2r71MoqPM= +github.com/gammazero/radixtree v0.2.5/go.mod h1:VPqqCDZ3YZZxAzUUsIF/ytFBigVWV7JIV1Stld8hri0= github.com/gbrlsnchs/jwt/v3 v3.0.1 h1:lbUmgAKpxnClrKloyIwpxm4OuWeDl5wLk52G91ODPw4= github.com/gbrlsnchs/jwt/v3 v3.0.1/go.mod h1:AncDcjXz18xetI3A6STfXq2w+LuTx8pQ8bGEwRN8zVM= github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= @@ -502,6 +534,7 @@ github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0 github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= +github.com/go-bindata/go-bindata/v3 v3.1.3/go.mod h1:1/zrpXsLD8YDIbhZRqXzm1Ghc7NhEvIN9+Z6R5/xH4I= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= github.com/go-chi/chi v4.1.0+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= @@ -719,6 +752,7 @@ github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+u github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= +github.com/google/gopacket v1.1.18/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= @@ -876,9 +910,15 @@ github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1: github.com/ipfs/bbloom v0.0.1/go.mod h1:oqo8CVWsJFMOZqTglBG4wydCE4IQA/G2/SEofB0rjUI= github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs= github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0= +github.com/ipfs/go-bitfield v1.0.0 h1:y/XHm2GEmD9wKngheWNNCNL0pzrWXZwCdQGv1ikXknQ= +github.com/ipfs/go-bitfield v1.0.0/go.mod h1:N/UiujQy+K+ceU1EF5EkVd1TNqevLrCQMIcAEPrdtus= github.com/ipfs/go-bitswap v0.0.9/go.mod h1:kAPf5qgn2W2DrgAcscZ3HrM9qh4pH+X8Fkk3UPrwvis= github.com/ipfs/go-bitswap v0.1.0/go.mod h1:FFJEf18E9izuCqUtHxbWEvq+reg7o4CW5wSAE1wsxj0= github.com/ipfs/go-bitswap v0.1.2/go.mod h1:qxSWS4NXGs7jQ6zQvoPY3+NmOfHHG47mhkiLzBpJQIs= +github.com/ipfs/go-bitswap v0.1.3/go.mod h1:YEQlFy0kkxops5Vy+OxWdRSEZIoS7I7KDIwoa5Chkps= +github.com/ipfs/go-bitswap v0.1.8/go.mod h1:TOWoxllhccevbWFUR2N7B1MTSVVge1s6XSMiCSA4MzM= +github.com/ipfs/go-bitswap v0.3.4/go.mod h1:4T7fvNv/LmOys+21tnLzGKncMeeXUYUd1nUiJ2teMvI= +github.com/ipfs/go-bitswap v0.4.0/go.mod h1:J2sAsp9UKxLgHDektSy3y3Q9OfQjM9sjhKBR1dlwrMg= github.com/ipfs/go-bitswap v0.5.1 h1:721YAEDBnLIrvcIMkCHCdqp34hA8jwL9yKMkyJpSpco= github.com/ipfs/go-bitswap v0.5.1/go.mod h1:P+ckC87ri1xFLvk74NlXdP0Kj9RmWAh4+H78sC6Qopo= github.com/ipfs/go-block-format v0.0.1/go.mod h1:DK/YYcsSUIVAFNwo/KZCdIIbpN0ROH/baNLgayt4pFc= @@ -887,6 +927,10 @@ github.com/ipfs/go-block-format v0.0.3 h1:r8t66QstRp/pd/or4dpnbVfXT5Gt7lOqRvC+/d github.com/ipfs/go-block-format v0.0.3/go.mod h1:4LmD4ZUw0mhO+JSKdpWwrzATiEfM7WWgQ8H5l6P8MVk= github.com/ipfs/go-blockservice v0.0.7/go.mod h1:EOfb9k/Y878ZTRY/CH0x5+ATtaipfbRhbvNSdgc/7So= github.com/ipfs/go-blockservice v0.1.0/go.mod h1:hzmMScl1kXHg3M2BjTymbVPjv627N7sYcvYaKbop39M= +github.com/ipfs/go-blockservice v0.1.1/go.mod h1:t+411r7psEUhLueM8C7aPA7cxCclv4O3VsUVxt9kz2I= +github.com/ipfs/go-blockservice v0.1.3/go.mod h1:OTZhFpkgY48kNzbgyvcexW9cHrpjBYIjSR0KoDOFOLU= +github.com/ipfs/go-blockservice v0.1.4/go.mod h1:OTZhFpkgY48kNzbgyvcexW9cHrpjBYIjSR0KoDOFOLU= +github.com/ipfs/go-blockservice v0.1.7/go.mod h1:GmS+BAt4hrwBKkzE11AFDQUrnvqjwFatGS2MY7wOjEM= github.com/ipfs/go-blockservice v0.2.1 h1:NJ4j/cwEfIg60rzAWcCIxRtOwbf6ZPK49MewNxObCPQ= github.com/ipfs/go-blockservice v0.2.1/go.mod h1:k6SiwmgyYgs4M/qt+ww6amPeUH9EISLRBnvUurKJhi8= github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= @@ -906,11 +950,14 @@ github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAK github.com/ipfs/go-datastore v0.0.5/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= github.com/ipfs/go-datastore v0.1.0/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= github.com/ipfs/go-datastore v0.1.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= +github.com/ipfs/go-datastore v0.3.0/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= github.com/ipfs/go-datastore v0.3.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= github.com/ipfs/go-datastore v0.4.0/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= github.com/ipfs/go-datastore v0.4.1/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= +github.com/ipfs/go-datastore v0.4.2/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= github.com/ipfs/go-datastore v0.4.4/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= github.com/ipfs/go-datastore v0.4.5/go.mod h1:eXTcaaiN6uOlVCLS9GjJUJtlvJfM3xk23w3fyfrmmJs= +github.com/ipfs/go-datastore v0.4.6/go.mod h1:XSipLSc64rFKSFRFGo1ecQl+WhYce3K7frtpHkyPFUc= github.com/ipfs/go-datastore v0.4.7-0.20211013204805-28a3721c2e66/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk= github.com/ipfs/go-datastore v0.5.0/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk= github.com/ipfs/go-datastore v0.5.1 h1:WkRhLuISI+XPD0uk3OskB0fYFSyqK8Ob5ZYew9Qa1nQ= @@ -922,29 +969,47 @@ github.com/ipfs/go-ds-badger v0.0.5/go.mod h1:g5AuuCGmr7efyzQhLL8MzwqcauPojGPUaH github.com/ipfs/go-ds-badger v0.0.7/go.mod h1:qt0/fWzZDoPW6jpQeqUjR5kBfhDNB65jd9YlmAvpQBk= github.com/ipfs/go-ds-badger v0.2.1/go.mod h1:Tx7l3aTph3FMFrRS838dcSJh+jjA7cX9DrGVwx/NOwE= github.com/ipfs/go-ds-badger v0.2.3/go.mod h1:pEYw0rgg3FIrywKKnL+Snr+w/LjJZVMTBRn4FS6UHUk= +github.com/ipfs/go-ds-badger v0.2.6/go.mod h1:02rnztVKA4aZwDuaRPTf8mpqcKmXP7mLl6JPxd14JHA= github.com/ipfs/go-ds-badger v0.2.7/go.mod h1:02rnztVKA4aZwDuaRPTf8mpqcKmXP7mLl6JPxd14JHA= github.com/ipfs/go-ds-badger v0.3.0 h1:xREL3V0EH9S219kFFueOYJJTcjgNSZ2HY1iSvN7U1Ro= github.com/ipfs/go-ds-badger v0.3.0/go.mod h1:1ke6mXNqeV8K3y5Ak2bAA0osoTfmxUdupVCGm4QUIek= github.com/ipfs/go-ds-badger2 v0.1.2 h1:sQc2q1gaXrv8YFNeUtxil0neuyDf9hnVHfLsi7lpXfE= github.com/ipfs/go-ds-badger2 v0.1.2/go.mod h1:3FtQmDv6fMubygEfU43bsFelYpIiXX/XEYA54l9eCwg= +github.com/ipfs/go-ds-flatfs v0.4.5/go.mod h1:e4TesLyZoA8k1gV/yCuBTnt2PJtypn4XUlB5n8KQMZY= +github.com/ipfs/go-ds-flatfs v0.5.1/go.mod h1:RWTV7oZD/yZYBKdbVIFXTX2fdY2Tbvl94NsWqmoyAX4= github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= github.com/ipfs/go-ds-leveldb v0.1.0/go.mod h1:hqAW8y4bwX5LWcCtku2rFNX3vjDZCy5LZCg+cSZvYb8= github.com/ipfs/go-ds-leveldb v0.4.1/go.mod h1:jpbku/YqBSsBc1qgME8BkWS4AxzF2cEu1Ii2r79Hh9s= github.com/ipfs/go-ds-leveldb v0.4.2/go.mod h1:jpbku/YqBSsBc1qgME8BkWS4AxzF2cEu1Ii2r79Hh9s= github.com/ipfs/go-ds-leveldb v0.5.0 h1:s++MEBbD3ZKc9/8/njrn4flZLnCuY9I79v94gBUNumo= github.com/ipfs/go-ds-leveldb v0.5.0/go.mod h1:d3XG9RUDzQ6V4SHi8+Xgj9j1XuEk1z82lquxrVbml/Q= +github.com/ipfs/go-ds-measure v0.1.0/go.mod h1:1nDiFrhLlwArTME1Ees2XaBOl49OoCgd2A3f8EchMSY= github.com/ipfs/go-ds-measure v0.2.0 h1:sG4goQe0KDTccHMyT45CY1XyUbxe5VwTKpg2LjApYyQ= github.com/ipfs/go-ds-measure v0.2.0/go.mod h1:SEUD/rE2PwRa4IQEC5FuNAmjJCyYObZr9UvVh8V3JxE= +github.com/ipfs/go-fetcher v1.5.0/go.mod h1:5pDZ0393oRF/fHiLmtFZtpMNBQfHOYNPtryWedVuSWE= +github.com/ipfs/go-fetcher v1.6.1/go.mod h1:27d/xMV8bodjVs9pugh/RCjjK2OZ68UgAMspMdingNo= +github.com/ipfs/go-filestore v0.0.3/go.mod h1:dvXRykFzyyXN2CdNlRGzDAkXMDPyI+D7JE066SiKLSE= +github.com/ipfs/go-filestore v0.1.0/go.mod h1:0KTrzoJnJ3sJDEDM09Vq8nz8H475rRyeq4i0n/bpF00= github.com/ipfs/go-filestore v1.1.0 h1:Pu4tLBi1bucu6/HU9llaOmb9yLFk/sgP+pW764zNDoE= github.com/ipfs/go-filestore v1.1.0/go.mod h1:6e1/5Y6NvLuCRdmda/KA4GUhXJQ3Uat6vcWm2DJfxc8= -github.com/ipfs/go-fs-lock v0.0.6 h1:sn3TWwNVQqSeNjlWy6zQ1uUGAZrV3hPOyEA6y1/N2a0= github.com/ipfs/go-fs-lock v0.0.6/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28L7zESmM= +github.com/ipfs/go-fs-lock v0.0.7 h1:6BR3dajORFrFTkb5EpCUFIAypsoxpGpDSVUdFwzgL9U= +github.com/ipfs/go-fs-lock v0.0.7/go.mod h1:Js8ka+FNYmgQRLrRXzU3CB/+Csr1BwrRilEcvYrHhhc= +github.com/ipfs/go-graphsync v0.8.0/go.mod h1:CLxN859dUTcXCav1DvNvmAUWPZfmNLjlGLJYy+c3dlM= +github.com/ipfs/go-graphsync v0.10.0/go.mod h1:cKIshzTaa5rCZjryH5xmSKZVGX9uk1wvwGvz2WEha5Y= github.com/ipfs/go-graphsync v0.11.0/go.mod h1:wC+c8vGVjAHthsVIl8LKr37cUra2GOaMYcQNNmMxDqE= github.com/ipfs/go-graphsync v0.11.5 h1:WA5hVxGBtcal6L6nqubKiqRolaZxbexOK3GumGFJRR4= github.com/ipfs/go-graphsync v0.11.5/go.mod h1:+/sZqRwRCQRrV7NCzgBtufmr5QGpUE98XSa7NlsztmM= +github.com/ipfs/go-ipfs v0.10.0/go.mod h1:HsnRkQdpruG6JMaycJyrlLwJdduw1dJv2rEPgWxdJvA= +github.com/ipfs/go-ipfs v0.11.0/go.mod h1:g68Thu2Ho11AWoHsN34P5fSK7iA6OWWRy3T/g8HLixc= github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08= github.com/ipfs/go-ipfs-blockstore v0.1.0/go.mod h1:5aD0AvHPi7mZc6Ci1WCAhiBQu2IsfTduLl+422H6Rqw= +github.com/ipfs/go-ipfs-blockstore v0.1.4/go.mod h1:Jxm3XMVjh6R17WvxFEiyKBLUGr86HgIYJW/D/MwqeYQ= +github.com/ipfs/go-ipfs-blockstore v0.1.6/go.mod h1:Jxm3XMVjh6R17WvxFEiyKBLUGr86HgIYJW/D/MwqeYQ= github.com/ipfs/go-ipfs-blockstore v0.2.1/go.mod h1:jGesd8EtCM3/zPgx+qr0/feTXGUeRai6adgwC+Q+JvE= +github.com/ipfs/go-ipfs-blockstore v1.0.1/go.mod h1:MGNZlHNEnR4KGgPHM3/k8lBySIOK2Ve+0KjZubKlaOE= +github.com/ipfs/go-ipfs-blockstore v1.0.4-0.20210205083733-fb07d7bc5aec/go.mod h1:feuklK+m9POeWJzYQO7l05yNEgUiX5oELBNA8/Be33E= +github.com/ipfs/go-ipfs-blockstore v1.0.4/go.mod h1:uL7/gTJ8QIZ3MtA3dWf+s1a0U3fJy2fcEZAsovpRp+w= github.com/ipfs/go-ipfs-blockstore v1.1.0/go.mod h1:5QDUApRqpgPcfGstCxYeMnjt/DYQtXXdJVCvxHHuWVk= github.com/ipfs/go-ipfs-blockstore v1.1.1/go.mod h1:w51tNR9y5+QXB0wkNcHt4O2aSZjTdqaEWaQdSxEyUOY= github.com/ipfs/go-ipfs-blockstore v1.1.2 h1:WCXoZcMYnvOTmlpX+RSSnhVN0uCmbWTeepTGX5lgiXw= @@ -954,10 +1019,13 @@ github.com/ipfs/go-ipfs-blocksutil v0.0.1/go.mod h1:Yq4M86uIOmxmGPUHv/uI7uKqZNtL github.com/ipfs/go-ipfs-chunker v0.0.1/go.mod h1:tWewYK0we3+rMbOh7pPFGDyypCtvGcBFymgY4rSDLAw= github.com/ipfs/go-ipfs-chunker v0.0.5 h1:ojCf7HV/m+uS2vhUGWcogIIxiO5ubl5O57Q7NapWLY8= github.com/ipfs/go-ipfs-chunker v0.0.5/go.mod h1:jhgdF8vxRHycr00k13FM8Y0E+6BoalYeobXmUyTreP8= -github.com/ipfs/go-ipfs-cmds v0.3.0 h1:mi9oYrSCox5aBhutqAYqw6/9crlyGbw4E/aJtwS4zI4= github.com/ipfs/go-ipfs-cmds v0.3.0/go.mod h1:ZgYiWVnCk43ChwoH8hAmI1IRbuVtq3GSTHwtRB/Kqhk= -github.com/ipfs/go-ipfs-config v0.5.3 h1:3GpI/xR9FoJNTjU6YvCMRbYyEi0dBVY5UtlUTcNRlSA= +github.com/ipfs/go-ipfs-cmds v0.6.0 h1:yAxdowQZzoFKjcLI08sXVNnqVj3jnABbf9smrPQmBsw= +github.com/ipfs/go-ipfs-cmds v0.6.0/go.mod h1:ZgYiWVnCk43ChwoH8hAmI1IRbuVtq3GSTHwtRB/Kqhk= github.com/ipfs/go-ipfs-config v0.5.3/go.mod h1:nSLCFtlaL+2rbl3F+9D4gQZQbT1LjRKx7TJg/IHz6oM= +github.com/ipfs/go-ipfs-config v0.16.0/go.mod h1:wz2lKzOjgJeYJa6zx8W9VT7mz+iSd0laBMqS/9wmX6A= +github.com/ipfs/go-ipfs-config v0.18.0 h1:Ta1aNGNEq6RIvzbw7dqzCVZJKb7j+Dd35JFnAOCpT8g= +github.com/ipfs/go-ipfs-config v0.18.0/go.mod h1:wz2lKzOjgJeYJa6zx8W9VT7mz+iSd0laBMqS/9wmX6A= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= github.com/ipfs/go-ipfs-delay v0.0.1 h1:r/UXYyRcddO6thwOnhiznIAiSvxMECGgtv35Xs1IeRQ= github.com/ipfs/go-ipfs-delay v0.0.1/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= @@ -979,11 +1047,16 @@ github.com/ipfs/go-ipfs-files v0.0.9 h1:OFyOfmuVDu9c5YtjSDORmwXzE6fmZikzZpzsnNkg github.com/ipfs/go-ipfs-files v0.0.9/go.mod h1:aFv2uQ/qxWpL/6lidWvnSQmaVqCrf0TBGoUr+C1Fo84= github.com/ipfs/go-ipfs-http-client v0.0.6 h1:k2QllZyP7Fz5hMgsX5hvHfn1WPG9Ngdy5WknQ7JNhBM= github.com/ipfs/go-ipfs-http-client v0.0.6/go.mod h1:8e2dQbntMZKxLfny+tyXJ7bJHZFERp/2vyzZdvkeLMc= +github.com/ipfs/go-ipfs-keystore v0.0.2/go.mod h1:H49tRmibOEs7gLMgbOsjC4dqh1u5e0R/SWuc2ScfgSo= +github.com/ipfs/go-ipfs-pinner v0.1.2/go.mod h1:/u9kMe+TyQybN21O5OBicdyx3x93lVI77PCtiTnArUk= +github.com/ipfs/go-ipfs-pinner v0.2.1/go.mod h1:l1AtLL5bovb7opnG77sh4Y10waINz3Y1ni6CvTzx7oo= github.com/ipfs/go-ipfs-posinfo v0.0.1 h1:Esoxj+1JgSjX0+ylc0hUmJCOv6V2vFoZiETLR6OtpRs= github.com/ipfs/go-ipfs-posinfo v0.0.1/go.mod h1:SwyeVP+jCwiDu0C313l/8jg6ZxM0qqtlt2a0vILTc1A= github.com/ipfs/go-ipfs-pq v0.0.1/go.mod h1:LWIqQpqfRG3fNc5XsnIhz/wQ2XXGyugQwls7BgUmUfY= github.com/ipfs/go-ipfs-pq v0.0.2 h1:e1vOOW6MuOwG2lqxcLA+wEn93i/9laCY8sXAw76jFOY= github.com/ipfs/go-ipfs-pq v0.0.2/go.mod h1:LWIqQpqfRG3fNc5XsnIhz/wQ2XXGyugQwls7BgUmUfY= +github.com/ipfs/go-ipfs-provider v0.6.1/go.mod h1:I4Cig3InhftbRJohph76Qy/P2uKEZILNGiKvDJmmC28= +github.com/ipfs/go-ipfs-provider v0.7.1/go.mod h1:QwdDYRYnC5sYGLlOwVDY/0ZB6T3zcMtu+5+GdGeUuw8= github.com/ipfs/go-ipfs-routing v0.0.1/go.mod h1:k76lf20iKFxQTjcJokbPM9iBXVXVZhcOwc360N4nuKs= github.com/ipfs/go-ipfs-routing v0.1.0/go.mod h1:hYoUkJLyAUKhF58tysKpids8RNDPO42BVMgK5dNsoqY= github.com/ipfs/go-ipfs-routing v0.2.1 h1:E+whHWhJkdN9YeoHZNj5itzc+OR292AJ2uE9FFiW0BY= @@ -1002,9 +1075,12 @@ github.com/ipfs/go-ipld-format v0.0.1/go.mod h1:kyJtbkDALmFHv3QR6et67i35QzO3S0dC github.com/ipfs/go-ipld-format v0.0.2/go.mod h1:4B6+FM2u9OJ9zCV+kSbgFAZlOrv1Hqbf0INGQgiKf9k= github.com/ipfs/go-ipld-format v0.2.0 h1:xGlJKkArkmBvowr+GMCX0FEZtkro71K1AwiKnL37mwA= github.com/ipfs/go-ipld-format v0.2.0/go.mod h1:3l3C1uKoadTPbeNfrDi+xMInYKlx2Cvg1BuydPSdzQs= +github.com/ipfs/go-ipld-git v0.1.1/go.mod h1:+VyMqF5lMcJh4rwEppV0e6g4nCCHXThLYYDpKUkJubI= github.com/ipfs/go-ipld-legacy v0.1.0/go.mod h1:86f5P/srAmh9GcIcWQR9lfFLZPrIyyXQeVlOWeeWEuI= github.com/ipfs/go-ipld-legacy v0.1.1 h1:BvD8PEuqwBHLTKqlGFTHSwrwFOMkVESEvwIYwR2cdcc= github.com/ipfs/go-ipld-legacy v0.1.1/go.mod h1:8AyKFCjgRPsQFf15ZQgDB8Din4DML/fOmKZkkFkrIEg= +github.com/ipfs/go-ipns v0.0.2/go.mod h1:WChil4e0/m9cIINWLxZe1Jtf77oz5L05rO2ei/uKJ5U= +github.com/ipfs/go-ipns v0.1.0/go.mod h1:3IbsuPkR6eAGcnx+E7j6HpOSbSQJPZ6zlRj+NK3jPxQ= github.com/ipfs/go-ipns v0.1.2 h1:O/s/0ht+4Jl9+VoxoUo0zaHjnZUS+aBQIKTuzdZ/ucI= github.com/ipfs/go-ipns v0.1.2/go.mod h1:ioQ0j02o6jdIVW+bmi18f4k2gRf0AV3kZ9KeHYHICnQ= github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= @@ -1028,39 +1104,60 @@ github.com/ipfs/go-log/v2 v2.3.0/go.mod h1:QqGoj30OTpnKaG/LKTGTxoP2mmQtjVMEnK72g github.com/ipfs/go-log/v2 v2.4.0 h1:iR/2o9PGWanVJrBgIH5Ff8mPGOwpqLaPIAFqSnsdlzk= github.com/ipfs/go-log/v2 v2.4.0/go.mod h1:nPZnh7Cj7lwS3LpRU5Mwr2ol1c2gXIEXuF6aywqrtmo= github.com/ipfs/go-merkledag v0.0.6/go.mod h1:QYPdnlvkOg7GnQRofu9XZimC5ZW5Wi3bKys/4GQQfto= +github.com/ipfs/go-merkledag v0.1.0/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= github.com/ipfs/go-merkledag v0.2.3/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= github.com/ipfs/go-merkledag v0.2.4/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= +github.com/ipfs/go-merkledag v0.3.0/go.mod h1:4pymaZLhSLNVuiCITYrpViD6vmfZ/Ws4n/L9tfNv3S4= +github.com/ipfs/go-merkledag v0.3.1/go.mod h1:fvkZNNZixVW6cKSZ/JfLlON5OlgTXNdRLz0p6QG/I2M= github.com/ipfs/go-merkledag v0.3.2/go.mod h1:fvkZNNZixVW6cKSZ/JfLlON5OlgTXNdRLz0p6QG/I2M= +github.com/ipfs/go-merkledag v0.4.0/go.mod h1:XshXBkhyeS63YNGisLL1uDSfuTyrQIxVUOg3ojR5MOE= github.com/ipfs/go-merkledag v0.5.1 h1:tr17GPP5XtPhvPPiWtu20tSGZiZDuTaJRXBLcr79Umk= github.com/ipfs/go-merkledag v0.5.1/go.mod h1:cLMZXx8J08idkp5+id62iVftUQV+HlYJ3PIhDfZsjA4= github.com/ipfs/go-metrics-interface v0.0.1 h1:j+cpbjYvu4R8zbleSs36gvB7jR+wsL2fGD6n0jO4kdg= github.com/ipfs/go-metrics-interface v0.0.1/go.mod h1:6s6euYU4zowdslK0GKHmqaIZ3j/b/tL7HTWtJ4VPgWY= github.com/ipfs/go-metrics-prometheus v0.0.2/go.mod h1:ELLU99AQQNi+zX6GCGm2lAgnzdSH3u5UVlCdqSXnEks= +github.com/ipfs/go-mfs v0.1.2/go.mod h1:T1QBiZPEpkPLzDqEJLNnbK55BVKVlNi2a+gVm4diFo0= +github.com/ipfs/go-mfs v0.2.1/go.mod h1:Woj80iuw4ajDnIP6+seRaoHpPsc9hmL0pk/nDNDWP88= +github.com/ipfs/go-namesys v0.3.1/go.mod h1:/BL4xk8LP5Lq82AmaRKyxZv/eYRlumNiU9SZUe1Hlps= +github.com/ipfs/go-namesys v0.4.0/go.mod h1:jpJwzodyP8DZdWN6DShRjVZw6gaqMr4nQLBSxU5cR6E= github.com/ipfs/go-path v0.0.7 h1:H06hKMquQ0aYtHiHryOMLpQC1qC3QwXwkahcEVD51Ho= github.com/ipfs/go-path v0.0.7/go.mod h1:6KTKmeRnBXgqrTvzFrPV3CamxcgvXX/4z79tfAd2Sno= github.com/ipfs/go-peertaskqueue v0.0.4/go.mod h1:03H8fhyeMfKNFWqzYEVyMbcPUeYrqP1MX6Kd+aN+rMQ= github.com/ipfs/go-peertaskqueue v0.1.0/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= +github.com/ipfs/go-peertaskqueue v0.1.1/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= +github.com/ipfs/go-peertaskqueue v0.2.0/go.mod h1:5/eNrBEbtSKWCG+kQK8K8fGNixoYUnr+P7jivavs9lY= +github.com/ipfs/go-peertaskqueue v0.4.0/go.mod h1:KL9F49hXJMoXCad8e5anivjN+kWdr+CyGcyh4K6doLc= github.com/ipfs/go-peertaskqueue v0.7.0/go.mod h1:M/akTIE/z1jGNXMU7kFB4TeSEFvj68ow0Rrb04donIU= github.com/ipfs/go-peertaskqueue v0.7.1 h1:7PLjon3RZwRQMgOTvYccZ+mjzkmds/7YzSWKFlBAypE= github.com/ipfs/go-peertaskqueue v0.7.1/go.mod h1:M/akTIE/z1jGNXMU7kFB4TeSEFvj68ow0Rrb04donIU= +github.com/ipfs/go-pinning-service-http-client v0.1.0/go.mod h1:tcCKmlkWWH9JUUkKs8CrOZBanacNc1dmKLfjlyXAMu4= github.com/ipfs/go-todocounter v0.0.1/go.mod h1:l5aErvQc8qKE2r7NDMjmq5UNAvuZy0rC8BHOplkWvZ4= +github.com/ipfs/go-unixfs v0.1.0/go.mod h1:lysk5ELhOso8+Fed9U1QTGey2ocsfaZ18h0NCO2Fj9s= github.com/ipfs/go-unixfs v0.2.2-0.20190827150610-868af2e9e5cb/go.mod h1:IwAAgul1UQIcNZzKPYZWOCijryFBeCV79cNubPzol+k= github.com/ipfs/go-unixfs v0.2.4/go.mod h1:SUdisfUjNoSDzzhGVxvCL9QO/nKdwXdr+gbMUdqcbYw= -github.com/ipfs/go-unixfs v0.2.6 h1:gq3U3T2vh8x6tXhfo3uSO3n+2z4yW0tYtNgVP/3sIyA= +github.com/ipfs/go-unixfs v0.2.5/go.mod h1:SUdisfUjNoSDzzhGVxvCL9QO/nKdwXdr+gbMUdqcbYw= github.com/ipfs/go-unixfs v0.2.6/go.mod h1:GTTzQvaZsTZARdNkkdjDKFFnBhmO3e5mIM1PkH/x4p0= +github.com/ipfs/go-unixfs v0.3.1 h1:LrfED0OGfG98ZEegO4/xiprx2O+yS+krCMQSp7zLVv8= +github.com/ipfs/go-unixfs v0.3.1/go.mod h1:h4qfQYzghiIc8ZNFKiLMFWOTzrWIAtzYQ59W/pCFf1o= +github.com/ipfs/go-unixfsnode v1.1.3/go.mod h1:ZZxUM5wXBC+G0Co9FjrYTOm+UlhZTjxLfRYdWY9veZ4= github.com/ipfs/go-verifcid v0.0.1 h1:m2HI7zIuR5TFyQ1b79Da5N9dnnCP1vcu2QqawmWlK2E= github.com/ipfs/go-verifcid v0.0.1/go.mod h1:5Hrva5KBeIog4A+UpqlaIU+DEstipcJYQQZc0g37pY0= -github.com/ipfs/interface-go-ipfs-core v0.4.0 h1:+mUiamyHIwedqP8ZgbCIwpy40oX7QcXUbo4CZOeJVJg= github.com/ipfs/interface-go-ipfs-core v0.4.0/go.mod h1:UJBcU6iNennuI05amq3FQ7g0JHUkibHFAfhfUIy927o= +github.com/ipfs/interface-go-ipfs-core v0.5.1/go.mod h1:lNBJrdXHtWS46evMPBdWtDQMDsrKcGbxCOGoKLkztOE= +github.com/ipfs/interface-go-ipfs-core v0.5.2 h1:m1/5U+WpOK2ZE7Qzs5iIu80QM1ZA3aWYi2Ilwpi+tdg= +github.com/ipfs/interface-go-ipfs-core v0.5.2/go.mod h1:lNBJrdXHtWS46evMPBdWtDQMDsrKcGbxCOGoKLkztOE= github.com/ipfs/iptb v1.4.0 h1:YFYTrCkLMRwk/35IMyC6+yjoQSHTEcNcefBStLJzgvo= github.com/ipfs/iptb v1.4.0/go.mod h1:1rzHpCYtNp87/+hTxG5TfCVn/yMY3dKnLn8tBiMfdmg= github.com/ipfs/iptb-plugins v0.3.0 h1:C1rpq1o5lUZtaAOkLIox5akh6ba4uk/3RwWc6ttVxw0= github.com/ipfs/iptb-plugins v0.3.0/go.mod h1:5QtOvckeIw4bY86gSH4fgh3p3gCSMn3FmIKr4gaBncA= +github.com/ipfs/tar-utils v0.0.1/go.mod h1:ACflm9wXvV9w0eMJt6yYXxS2zuIV+yXGNwbuq1bhLeE= +github.com/ipfs/tar-utils v0.0.2/go.mod h1:4qlnRWgTVljIMhSG2SqRYn66NT+3wrv/kZt9V+eqxDM= github.com/ipld/go-car v0.1.0/go.mod h1:RCWzaUh2i4mOEkB3W45Vc+9jnS/M6Qay5ooytiBHl3g= +github.com/ipld/go-car v0.3.1/go.mod h1:dPkEWeAK8KaVvH5TahaCs6Mncpd4lDMpkbs0/SPzuVs= +github.com/ipld/go-car v0.3.2/go.mod h1:WEjynkVt04dr0GwJhry0KlaTeSDEiEYyMPOxDBQ17KE= github.com/ipld/go-car v0.3.3-0.20211210032800-e6f244225a16/go.mod h1:/wkKF4908ULT4dFIFIUZYcfjAnj+KFnJvlh8Hsz1FbQ= github.com/ipld/go-car v0.3.3 h1:D6y+jvg9h2ZSv7GLUMWUwg5VTLy1E7Ak+uQw5orOg3I= github.com/ipld/go-car v0.3.3/go.mod h1:/wkKF4908ULT4dFIFIUZYcfjAnj+KFnJvlh8Hsz1FbQ= -github.com/ipld/go-car/v2 v2.1.1-0.20211211000942-be2525f6bf2d/go.mod h1:+2Yvf0Z3wzkv7NeI69i8tuZ+ft7jyjPYIWZzeVNeFcI= github.com/ipld/go-car/v2 v2.1.1 h1:saaKz4nC0AdfCGHLYKeXLGn8ivoPC54fyS55uyOLKwA= github.com/ipld/go-car/v2 v2.1.1/go.mod h1:+2Yvf0Z3wzkv7NeI69i8tuZ+ft7jyjPYIWZzeVNeFcI= github.com/ipld/go-codec-dagpb v1.2.0/go.mod h1:6nBN7X7h8EOsEejZGqC7tej5drsdBAXbMHyBT+Fne5s= @@ -1071,8 +1168,12 @@ github.com/ipld/go-ipld-prime v0.9.0/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/j github.com/ipld/go-ipld-prime v0.9.1-0.20210324083106-dc342a9917db/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= github.com/ipld/go-ipld-prime v0.10.0/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= github.com/ipld/go-ipld-prime v0.11.0/go.mod h1:+WIAkokurHmZ/KwzDOMUuoeJgaRQktHtEaLglS3ZeV8= +github.com/ipld/go-ipld-prime v0.12.2/go.mod h1:PaeLYq8k6dJLmDUSLrzkEpoGV4PEfe/1OtFN/eALOc8= github.com/ipld/go-ipld-prime v0.12.3/go.mod h1:PaeLYq8k6dJLmDUSLrzkEpoGV4PEfe/1OtFN/eALOc8= +github.com/ipld/go-ipld-prime v0.12.4-0.20211026094848-168715526f2d/go.mod h1:JUI6cS52J83Tz5li0Zl6M2tDX4r5x68Y77K1fbXHFYo= github.com/ipld/go-ipld-prime v0.14.0/go.mod h1:9ASQLwUFLptCov6lIYc70GRB4V7UTyLD0IJtrDJe6ZM= +github.com/ipld/go-ipld-prime v0.14.1/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= +github.com/ipld/go-ipld-prime v0.14.2/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= github.com/ipld/go-ipld-prime v0.14.3-0.20211207234443-319145880958/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= github.com/ipld/go-ipld-prime v0.14.3 h1:cGUmxSws2IHurn00/iLMDapeXsnf9+FyAtYVy8G/JsQ= github.com/ipld/go-ipld-prime v0.14.3/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= @@ -1081,6 +1182,10 @@ github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20211210234204-ce2a1c70cd github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20211210234204-ce2a1c70cd73/go.mod h1:2PJ0JgxyB08t0b2WKrcuqI3di0V+5n6RS/LTUJhkoxY= github.com/ipld/go-ipld-selector-text-lite v0.0.1 h1:lNqFsQpBHc3p5xHob2KvEg/iM5dIFn6iw4L/Hh+kS1Y= github.com/ipld/go-ipld-selector-text-lite v0.0.1/go.mod h1:U2CQmFb+uWzfIEF3I1arrDa5rwtj00PrpiwwCO+k1RM= +github.com/ipld/go-storethehash v0.0.0-20210915160027-d72ca9b0968c/go.mod h1:PwE6iq8TiWJRI3zMGA1RtkFAnrDMK93dLA5SUeu0lH8= +github.com/ipld/go-storethehash v0.0.0-20211122175924-41b16c131842/go.mod h1:PwE6iq8TiWJRI3zMGA1RtkFAnrDMK93dLA5SUeu0lH8= +github.com/ipld/go-storethehash v0.0.1 h1:U9E9n3dE0IaImSNbRcUmm5Dk9UPiS9H0i+LmCFFGJBI= +github.com/ipld/go-storethehash v0.0.1/go.mod h1:w8cQfWInks8lvvbQTiKbCPusU9v0sqiViBihTHbavpQ= github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52 h1:QG4CGBqCeuBo6aZlGAamSkxWdgWfZGeE49eUOWJPA4c= github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52/go.mod h1:fdg+/X9Gg4AsAIzWpEHwnqd+QY3b7lajxyjE1m4hkq4= github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= @@ -1209,6 +1314,7 @@ github.com/libp2p/go-conn-security-multistream v0.2.0/go.mod h1:hZN4MjlNetKD3Rq5 github.com/libp2p/go-conn-security-multistream v0.2.1/go.mod h1:cR1d8gA0Hr59Fj6NhaTpFhJZrjSYuNmhpT2r25zYR70= github.com/libp2p/go-conn-security-multistream v0.3.0 h1:9UCIKlBL1hC9u7nkMXpD1nkc/T53PKMAn3/k9ivBAVc= github.com/libp2p/go-conn-security-multistream v0.3.0/go.mod h1:EEP47t4fw/bTelVmEzIDqSe69hO/ip52xBEhZMLWAHM= +github.com/libp2p/go-doh-resolver v0.3.1/go.mod h1:y5go1ZppAq9N2eppbX0xON01CyPBeUg2yS6BTssssog= github.com/libp2p/go-eventbus v0.0.2/go.mod h1:Hr/yGlwxA/stuLnpMiu82lpNKpvRy3EaJxPu40XYOwk= github.com/libp2p/go-eventbus v0.1.0/go.mod h1:vROgu5cs5T7cv7POWlWxBaVLxfSegC5UGQf8A2eEmx4= github.com/libp2p/go-eventbus v0.2.1 h1:VanAdErQnpTioN2TowqNcOijf6YwhuODe4pPKSDpxGc= @@ -1228,8 +1334,12 @@ github.com/libp2p/go-libp2p v0.7.4/go.mod h1:oXsBlTLF1q7pxr+9w6lqzS1ILpyHsaBPniV github.com/libp2p/go-libp2p v0.8.1/go.mod h1:QRNH9pwdbEBpx5DTJYg+qxcVaDMAz3Ee/qDKwXujH5o= github.com/libp2p/go-libp2p v0.8.3/go.mod h1:EsH1A+8yoWK+L4iKcbPYu6MPluZ+CHWI9El8cTaefiM= github.com/libp2p/go-libp2p v0.10.0/go.mod h1:yBJNpb+mGJdgrwbKAKrhPU0u3ogyNFTfjJ6bdM+Q/G8= +github.com/libp2p/go-libp2p v0.12.0/go.mod h1:FpHZrfC1q7nA8jitvdjKBDF31hguaC676g/nT9PgQM0= +github.com/libp2p/go-libp2p v0.13.0/go.mod h1:pM0beYdACRfHO1WcJlp65WXyG2A6NqYM+t2DTVAJxMo= +github.com/libp2p/go-libp2p v0.14.0/go.mod h1:dsQrWLAoIn+GkHPN/U+yypizkHiB9tnv79Os+kSgQ4Q= github.com/libp2p/go-libp2p v0.14.3/go.mod h1:d12V4PdKbpL0T1/gsUNN8DfgMuRPDX8bS2QxCZlwRH0= github.com/libp2p/go-libp2p v0.14.4/go.mod h1:EIRU0Of4J5S8rkockZM7eJp2S0UrCyi55m2kJVru3rM= +github.com/libp2p/go-libp2p v0.15.0/go.mod h1:8Ljmwon0cZZYKrOCjFeLwQEK8bqR42dOheUZ1kSKhP0= github.com/libp2p/go-libp2p v0.16.0/go.mod h1:ump42BsirwAWxKzsCiFnTtN1Yc+DuPu76fyMX364/O4= github.com/libp2p/go-libp2p v0.17.0 h1:8l4GV401OSd4dFRyHDtIT/mEzdh/aQGoFC8xshYgm5M= github.com/libp2p/go-libp2p v0.17.0/go.mod h1:Fkin50rsGdv5mm5BshBUtPRZknt9esfmYXBOYcwOTgw= @@ -1243,6 +1353,7 @@ github.com/libp2p/go-libp2p-autonat v0.2.0/go.mod h1:DX+9teU4pEEoZUqR1PiMlqliONQ github.com/libp2p/go-libp2p-autonat v0.2.1/go.mod h1:MWtAhV5Ko1l6QBsHQNSuM6b1sRkXrpk0/LqCr+vCVxI= github.com/libp2p/go-libp2p-autonat v0.2.2/go.mod h1:HsM62HkqZmHR2k1xgX34WuWDzk/nBwNHoeyyT4IWV6A= github.com/libp2p/go-libp2p-autonat v0.2.3/go.mod h1:2U6bNWCNsAG9LEbwccBDQbjzQ8Krdjge1jLTE9rdoMM= +github.com/libp2p/go-libp2p-autonat v0.4.0/go.mod h1:YxaJlpr81FhdOv3W3BTconZPfhaYivRdf53g+S2wobk= github.com/libp2p/go-libp2p-autonat v0.4.2/go.mod h1:YxaJlpr81FhdOv3W3BTconZPfhaYivRdf53g+S2wobk= github.com/libp2p/go-libp2p-autonat v0.6.0/go.mod h1:bFC6kY8jwzNNWoqc8iGE57vsfwyJ/lP4O4DOV1e0B2o= github.com/libp2p/go-libp2p-autonat v0.7.0 h1:rCP5s+A2dlhM1Xd66wurE0k7S7pPmM0D+FlqqSBXxks= @@ -1315,15 +1426,22 @@ github.com/libp2p/go-libp2p-discovery v0.2.0/go.mod h1:s4VGaxYMbw4+4+tsoQTqh7wfx github.com/libp2p/go-libp2p-discovery v0.3.0/go.mod h1:o03drFnz9BVAZdzC/QUQ+NeQOu38Fu7LJGEOK2gQltw= github.com/libp2p/go-libp2p-discovery v0.4.0/go.mod h1:bZ0aJSrFc/eX2llP0ryhb1kpgkPyTo23SJ5b7UQCMh4= github.com/libp2p/go-libp2p-discovery v0.5.0/go.mod h1:+srtPIU9gDaBNu//UHvcdliKBIcr4SfDcm0/PfPJLug= +github.com/libp2p/go-libp2p-discovery v0.5.1/go.mod h1:+srtPIU9gDaBNu//UHvcdliKBIcr4SfDcm0/PfPJLug= github.com/libp2p/go-libp2p-discovery v0.6.0 h1:1XdPmhMJr8Tmj/yUfkJMIi8mgwWrLUsCB3bMxdT+DSo= github.com/libp2p/go-libp2p-discovery v0.6.0/go.mod h1:/u1voHt0tKIe5oIA1RHBKQLVCWPna2dXmPNHc2zR9S8= +github.com/libp2p/go-libp2p-gostream v0.3.0/go.mod h1:pLBQu8db7vBMNINGsAwLL/ZCE8wng5V1FThoaE5rNjc= +github.com/libp2p/go-libp2p-gostream v0.3.1 h1:XlwohsPn6uopGluEWs1Csv1QCEjrTXf2ZQagzZ5paAg= +github.com/libp2p/go-libp2p-gostream v0.3.1/go.mod h1:1V3b+u4Zhaq407UUY9JLCpboaeufAeVQbnvAt12LRsI= github.com/libp2p/go-libp2p-host v0.0.1/go.mod h1:qWd+H1yuU0m5CwzAkvbSjqKairayEHdR5MMl7Cwa7Go= github.com/libp2p/go-libp2p-host v0.0.3/go.mod h1:Y/qPyA6C8j2coYyos1dfRm0I8+nvd4TGrDGt4tA7JR8= +github.com/libp2p/go-libp2p-http v0.2.1/go.mod h1:9KdioZ7XqNH0eZkZG9bulZLzHv11A7/12fT97agqWhg= github.com/libp2p/go-libp2p-interface-connmgr v0.0.1/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k= github.com/libp2p/go-libp2p-interface-connmgr v0.0.4/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k= github.com/libp2p/go-libp2p-interface-connmgr v0.0.5/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k= github.com/libp2p/go-libp2p-interface-pnet v0.0.1/go.mod h1:el9jHpQAXK5dnTpKA4yfCNBZXvrzdOU75zz+C6ryp3k= github.com/libp2p/go-libp2p-kad-dht v0.2.1/go.mod h1:k7ONOlup7HKzQ68dE6lSnp07cdxdkmnRa+6B4Fh9/w0= +github.com/libp2p/go-libp2p-kad-dht v0.11.1/go.mod h1:5ojtR2acDPqh/jXf5orWy8YGb8bHQDS+qeDcoscL/PI= +github.com/libp2p/go-libp2p-kad-dht v0.13.1/go.mod h1:iVdxmsKHVPQSCGPP4V/A+tDFCLsxrREZUBX8ohOcKDw= github.com/libp2p/go-libp2p-kad-dht v0.15.0 h1:Ke+Oj78gX5UDXnA6HBdrgvi+fStJxgYTDa51U0TsCLo= github.com/libp2p/go-libp2p-kad-dht v0.15.0/go.mod h1:rZtPxYu1TnHHz6n1RggdGrxUX/tA1C2/Wiw3ZMUDrU0= github.com/libp2p/go-libp2p-kbucket v0.2.1/go.mod h1:/Rtu8tqbJ4WQ2KTCOMJhggMukOLNLNPY1EtEWWLxUvc= @@ -1339,6 +1457,7 @@ github.com/libp2p/go-libp2p-mplex v0.2.0/go.mod h1:Ejl9IyjvXJ0T9iqUTE1jpYATQ9NM3 github.com/libp2p/go-libp2p-mplex v0.2.1/go.mod h1:SC99Rxs8Vuzrf/6WhmH41kNn13TiYdAWNYHrwImKLnE= github.com/libp2p/go-libp2p-mplex v0.2.2/go.mod h1:74S9eum0tVQdAfFiKxAyKzNdSuLqw5oadDq7+L/FELo= github.com/libp2p/go-libp2p-mplex v0.2.3/go.mod h1:CK3p2+9qH9x+7ER/gWWDYJ3QW5ZxWDkm+dVvjfuG3ek= +github.com/libp2p/go-libp2p-mplex v0.3.0/go.mod h1:l9QWxRbbb5/hQMECEb908GbS9Sm2UAR2KFZKUJEynEs= github.com/libp2p/go-libp2p-mplex v0.4.0/go.mod h1:yCyWJE2sc6TBTnFpjvLuEJgTSw/u+MamvzILKdX7asw= github.com/libp2p/go-libp2p-mplex v0.4.1 h1:/pyhkP1nLwjG3OM+VuaNJkQT/Pqq73WzB3aDN3Fx1sc= github.com/libp2p/go-libp2p-mplex v0.4.1/go.mod h1:cmy+3GfqfM1PceHTLL7zQzAAYaryDu6iPSC+CIb094g= @@ -1352,7 +1471,9 @@ github.com/libp2p/go-libp2p-net v0.0.2/go.mod h1:Yt3zgmlsHOgUWSXmt5V/Jpz9upuJBE8 github.com/libp2p/go-libp2p-netutil v0.0.1/go.mod h1:GdusFvujWZI9Vt0X5BKqwWWmZFxecf9Gt03cKxm2f/Q= github.com/libp2p/go-libp2p-netutil v0.1.0 h1:zscYDNVEcGxyUpMd0JReUZTrpMfia8PmLKcKF72EAMQ= github.com/libp2p/go-libp2p-netutil v0.1.0/go.mod h1:3Qv/aDqtMLTUyQeundkKsA+YCThNdbQD54k3TqjpbFU= +github.com/libp2p/go-libp2p-noise v0.1.1/go.mod h1:QDFLdKX7nluB7DEnlVPbz7xlLHdwHFA9HiohJRr3vwM= github.com/libp2p/go-libp2p-noise v0.2.0/go.mod h1:IEbYhBBzGyvdLBoxxULL/SGbJARhUeqlO8lVSREYu2Q= +github.com/libp2p/go-libp2p-noise v0.2.2/go.mod h1:IEbYhBBzGyvdLBoxxULL/SGbJARhUeqlO8lVSREYu2Q= github.com/libp2p/go-libp2p-noise v0.3.0 h1:NCVH7evhVt9njbTQshzT7N1S3Q6fjj9M11FCgfH5+cA= github.com/libp2p/go-libp2p-noise v0.3.0/go.mod h1:JNjHbociDJKHD64KTkzGnzqJ0FEV5gHJa6AB00kbCNQ= github.com/libp2p/go-libp2p-peer v0.0.1/go.mod h1:nXQvOBbwVqoP+T5Y5nCjeH4sP9IX/J0AMzcDUVruVoo= @@ -1380,14 +1501,20 @@ github.com/libp2p/go-libp2p-protocol v0.0.1/go.mod h1:Af9n4PiruirSDjHycM1QuiMi/1 github.com/libp2p/go-libp2p-protocol v0.1.0/go.mod h1:KQPHpAabB57XQxGrXCNvbL6UEXfQqUgC/1adR2Xtflk= github.com/libp2p/go-libp2p-pubsub v0.1.1/go.mod h1:ZwlKzRSe1eGvSIdU5bD7+8RZN/Uzw0t1Bp9R1znpR/Q= github.com/libp2p/go-libp2p-pubsub v0.3.2/go.mod h1:Uss7/Cfz872KggNb+doCVPHeCDmXB7z500m/R8DaAUk= +github.com/libp2p/go-libp2p-pubsub v0.4.0/go.mod h1:izkeMLvz6Ht8yAISXjx60XUQZMq9ZMe5h2ih4dLIBIQ= +github.com/libp2p/go-libp2p-pubsub v0.5.4/go.mod h1:gVOzwebXVdSMDQBTfH8ACO5EJ4SQrvsHqCmYsCZpD0E= +github.com/libp2p/go-libp2p-pubsub v0.5.6/go.mod h1:gVOzwebXVdSMDQBTfH8ACO5EJ4SQrvsHqCmYsCZpD0E= github.com/libp2p/go-libp2p-pubsub v0.6.0 h1:98+RXuEWW17U6cAijK1yaTf6mw/B+n5yPA421z+dlo0= github.com/libp2p/go-libp2p-pubsub v0.6.0/go.mod h1:nJv87QM2cU0w45KPR1rZicq+FmFIOD16zmT+ep1nOmg= +github.com/libp2p/go-libp2p-pubsub-router v0.4.0/go.mod h1:hs0j0ugcBjMOMgJ6diOlZM2rZEId/w5Gg86E+ac4SmQ= +github.com/libp2p/go-libp2p-pubsub-router v0.5.0/go.mod h1:TRJKskSem3C0aSb3CmRgPwq6IleVFzds6hS09fmZbGM= github.com/libp2p/go-libp2p-pubsub-tracer v0.0.0-20200626141350-e730b32bf1e6 h1:2lH7rMlvDPSvXeOR+g7FE6aqiEwxtpxWKQL8uigk5fQ= github.com/libp2p/go-libp2p-pubsub-tracer v0.0.0-20200626141350-e730b32bf1e6/go.mod h1:8ZodgKS4qRLayfw9FDKDd9DX4C16/GMofDxSldG8QPI= github.com/libp2p/go-libp2p-quic-transport v0.1.1/go.mod h1:wqG/jzhF3Pu2NrhJEvE+IE0NTHNXslOPn9JQzyCAxzU= github.com/libp2p/go-libp2p-quic-transport v0.5.0/go.mod h1:IEcuC5MLxvZ5KuHKjRu+dr3LjCT1Be3rcD/4d8JrX8M= github.com/libp2p/go-libp2p-quic-transport v0.10.0/go.mod h1:RfJbZ8IqXIhxBRm5hqUEJqjiiY8xmEuq3HUDS993MkA= github.com/libp2p/go-libp2p-quic-transport v0.11.2/go.mod h1:wlanzKtIh6pHrq+0U3p3DY9PJfGqxMgPaGKaK5LifwQ= +github.com/libp2p/go-libp2p-quic-transport v0.12.0/go.mod h1:EKHqxZbWE/FhDJZ6ebyZ/4v3X9zyuuuKIN0XR9vANT0= github.com/libp2p/go-libp2p-quic-transport v0.13.0/go.mod h1:39/ZWJ1TW/jx1iFkKzzUg00W6tDJh73FC0xYudjr7Hc= github.com/libp2p/go-libp2p-quic-transport v0.15.0/go.mod h1:wv4uGwjcqe8Mhjj7N/Ic0aKjA+/10UnMlSzLO0yRpYQ= github.com/libp2p/go-libp2p-quic-transport v0.15.2 h1:wHBEceRy+1/8Ec8dAIyr+/P7L2YefIGprPVy5LrMM+k= @@ -1416,6 +1543,8 @@ github.com/libp2p/go-libp2p-swarm v0.2.4/go.mod h1:/xIpHFPPh3wmSthtxdGbkHZ0OET1h github.com/libp2p/go-libp2p-swarm v0.2.7/go.mod h1:ZSJ0Q+oq/B1JgfPHJAT2HTall+xYRNYp1xs4S2FBWKA= github.com/libp2p/go-libp2p-swarm v0.2.8/go.mod h1:JQKMGSth4SMqonruY0a8yjlPVIkb0mdNSwckW7OYziM= github.com/libp2p/go-libp2p-swarm v0.3.0/go.mod h1:hdv95GWCTmzkgeJpP+GK/9D9puJegb7H57B5hWQR5Kk= +github.com/libp2p/go-libp2p-swarm v0.3.1/go.mod h1:hdv95GWCTmzkgeJpP+GK/9D9puJegb7H57B5hWQR5Kk= +github.com/libp2p/go-libp2p-swarm v0.4.0/go.mod h1:XVFcO52VoLoo0eitSxNQWYq4D6sydGOweTOAjJNraCw= github.com/libp2p/go-libp2p-swarm v0.5.0/go.mod h1:sU9i6BoHE0Ve5SKz3y9WfKrh8dUat6JknzUehFx8xW4= github.com/libp2p/go-libp2p-swarm v0.5.3/go.mod h1:NBn7eNW2lu568L7Ns9wdFrOhgRlkRnIDg0FLKbuu3i8= github.com/libp2p/go-libp2p-swarm v0.8.0/go.mod h1:sOMp6dPuqco0r0GHTzfVheVBh6UEL0L1lXUZ5ot2Fvc= @@ -1435,6 +1564,7 @@ github.com/libp2p/go-libp2p-testing v0.5.0/go.mod h1:QBk8fqIL1XNcno/l3/hhaIEn4aL github.com/libp2p/go-libp2p-testing v0.6.0 h1:tV/wz6mS1VoAYA/5DGTiyzw9TJ+eXMCMvzU5VPLJSgg= github.com/libp2p/go-libp2p-testing v0.6.0/go.mod h1:QBk8fqIL1XNcno/l3/hhaIEn4aLRijpYOR+zVjjlh+A= github.com/libp2p/go-libp2p-tls v0.1.3/go.mod h1:wZfuewxOndz5RTnCAxFliGjvYSDA40sKitV4c50uI1M= +github.com/libp2p/go-libp2p-tls v0.2.0/go.mod h1:twrp2Ci4lE2GYspA1AnlYm+boYjqVruxDKJJj7s6xrc= github.com/libp2p/go-libp2p-tls v0.3.0/go.mod h1:fwF5X6PWGxm6IDRwF3V8AVCCj/hOd5oFlg+wo2FxJDY= github.com/libp2p/go-libp2p-tls v0.3.1 h1:lsE2zYte+rZCEOHF72J1Fg3XK3dGQyKvI6i5ehJfEp0= github.com/libp2p/go-libp2p-tls v0.3.1/go.mod h1:fwF5X6PWGxm6IDRwF3V8AVCCj/hOd5oFlg+wo2FxJDY= @@ -1444,6 +1574,7 @@ github.com/libp2p/go-libp2p-transport-upgrader v0.0.4/go.mod h1:RGq+tupk+oj7PzL2 github.com/libp2p/go-libp2p-transport-upgrader v0.1.1/go.mod h1:IEtA6or8JUbsV07qPW4r01GnTenLW4oi3lOPbUMGJJA= github.com/libp2p/go-libp2p-transport-upgrader v0.2.0/go.mod h1:mQcrHj4asu6ArfSoMuyojOdjx73Q47cYD7s5+gZOlns= github.com/libp2p/go-libp2p-transport-upgrader v0.3.0/go.mod h1:i+SKzbRnvXdVbU3D1dwydnTmKRPXiAR/fyvi1dXuL4o= +github.com/libp2p/go-libp2p-transport-upgrader v0.4.0/go.mod h1:J4ko0ObtZSmgn5BX5AmegP+dK3CSnU2lMCKsSq/EY0s= github.com/libp2p/go-libp2p-transport-upgrader v0.4.2/go.mod h1:NR8ne1VwfreD5VIWIU62Agt/J18ekORFU/j1i2y8zvk= github.com/libp2p/go-libp2p-transport-upgrader v0.4.3/go.mod h1:bpkldbOWXMrXhpZbSV1mQxTrefOg2Fi+k1ClDSA4ppw= github.com/libp2p/go-libp2p-transport-upgrader v0.4.6/go.mod h1:JE0WQuQdy+uLZ5zOaI3Nw9dWGYJIA7mywEtP2lMvnyk= @@ -1461,6 +1592,8 @@ github.com/libp2p/go-libp2p-yamux v0.2.7/go.mod h1:X28ENrBMU/nm4I3Nx4sZ4dgjZ6VhL github.com/libp2p/go-libp2p-yamux v0.2.8/go.mod h1:/t6tDqeuZf0INZMTgd0WxIRbtK2EzI2h7HbFm9eAKI4= github.com/libp2p/go-libp2p-yamux v0.4.0/go.mod h1:+DWDjtFMzoAwYLVkNZftoucn7PelNoy5nm3tZ3/Zw30= github.com/libp2p/go-libp2p-yamux v0.5.0/go.mod h1:AyR8k5EzyM2QN9Bbdg6X1SkVVuqLwTGf0L4DFq9g6po= +github.com/libp2p/go-libp2p-yamux v0.5.1/go.mod h1:dowuvDu8CRWmr0iqySMiSxK+W0iL5cMVO9S94Y6gkv4= +github.com/libp2p/go-libp2p-yamux v0.5.3/go.mod h1:Vy3TMonBAfTMXHWopsMc8iX/XGRYrRlpUaMzaeuHV/s= github.com/libp2p/go-libp2p-yamux v0.5.4/go.mod h1:tfrXbyaTqqSU654GTvK3ocnSZL3BuHoeTSqhcel1wsE= github.com/libp2p/go-libp2p-yamux v0.6.0/go.mod h1:MRhd6mAYnFRnSISp4M8i0ClV/j+mWHo2mYLifWGw33k= github.com/libp2p/go-libp2p-yamux v0.7.0 h1:bVXHbTj/XH4uBBsPrg26BlDABk5WYRlssY73P0SjhPc= @@ -1514,6 +1647,7 @@ github.com/libp2p/go-sockaddr v0.0.2/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2L github.com/libp2p/go-sockaddr v0.1.0/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= github.com/libp2p/go-sockaddr v0.1.1 h1:yD80l2ZOdGksnOyHrhxDdTDFrf7Oy+v3FMVArIRgZxQ= github.com/libp2p/go-sockaddr v0.1.1/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= +github.com/libp2p/go-socket-activation v0.1.0/go.mod h1:gzda2dNkMG5Ti2OfWNNwW0FDIbj0g/aJJU320FcLfhk= github.com/libp2p/go-stream-muxer v0.0.1/go.mod h1:bAo8x7YkSpadMTbtTaxGVHWUQsR/l5MEaHbKaliuT14= github.com/libp2p/go-stream-muxer v0.1.0/go.mod h1:8JAVsjeRBCWwPoZeH0W1imLOcriqXJyFvB0mR4A04sQ= github.com/libp2p/go-stream-muxer-multistream v0.1.1/go.mod h1:zmGdfkQ1AzOECIAcccoL8L//laqawOsO03zX8Sa+eGw= @@ -1524,9 +1658,11 @@ github.com/libp2p/go-tcp-transport v0.0.4/go.mod h1:+E8HvC8ezEVOxIo3V5vCK9l1y/19 github.com/libp2p/go-tcp-transport v0.1.0/go.mod h1:oJ8I5VXryj493DEJ7OsBieu8fcg2nHGctwtInJVpipc= github.com/libp2p/go-tcp-transport v0.1.1/go.mod h1:3HzGvLbx6etZjnFlERyakbaYPdfjg2pWP97dFZworkY= github.com/libp2p/go-tcp-transport v0.2.0/go.mod h1:vX2U0CnWimU4h0SGSEsg++AzvBcroCGYw28kh94oLe0= +github.com/libp2p/go-tcp-transport v0.2.1/go.mod h1:zskiJ70MEfWz2MKxvFB/Pv+tPIB1PpPUrHIWQ8aFw7M= github.com/libp2p/go-tcp-transport v0.2.3/go.mod h1:9dvr03yqrPyYGIEN6Dy5UvdJZjyPFvl1S/igQ5QD1SU= github.com/libp2p/go-tcp-transport v0.2.4/go.mod h1:9dvr03yqrPyYGIEN6Dy5UvdJZjyPFvl1S/igQ5QD1SU= github.com/libp2p/go-tcp-transport v0.2.7/go.mod h1:lue9p1b3VmZj1MhhEGB/etmvF/nBQ0X9CW2DutBT3MM= +github.com/libp2p/go-tcp-transport v0.2.8/go.mod h1:64rSfVidkYPLqbzpcN2IwHY4pmgirp67h++hZ/rcndQ= github.com/libp2p/go-tcp-transport v0.4.0 h1:VDyg4j6en3OuXf90gfDQh5Sy9KowO9udnd0OU8PP6zg= github.com/libp2p/go-tcp-transport v0.4.0/go.mod h1:0y52Rwrn4076xdJYu/51/qJIdxz+EWDAOG2S45sV3VI= github.com/libp2p/go-testutil v0.0.1/go.mod h1:iAcJc/DKJQanJ5ws2V+u5ywdL2n12X1WbbEG+Jjy69I= @@ -1550,9 +1686,12 @@ github.com/libp2p/go-yamux v1.3.7/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/h github.com/libp2p/go-yamux v1.4.0/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= github.com/libp2p/go-yamux v1.4.1 h1:P1Fe9vF4th5JOxxgQvfbOHkrGqIZniTLf+ddhZp8YTI= github.com/libp2p/go-yamux v1.4.1/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= +github.com/libp2p/go-yamux/v2 v2.0.0/go.mod h1:NVWira5+sVUIU6tu1JWvaRn1dRnG+cawOJiflsAM+7U= +github.com/libp2p/go-yamux/v2 v2.1.1/go.mod h1:3So6P6TV6r75R9jiBpiIKgU/66lOarCZjqROGxzPpPQ= github.com/libp2p/go-yamux/v2 v2.2.0/go.mod h1:3So6P6TV6r75R9jiBpiIKgU/66lOarCZjqROGxzPpPQ= github.com/libp2p/go-yamux/v2 v2.3.0 h1:luRV68GS1vqqr6EFUjtu1kr51d+IbW0gSowu8emYWAI= github.com/libp2p/go-yamux/v2 v2.3.0/go.mod h1:iTU+lOIn/2h0AgKcL49clNTwfEw+WSfDYrXe05EyKIs= +github.com/libp2p/zeroconf/v2 v2.0.0/go.mod h1:J85R/d9joD8u8F9aHM8pBXygtG9W02enEwS+wWeL6yo= github.com/libp2p/zeroconf/v2 v2.1.1/go.mod h1:fuJqLnUwZTshS3U/bMRJ3+ow/v9oid1n0DmyYyNO1Xs= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= @@ -1620,6 +1759,7 @@ github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9 github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg= github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= @@ -1642,6 +1782,7 @@ github.com/miekg/dns v1.1.22/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKju github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.28/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.29/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= +github.com/miekg/dns v1.1.31/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= @@ -1706,13 +1847,15 @@ github.com/multiformats/go-multiaddr v0.3.0/go.mod h1:dF9kph9wfJ+3VLAaeBqo9Of8x4 github.com/multiformats/go-multiaddr v0.3.1/go.mod h1:uPbspcUPd5AfaP6ql3ujFY+QWzmBD8uLLL4bXW0XfGc= github.com/multiformats/go-multiaddr v0.3.3/go.mod h1:lCKNGP1EQ1eZ35Za2wlqnabm9xQkib3fyB+nZXHLag0= github.com/multiformats/go-multiaddr v0.4.0/go.mod h1:YcpyLH8ZPudLxQlemYBPhSm0/oCXAT8Z4mzFpyoPyRc= -github.com/multiformats/go-multiaddr v0.4.1 h1:Pq37uLx3hsyNlTDir7FZyU8+cFCTqd5y1KiM2IzOutI= github.com/multiformats/go-multiaddr v0.4.1/go.mod h1:3afI9HfVW8csiF8UZqtpYRiDyew8pRX7qLIGHu9FLuM= +github.com/multiformats/go-multiaddr v0.5.0 h1:i/JuOoVg4szYQ4YEzDGtb2h0o8M7CG/Yq6cGlcjWZpM= +github.com/multiformats/go-multiaddr v0.5.0/go.mod h1:3KAxNkUqLTJ20AAwN4XVX4kZar+bR+gh4zgbfr3SNug= github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.0.3/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.1.0/go.mod h1:01k2RAqtoXIuPa3DCavAE9/6jc6nM0H3EgZyfUhN2oY= github.com/multiformats/go-multiaddr-dns v0.2.0/go.mod h1:TJ5pr5bBO7Y1B18djPuRsVkduhQH2YqYSbxWJzYGdK0= +github.com/multiformats/go-multiaddr-dns v0.3.0/go.mod h1:mNzQ4eTGDg0ll1N9jKPOUogZPoJ30W8a7zk66FQPpdQ= github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A= github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk= github.com/multiformats/go-multiaddr-fmt v0.0.1/go.mod h1:aBYjqL4T/7j4Qx+R73XSv/8JsgnRFlf0w2KGLCmXl3Q= @@ -1732,8 +1875,9 @@ github.com/multiformats/go-multibase v0.0.3 h1:l/B6bJDQjvQ5G52jw4QGSYeOTZoAwIO77 github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= github.com/multiformats/go-multicodec v0.2.0/go.mod h1:/y4YVwkfMyry5kFbMTbLJKErhycTIftytRV+llXdyS4= github.com/multiformats/go-multicodec v0.3.0/go.mod h1:qGGaQmioCDh+TeFOnxrbU0DaIPw8yFgAZgFG0V7p1qQ= -github.com/multiformats/go-multicodec v0.3.1-0.20210902112759-1539a079fd61 h1:ZrUuMKNgJ52qHPoQ+bx0h0uBfcWmN7Px+4uKSZeesiI= github.com/multiformats/go-multicodec v0.3.1-0.20210902112759-1539a079fd61/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ= +github.com/multiformats/go-multicodec v0.4.0 h1:fbqb6ky7erjdD+/zaEBJgZWu1i8D6i/wmPywGK7sdow= +github.com/multiformats/go-multicodec v0.4.0/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ= github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= @@ -1742,12 +1886,14 @@ github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpK github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= github.com/multiformats/go-multihash v0.0.14/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= github.com/multiformats/go-multihash v0.0.15/go.mod h1:D6aZrWNLFTV/ynMpKsNtB40mJzmCl4jb1alC0OvHiHg= +github.com/multiformats/go-multihash v0.0.16/go.mod h1:zhfEIgVnB/rPMfxgFw15ZmGoNaKyNUIE4IWHG/kC+Ag= github.com/multiformats/go-multihash v0.1.0 h1:CgAgwqk3//SVEw3T+6DqI4mWMyRuDwZtOWcJT0q9+EA= github.com/multiformats/go-multihash v0.1.0/go.mod h1:RJlXsxt6vHGaia+S8We0ErjhojtKzPP2AH4+kYM7k84= github.com/multiformats/go-multistream v0.0.1/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= github.com/multiformats/go-multistream v0.0.4/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= github.com/multiformats/go-multistream v0.1.1/go.mod h1:KmHZ40hzVxiaiwlj3MEbYgK9JFk2/9UktWZAF54Du38= +github.com/multiformats/go-multistream v0.2.0/go.mod h1:5GZPQZbkWOLOn3J2y4Y99vVW7vOfsAflxARk3x14o6k= github.com/multiformats/go-multistream v0.2.1/go.mod h1:5GZPQZbkWOLOn3J2y4Y99vVW7vOfsAflxARk3x14o6k= github.com/multiformats/go-multistream v0.2.2 h1:TCYu1BHTDr1F/Qm75qwYISQdzGcRdC21nFgQW7l7GBo= github.com/multiformats/go-multistream v0.2.2/go.mod h1:UIcnm7Zuo8HKG+HkWgfQsGL+/MIEhyTqbODbIUwSXKs= @@ -1880,6 +2026,7 @@ github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeD github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.4.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_golang v1.6.0/go.mod h1:ZLOG9ck3JLRdB5MgO8f+lLTe83AXG6ro35rLTxvnIl4= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU= github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU= @@ -1923,6 +2070,7 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/prometheus v0.0.0-20200609090129-a6600f564e3c/go.mod h1:S5n0C6tSgdnwWshBUceRx5G1OsjLv/EeZ9t3wIfEtsY= +github.com/prometheus/statsd_exporter v0.20.0/go.mod h1:YL3FWCG8JBBtaUSxAg4Gz2ZYu22bS84XM89ZQXXTWmQ= github.com/prometheus/statsd_exporter v0.21.0 h1:hA05Q5RFeIjgwKIYEdFd59xu5Wwaznf33yKI+pyX6T8= github.com/prometheus/statsd_exporter v0.21.0/go.mod h1:rbT83sZq2V+p73lHhPZfMc3MLCHmSHelCh9hSGYNLTQ= github.com/raulk/clock v1.1.0 h1:dpb29+UKMbLqiU/jqIJptgLR1nn23HLgMY0sTCDza5Y= @@ -2072,6 +2220,7 @@ github.com/tj/go-spin v1.1.0 h1:lhdWZsvImxvZ3q1C5OIB7d72DuOwP4O2NdBg9PyzNds= github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= github.com/uber-go/tally v3.3.15+incompatible/go.mod h1:YDTIBxdXyOU/sCWilKB4bgyufu1cEi0jdVnRdxvjnmU= github.com/uber/athenadriver v1.1.4/go.mod h1:tQjho4NzXw55LGfSZEcETuYydpY1vtmixUabHkC1K/E= github.com/uber/jaeger-client-go v2.15.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= @@ -2090,8 +2239,9 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.0.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= -github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4= github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= +github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= +github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= @@ -2101,8 +2251,9 @@ github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= github.com/wangjia184/sortedset v0.0.0-20160527075905-f5d03557ba30/go.mod h1:YkocrP2K2tcw938x9gCOmT5G5eCD6jsTz0SZuyAqwIE= -github.com/warpfork/go-testmark v0.3.0 h1:Q81c4u7hT+BR5kNfNQhEF0VT2pmL7+Kk0wD+ORYl7iA= github.com/warpfork/go-testmark v0.3.0/go.mod h1:jhEf8FVxd+F17juRubpmut64NEG6I2rgkUhlcqqXwE0= +github.com/warpfork/go-testmark v0.9.0 h1:nc+uaCiv5lFQLYjhuC2LTYeJ7JaC+gdDmsz9r0ISy0Y= +github.com/warpfork/go-testmark v0.9.0/go.mod h1:jhEf8FVxd+F17juRubpmut64NEG6I2rgkUhlcqqXwE0= github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= github.com/warpfork/go-wish v0.0.0-20190328234359-8b3e70f8e830/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a h1:G++j5e0OC488te356JvdhaM8YS6nMsjLAYF7JxCv07w= @@ -2130,8 +2281,9 @@ github.com/whyrusleeping/cbor-gen v0.0.0-20200826160007-0b9f6c5fb163/go.mod h1:f github.com/whyrusleeping/cbor-gen v0.0.0-20210118024343-169e9d70c0c2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20210219115102-f37d292932f2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20210303213153-67a261a1d291/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= -github.com/whyrusleeping/cbor-gen v0.0.0-20210713220151-be142a5ae1a8 h1:TEv7MId88TyIqIUL4hbf9otOookIolMxlEbN0ro671Y= github.com/whyrusleeping/cbor-gen v0.0.0-20210713220151-be142a5ae1a8/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= +github.com/whyrusleeping/cbor-gen v0.0.0-20211110122933-f57984553008 h1:7WtW9D9VGpmRLuQmrPy2JobUNdka95z3MKEVpELtOjo= +github.com/whyrusleeping/cbor-gen v0.0.0-20211110122933-f57984553008/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f/go.mod h1:p9UJB6dDgdPgMJZs7UjUOdulKyRr9fqkS+6JKAInPy8= github.com/whyrusleeping/go-ctrlnet v0.0.0-20180313164037-f564fbbdaa95/go.mod h1:SJqKCCPXRfBFCwXjfNT/skfsceF7+MBFLI2OrvuRA7g= @@ -2140,6 +2292,7 @@ github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= github.com/whyrusleeping/go-logging v0.0.1/go.mod h1:lDPYj54zutzG1XYfHAhcc7oNXEburHQBn+Iqd4yS4vE= github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f/go.mod h1:cZNvX9cFybI01GriPRMXDtczuvUhgbcYr9iCGaNlRv8= +github.com/whyrusleeping/go-sysinfo v0.0.0-20190219211824-4a357d4b90b1/go.mod h1:tKH72zYNt/exx6/5IQO6L9LoQ0rEjd5SbbWaDTs9Zso= github.com/whyrusleeping/ledger-filecoin-go v0.9.1-0.20201010031517-c3dcc1bddce4 h1:NwiwjQDB3CzQ5XH0rdMh1oQqzJH7O2PSLWxif/w3zsY= github.com/whyrusleeping/ledger-filecoin-go v0.9.1-0.20201010031517-c3dcc1bddce4/go.mod h1:K+EVq8d5QcQ2At5VECsA+SNZvWefyBXh8TnIsxo1OvQ= github.com/whyrusleeping/mafmt v1.2.8/go.mod h1:faQJFPbLSxzD9xpA02ttW/tS9vZykNvXwGvqIpk20FA= @@ -2166,6 +2319,7 @@ github.com/xorcare/golden v0.6.0/go.mod h1:7T39/ZMvaSEZlBPoYfVFmsBLmUl3uz9IuzWj/ github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542 h1:oWgZJmC1DorFZDpfMfWg7xk29yEOZiXmo/wZl+utTI8= github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542/go.mod h1:7T39/ZMvaSEZlBPoYfVFmsBLmUl3uz9IuzWj/U6FtvQ= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/ybbus/jsonrpc/v2 v2.1.6/go.mod h1:rIuG1+ORoiqocf9xs/v+ecaAVeo3zcZHQgInyKFMeg0= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -2238,14 +2392,18 @@ go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/dig v1.10.0 h1:yLmDDj9/zuDjv3gz8GQGviXMs9TfysIUMUilCpgzUJY= go.uber.org/dig v1.10.0/go.mod h1:X34SnWGr8Fyla9zQNO2GSO2D+TIuqB14OS8JhYocIyw= -go.uber.org/fx v1.9.0 h1:7OAz8ucp35AU8eydejpYG7QrbE8rLKzGhHbZlJi5LYY= -go.uber.org/fx v1.9.0/go.mod h1:mFdUyAUuJ3w4jAckiKSKbldsxy1ojpAMJ+dVZg5Y0Aw= +go.uber.org/dig v1.12.0 h1:l1GQeZpEbss0/M4l/ZotuBndCrkMdjnygzgcuOjAdaY= +go.uber.org/dig v1.12.0/go.mod h1:X34SnWGr8Fyla9zQNO2GSO2D+TIuqB14OS8JhYocIyw= +go.uber.org/fx v1.13.1/go.mod h1:bREWhavnedxpJeTq9pQT53BbvwhUv7TcpsOqcH4a+3w= +go.uber.org/fx v1.15.0 h1:kcfBpAm98n0ksanyyZLFE/Q3T7yPi13Ge2liu3TxR+A= +go.uber.org/fx v1.15.0/go.mod h1:jI3RazQUhGv5KkpZIRv+kuP4CcgX3fnc0qX8bLnzbx8= +go.uber.org/goleak v0.10.0/go.mod h1:VCZuO8V8mFPlL0F5J5GK1rtHV3DrFcQ1R8ryq7FK0aI= go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 h1:sHOAIxRGBp443oHZIPB+HsUGaksVCXVQENPxwTfQdH4= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= @@ -2323,6 +2481,8 @@ golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210813211128-0a44fdfbc16e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210915214749-c084706c2272/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b h1:QAqMVf3pSa6eeTsuklijukjXBlj7Es2QQplab+/RbQ4= golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -2358,6 +2518,7 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= @@ -2370,6 +2531,7 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -2438,6 +2600,7 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -2529,6 +2692,7 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191206220618-eeba5f6aabab/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2584,7 +2748,9 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211025112917-711f33c9992c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211209171907-798191bca915 h1:P+8mCzuEpyszAT6T42q0sxU+eveBAF/cJ2Kp0x6/8+0= golang.org/x/sys v0.0.0-20211209171907-798191bca915/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -2648,6 +2814,7 @@ golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191030062658-86caa796c7ab/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191114200427-caa0b0f7d508/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -2687,6 +2854,7 @@ golang.org/x/tools v0.0.0-20201112185108-eeaa07dd7696/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1-0.20210225150353-54dc8c5edb56/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= @@ -2835,6 +3003,7 @@ gopkg.in/fsnotify/fsnotify.v1 v1.4.7/go.mod h1:Fyux9zXlo4rWoMSIzpn9fDAYjalPqJ/K1 gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= @@ -2896,6 +3065,7 @@ modernc.org/strutil v1.1.0 h1:+1/yCzZxY2pZwwrsbH+4T7BQMoLQ9QiBshRC9eicYsc= modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= modernc.org/xc v1.0.0 h1:7ccXrupWZIS3twbUGrtKmHS2DXY6xegFua+6O3xgAFU= modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= +pgregory.net/rapid v0.4.7/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= From 051d993d62e727879ffa0bbf35eddbefee921057 Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Wed, 12 Jan 2022 17:48:12 +0400 Subject: [PATCH 042/385] update markets --- go.mod | 2 +- go.sum | 51 ++----------------------------------- testplans/lotus-soup/go.mod | 2 +- testplans/lotus-soup/go.sum | 50 ++---------------------------------- 4 files changed, 6 insertions(+), 99 deletions(-) diff --git a/go.mod b/go.mod index 04a19d32995..0fabad4e1a6 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,7 @@ require ( github.com/filecoin-project/go-data-transfer v1.12.1 github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 - github.com/filecoin-project/go-fil-markets v1.14.2-0.20220112094113-068e7f35a0e0 + github.com/filecoin-project/go-fil-markets v1.15.0 github.com/filecoin-project/go-indexer-core v0.2.7 github.com/filecoin-project/go-jsonrpc v0.1.5 github.com/filecoin-project/go-padreader v0.0.1 diff --git a/go.sum b/go.sum index 4dbbdc31cfa..2771e6e23e1 100644 --- a/go.sum +++ b/go.sum @@ -33,7 +33,6 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -contrib.go.opencensus.io/exporter/prometheus v0.3.0/go.mod h1:rpCPVQKhiyH8oomWgm34ZmgIdZa8OVYO5WAIygPbBBE= contrib.go.opencensus.io/exporter/prometheus v0.4.0 h1:0QfIkj9z/iVZgK31D9H9ohjjIDApI2GOPScCKwxedbs= contrib.go.opencensus.io/exporter/prometheus v0.4.0/go.mod h1:o7cosnyfuPVK0tB8q0QmaQNhGnptITnPQB+z1+qeFB0= dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= @@ -335,8 +334,8 @@ github.com/filecoin-project/go-fil-commcid v0.1.0 h1:3R4ds1A9r6cr8mvZBfMYxTS88Oq github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7LXep5bFEVOVmQWHJvl2mgsGo= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8= -github.com/filecoin-project/go-fil-markets v1.14.2-0.20220112094113-068e7f35a0e0 h1:C3rdpJJQm8/UX3aAPNbVHzSEDjI9EvD1jb2eroA3aK8= -github.com/filecoin-project/go-fil-markets v1.14.2-0.20220112094113-068e7f35a0e0/go.mod h1:H1pk9szltDLCOvQW/6fy0ugvUnDY7CDCf9HJSGSoj60= +github.com/filecoin-project/go-fil-markets v1.15.0 h1:PjoALE+brZTdZCteaj05KXt4lP5eWVWDeZmfwVAXa4w= +github.com/filecoin-project/go-fil-markets v1.15.0/go.mod h1:d6oFs7L6NCIcjY0p31KjbKAEhc0WIn8dguxGGIdTiXo= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= @@ -345,7 +344,6 @@ github.com/filecoin-project/go-hamt-ipld/v3 v3.0.1/go.mod h1:gXpNmr3oQx8l3o7qkGy github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0 h1:rVVNq0x6RGQIzCo1iiJlGFm9AGIZzeifggxtKMU7zmI= github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0/go.mod h1:bxmzgT8tmeVQA1/gvBwFmYdT8SOFUwB3ovSUfG1Ux0g= github.com/filecoin-project/go-indexer-core v0.2.4/go.mod h1:MSe5aRWmfRB+5syR4yDV+OApgJU+MUJ4rl9VUuzwCfc= -github.com/filecoin-project/go-indexer-core v0.2.6/go.mod h1:wW5Ab0gJXL2vT4iEMbPUfPs773iMc86Q8GtfSEqmu3Y= github.com/filecoin-project/go-indexer-core v0.2.7 h1:D0egR6Q3Jkp5r4klxkdDQvjXeLx3cwZMKE55qop2xCI= github.com/filecoin-project/go-indexer-core v0.2.7/go.mod h1:6YD7KwDOQ+03DdAitviL7h1fksIU6a4j52yPnA/E1PU= github.com/filecoin-project/go-jsonrpc v0.1.5 h1:ckxqZ09ivBAVf5CSmxxrqqNHC7PJm3GYGtYKiNQ+vGk= @@ -374,7 +372,6 @@ github.com/filecoin-project/go-statestore v0.2.0 h1:cRRO0aPLrxKQCZ2UOQbzFGn4WDNd github.com/filecoin-project/go-statestore v0.2.0/go.mod h1:8sjBYbS35HwPzct7iT4lIXjLlYyPor80aU7t7a/Kspo= github.com/filecoin-project/go-storedcounter v0.1.0 h1:Mui6wSUBC+cQGHbDUBcO7rfh5zQkWJM/CpAZa/uOuus= github.com/filecoin-project/go-storedcounter v0.1.0/go.mod h1:4ceukaXi4vFURIoxYMfKzaRF5Xv/Pinh2oTnoxpv+z8= -github.com/filecoin-project/index-provider v0.1.1-0.20220107223914-37c38e2b284d/go.mod h1:pTZVxt9mF+YCYSfNsn7i0rwhoMBmbjfSDAQVoxWGP10= github.com/filecoin-project/index-provider v0.2.0 h1:r1VPVhtWrU5+6Mo6g2Ozr5NXWMFz1qHt0NKJzV5ELZ8= github.com/filecoin-project/index-provider v0.2.0/go.mod h1:eYiwZfJNadwn/8Grwn2e4nX2cH4PYl2k8SZqm9k+eCA= github.com/filecoin-project/specs-actors v0.9.13/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= @@ -400,7 +397,6 @@ github.com/filecoin-project/specs-actors/v7 v7.0.0-20211230214648-aeae366b083a h github.com/filecoin-project/specs-actors/v7 v7.0.0-20211230214648-aeae366b083a/go.mod h1:p6LIOFezA1rgRLMewbvdi3Pp6SAu+q9FtJ9CAleSjrE= github.com/filecoin-project/specs-storage v0.1.1-0.20211228030229-6d460d25a0c9 h1:oUYOvF7EvdXS0Zmk9mNkaB6Bu0l+WXBYPzVodKMiLug= github.com/filecoin-project/specs-storage v0.1.1-0.20211228030229-6d460d25a0c9/go.mod h1:Tb88Zq+IBJbvAn3mS89GYj3jdRThBTE/771HCVZdRJU= -github.com/filecoin-project/storetheindex v0.2.0/go.mod h1:P3Hd3sIWEkBU1fPnE49Y8nh/mdErOdIfiHBb85QAWfg= github.com/filecoin-project/storetheindex v0.2.1 h1:jhsMh5O52bBU/NrnjJs2iLPI92T38kjlU9bk/dP0sts= github.com/filecoin-project/storetheindex v0.2.1/go.mod h1:Tc5mYdAnGUzly40cuo35yITDD3XhF9EX5BO7evGsJ5M= github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg= @@ -422,7 +418,6 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= -github.com/gabriel-vasile/mimetype v1.1.2/go.mod h1:6CDPel/o/3/s4+bp6kIbsWATq8pmgOisOPG40CJa6To= github.com/gabriel-vasile/mimetype v1.4.0/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8= github.com/gammazero/keymutex v0.0.2 h1:cmpLBJHdEwn+WlR5Z/o9/BN92znSZTp5AKPQDpu1QcI= github.com/gammazero/keymutex v0.0.2/go.mod h1:qtzWCCLMisQUmVa4dvqHVgwfh4BP2YB7JxNDGXnsKrs= @@ -566,7 +561,6 @@ github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+u github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= -github.com/google/gopacket v1.1.18/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= @@ -694,10 +688,8 @@ github.com/ipfs/go-bitfield v1.0.0/go.mod h1:N/UiujQy+K+ceU1EF5EkVd1TNqevLrCQMIc github.com/ipfs/go-bitswap v0.0.9/go.mod h1:kAPf5qgn2W2DrgAcscZ3HrM9qh4pH+X8Fkk3UPrwvis= github.com/ipfs/go-bitswap v0.1.0/go.mod h1:FFJEf18E9izuCqUtHxbWEvq+reg7o4CW5wSAE1wsxj0= github.com/ipfs/go-bitswap v0.1.2/go.mod h1:qxSWS4NXGs7jQ6zQvoPY3+NmOfHHG47mhkiLzBpJQIs= -github.com/ipfs/go-bitswap v0.1.3/go.mod h1:YEQlFy0kkxops5Vy+OxWdRSEZIoS7I7KDIwoa5Chkps= github.com/ipfs/go-bitswap v0.1.8/go.mod h1:TOWoxllhccevbWFUR2N7B1MTSVVge1s6XSMiCSA4MzM= github.com/ipfs/go-bitswap v0.3.4/go.mod h1:4T7fvNv/LmOys+21tnLzGKncMeeXUYUd1nUiJ2teMvI= -github.com/ipfs/go-bitswap v0.4.0/go.mod h1:J2sAsp9UKxLgHDektSy3y3Q9OfQjM9sjhKBR1dlwrMg= github.com/ipfs/go-bitswap v0.5.1 h1:721YAEDBnLIrvcIMkCHCdqp34hA8jwL9yKMkyJpSpco= github.com/ipfs/go-bitswap v0.5.1/go.mod h1:P+ckC87ri1xFLvk74NlXdP0Kj9RmWAh4+H78sC6Qopo= github.com/ipfs/go-block-format v0.0.1/go.mod h1:DK/YYcsSUIVAFNwo/KZCdIIbpN0ROH/baNLgayt4pFc= @@ -706,7 +698,6 @@ github.com/ipfs/go-block-format v0.0.3 h1:r8t66QstRp/pd/or4dpnbVfXT5Gt7lOqRvC+/d github.com/ipfs/go-block-format v0.0.3/go.mod h1:4LmD4ZUw0mhO+JSKdpWwrzATiEfM7WWgQ8H5l6P8MVk= github.com/ipfs/go-blockservice v0.0.7/go.mod h1:EOfb9k/Y878ZTRY/CH0x5+ATtaipfbRhbvNSdgc/7So= github.com/ipfs/go-blockservice v0.1.0/go.mod h1:hzmMScl1kXHg3M2BjTymbVPjv627N7sYcvYaKbop39M= -github.com/ipfs/go-blockservice v0.1.1/go.mod h1:t+411r7psEUhLueM8C7aPA7cxCclv4O3VsUVxt9kz2I= github.com/ipfs/go-blockservice v0.1.3/go.mod h1:OTZhFpkgY48kNzbgyvcexW9cHrpjBYIjSR0KoDOFOLU= github.com/ipfs/go-blockservice v0.1.4/go.mod h1:OTZhFpkgY48kNzbgyvcexW9cHrpjBYIjSR0KoDOFOLU= github.com/ipfs/go-blockservice v0.1.7/go.mod h1:GmS+BAt4hrwBKkzE11AFDQUrnvqjwFatGS2MY7wOjEM= @@ -729,7 +720,6 @@ github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAK github.com/ipfs/go-datastore v0.0.5/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= github.com/ipfs/go-datastore v0.1.0/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= github.com/ipfs/go-datastore v0.1.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= -github.com/ipfs/go-datastore v0.3.0/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= github.com/ipfs/go-datastore v0.3.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= github.com/ipfs/go-datastore v0.4.0/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= github.com/ipfs/go-datastore v0.4.1/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= @@ -754,7 +744,6 @@ github.com/ipfs/go-ds-badger v0.3.0 h1:xREL3V0EH9S219kFFueOYJJTcjgNSZ2HY1iSvN7U1 github.com/ipfs/go-ds-badger v0.3.0/go.mod h1:1ke6mXNqeV8K3y5Ak2bAA0osoTfmxUdupVCGm4QUIek= github.com/ipfs/go-ds-badger2 v0.1.2 h1:sQc2q1gaXrv8YFNeUtxil0neuyDf9hnVHfLsi7lpXfE= github.com/ipfs/go-ds-badger2 v0.1.2/go.mod h1:3FtQmDv6fMubygEfU43bsFelYpIiXX/XEYA54l9eCwg= -github.com/ipfs/go-ds-flatfs v0.4.5/go.mod h1:e4TesLyZoA8k1gV/yCuBTnt2PJtypn4XUlB5n8KQMZY= github.com/ipfs/go-ds-flatfs v0.5.1/go.mod h1:RWTV7oZD/yZYBKdbVIFXTX2fdY2Tbvl94NsWqmoyAX4= github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= github.com/ipfs/go-ds-leveldb v0.1.0/go.mod h1:hqAW8y4bwX5LWcCtku2rFNX3vjDZCy5LZCg+cSZvYb8= @@ -762,24 +751,20 @@ github.com/ipfs/go-ds-leveldb v0.4.1/go.mod h1:jpbku/YqBSsBc1qgME8BkWS4AxzF2cEu1 github.com/ipfs/go-ds-leveldb v0.4.2/go.mod h1:jpbku/YqBSsBc1qgME8BkWS4AxzF2cEu1Ii2r79Hh9s= github.com/ipfs/go-ds-leveldb v0.5.0 h1:s++MEBbD3ZKc9/8/njrn4flZLnCuY9I79v94gBUNumo= github.com/ipfs/go-ds-leveldb v0.5.0/go.mod h1:d3XG9RUDzQ6V4SHi8+Xgj9j1XuEk1z82lquxrVbml/Q= -github.com/ipfs/go-ds-measure v0.1.0/go.mod h1:1nDiFrhLlwArTME1Ees2XaBOl49OoCgd2A3f8EchMSY= github.com/ipfs/go-ds-measure v0.2.0 h1:sG4goQe0KDTccHMyT45CY1XyUbxe5VwTKpg2LjApYyQ= github.com/ipfs/go-ds-measure v0.2.0/go.mod h1:SEUD/rE2PwRa4IQEC5FuNAmjJCyYObZr9UvVh8V3JxE= github.com/ipfs/go-fetcher v1.5.0/go.mod h1:5pDZ0393oRF/fHiLmtFZtpMNBQfHOYNPtryWedVuSWE= github.com/ipfs/go-fetcher v1.6.1/go.mod h1:27d/xMV8bodjVs9pugh/RCjjK2OZ68UgAMspMdingNo= -github.com/ipfs/go-filestore v0.0.3/go.mod h1:dvXRykFzyyXN2CdNlRGzDAkXMDPyI+D7JE066SiKLSE= github.com/ipfs/go-filestore v0.1.0/go.mod h1:0KTrzoJnJ3sJDEDM09Vq8nz8H475rRyeq4i0n/bpF00= github.com/ipfs/go-filestore v1.1.0 h1:Pu4tLBi1bucu6/HU9llaOmb9yLFk/sgP+pW764zNDoE= github.com/ipfs/go-filestore v1.1.0/go.mod h1:6e1/5Y6NvLuCRdmda/KA4GUhXJQ3Uat6vcWm2DJfxc8= github.com/ipfs/go-fs-lock v0.0.6/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28L7zESmM= github.com/ipfs/go-fs-lock v0.0.7 h1:6BR3dajORFrFTkb5EpCUFIAypsoxpGpDSVUdFwzgL9U= github.com/ipfs/go-fs-lock v0.0.7/go.mod h1:Js8ka+FNYmgQRLrRXzU3CB/+Csr1BwrRilEcvYrHhhc= -github.com/ipfs/go-graphsync v0.8.0/go.mod h1:CLxN859dUTcXCav1DvNvmAUWPZfmNLjlGLJYy+c3dlM= github.com/ipfs/go-graphsync v0.10.0/go.mod h1:cKIshzTaa5rCZjryH5xmSKZVGX9uk1wvwGvz2WEha5Y= github.com/ipfs/go-graphsync v0.11.0/go.mod h1:wC+c8vGVjAHthsVIl8LKr37cUra2GOaMYcQNNmMxDqE= github.com/ipfs/go-graphsync v0.11.5 h1:WA5hVxGBtcal6L6nqubKiqRolaZxbexOK3GumGFJRR4= github.com/ipfs/go-graphsync v0.11.5/go.mod h1:+/sZqRwRCQRrV7NCzgBtufmr5QGpUE98XSa7NlsztmM= -github.com/ipfs/go-ipfs v0.10.0/go.mod h1:HsnRkQdpruG6JMaycJyrlLwJdduw1dJv2rEPgWxdJvA= github.com/ipfs/go-ipfs v0.11.0/go.mod h1:g68Thu2Ho11AWoHsN34P5fSK7iA6OWWRy3T/g8HLixc= github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08= github.com/ipfs/go-ipfs-blockstore v0.1.0/go.mod h1:5aD0AvHPi7mZc6Ci1WCAhiBQu2IsfTduLl+422H6Rqw= @@ -802,7 +787,6 @@ github.com/ipfs/go-ipfs-cmds v0.3.0/go.mod h1:ZgYiWVnCk43ChwoH8hAmI1IRbuVtq3GSTH github.com/ipfs/go-ipfs-cmds v0.6.0 h1:yAxdowQZzoFKjcLI08sXVNnqVj3jnABbf9smrPQmBsw= github.com/ipfs/go-ipfs-cmds v0.6.0/go.mod h1:ZgYiWVnCk43ChwoH8hAmI1IRbuVtq3GSTHwtRB/Kqhk= github.com/ipfs/go-ipfs-config v0.5.3/go.mod h1:nSLCFtlaL+2rbl3F+9D4gQZQbT1LjRKx7TJg/IHz6oM= -github.com/ipfs/go-ipfs-config v0.16.0/go.mod h1:wz2lKzOjgJeYJa6zx8W9VT7mz+iSd0laBMqS/9wmX6A= github.com/ipfs/go-ipfs-config v0.18.0 h1:Ta1aNGNEq6RIvzbw7dqzCVZJKb7j+Dd35JFnAOCpT8g= github.com/ipfs/go-ipfs-config v0.18.0/go.mod h1:wz2lKzOjgJeYJa6zx8W9VT7mz+iSd0laBMqS/9wmX6A= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= @@ -827,14 +811,12 @@ github.com/ipfs/go-ipfs-files v0.0.9/go.mod h1:aFv2uQ/qxWpL/6lidWvnSQmaVqCrf0TBG github.com/ipfs/go-ipfs-http-client v0.0.6 h1:k2QllZyP7Fz5hMgsX5hvHfn1WPG9Ngdy5WknQ7JNhBM= github.com/ipfs/go-ipfs-http-client v0.0.6/go.mod h1:8e2dQbntMZKxLfny+tyXJ7bJHZFERp/2vyzZdvkeLMc= github.com/ipfs/go-ipfs-keystore v0.0.2/go.mod h1:H49tRmibOEs7gLMgbOsjC4dqh1u5e0R/SWuc2ScfgSo= -github.com/ipfs/go-ipfs-pinner v0.1.2/go.mod h1:/u9kMe+TyQybN21O5OBicdyx3x93lVI77PCtiTnArUk= github.com/ipfs/go-ipfs-pinner v0.2.1/go.mod h1:l1AtLL5bovb7opnG77sh4Y10waINz3Y1ni6CvTzx7oo= github.com/ipfs/go-ipfs-posinfo v0.0.1 h1:Esoxj+1JgSjX0+ylc0hUmJCOv6V2vFoZiETLR6OtpRs= github.com/ipfs/go-ipfs-posinfo v0.0.1/go.mod h1:SwyeVP+jCwiDu0C313l/8jg6ZxM0qqtlt2a0vILTc1A= github.com/ipfs/go-ipfs-pq v0.0.1/go.mod h1:LWIqQpqfRG3fNc5XsnIhz/wQ2XXGyugQwls7BgUmUfY= github.com/ipfs/go-ipfs-pq v0.0.2 h1:e1vOOW6MuOwG2lqxcLA+wEn93i/9laCY8sXAw76jFOY= github.com/ipfs/go-ipfs-pq v0.0.2/go.mod h1:LWIqQpqfRG3fNc5XsnIhz/wQ2XXGyugQwls7BgUmUfY= -github.com/ipfs/go-ipfs-provider v0.6.1/go.mod h1:I4Cig3InhftbRJohph76Qy/P2uKEZILNGiKvDJmmC28= github.com/ipfs/go-ipfs-provider v0.7.1/go.mod h1:QwdDYRYnC5sYGLlOwVDY/0ZB6T3zcMtu+5+GdGeUuw8= github.com/ipfs/go-ipfs-routing v0.0.1/go.mod h1:k76lf20iKFxQTjcJokbPM9iBXVXVZhcOwc360N4nuKs= github.com/ipfs/go-ipfs-routing v0.1.0/go.mod h1:hYoUkJLyAUKhF58tysKpids8RNDPO42BVMgK5dNsoqY= @@ -858,8 +840,6 @@ github.com/ipfs/go-ipld-git v0.1.1/go.mod h1:+VyMqF5lMcJh4rwEppV0e6g4nCCHXThLYYD github.com/ipfs/go-ipld-legacy v0.1.0/go.mod h1:86f5P/srAmh9GcIcWQR9lfFLZPrIyyXQeVlOWeeWEuI= github.com/ipfs/go-ipld-legacy v0.1.1 h1:BvD8PEuqwBHLTKqlGFTHSwrwFOMkVESEvwIYwR2cdcc= github.com/ipfs/go-ipld-legacy v0.1.1/go.mod h1:8AyKFCjgRPsQFf15ZQgDB8Din4DML/fOmKZkkFkrIEg= -github.com/ipfs/go-ipns v0.0.2/go.mod h1:WChil4e0/m9cIINWLxZe1Jtf77oz5L05rO2ei/uKJ5U= -github.com/ipfs/go-ipns v0.1.0/go.mod h1:3IbsuPkR6eAGcnx+E7j6HpOSbSQJPZ6zlRj+NK3jPxQ= github.com/ipfs/go-ipns v0.1.2 h1:O/s/0ht+4Jl9+VoxoUo0zaHjnZUS+aBQIKTuzdZ/ucI= github.com/ipfs/go-ipns v0.1.2/go.mod h1:ioQ0j02o6jdIVW+bmi18f4k2gRf0AV3kZ9KeHYHICnQ= github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= @@ -883,11 +863,8 @@ github.com/ipfs/go-log/v2 v2.3.0/go.mod h1:QqGoj30OTpnKaG/LKTGTxoP2mmQtjVMEnK72g github.com/ipfs/go-log/v2 v2.4.0 h1:iR/2o9PGWanVJrBgIH5Ff8mPGOwpqLaPIAFqSnsdlzk= github.com/ipfs/go-log/v2 v2.4.0/go.mod h1:nPZnh7Cj7lwS3LpRU5Mwr2ol1c2gXIEXuF6aywqrtmo= github.com/ipfs/go-merkledag v0.0.6/go.mod h1:QYPdnlvkOg7GnQRofu9XZimC5ZW5Wi3bKys/4GQQfto= -github.com/ipfs/go-merkledag v0.1.0/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= github.com/ipfs/go-merkledag v0.2.3/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= github.com/ipfs/go-merkledag v0.2.4/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= -github.com/ipfs/go-merkledag v0.3.0/go.mod h1:4pymaZLhSLNVuiCITYrpViD6vmfZ/Ws4n/L9tfNv3S4= -github.com/ipfs/go-merkledag v0.3.1/go.mod h1:fvkZNNZixVW6cKSZ/JfLlON5OlgTXNdRLz0p6QG/I2M= github.com/ipfs/go-merkledag v0.3.2/go.mod h1:fvkZNNZixVW6cKSZ/JfLlON5OlgTXNdRLz0p6QG/I2M= github.com/ipfs/go-merkledag v0.4.0/go.mod h1:XshXBkhyeS63YNGisLL1uDSfuTyrQIxVUOg3ojR5MOE= github.com/ipfs/go-merkledag v0.5.1 h1:tr17GPP5XtPhvPPiWtu20tSGZiZDuTaJRXBLcr79Umk= @@ -896,9 +873,7 @@ github.com/ipfs/go-metrics-interface v0.0.1 h1:j+cpbjYvu4R8zbleSs36gvB7jR+wsL2fG github.com/ipfs/go-metrics-interface v0.0.1/go.mod h1:6s6euYU4zowdslK0GKHmqaIZ3j/b/tL7HTWtJ4VPgWY= github.com/ipfs/go-metrics-prometheus v0.0.2 h1:9i2iljLg12S78OhC6UAiXi176xvQGiZaGVF1CUVdE+s= github.com/ipfs/go-metrics-prometheus v0.0.2/go.mod h1:ELLU99AQQNi+zX6GCGm2lAgnzdSH3u5UVlCdqSXnEks= -github.com/ipfs/go-mfs v0.1.2/go.mod h1:T1QBiZPEpkPLzDqEJLNnbK55BVKVlNi2a+gVm4diFo0= github.com/ipfs/go-mfs v0.2.1/go.mod h1:Woj80iuw4ajDnIP6+seRaoHpPsc9hmL0pk/nDNDWP88= -github.com/ipfs/go-namesys v0.3.1/go.mod h1:/BL4xk8LP5Lq82AmaRKyxZv/eYRlumNiU9SZUe1Hlps= github.com/ipfs/go-namesys v0.4.0/go.mod h1:jpJwzodyP8DZdWN6DShRjVZw6gaqMr4nQLBSxU5cR6E= github.com/ipfs/go-path v0.0.7 h1:H06hKMquQ0aYtHiHryOMLpQC1qC3QwXwkahcEVD51Ho= github.com/ipfs/go-path v0.0.7/go.mod h1:6KTKmeRnBXgqrTvzFrPV3CamxcgvXX/4z79tfAd2Sno= @@ -906,16 +881,13 @@ github.com/ipfs/go-peertaskqueue v0.0.4/go.mod h1:03H8fhyeMfKNFWqzYEVyMbcPUeYrqP github.com/ipfs/go-peertaskqueue v0.1.0/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= github.com/ipfs/go-peertaskqueue v0.1.1/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= github.com/ipfs/go-peertaskqueue v0.2.0/go.mod h1:5/eNrBEbtSKWCG+kQK8K8fGNixoYUnr+P7jivavs9lY= -github.com/ipfs/go-peertaskqueue v0.4.0/go.mod h1:KL9F49hXJMoXCad8e5anivjN+kWdr+CyGcyh4K6doLc= github.com/ipfs/go-peertaskqueue v0.7.0/go.mod h1:M/akTIE/z1jGNXMU7kFB4TeSEFvj68ow0Rrb04donIU= github.com/ipfs/go-peertaskqueue v0.7.1 h1:7PLjon3RZwRQMgOTvYccZ+mjzkmds/7YzSWKFlBAypE= github.com/ipfs/go-peertaskqueue v0.7.1/go.mod h1:M/akTIE/z1jGNXMU7kFB4TeSEFvj68ow0Rrb04donIU= github.com/ipfs/go-pinning-service-http-client v0.1.0/go.mod h1:tcCKmlkWWH9JUUkKs8CrOZBanacNc1dmKLfjlyXAMu4= github.com/ipfs/go-todocounter v0.0.1/go.mod h1:l5aErvQc8qKE2r7NDMjmq5UNAvuZy0rC8BHOplkWvZ4= -github.com/ipfs/go-unixfs v0.1.0/go.mod h1:lysk5ELhOso8+Fed9U1QTGey2ocsfaZ18h0NCO2Fj9s= github.com/ipfs/go-unixfs v0.2.2-0.20190827150610-868af2e9e5cb/go.mod h1:IwAAgul1UQIcNZzKPYZWOCijryFBeCV79cNubPzol+k= github.com/ipfs/go-unixfs v0.2.4/go.mod h1:SUdisfUjNoSDzzhGVxvCL9QO/nKdwXdr+gbMUdqcbYw= -github.com/ipfs/go-unixfs v0.2.5/go.mod h1:SUdisfUjNoSDzzhGVxvCL9QO/nKdwXdr+gbMUdqcbYw= github.com/ipfs/go-unixfs v0.2.6/go.mod h1:GTTzQvaZsTZARdNkkdjDKFFnBhmO3e5mIM1PkH/x4p0= github.com/ipfs/go-unixfs v0.3.1 h1:LrfED0OGfG98ZEegO4/xiprx2O+yS+krCMQSp7zLVv8= github.com/ipfs/go-unixfs v0.3.1/go.mod h1:h4qfQYzghiIc8ZNFKiLMFWOTzrWIAtzYQ59W/pCFf1o= @@ -923,17 +895,14 @@ github.com/ipfs/go-unixfsnode v1.1.3/go.mod h1:ZZxUM5wXBC+G0Co9FjrYTOm+UlhZTjxLf github.com/ipfs/go-verifcid v0.0.1 h1:m2HI7zIuR5TFyQ1b79Da5N9dnnCP1vcu2QqawmWlK2E= github.com/ipfs/go-verifcid v0.0.1/go.mod h1:5Hrva5KBeIog4A+UpqlaIU+DEstipcJYQQZc0g37pY0= github.com/ipfs/interface-go-ipfs-core v0.4.0/go.mod h1:UJBcU6iNennuI05amq3FQ7g0JHUkibHFAfhfUIy927o= -github.com/ipfs/interface-go-ipfs-core v0.5.1/go.mod h1:lNBJrdXHtWS46evMPBdWtDQMDsrKcGbxCOGoKLkztOE= github.com/ipfs/interface-go-ipfs-core v0.5.2 h1:m1/5U+WpOK2ZE7Qzs5iIu80QM1ZA3aWYi2Ilwpi+tdg= github.com/ipfs/interface-go-ipfs-core v0.5.2/go.mod h1:lNBJrdXHtWS46evMPBdWtDQMDsrKcGbxCOGoKLkztOE= github.com/ipfs/iptb v1.4.0 h1:YFYTrCkLMRwk/35IMyC6+yjoQSHTEcNcefBStLJzgvo= github.com/ipfs/iptb v1.4.0/go.mod h1:1rzHpCYtNp87/+hTxG5TfCVn/yMY3dKnLn8tBiMfdmg= github.com/ipfs/iptb-plugins v0.3.0 h1:C1rpq1o5lUZtaAOkLIox5akh6ba4uk/3RwWc6ttVxw0= github.com/ipfs/iptb-plugins v0.3.0/go.mod h1:5QtOvckeIw4bY86gSH4fgh3p3gCSMn3FmIKr4gaBncA= -github.com/ipfs/tar-utils v0.0.1/go.mod h1:ACflm9wXvV9w0eMJt6yYXxS2zuIV+yXGNwbuq1bhLeE= github.com/ipfs/tar-utils v0.0.2/go.mod h1:4qlnRWgTVljIMhSG2SqRYn66NT+3wrv/kZt9V+eqxDM= github.com/ipld/go-car v0.1.0/go.mod h1:RCWzaUh2i4mOEkB3W45Vc+9jnS/M6Qay5ooytiBHl3g= -github.com/ipld/go-car v0.3.1/go.mod h1:dPkEWeAK8KaVvH5TahaCs6Mncpd4lDMpkbs0/SPzuVs= github.com/ipld/go-car v0.3.2/go.mod h1:WEjynkVt04dr0GwJhry0KlaTeSDEiEYyMPOxDBQ17KE= github.com/ipld/go-car v0.3.3-0.20211210032800-e6f244225a16/go.mod h1:/wkKF4908ULT4dFIFIUZYcfjAnj+KFnJvlh8Hsz1FbQ= github.com/ipld/go-car v0.3.3 h1:D6y+jvg9h2ZSv7GLUMWUwg5VTLy1E7Ak+uQw5orOg3I= @@ -948,9 +917,7 @@ github.com/ipld/go-ipld-prime v0.9.0/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/j github.com/ipld/go-ipld-prime v0.9.1-0.20210324083106-dc342a9917db/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= github.com/ipld/go-ipld-prime v0.10.0/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= github.com/ipld/go-ipld-prime v0.11.0/go.mod h1:+WIAkokurHmZ/KwzDOMUuoeJgaRQktHtEaLglS3ZeV8= -github.com/ipld/go-ipld-prime v0.12.2/go.mod h1:PaeLYq8k6dJLmDUSLrzkEpoGV4PEfe/1OtFN/eALOc8= github.com/ipld/go-ipld-prime v0.12.3/go.mod h1:PaeLYq8k6dJLmDUSLrzkEpoGV4PEfe/1OtFN/eALOc8= -github.com/ipld/go-ipld-prime v0.12.4-0.20211026094848-168715526f2d/go.mod h1:JUI6cS52J83Tz5li0Zl6M2tDX4r5x68Y77K1fbXHFYo= github.com/ipld/go-ipld-prime v0.14.0/go.mod h1:9ASQLwUFLptCov6lIYc70GRB4V7UTyLD0IJtrDJe6ZM= github.com/ipld/go-ipld-prime v0.14.1/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= github.com/ipld/go-ipld-prime v0.14.2/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= @@ -963,7 +930,6 @@ github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20211210234204-ce2a1c70cd github.com/ipld/go-ipld-selector-text-lite v0.0.1 h1:lNqFsQpBHc3p5xHob2KvEg/iM5dIFn6iw4L/Hh+kS1Y= github.com/ipld/go-ipld-selector-text-lite v0.0.1/go.mod h1:U2CQmFb+uWzfIEF3I1arrDa5rwtj00PrpiwwCO+k1RM= github.com/ipld/go-storethehash v0.0.0-20210915160027-d72ca9b0968c/go.mod h1:PwE6iq8TiWJRI3zMGA1RtkFAnrDMK93dLA5SUeu0lH8= -github.com/ipld/go-storethehash v0.0.0-20211122175924-41b16c131842/go.mod h1:PwE6iq8TiWJRI3zMGA1RtkFAnrDMK93dLA5SUeu0lH8= github.com/ipld/go-storethehash v0.0.1 h1:U9E9n3dE0IaImSNbRcUmm5Dk9UPiS9H0i+LmCFFGJBI= github.com/ipld/go-storethehash v0.0.1/go.mod h1:w8cQfWInks8lvvbQTiKbCPusU9v0sqiViBihTHbavpQ= github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52 h1:QG4CGBqCeuBo6aZlGAamSkxWdgWfZGeE49eUOWJPA4c= @@ -1193,8 +1159,6 @@ github.com/libp2p/go-libp2p-interface-connmgr v0.0.4/go.mod h1:GarlRLH0LdeWcLnYM github.com/libp2p/go-libp2p-interface-connmgr v0.0.5/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k= github.com/libp2p/go-libp2p-interface-pnet v0.0.1/go.mod h1:el9jHpQAXK5dnTpKA4yfCNBZXvrzdOU75zz+C6ryp3k= github.com/libp2p/go-libp2p-kad-dht v0.2.1/go.mod h1:k7ONOlup7HKzQ68dE6lSnp07cdxdkmnRa+6B4Fh9/w0= -github.com/libp2p/go-libp2p-kad-dht v0.11.1/go.mod h1:5ojtR2acDPqh/jXf5orWy8YGb8bHQDS+qeDcoscL/PI= -github.com/libp2p/go-libp2p-kad-dht v0.13.1/go.mod h1:iVdxmsKHVPQSCGPP4V/A+tDFCLsxrREZUBX8ohOcKDw= github.com/libp2p/go-libp2p-kad-dht v0.15.0 h1:Ke+Oj78gX5UDXnA6HBdrgvi+fStJxgYTDa51U0TsCLo= github.com/libp2p/go-libp2p-kad-dht v0.15.0/go.mod h1:rZtPxYu1TnHHz6n1RggdGrxUX/tA1C2/Wiw3ZMUDrU0= github.com/libp2p/go-libp2p-kbucket v0.2.1/go.mod h1:/Rtu8tqbJ4WQ2KTCOMJhggMukOLNLNPY1EtEWWLxUvc= @@ -1251,17 +1215,13 @@ github.com/libp2p/go-libp2p-pnet v0.2.0/go.mod h1:Qqvq6JH/oMZGwqs3N1Fqhv8NVhrdYc github.com/libp2p/go-libp2p-protocol v0.0.1/go.mod h1:Af9n4PiruirSDjHycM1QuiMi/1VZNHYcK8cLgFJLZ4s= github.com/libp2p/go-libp2p-protocol v0.1.0/go.mod h1:KQPHpAabB57XQxGrXCNvbL6UEXfQqUgC/1adR2Xtflk= github.com/libp2p/go-libp2p-pubsub v0.1.1/go.mod h1:ZwlKzRSe1eGvSIdU5bD7+8RZN/Uzw0t1Bp9R1znpR/Q= -github.com/libp2p/go-libp2p-pubsub v0.4.0/go.mod h1:izkeMLvz6Ht8yAISXjx60XUQZMq9ZMe5h2ih4dLIBIQ= -github.com/libp2p/go-libp2p-pubsub v0.5.4/go.mod h1:gVOzwebXVdSMDQBTfH8ACO5EJ4SQrvsHqCmYsCZpD0E= github.com/libp2p/go-libp2p-pubsub v0.5.6/go.mod h1:gVOzwebXVdSMDQBTfH8ACO5EJ4SQrvsHqCmYsCZpD0E= github.com/libp2p/go-libp2p-pubsub v0.6.0 h1:98+RXuEWW17U6cAijK1yaTf6mw/B+n5yPA421z+dlo0= github.com/libp2p/go-libp2p-pubsub v0.6.0/go.mod h1:nJv87QM2cU0w45KPR1rZicq+FmFIOD16zmT+ep1nOmg= -github.com/libp2p/go-libp2p-pubsub-router v0.4.0/go.mod h1:hs0j0ugcBjMOMgJ6diOlZM2rZEId/w5Gg86E+ac4SmQ= github.com/libp2p/go-libp2p-pubsub-router v0.5.0/go.mod h1:TRJKskSem3C0aSb3CmRgPwq6IleVFzds6hS09fmZbGM= github.com/libp2p/go-libp2p-quic-transport v0.1.1/go.mod h1:wqG/jzhF3Pu2NrhJEvE+IE0NTHNXslOPn9JQzyCAxzU= github.com/libp2p/go-libp2p-quic-transport v0.10.0/go.mod h1:RfJbZ8IqXIhxBRm5hqUEJqjiiY8xmEuq3HUDS993MkA= github.com/libp2p/go-libp2p-quic-transport v0.11.2/go.mod h1:wlanzKtIh6pHrq+0U3p3DY9PJfGqxMgPaGKaK5LifwQ= -github.com/libp2p/go-libp2p-quic-transport v0.12.0/go.mod h1:EKHqxZbWE/FhDJZ6ebyZ/4v3X9zyuuuKIN0XR9vANT0= github.com/libp2p/go-libp2p-quic-transport v0.13.0/go.mod h1:39/ZWJ1TW/jx1iFkKzzUg00W6tDJh73FC0xYudjr7Hc= github.com/libp2p/go-libp2p-quic-transport v0.15.0/go.mod h1:wv4uGwjcqe8Mhjj7N/Ic0aKjA+/10UnMlSzLO0yRpYQ= github.com/libp2p/go-libp2p-quic-transport v0.15.2 h1:wHBEceRy+1/8Ec8dAIyr+/P7L2YefIGprPVy5LrMM+k= @@ -1730,7 +1690,6 @@ github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQ github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.4.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.6.0/go.mod h1:ZLOG9ck3JLRdB5MgO8f+lLTe83AXG6ro35rLTxvnIl4= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU= github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU= @@ -1772,7 +1731,6 @@ github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/statsd_exporter v0.20.0/go.mod h1:YL3FWCG8JBBtaUSxAg4Gz2ZYu22bS84XM89ZQXXTWmQ= github.com/prometheus/statsd_exporter v0.21.0 h1:hA05Q5RFeIjgwKIYEdFd59xu5Wwaznf33yKI+pyX6T8= github.com/prometheus/statsd_exporter v0.21.0/go.mod h1:rbT83sZq2V+p73lHhPZfMc3MLCHmSHelCh9hSGYNLTQ= github.com/raulk/clock v1.1.0 h1:dpb29+UKMbLqiU/jqIJptgLR1nn23HLgMY0sTCDza5Y= @@ -2060,13 +2018,10 @@ go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/dig v1.10.0/go.mod h1:X34SnWGr8Fyla9zQNO2GSO2D+TIuqB14OS8JhYocIyw= go.uber.org/dig v1.12.0 h1:l1GQeZpEbss0/M4l/ZotuBndCrkMdjnygzgcuOjAdaY= go.uber.org/dig v1.12.0/go.mod h1:X34SnWGr8Fyla9zQNO2GSO2D+TIuqB14OS8JhYocIyw= -go.uber.org/fx v1.13.1/go.mod h1:bREWhavnedxpJeTq9pQT53BbvwhUv7TcpsOqcH4a+3w= go.uber.org/fx v1.15.0 h1:kcfBpAm98n0ksanyyZLFE/Q3T7yPi13Ge2liu3TxR+A= go.uber.org/fx v1.15.0/go.mod h1:jI3RazQUhGv5KkpZIRv+kuP4CcgX3fnc0qX8bLnzbx8= -go.uber.org/goleak v0.10.0/go.mod h1:VCZuO8V8mFPlL0F5J5GK1rtHV3DrFcQ1R8ryq7FK0aI= go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= @@ -2342,7 +2297,6 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2433,7 +2387,6 @@ golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191030062658-86caa796c7ab/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191114200427-caa0b0f7d508/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= diff --git a/testplans/lotus-soup/go.mod b/testplans/lotus-soup/go.mod index 6ba232cdc43..f7907c4b2e7 100644 --- a/testplans/lotus-soup/go.mod +++ b/testplans/lotus-soup/go.mod @@ -9,7 +9,7 @@ require ( github.com/drand/drand v1.3.0 github.com/filecoin-project/go-address v0.0.6 github.com/filecoin-project/go-data-transfer v1.12.1 - github.com/filecoin-project/go-fil-markets v1.14.2-0.20220112094113-068e7f35a0e0 + github.com/filecoin-project/go-fil-markets v1.15.0 github.com/filecoin-project/go-jsonrpc v0.1.5 github.com/filecoin-project/go-state-types v0.1.1 github.com/filecoin-project/go-storedcounter v0.1.0 diff --git a/testplans/lotus-soup/go.sum b/testplans/lotus-soup/go.sum index c53300eca59..8751bff12b5 100644 --- a/testplans/lotus-soup/go.sum +++ b/testplans/lotus-soup/go.sum @@ -38,7 +38,6 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE= -contrib.go.opencensus.io/exporter/prometheus v0.3.0/go.mod h1:rpCPVQKhiyH8oomWgm34ZmgIdZa8OVYO5WAIygPbBBE= contrib.go.opencensus.io/exporter/prometheus v0.4.0 h1:0QfIkj9z/iVZgK31D9H9ohjjIDApI2GOPScCKwxedbs= contrib.go.opencensus.io/exporter/prometheus v0.4.0/go.mod h1:o7cosnyfuPVK0tB8q0QmaQNhGnptITnPQB+z1+qeFB0= dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= @@ -426,8 +425,8 @@ github.com/filecoin-project/go-fil-commcid v0.1.0 h1:3R4ds1A9r6cr8mvZBfMYxTS88Oq github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7LXep5bFEVOVmQWHJvl2mgsGo= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8= -github.com/filecoin-project/go-fil-markets v1.14.2-0.20220112094113-068e7f35a0e0 h1:C3rdpJJQm8/UX3aAPNbVHzSEDjI9EvD1jb2eroA3aK8= -github.com/filecoin-project/go-fil-markets v1.14.2-0.20220112094113-068e7f35a0e0/go.mod h1:H1pk9szltDLCOvQW/6fy0ugvUnDY7CDCf9HJSGSoj60= +github.com/filecoin-project/go-fil-markets v1.15.0 h1:PjoALE+brZTdZCteaj05KXt4lP5eWVWDeZmfwVAXa4w= +github.com/filecoin-project/go-fil-markets v1.15.0/go.mod h1:d6oFs7L6NCIcjY0p31KjbKAEhc0WIn8dguxGGIdTiXo= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= @@ -436,7 +435,6 @@ github.com/filecoin-project/go-hamt-ipld/v3 v3.0.1/go.mod h1:gXpNmr3oQx8l3o7qkGy github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0 h1:rVVNq0x6RGQIzCo1iiJlGFm9AGIZzeifggxtKMU7zmI= github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0/go.mod h1:bxmzgT8tmeVQA1/gvBwFmYdT8SOFUwB3ovSUfG1Ux0g= github.com/filecoin-project/go-indexer-core v0.2.4/go.mod h1:MSe5aRWmfRB+5syR4yDV+OApgJU+MUJ4rl9VUuzwCfc= -github.com/filecoin-project/go-indexer-core v0.2.6/go.mod h1:wW5Ab0gJXL2vT4iEMbPUfPs773iMc86Q8GtfSEqmu3Y= github.com/filecoin-project/go-indexer-core v0.2.7 h1:D0egR6Q3Jkp5r4klxkdDQvjXeLx3cwZMKE55qop2xCI= github.com/filecoin-project/go-indexer-core v0.2.7/go.mod h1:6YD7KwDOQ+03DdAitviL7h1fksIU6a4j52yPnA/E1PU= github.com/filecoin-project/go-jsonrpc v0.1.5 h1:ckxqZ09ivBAVf5CSmxxrqqNHC7PJm3GYGtYKiNQ+vGk= @@ -465,7 +463,6 @@ github.com/filecoin-project/go-statestore v0.2.0 h1:cRRO0aPLrxKQCZ2UOQbzFGn4WDNd github.com/filecoin-project/go-statestore v0.2.0/go.mod h1:8sjBYbS35HwPzct7iT4lIXjLlYyPor80aU7t7a/Kspo= github.com/filecoin-project/go-storedcounter v0.1.0 h1:Mui6wSUBC+cQGHbDUBcO7rfh5zQkWJM/CpAZa/uOuus= github.com/filecoin-project/go-storedcounter v0.1.0/go.mod h1:4ceukaXi4vFURIoxYMfKzaRF5Xv/Pinh2oTnoxpv+z8= -github.com/filecoin-project/index-provider v0.1.1-0.20220107223914-37c38e2b284d/go.mod h1:pTZVxt9mF+YCYSfNsn7i0rwhoMBmbjfSDAQVoxWGP10= github.com/filecoin-project/index-provider v0.2.0 h1:r1VPVhtWrU5+6Mo6g2Ozr5NXWMFz1qHt0NKJzV5ELZ8= github.com/filecoin-project/index-provider v0.2.0/go.mod h1:eYiwZfJNadwn/8Grwn2e4nX2cH4PYl2k8SZqm9k+eCA= github.com/filecoin-project/specs-actors v0.9.13/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= @@ -491,7 +488,6 @@ github.com/filecoin-project/specs-actors/v7 v7.0.0-20211230214648-aeae366b083a h github.com/filecoin-project/specs-actors/v7 v7.0.0-20211230214648-aeae366b083a/go.mod h1:p6LIOFezA1rgRLMewbvdi3Pp6SAu+q9FtJ9CAleSjrE= github.com/filecoin-project/specs-storage v0.1.1-0.20211228030229-6d460d25a0c9 h1:oUYOvF7EvdXS0Zmk9mNkaB6Bu0l+WXBYPzVodKMiLug= github.com/filecoin-project/specs-storage v0.1.1-0.20211228030229-6d460d25a0c9/go.mod h1:Tb88Zq+IBJbvAn3mS89GYj3jdRThBTE/771HCVZdRJU= -github.com/filecoin-project/storetheindex v0.2.0/go.mod h1:P3Hd3sIWEkBU1fPnE49Y8nh/mdErOdIfiHBb85QAWfg= github.com/filecoin-project/storetheindex v0.2.1 h1:jhsMh5O52bBU/NrnjJs2iLPI92T38kjlU9bk/dP0sts= github.com/filecoin-project/storetheindex v0.2.1/go.mod h1:Tc5mYdAnGUzly40cuo35yITDD3XhF9EX5BO7evGsJ5M= github.com/filecoin-project/test-vectors/schema v0.0.5/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E= @@ -514,7 +510,6 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= -github.com/gabriel-vasile/mimetype v1.1.2/go.mod h1:6CDPel/o/3/s4+bp6kIbsWATq8pmgOisOPG40CJa6To= github.com/gabriel-vasile/mimetype v1.4.0/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8= github.com/gammazero/keymutex v0.0.2 h1:cmpLBJHdEwn+WlR5Z/o9/BN92znSZTp5AKPQDpu1QcI= github.com/gammazero/keymutex v0.0.2/go.mod h1:qtzWCCLMisQUmVa4dvqHVgwfh4BP2YB7JxNDGXnsKrs= @@ -752,7 +747,6 @@ github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+u github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= -github.com/google/gopacket v1.1.18/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= @@ -915,10 +909,8 @@ github.com/ipfs/go-bitfield v1.0.0/go.mod h1:N/UiujQy+K+ceU1EF5EkVd1TNqevLrCQMIc github.com/ipfs/go-bitswap v0.0.9/go.mod h1:kAPf5qgn2W2DrgAcscZ3HrM9qh4pH+X8Fkk3UPrwvis= github.com/ipfs/go-bitswap v0.1.0/go.mod h1:FFJEf18E9izuCqUtHxbWEvq+reg7o4CW5wSAE1wsxj0= github.com/ipfs/go-bitswap v0.1.2/go.mod h1:qxSWS4NXGs7jQ6zQvoPY3+NmOfHHG47mhkiLzBpJQIs= -github.com/ipfs/go-bitswap v0.1.3/go.mod h1:YEQlFy0kkxops5Vy+OxWdRSEZIoS7I7KDIwoa5Chkps= github.com/ipfs/go-bitswap v0.1.8/go.mod h1:TOWoxllhccevbWFUR2N7B1MTSVVge1s6XSMiCSA4MzM= github.com/ipfs/go-bitswap v0.3.4/go.mod h1:4T7fvNv/LmOys+21tnLzGKncMeeXUYUd1nUiJ2teMvI= -github.com/ipfs/go-bitswap v0.4.0/go.mod h1:J2sAsp9UKxLgHDektSy3y3Q9OfQjM9sjhKBR1dlwrMg= github.com/ipfs/go-bitswap v0.5.1 h1:721YAEDBnLIrvcIMkCHCdqp34hA8jwL9yKMkyJpSpco= github.com/ipfs/go-bitswap v0.5.1/go.mod h1:P+ckC87ri1xFLvk74NlXdP0Kj9RmWAh4+H78sC6Qopo= github.com/ipfs/go-block-format v0.0.1/go.mod h1:DK/YYcsSUIVAFNwo/KZCdIIbpN0ROH/baNLgayt4pFc= @@ -927,7 +919,6 @@ github.com/ipfs/go-block-format v0.0.3 h1:r8t66QstRp/pd/or4dpnbVfXT5Gt7lOqRvC+/d github.com/ipfs/go-block-format v0.0.3/go.mod h1:4LmD4ZUw0mhO+JSKdpWwrzATiEfM7WWgQ8H5l6P8MVk= github.com/ipfs/go-blockservice v0.0.7/go.mod h1:EOfb9k/Y878ZTRY/CH0x5+ATtaipfbRhbvNSdgc/7So= github.com/ipfs/go-blockservice v0.1.0/go.mod h1:hzmMScl1kXHg3M2BjTymbVPjv627N7sYcvYaKbop39M= -github.com/ipfs/go-blockservice v0.1.1/go.mod h1:t+411r7psEUhLueM8C7aPA7cxCclv4O3VsUVxt9kz2I= github.com/ipfs/go-blockservice v0.1.3/go.mod h1:OTZhFpkgY48kNzbgyvcexW9cHrpjBYIjSR0KoDOFOLU= github.com/ipfs/go-blockservice v0.1.4/go.mod h1:OTZhFpkgY48kNzbgyvcexW9cHrpjBYIjSR0KoDOFOLU= github.com/ipfs/go-blockservice v0.1.7/go.mod h1:GmS+BAt4hrwBKkzE11AFDQUrnvqjwFatGS2MY7wOjEM= @@ -950,7 +941,6 @@ github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAK github.com/ipfs/go-datastore v0.0.5/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= github.com/ipfs/go-datastore v0.1.0/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= github.com/ipfs/go-datastore v0.1.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= -github.com/ipfs/go-datastore v0.3.0/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= github.com/ipfs/go-datastore v0.3.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= github.com/ipfs/go-datastore v0.4.0/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= github.com/ipfs/go-datastore v0.4.1/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= @@ -975,7 +965,6 @@ github.com/ipfs/go-ds-badger v0.3.0 h1:xREL3V0EH9S219kFFueOYJJTcjgNSZ2HY1iSvN7U1 github.com/ipfs/go-ds-badger v0.3.0/go.mod h1:1ke6mXNqeV8K3y5Ak2bAA0osoTfmxUdupVCGm4QUIek= github.com/ipfs/go-ds-badger2 v0.1.2 h1:sQc2q1gaXrv8YFNeUtxil0neuyDf9hnVHfLsi7lpXfE= github.com/ipfs/go-ds-badger2 v0.1.2/go.mod h1:3FtQmDv6fMubygEfU43bsFelYpIiXX/XEYA54l9eCwg= -github.com/ipfs/go-ds-flatfs v0.4.5/go.mod h1:e4TesLyZoA8k1gV/yCuBTnt2PJtypn4XUlB5n8KQMZY= github.com/ipfs/go-ds-flatfs v0.5.1/go.mod h1:RWTV7oZD/yZYBKdbVIFXTX2fdY2Tbvl94NsWqmoyAX4= github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= github.com/ipfs/go-ds-leveldb v0.1.0/go.mod h1:hqAW8y4bwX5LWcCtku2rFNX3vjDZCy5LZCg+cSZvYb8= @@ -983,24 +972,20 @@ github.com/ipfs/go-ds-leveldb v0.4.1/go.mod h1:jpbku/YqBSsBc1qgME8BkWS4AxzF2cEu1 github.com/ipfs/go-ds-leveldb v0.4.2/go.mod h1:jpbku/YqBSsBc1qgME8BkWS4AxzF2cEu1Ii2r79Hh9s= github.com/ipfs/go-ds-leveldb v0.5.0 h1:s++MEBbD3ZKc9/8/njrn4flZLnCuY9I79v94gBUNumo= github.com/ipfs/go-ds-leveldb v0.5.0/go.mod h1:d3XG9RUDzQ6V4SHi8+Xgj9j1XuEk1z82lquxrVbml/Q= -github.com/ipfs/go-ds-measure v0.1.0/go.mod h1:1nDiFrhLlwArTME1Ees2XaBOl49OoCgd2A3f8EchMSY= github.com/ipfs/go-ds-measure v0.2.0 h1:sG4goQe0KDTccHMyT45CY1XyUbxe5VwTKpg2LjApYyQ= github.com/ipfs/go-ds-measure v0.2.0/go.mod h1:SEUD/rE2PwRa4IQEC5FuNAmjJCyYObZr9UvVh8V3JxE= github.com/ipfs/go-fetcher v1.5.0/go.mod h1:5pDZ0393oRF/fHiLmtFZtpMNBQfHOYNPtryWedVuSWE= github.com/ipfs/go-fetcher v1.6.1/go.mod h1:27d/xMV8bodjVs9pugh/RCjjK2OZ68UgAMspMdingNo= -github.com/ipfs/go-filestore v0.0.3/go.mod h1:dvXRykFzyyXN2CdNlRGzDAkXMDPyI+D7JE066SiKLSE= github.com/ipfs/go-filestore v0.1.0/go.mod h1:0KTrzoJnJ3sJDEDM09Vq8nz8H475rRyeq4i0n/bpF00= github.com/ipfs/go-filestore v1.1.0 h1:Pu4tLBi1bucu6/HU9llaOmb9yLFk/sgP+pW764zNDoE= github.com/ipfs/go-filestore v1.1.0/go.mod h1:6e1/5Y6NvLuCRdmda/KA4GUhXJQ3Uat6vcWm2DJfxc8= github.com/ipfs/go-fs-lock v0.0.6/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28L7zESmM= github.com/ipfs/go-fs-lock v0.0.7 h1:6BR3dajORFrFTkb5EpCUFIAypsoxpGpDSVUdFwzgL9U= github.com/ipfs/go-fs-lock v0.0.7/go.mod h1:Js8ka+FNYmgQRLrRXzU3CB/+Csr1BwrRilEcvYrHhhc= -github.com/ipfs/go-graphsync v0.8.0/go.mod h1:CLxN859dUTcXCav1DvNvmAUWPZfmNLjlGLJYy+c3dlM= github.com/ipfs/go-graphsync v0.10.0/go.mod h1:cKIshzTaa5rCZjryH5xmSKZVGX9uk1wvwGvz2WEha5Y= github.com/ipfs/go-graphsync v0.11.0/go.mod h1:wC+c8vGVjAHthsVIl8LKr37cUra2GOaMYcQNNmMxDqE= github.com/ipfs/go-graphsync v0.11.5 h1:WA5hVxGBtcal6L6nqubKiqRolaZxbexOK3GumGFJRR4= github.com/ipfs/go-graphsync v0.11.5/go.mod h1:+/sZqRwRCQRrV7NCzgBtufmr5QGpUE98XSa7NlsztmM= -github.com/ipfs/go-ipfs v0.10.0/go.mod h1:HsnRkQdpruG6JMaycJyrlLwJdduw1dJv2rEPgWxdJvA= github.com/ipfs/go-ipfs v0.11.0/go.mod h1:g68Thu2Ho11AWoHsN34P5fSK7iA6OWWRy3T/g8HLixc= github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08= github.com/ipfs/go-ipfs-blockstore v0.1.0/go.mod h1:5aD0AvHPi7mZc6Ci1WCAhiBQu2IsfTduLl+422H6Rqw= @@ -1023,7 +1008,6 @@ github.com/ipfs/go-ipfs-cmds v0.3.0/go.mod h1:ZgYiWVnCk43ChwoH8hAmI1IRbuVtq3GSTH github.com/ipfs/go-ipfs-cmds v0.6.0 h1:yAxdowQZzoFKjcLI08sXVNnqVj3jnABbf9smrPQmBsw= github.com/ipfs/go-ipfs-cmds v0.6.0/go.mod h1:ZgYiWVnCk43ChwoH8hAmI1IRbuVtq3GSTHwtRB/Kqhk= github.com/ipfs/go-ipfs-config v0.5.3/go.mod h1:nSLCFtlaL+2rbl3F+9D4gQZQbT1LjRKx7TJg/IHz6oM= -github.com/ipfs/go-ipfs-config v0.16.0/go.mod h1:wz2lKzOjgJeYJa6zx8W9VT7mz+iSd0laBMqS/9wmX6A= github.com/ipfs/go-ipfs-config v0.18.0 h1:Ta1aNGNEq6RIvzbw7dqzCVZJKb7j+Dd35JFnAOCpT8g= github.com/ipfs/go-ipfs-config v0.18.0/go.mod h1:wz2lKzOjgJeYJa6zx8W9VT7mz+iSd0laBMqS/9wmX6A= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= @@ -1048,14 +1032,12 @@ github.com/ipfs/go-ipfs-files v0.0.9/go.mod h1:aFv2uQ/qxWpL/6lidWvnSQmaVqCrf0TBG github.com/ipfs/go-ipfs-http-client v0.0.6 h1:k2QllZyP7Fz5hMgsX5hvHfn1WPG9Ngdy5WknQ7JNhBM= github.com/ipfs/go-ipfs-http-client v0.0.6/go.mod h1:8e2dQbntMZKxLfny+tyXJ7bJHZFERp/2vyzZdvkeLMc= github.com/ipfs/go-ipfs-keystore v0.0.2/go.mod h1:H49tRmibOEs7gLMgbOsjC4dqh1u5e0R/SWuc2ScfgSo= -github.com/ipfs/go-ipfs-pinner v0.1.2/go.mod h1:/u9kMe+TyQybN21O5OBicdyx3x93lVI77PCtiTnArUk= github.com/ipfs/go-ipfs-pinner v0.2.1/go.mod h1:l1AtLL5bovb7opnG77sh4Y10waINz3Y1ni6CvTzx7oo= github.com/ipfs/go-ipfs-posinfo v0.0.1 h1:Esoxj+1JgSjX0+ylc0hUmJCOv6V2vFoZiETLR6OtpRs= github.com/ipfs/go-ipfs-posinfo v0.0.1/go.mod h1:SwyeVP+jCwiDu0C313l/8jg6ZxM0qqtlt2a0vILTc1A= github.com/ipfs/go-ipfs-pq v0.0.1/go.mod h1:LWIqQpqfRG3fNc5XsnIhz/wQ2XXGyugQwls7BgUmUfY= github.com/ipfs/go-ipfs-pq v0.0.2 h1:e1vOOW6MuOwG2lqxcLA+wEn93i/9laCY8sXAw76jFOY= github.com/ipfs/go-ipfs-pq v0.0.2/go.mod h1:LWIqQpqfRG3fNc5XsnIhz/wQ2XXGyugQwls7BgUmUfY= -github.com/ipfs/go-ipfs-provider v0.6.1/go.mod h1:I4Cig3InhftbRJohph76Qy/P2uKEZILNGiKvDJmmC28= github.com/ipfs/go-ipfs-provider v0.7.1/go.mod h1:QwdDYRYnC5sYGLlOwVDY/0ZB6T3zcMtu+5+GdGeUuw8= github.com/ipfs/go-ipfs-routing v0.0.1/go.mod h1:k76lf20iKFxQTjcJokbPM9iBXVXVZhcOwc360N4nuKs= github.com/ipfs/go-ipfs-routing v0.1.0/go.mod h1:hYoUkJLyAUKhF58tysKpids8RNDPO42BVMgK5dNsoqY= @@ -1079,8 +1061,6 @@ github.com/ipfs/go-ipld-git v0.1.1/go.mod h1:+VyMqF5lMcJh4rwEppV0e6g4nCCHXThLYYD github.com/ipfs/go-ipld-legacy v0.1.0/go.mod h1:86f5P/srAmh9GcIcWQR9lfFLZPrIyyXQeVlOWeeWEuI= github.com/ipfs/go-ipld-legacy v0.1.1 h1:BvD8PEuqwBHLTKqlGFTHSwrwFOMkVESEvwIYwR2cdcc= github.com/ipfs/go-ipld-legacy v0.1.1/go.mod h1:8AyKFCjgRPsQFf15ZQgDB8Din4DML/fOmKZkkFkrIEg= -github.com/ipfs/go-ipns v0.0.2/go.mod h1:WChil4e0/m9cIINWLxZe1Jtf77oz5L05rO2ei/uKJ5U= -github.com/ipfs/go-ipns v0.1.0/go.mod h1:3IbsuPkR6eAGcnx+E7j6HpOSbSQJPZ6zlRj+NK3jPxQ= github.com/ipfs/go-ipns v0.1.2 h1:O/s/0ht+4Jl9+VoxoUo0zaHjnZUS+aBQIKTuzdZ/ucI= github.com/ipfs/go-ipns v0.1.2/go.mod h1:ioQ0j02o6jdIVW+bmi18f4k2gRf0AV3kZ9KeHYHICnQ= github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= @@ -1104,11 +1084,8 @@ github.com/ipfs/go-log/v2 v2.3.0/go.mod h1:QqGoj30OTpnKaG/LKTGTxoP2mmQtjVMEnK72g github.com/ipfs/go-log/v2 v2.4.0 h1:iR/2o9PGWanVJrBgIH5Ff8mPGOwpqLaPIAFqSnsdlzk= github.com/ipfs/go-log/v2 v2.4.0/go.mod h1:nPZnh7Cj7lwS3LpRU5Mwr2ol1c2gXIEXuF6aywqrtmo= github.com/ipfs/go-merkledag v0.0.6/go.mod h1:QYPdnlvkOg7GnQRofu9XZimC5ZW5Wi3bKys/4GQQfto= -github.com/ipfs/go-merkledag v0.1.0/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= github.com/ipfs/go-merkledag v0.2.3/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= github.com/ipfs/go-merkledag v0.2.4/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= -github.com/ipfs/go-merkledag v0.3.0/go.mod h1:4pymaZLhSLNVuiCITYrpViD6vmfZ/Ws4n/L9tfNv3S4= -github.com/ipfs/go-merkledag v0.3.1/go.mod h1:fvkZNNZixVW6cKSZ/JfLlON5OlgTXNdRLz0p6QG/I2M= github.com/ipfs/go-merkledag v0.3.2/go.mod h1:fvkZNNZixVW6cKSZ/JfLlON5OlgTXNdRLz0p6QG/I2M= github.com/ipfs/go-merkledag v0.4.0/go.mod h1:XshXBkhyeS63YNGisLL1uDSfuTyrQIxVUOg3ojR5MOE= github.com/ipfs/go-merkledag v0.5.1 h1:tr17GPP5XtPhvPPiWtu20tSGZiZDuTaJRXBLcr79Umk= @@ -1116,9 +1093,7 @@ github.com/ipfs/go-merkledag v0.5.1/go.mod h1:cLMZXx8J08idkp5+id62iVftUQV+HlYJ3P github.com/ipfs/go-metrics-interface v0.0.1 h1:j+cpbjYvu4R8zbleSs36gvB7jR+wsL2fGD6n0jO4kdg= github.com/ipfs/go-metrics-interface v0.0.1/go.mod h1:6s6euYU4zowdslK0GKHmqaIZ3j/b/tL7HTWtJ4VPgWY= github.com/ipfs/go-metrics-prometheus v0.0.2/go.mod h1:ELLU99AQQNi+zX6GCGm2lAgnzdSH3u5UVlCdqSXnEks= -github.com/ipfs/go-mfs v0.1.2/go.mod h1:T1QBiZPEpkPLzDqEJLNnbK55BVKVlNi2a+gVm4diFo0= github.com/ipfs/go-mfs v0.2.1/go.mod h1:Woj80iuw4ajDnIP6+seRaoHpPsc9hmL0pk/nDNDWP88= -github.com/ipfs/go-namesys v0.3.1/go.mod h1:/BL4xk8LP5Lq82AmaRKyxZv/eYRlumNiU9SZUe1Hlps= github.com/ipfs/go-namesys v0.4.0/go.mod h1:jpJwzodyP8DZdWN6DShRjVZw6gaqMr4nQLBSxU5cR6E= github.com/ipfs/go-path v0.0.7 h1:H06hKMquQ0aYtHiHryOMLpQC1qC3QwXwkahcEVD51Ho= github.com/ipfs/go-path v0.0.7/go.mod h1:6KTKmeRnBXgqrTvzFrPV3CamxcgvXX/4z79tfAd2Sno= @@ -1126,16 +1101,13 @@ github.com/ipfs/go-peertaskqueue v0.0.4/go.mod h1:03H8fhyeMfKNFWqzYEVyMbcPUeYrqP github.com/ipfs/go-peertaskqueue v0.1.0/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= github.com/ipfs/go-peertaskqueue v0.1.1/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= github.com/ipfs/go-peertaskqueue v0.2.0/go.mod h1:5/eNrBEbtSKWCG+kQK8K8fGNixoYUnr+P7jivavs9lY= -github.com/ipfs/go-peertaskqueue v0.4.0/go.mod h1:KL9F49hXJMoXCad8e5anivjN+kWdr+CyGcyh4K6doLc= github.com/ipfs/go-peertaskqueue v0.7.0/go.mod h1:M/akTIE/z1jGNXMU7kFB4TeSEFvj68ow0Rrb04donIU= github.com/ipfs/go-peertaskqueue v0.7.1 h1:7PLjon3RZwRQMgOTvYccZ+mjzkmds/7YzSWKFlBAypE= github.com/ipfs/go-peertaskqueue v0.7.1/go.mod h1:M/akTIE/z1jGNXMU7kFB4TeSEFvj68ow0Rrb04donIU= github.com/ipfs/go-pinning-service-http-client v0.1.0/go.mod h1:tcCKmlkWWH9JUUkKs8CrOZBanacNc1dmKLfjlyXAMu4= github.com/ipfs/go-todocounter v0.0.1/go.mod h1:l5aErvQc8qKE2r7NDMjmq5UNAvuZy0rC8BHOplkWvZ4= -github.com/ipfs/go-unixfs v0.1.0/go.mod h1:lysk5ELhOso8+Fed9U1QTGey2ocsfaZ18h0NCO2Fj9s= github.com/ipfs/go-unixfs v0.2.2-0.20190827150610-868af2e9e5cb/go.mod h1:IwAAgul1UQIcNZzKPYZWOCijryFBeCV79cNubPzol+k= github.com/ipfs/go-unixfs v0.2.4/go.mod h1:SUdisfUjNoSDzzhGVxvCL9QO/nKdwXdr+gbMUdqcbYw= -github.com/ipfs/go-unixfs v0.2.5/go.mod h1:SUdisfUjNoSDzzhGVxvCL9QO/nKdwXdr+gbMUdqcbYw= github.com/ipfs/go-unixfs v0.2.6/go.mod h1:GTTzQvaZsTZARdNkkdjDKFFnBhmO3e5mIM1PkH/x4p0= github.com/ipfs/go-unixfs v0.3.1 h1:LrfED0OGfG98ZEegO4/xiprx2O+yS+krCMQSp7zLVv8= github.com/ipfs/go-unixfs v0.3.1/go.mod h1:h4qfQYzghiIc8ZNFKiLMFWOTzrWIAtzYQ59W/pCFf1o= @@ -1143,17 +1115,14 @@ github.com/ipfs/go-unixfsnode v1.1.3/go.mod h1:ZZxUM5wXBC+G0Co9FjrYTOm+UlhZTjxLf github.com/ipfs/go-verifcid v0.0.1 h1:m2HI7zIuR5TFyQ1b79Da5N9dnnCP1vcu2QqawmWlK2E= github.com/ipfs/go-verifcid v0.0.1/go.mod h1:5Hrva5KBeIog4A+UpqlaIU+DEstipcJYQQZc0g37pY0= github.com/ipfs/interface-go-ipfs-core v0.4.0/go.mod h1:UJBcU6iNennuI05amq3FQ7g0JHUkibHFAfhfUIy927o= -github.com/ipfs/interface-go-ipfs-core v0.5.1/go.mod h1:lNBJrdXHtWS46evMPBdWtDQMDsrKcGbxCOGoKLkztOE= github.com/ipfs/interface-go-ipfs-core v0.5.2 h1:m1/5U+WpOK2ZE7Qzs5iIu80QM1ZA3aWYi2Ilwpi+tdg= github.com/ipfs/interface-go-ipfs-core v0.5.2/go.mod h1:lNBJrdXHtWS46evMPBdWtDQMDsrKcGbxCOGoKLkztOE= github.com/ipfs/iptb v1.4.0 h1:YFYTrCkLMRwk/35IMyC6+yjoQSHTEcNcefBStLJzgvo= github.com/ipfs/iptb v1.4.0/go.mod h1:1rzHpCYtNp87/+hTxG5TfCVn/yMY3dKnLn8tBiMfdmg= github.com/ipfs/iptb-plugins v0.3.0 h1:C1rpq1o5lUZtaAOkLIox5akh6ba4uk/3RwWc6ttVxw0= github.com/ipfs/iptb-plugins v0.3.0/go.mod h1:5QtOvckeIw4bY86gSH4fgh3p3gCSMn3FmIKr4gaBncA= -github.com/ipfs/tar-utils v0.0.1/go.mod h1:ACflm9wXvV9w0eMJt6yYXxS2zuIV+yXGNwbuq1bhLeE= github.com/ipfs/tar-utils v0.0.2/go.mod h1:4qlnRWgTVljIMhSG2SqRYn66NT+3wrv/kZt9V+eqxDM= github.com/ipld/go-car v0.1.0/go.mod h1:RCWzaUh2i4mOEkB3W45Vc+9jnS/M6Qay5ooytiBHl3g= -github.com/ipld/go-car v0.3.1/go.mod h1:dPkEWeAK8KaVvH5TahaCs6Mncpd4lDMpkbs0/SPzuVs= github.com/ipld/go-car v0.3.2/go.mod h1:WEjynkVt04dr0GwJhry0KlaTeSDEiEYyMPOxDBQ17KE= github.com/ipld/go-car v0.3.3-0.20211210032800-e6f244225a16/go.mod h1:/wkKF4908ULT4dFIFIUZYcfjAnj+KFnJvlh8Hsz1FbQ= github.com/ipld/go-car v0.3.3 h1:D6y+jvg9h2ZSv7GLUMWUwg5VTLy1E7Ak+uQw5orOg3I= @@ -1168,9 +1137,7 @@ github.com/ipld/go-ipld-prime v0.9.0/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/j github.com/ipld/go-ipld-prime v0.9.1-0.20210324083106-dc342a9917db/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= github.com/ipld/go-ipld-prime v0.10.0/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= github.com/ipld/go-ipld-prime v0.11.0/go.mod h1:+WIAkokurHmZ/KwzDOMUuoeJgaRQktHtEaLglS3ZeV8= -github.com/ipld/go-ipld-prime v0.12.2/go.mod h1:PaeLYq8k6dJLmDUSLrzkEpoGV4PEfe/1OtFN/eALOc8= github.com/ipld/go-ipld-prime v0.12.3/go.mod h1:PaeLYq8k6dJLmDUSLrzkEpoGV4PEfe/1OtFN/eALOc8= -github.com/ipld/go-ipld-prime v0.12.4-0.20211026094848-168715526f2d/go.mod h1:JUI6cS52J83Tz5li0Zl6M2tDX4r5x68Y77K1fbXHFYo= github.com/ipld/go-ipld-prime v0.14.0/go.mod h1:9ASQLwUFLptCov6lIYc70GRB4V7UTyLD0IJtrDJe6ZM= github.com/ipld/go-ipld-prime v0.14.1/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= github.com/ipld/go-ipld-prime v0.14.2/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= @@ -1183,7 +1150,6 @@ github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20211210234204-ce2a1c70cd github.com/ipld/go-ipld-selector-text-lite v0.0.1 h1:lNqFsQpBHc3p5xHob2KvEg/iM5dIFn6iw4L/Hh+kS1Y= github.com/ipld/go-ipld-selector-text-lite v0.0.1/go.mod h1:U2CQmFb+uWzfIEF3I1arrDa5rwtj00PrpiwwCO+k1RM= github.com/ipld/go-storethehash v0.0.0-20210915160027-d72ca9b0968c/go.mod h1:PwE6iq8TiWJRI3zMGA1RtkFAnrDMK93dLA5SUeu0lH8= -github.com/ipld/go-storethehash v0.0.0-20211122175924-41b16c131842/go.mod h1:PwE6iq8TiWJRI3zMGA1RtkFAnrDMK93dLA5SUeu0lH8= github.com/ipld/go-storethehash v0.0.1 h1:U9E9n3dE0IaImSNbRcUmm5Dk9UPiS9H0i+LmCFFGJBI= github.com/ipld/go-storethehash v0.0.1/go.mod h1:w8cQfWInks8lvvbQTiKbCPusU9v0sqiViBihTHbavpQ= github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52 h1:QG4CGBqCeuBo6aZlGAamSkxWdgWfZGeE49eUOWJPA4c= @@ -1440,8 +1406,6 @@ github.com/libp2p/go-libp2p-interface-connmgr v0.0.4/go.mod h1:GarlRLH0LdeWcLnYM github.com/libp2p/go-libp2p-interface-connmgr v0.0.5/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k= github.com/libp2p/go-libp2p-interface-pnet v0.0.1/go.mod h1:el9jHpQAXK5dnTpKA4yfCNBZXvrzdOU75zz+C6ryp3k= github.com/libp2p/go-libp2p-kad-dht v0.2.1/go.mod h1:k7ONOlup7HKzQ68dE6lSnp07cdxdkmnRa+6B4Fh9/w0= -github.com/libp2p/go-libp2p-kad-dht v0.11.1/go.mod h1:5ojtR2acDPqh/jXf5orWy8YGb8bHQDS+qeDcoscL/PI= -github.com/libp2p/go-libp2p-kad-dht v0.13.1/go.mod h1:iVdxmsKHVPQSCGPP4V/A+tDFCLsxrREZUBX8ohOcKDw= github.com/libp2p/go-libp2p-kad-dht v0.15.0 h1:Ke+Oj78gX5UDXnA6HBdrgvi+fStJxgYTDa51U0TsCLo= github.com/libp2p/go-libp2p-kad-dht v0.15.0/go.mod h1:rZtPxYu1TnHHz6n1RggdGrxUX/tA1C2/Wiw3ZMUDrU0= github.com/libp2p/go-libp2p-kbucket v0.2.1/go.mod h1:/Rtu8tqbJ4WQ2KTCOMJhggMukOLNLNPY1EtEWWLxUvc= @@ -1501,12 +1465,9 @@ github.com/libp2p/go-libp2p-protocol v0.0.1/go.mod h1:Af9n4PiruirSDjHycM1QuiMi/1 github.com/libp2p/go-libp2p-protocol v0.1.0/go.mod h1:KQPHpAabB57XQxGrXCNvbL6UEXfQqUgC/1adR2Xtflk= github.com/libp2p/go-libp2p-pubsub v0.1.1/go.mod h1:ZwlKzRSe1eGvSIdU5bD7+8RZN/Uzw0t1Bp9R1znpR/Q= github.com/libp2p/go-libp2p-pubsub v0.3.2/go.mod h1:Uss7/Cfz872KggNb+doCVPHeCDmXB7z500m/R8DaAUk= -github.com/libp2p/go-libp2p-pubsub v0.4.0/go.mod h1:izkeMLvz6Ht8yAISXjx60XUQZMq9ZMe5h2ih4dLIBIQ= -github.com/libp2p/go-libp2p-pubsub v0.5.4/go.mod h1:gVOzwebXVdSMDQBTfH8ACO5EJ4SQrvsHqCmYsCZpD0E= github.com/libp2p/go-libp2p-pubsub v0.5.6/go.mod h1:gVOzwebXVdSMDQBTfH8ACO5EJ4SQrvsHqCmYsCZpD0E= github.com/libp2p/go-libp2p-pubsub v0.6.0 h1:98+RXuEWW17U6cAijK1yaTf6mw/B+n5yPA421z+dlo0= github.com/libp2p/go-libp2p-pubsub v0.6.0/go.mod h1:nJv87QM2cU0w45KPR1rZicq+FmFIOD16zmT+ep1nOmg= -github.com/libp2p/go-libp2p-pubsub-router v0.4.0/go.mod h1:hs0j0ugcBjMOMgJ6diOlZM2rZEId/w5Gg86E+ac4SmQ= github.com/libp2p/go-libp2p-pubsub-router v0.5.0/go.mod h1:TRJKskSem3C0aSb3CmRgPwq6IleVFzds6hS09fmZbGM= github.com/libp2p/go-libp2p-pubsub-tracer v0.0.0-20200626141350-e730b32bf1e6 h1:2lH7rMlvDPSvXeOR+g7FE6aqiEwxtpxWKQL8uigk5fQ= github.com/libp2p/go-libp2p-pubsub-tracer v0.0.0-20200626141350-e730b32bf1e6/go.mod h1:8ZodgKS4qRLayfw9FDKDd9DX4C16/GMofDxSldG8QPI= @@ -1514,7 +1475,6 @@ github.com/libp2p/go-libp2p-quic-transport v0.1.1/go.mod h1:wqG/jzhF3Pu2NrhJEvE+ github.com/libp2p/go-libp2p-quic-transport v0.5.0/go.mod h1:IEcuC5MLxvZ5KuHKjRu+dr3LjCT1Be3rcD/4d8JrX8M= github.com/libp2p/go-libp2p-quic-transport v0.10.0/go.mod h1:RfJbZ8IqXIhxBRm5hqUEJqjiiY8xmEuq3HUDS993MkA= github.com/libp2p/go-libp2p-quic-transport v0.11.2/go.mod h1:wlanzKtIh6pHrq+0U3p3DY9PJfGqxMgPaGKaK5LifwQ= -github.com/libp2p/go-libp2p-quic-transport v0.12.0/go.mod h1:EKHqxZbWE/FhDJZ6ebyZ/4v3X9zyuuuKIN0XR9vANT0= github.com/libp2p/go-libp2p-quic-transport v0.13.0/go.mod h1:39/ZWJ1TW/jx1iFkKzzUg00W6tDJh73FC0xYudjr7Hc= github.com/libp2p/go-libp2p-quic-transport v0.15.0/go.mod h1:wv4uGwjcqe8Mhjj7N/Ic0aKjA+/10UnMlSzLO0yRpYQ= github.com/libp2p/go-libp2p-quic-transport v0.15.2 h1:wHBEceRy+1/8Ec8dAIyr+/P7L2YefIGprPVy5LrMM+k= @@ -2026,7 +1986,6 @@ github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeD github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.4.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.6.0/go.mod h1:ZLOG9ck3JLRdB5MgO8f+lLTe83AXG6ro35rLTxvnIl4= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU= github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU= @@ -2070,7 +2029,6 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/prometheus v0.0.0-20200609090129-a6600f564e3c/go.mod h1:S5n0C6tSgdnwWshBUceRx5G1OsjLv/EeZ9t3wIfEtsY= -github.com/prometheus/statsd_exporter v0.20.0/go.mod h1:YL3FWCG8JBBtaUSxAg4Gz2ZYu22bS84XM89ZQXXTWmQ= github.com/prometheus/statsd_exporter v0.21.0 h1:hA05Q5RFeIjgwKIYEdFd59xu5Wwaznf33yKI+pyX6T8= github.com/prometheus/statsd_exporter v0.21.0/go.mod h1:rbT83sZq2V+p73lHhPZfMc3MLCHmSHelCh9hSGYNLTQ= github.com/raulk/clock v1.1.0 h1:dpb29+UKMbLqiU/jqIJptgLR1nn23HLgMY0sTCDza5Y= @@ -2392,13 +2350,10 @@ go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/dig v1.10.0/go.mod h1:X34SnWGr8Fyla9zQNO2GSO2D+TIuqB14OS8JhYocIyw= go.uber.org/dig v1.12.0 h1:l1GQeZpEbss0/M4l/ZotuBndCrkMdjnygzgcuOjAdaY= go.uber.org/dig v1.12.0/go.mod h1:X34SnWGr8Fyla9zQNO2GSO2D+TIuqB14OS8JhYocIyw= -go.uber.org/fx v1.13.1/go.mod h1:bREWhavnedxpJeTq9pQT53BbvwhUv7TcpsOqcH4a+3w= go.uber.org/fx v1.15.0 h1:kcfBpAm98n0ksanyyZLFE/Q3T7yPi13Ge2liu3TxR+A= go.uber.org/fx v1.15.0/go.mod h1:jI3RazQUhGv5KkpZIRv+kuP4CcgX3fnc0qX8bLnzbx8= -go.uber.org/goleak v0.10.0/go.mod h1:VCZuO8V8mFPlL0F5J5GK1rtHV3DrFcQ1R8ryq7FK0aI= go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= @@ -2814,7 +2769,6 @@ golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191030062658-86caa796c7ab/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191114200427-caa0b0f7d508/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= From 8c8652e7bb25fd7f6c5846154c4b1152208be09e Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Wed, 12 Jan 2022 18:06:48 +0400 Subject: [PATCH 043/385] add a new cli --- api/api_storage.go | 3 +++ api/proxy_gen.go | 13 +++++++++++ build/openrpc/full.json.gz | Bin 26593 -> 26596 bytes build/openrpc/miner.json.gz | Bin 12927 -> 12982 bytes build/openrpc/worker.json.gz | Bin 3804 -> 3805 bytes cmd/lotus-miner/index_provider.go | 28 +++++++++++++++++++++++ documentation/en/api-v0-methods-miner.md | 11 +++++++++ documentation/en/cli-lotus-miner.md | 19 +++++++++++++-- node/impl/storminer.go | 4 ++++ 9 files changed, 76 insertions(+), 2 deletions(-) diff --git a/api/api_storage.go b/api/api_storage.go index 69212074983..decd534d683 100644 --- a/api/api_storage.go +++ b/api/api_storage.go @@ -223,6 +223,9 @@ type StorageMiner interface { // so they can download its index IndexerAnnounceDeal(ctx context.Context, proposalCid cid.Cid) error //perm:admin + // IndexerAnnounceAllDeals informs the indexer nodes aboutall active deals. + IndexerAnnounceAllDeals(ctx context.Context) error //perm:admin + // DagstorePieceIndexSize returns the size of the piece index. DagstorePieceIndexSize(ctx context.Context) (int64, error) //perm:admin diff --git a/api/proxy_gen.go b/api/proxy_gen.go index ff491919ebb..fc9f2f8d53f 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -671,6 +671,8 @@ type StorageMinerStruct struct { DealsSetPieceCidBlocklist func(p0 context.Context, p1 []cid.Cid) error `perm:"admin"` + IndexerAnnounceAllDeals func(p0 context.Context) error `perm:"admin"` + IndexerAnnounceDeal func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` MarketCancelDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` @@ -3994,6 +3996,17 @@ func (s *StorageMinerStub) DealsSetPieceCidBlocklist(p0 context.Context, p1 []ci return ErrNotSupported } +func (s *StorageMinerStruct) IndexerAnnounceAllDeals(p0 context.Context) error { + if s.Internal.IndexerAnnounceAllDeals == nil { + return ErrNotSupported + } + return s.Internal.IndexerAnnounceAllDeals(p0) +} + +func (s *StorageMinerStub) IndexerAnnounceAllDeals(p0 context.Context) error { + return ErrNotSupported +} + func (s *StorageMinerStruct) IndexerAnnounceDeal(p0 context.Context, p1 cid.Cid) error { if s.Internal.IndexerAnnounceDeal == nil { return ErrNotSupported diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index a15f7d23f72ccec2e7d5e7b0c906d8c61028e1a8..7cccdfb9bfeb71afad4f1ea23c7cd0da3911cb16 100644 GIT binary patch delta 16729 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 M|E!P#iYZ400H#c#Y5)KL delta 16717 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 diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index e205226dd7cbfa08bedcb358841385ed05ad5911..083a54e39d24ce6be46887d393f2e626ae1ccf74 100644 GIT binary patch literal 12982 zcmV;nGD*!JiwFP!00000|LlExbKADE_*cR3_s2~-vO_(rhiCeSV<)Lkoz~ZO+Ivsz zIfY0_!Zih|BxGC7_`ClG0N(`omaI5Dr_)*_xL5%D!eV#vO|w^sI4eUt*1Cti!=cvE zFqzrf@i&cPY9Z}dyRhln1y`4+;N

u3+iaj{MK7v270|G-2K+H*%+BD%0mS3Cat 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 literal 12927 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 diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index 7049571e9b281b3093f19f69217fe8509271ded9..1bb3fa8f191938fdd300ce4a814a99cf2d360567 100644 GIT binary patch delta 2919 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 R{|^8F|Nm#&edH*~005Ka%2@ya delta 2921 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 TJ^z0I00960CiM*tD9Hc-oMYAc diff --git a/cmd/lotus-miner/index_provider.go b/cmd/lotus-miner/index_provider.go index fa9574460e2..cf97e35bf15 100644 --- a/cmd/lotus-miner/index_provider.go +++ b/cmd/lotus-miner/index_provider.go @@ -16,6 +16,7 @@ var indexProvCmd = &cli.Command{ Usage: "Manage the index provider on the markets subsystem", Subcommands: []*cli.Command{ indexProvAnnounceCmd, + indexProvAnnounceAllCmd, }, } @@ -56,3 +57,30 @@ var indexProvAnnounceCmd = &cli.Command{ return marketsApi.IndexerAnnounceDeal(ctx, proposalCid) }, } + +var indexProvAnnounceAllCmd = &cli.Command{ + Name: "announce-all", + Usage: "Announce all active deals to indexers so they can download its indices", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "color", + Usage: "use color in display output", + DefaultText: "depends on output being a TTY", + }, + }, + Action: func(cctx *cli.Context) error { + if cctx.IsSet("color") { + color.NoColor = !cctx.Bool("color") + } + + marketsApi, closer, err := lcli.GetMarketsAPI(cctx) + if err != nil { + return err + } + defer closer() + + ctx := lcli.ReqContext(cctx) + + return marketsApi.IndexerAnnounceAllDeals(ctx) + }, +} diff --git a/documentation/en/api-v0-methods-miner.md b/documentation/en/api-v0-methods-miner.md index 2173d364101..030c9c58ff1 100644 --- a/documentation/en/api-v0-methods-miner.md +++ b/documentation/en/api-v0-methods-miner.md @@ -46,6 +46,7 @@ * [I](#I) * [ID](#ID) * [Indexer](#Indexer) + * [IndexerAnnounceAllDeals](#IndexerAnnounceAllDeals) * [IndexerAnnounceDeal](#IndexerAnnounceDeal) * [Log](#Log) * [LogAlerts](#LogAlerts) @@ -810,6 +811,16 @@ Response: `"12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf"` ## Indexer +### IndexerAnnounceAllDeals +IndexerAnnounceAllDeals informs the indexer nodes aboutall active deals. + + +Perms: admin + +Inputs: `null` + +Response: `{}` + ### IndexerAnnounceDeal IndexerAnnounceDeal informs indexer nodes that a new deal was received, so they can download its index diff --git a/documentation/en/cli-lotus-miner.md b/documentation/en/cli-lotus-miner.md index 450a3dee3d9..578b73f19fb 100644 --- a/documentation/en/cli-lotus-miner.md +++ b/documentation/en/cli-lotus-miner.md @@ -1168,8 +1168,9 @@ USAGE: lotus-miner index command [command options] [arguments...] COMMANDS: - announce Announce a deal to indexers so they can download its index - help, h Shows a list of commands or help for one command + announce Announce a deal to indexers so they can download its index + announce-all Announce all active deals to indexers so they can download its indices + help, h Shows a list of commands or help for one command OPTIONS: --help, -h show help (default: false) @@ -1190,6 +1191,20 @@ OPTIONS: ``` +### lotus-miner index announce-all +``` +NAME: + lotus-miner index announce-all - Announce all active deals to indexers so they can download its indices + +USAGE: + lotus-miner index announce-all [command options] [arguments...] + +OPTIONS: + --color use color in display output (default: depends on output being a TTY) + --help, -h show help (default: false) + +``` + ## lotus-miner net ``` NAME: diff --git a/node/impl/storminer.go b/node/impl/storminer.go index 62eda3001a8..80f189344cc 100644 --- a/node/impl/storminer.go +++ b/node/impl/storminer.go @@ -1008,6 +1008,10 @@ func (sm *StorageMinerAPI) IndexerAnnounceDeal(ctx context.Context, proposalCid return sm.StorageProvider.AnnounceDealToIndexer(ctx, proposalCid) } +func (sm *StorageMinerAPI) IndexerAnnounceAllDeals(ctx context.Context) error { + return sm.StorageProvider.AnnounceAllDealsToIndexer(ctx) +} + func (sm *StorageMinerAPI) DagstorePieceIndexSize(ctx context.Context) (int64, error) { if sm.DAGStore == nil { return 0, fmt.Errorf("dagstore not available on this node") From b780a64ed9e182ff5a777b40caf3ffc86e90c9d7 Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Thu, 13 Jan 2022 15:31:15 +0400 Subject: [PATCH 044/385] send markets multiaddrs to the engine --- node/modules/storageminer_idxprov.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/node/modules/storageminer_idxprov.go b/node/modules/storageminer_idxprov.go index b0e0e97d062..be07341429a 100644 --- a/node/modules/storageminer_idxprov.go +++ b/node/modules/storageminer_idxprov.go @@ -48,8 +48,8 @@ type IdxProv struct { peerstore.Peerstore } -func IndexerProvider(cfg config.IndexerProviderConfig) func(params IdxProv) (provider.Interface, error) { - return func(args IdxProv) (provider.Interface, error) { +func IndexerProvider(cfg config.IndexerProviderConfig) func(params IdxProv, marketHost host.Host) (provider.Interface, error) { + return func(args IdxProv, marketHost host.Host) (provider.Interface, error) { ipds := namespace.Wrap(args.Datastore, datastore.NewKey("/indexer-provider")) pkey := args.Peerstore.PrivKey(args.PeerID) @@ -67,7 +67,12 @@ func IndexerProvider(cfg config.IndexerProviderConfig) func(params IdxProv) (pro return nil, err } - e, err := engine.New(cfg.Ingest, pkey, dt, h, ipds, nil) + var maddrs []string + for _, a := range marketHost.Addrs() { + maddrs = append(maddrs, a.String()) + } + + e, err := engine.New(cfg.Ingest, pkey, dt, h, ipds, maddrs) if err != nil { return nil, xerrors.Errorf("creating indexer provider engine: %w", err) } From 8459d75597df8c0e9b09d11abb80fc8637139f48 Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Thu, 13 Jan 2022 16:15:43 +0400 Subject: [PATCH 045/385] update index provider config --- node/config/def.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/node/config/def.go b/node/config/def.go index 838418e8c31..f8c4b9ba0f6 100644 --- a/node/config/def.go +++ b/node/config/def.go @@ -233,11 +233,7 @@ func DefaultStorageMiner() *StorageMiner { // TODO: Remove hardcoded defaults once provider library exposes them. // See: https://github.com/filecoin-project/index-provider/issues/108 - cfg.IndexerProvider.Ingest = ipconfig.Ingest{ - LinkCacheSize: 1024, - LinkedChunkSize: 100, - PubSubTopic: "indexer/ingest", - } + cfg.IndexerProvider.Ingest = ipconfig.NewIngest() cfg.Common.API.ListenAddress = "/ip4/127.0.0.1/tcp/2345/http" cfg.Common.API.RemoteListenAddress = "127.0.0.1:2345" From d9562e2aeef55eee06d439241b84ce59c4f4fbc4 Mon Sep 17 00:00:00 2001 From: Cory Schwartz Date: Fri, 14 Jan 2022 03:01:12 -0800 Subject: [PATCH 046/385] restore appiamge --- .circleci/config.yml | 21 ++++++++++++++++++++- .circleci/template.yml | 9 +++++++++ AppImageBuilder.yml | 10 +++++----- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 53611d56515..f60cbdc6c75 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -390,7 +390,7 @@ jobs: build-appimage: machine: - image: ubuntu-2004:202104-01 + image: ubuntu-2004:202111-02 steps: - checkout - attach_workspace: @@ -398,6 +398,16 @@ jobs: - run: name: install appimage-builder command: | + # appimage-builder requires /dev/snd to exist. It creates containers during the testing phase + # that pass sound devices from the host to the testing container. (hard coded!) + # https://github.com/AppImageCrafters/appimage-builder/blob/master/appimagebuilder/modules/test/execution_test.py#L54 + # Circleci doesn't provide a working sound device; this is enough to fake it. + if [ ! -e /dev/snd ] + then + sudo mkdir /dev/snd + sudo mknod /dev/snd/ControlC0 c 1 2 + fi + # docs: https://appimage-builder.readthedocs.io/en/latest/intro/install.html sudo apt update sudo apt install -y python3-pip python3-setuptools patchelf desktop-file-utils libgdk-pixbuf2.0-dev fakeroot strace @@ -981,10 +991,19 @@ workflows: tags: only: - /^v\d+\.\d+\.\d+(-rc\d+)?$/ + - build-appimage: + filters: + branches: + ignore: + - /.*/ + tags: + only: + - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - publish: requires: - build-all - build-macos + - build-appimage filters: branches: ignore: diff --git a/.circleci/template.yml b/.circleci/template.yml index ef6818c6d5b..72133b1cdd6 100644 --- a/.circleci/template.yml +++ b/.circleci/template.yml @@ -816,10 +816,19 @@ workflows: tags: only: - /^v\d+\.\d+\.\d+(-rc\d+)?$/ + - build-appimage: + filters: + branches: + ignore: + - /.*/ + tags: + only: + - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - publish: requires: - build-all - build-macos + - build-appimage filters: branches: ignore: diff --git a/AppImageBuilder.yml b/AppImageBuilder.yml index 19c74e4a26a..ff01b211229 100644 --- a/AppImageBuilder.yml +++ b/AppImageBuilder.yml @@ -49,23 +49,23 @@ AppDir: fedora: image: appimagecrafters/tests-env:fedora-30 command: ./AppRun - use_host_x: true + use_host_x: false debian: image: appimagecrafters/tests-env:debian-stable command: ./AppRun - use_host_x: true + use_host_x: false arch: image: appimagecrafters/tests-env:archlinux-latest command: ./AppRun - use_host_x: true + use_host_x: false centos: image: appimagecrafters/tests-env:centos-7 command: ./AppRun - use_host_x: true + use_host_x: false ubuntu: image: appimagecrafters/tests-env:ubuntu-xenial command: ./AppRun - use_host_x: true + use_host_x: false AppImage: arch: x86_64 update-information: guess From 899db1f7c3b8497f4948ce52f871453295edabce Mon Sep 17 00:00:00 2001 From: Cory Schwartz Date: Fri, 14 Jan 2022 03:07:20 -0800 Subject: [PATCH 047/385] fix template --- .circleci/template.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.circleci/template.yml b/.circleci/template.yml index 72133b1cdd6..c091c7b4228 100644 --- a/.circleci/template.yml +++ b/.circleci/template.yml @@ -390,7 +390,7 @@ jobs: build-appimage: machine: - image: ubuntu-2004:202104-01 + image: ubuntu-2004:202111-02 steps: - checkout - attach_workspace: @@ -398,6 +398,16 @@ jobs: - run: name: install appimage-builder command: | + # appimage-builder requires /dev/snd to exist. It creates containers during the testing phase + # that pass sound devices from the host to the testing container. (hard coded!) + # https://github.com/AppImageCrafters/appimage-builder/blob/master/appimagebuilder/modules/test/execution_test.py#L54 + # Circleci doesn't provide a working sound device; this is enough to fake it. + if [ ! -e /dev/snd ] + then + sudo mkdir /dev/snd + sudo mknod /dev/snd/ControlC0 c 1 2 + fi + # docs: https://appimage-builder.readthedocs.io/en/latest/intro/install.html sudo apt update sudo apt install -y python3-pip python3-setuptools patchelf desktop-file-utils libgdk-pixbuf2.0-dev fakeroot strace From 1cd93e63fdee10666cc0371cae2a535c64cd136d Mon Sep 17 00:00:00 2001 From: Cory Schwartz Date: Tue, 18 Jan 2022 17:35:34 -0800 Subject: [PATCH 048/385] edge --- .circleci/config.yml | 8 +++++++- tools/packer/lotus-snap.pkr.hcl | 2 +- tools/packer/setup-snap.sh | 7 ++++--- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 7a66a852986..a13a5796bee 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1058,7 +1058,13 @@ workflows: tags: only: - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - - publish-packer-snap + - publish-snapcaft: + name: publish-snapcraft-temporary + channel: edge + - publish-packer-snap: + name: publish-packer-snap-temporary + requires: + - publish-snapcraft-temporary nightly: triggers: diff --git a/tools/packer/lotus-snap.pkr.hcl b/tools/packer/lotus-snap.pkr.hcl index ef0f52f8cec..8ceb743d088 100644 --- a/tools/packer/lotus-snap.pkr.hcl +++ b/tools/packer/lotus-snap.pkr.hcl @@ -10,7 +10,7 @@ variable "lotus_network" { locals { timestamp = regex_replace(timestamp(), "[- TZ:]", "") -} +} source "amazon-ebs" "lotus" { ami_name = "lotus-${var.lotus_network}-snap-${local.timestamp}" diff --git a/tools/packer/setup-snap.sh b/tools/packer/setup-snap.sh index d72ca876249..e4f838d9bed 100644 --- a/tools/packer/setup-snap.sh +++ b/tools/packer/setup-snap.sh @@ -26,13 +26,14 @@ MANAGED_FILES=( apt update apt reinstall snapd -snap install lotus-filecoin +snap install lotus-filecoin --channel=edge snap alias lotus-filecoin.lotus lotus +snap alias lotus-file.con.lotus-daemon lotus-daemon snap alias lotus-filecoin.lotus-miner lotus-miner -snap alias lotus-filecoin.lotus-miner lotus-worker +snap alias lotus-filecoin.lotus-worker lotus-worker -#snap stop lotus-filecoin.lotus-daemon +snap stop lotus-filecoin.lotus-daemon # Setup firewall yes | ufw enable From afac38e4920b9503333f90fbc6e3fed50d47ed1b Mon Sep 17 00:00:00 2001 From: Cory Schwartz Date: Tue, 18 Jan 2022 17:36:44 -0800 Subject: [PATCH 049/385] spelling --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a13a5796bee..d967837dc35 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1058,7 +1058,7 @@ workflows: tags: only: - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - - publish-snapcaft: + - publish-snapcraft: name: publish-snapcraft-temporary channel: edge - publish-packer-snap: From 9e40e246ec2951378d22cfa3ca13f829da5df7c1 Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Wed, 19 Jan 2022 11:36:07 +0400 Subject: [PATCH 050/385] deps update --- go.mod | 8 ++++---- go.sum | 19 ++++++++++--------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/go.mod b/go.mod index 0fabad4e1a6..6ffd35fbe10 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/elastic/gosigar v0.14.1 github.com/etclabscore/go-openrpc-reflect v0.0.36 github.com/fatih/color v1.13.0 - github.com/filecoin-project/dagstore v0.5.1 + github.com/filecoin-project/dagstore v0.5.2-0.20220119071824-e45c4d71e2d1 github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200910194244-f640612a1a1f github.com/filecoin-project/go-address v0.0.6 github.com/filecoin-project/go-bitfield v0.2.4 @@ -36,7 +36,7 @@ require ( github.com/filecoin-project/go-data-transfer v1.12.1 github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 - github.com/filecoin-project/go-fil-markets v1.15.0 + github.com/filecoin-project/go-fil-markets v1.15.1-0.20220119073341-c6bf7824c5ae github.com/filecoin-project/go-indexer-core v0.2.7 github.com/filecoin-project/go-jsonrpc v0.1.5 github.com/filecoin-project/go-padreader v0.0.1 @@ -45,7 +45,7 @@ require ( github.com/filecoin-project/go-statemachine v1.0.1 github.com/filecoin-project/go-statestore v0.2.0 github.com/filecoin-project/go-storedcounter v0.1.0 - github.com/filecoin-project/index-provider v0.2.0 + github.com/filecoin-project/index-provider v0.2.1 github.com/filecoin-project/specs-actors v0.9.14 github.com/filecoin-project/specs-actors/v2 v2.3.6 github.com/filecoin-project/specs-actors/v3 v3.1.1 @@ -94,7 +94,7 @@ require ( github.com/ipfs/go-ipld-cbor v0.0.6 github.com/ipfs/go-ipld-format v0.2.0 github.com/ipfs/go-ipld-legacy v0.1.1 // indirect - github.com/ipfs/go-log/v2 v2.4.0 + github.com/ipfs/go-log/v2 v2.5.0 github.com/ipfs/go-merkledag v0.5.1 github.com/ipfs/go-metrics-interface v0.0.1 github.com/ipfs/go-metrics-prometheus v0.0.2 diff --git a/go.sum b/go.sum index 2771e6e23e1..9b598cac668 100644 --- a/go.sum +++ b/go.sum @@ -297,8 +297,8 @@ github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/filecoin-project/dagstore v0.5.1 h1:ojzW/8z4PiquPDSA3EJ+Y4JcL+SWuloLaisy/hYcKMA= -github.com/filecoin-project/dagstore v0.5.1/go.mod h1:OdlK3x5m3Mol874WC2bI79H4H2+leN+FabwWdW2D/wY= +github.com/filecoin-project/dagstore v0.5.2-0.20220119071824-e45c4d71e2d1 h1:/gyP12PCKJ/d+JkP+Jza4YE/9tpSiCPO3OBQ5YeK63w= +github.com/filecoin-project/dagstore v0.5.2-0.20220119071824-e45c4d71e2d1/go.mod h1:OdlK3x5m3Mol874WC2bI79H4H2+leN+FabwWdW2D/wY= github.com/filecoin-project/go-address v0.0.3/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= github.com/filecoin-project/go-address v0.0.5/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= github.com/filecoin-project/go-address v0.0.6 h1:DWQtj38ax+ogHwyH3VULRIoT8E6loyXqsk/p81xoY7M= @@ -334,8 +334,8 @@ github.com/filecoin-project/go-fil-commcid v0.1.0 h1:3R4ds1A9r6cr8mvZBfMYxTS88Oq github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7LXep5bFEVOVmQWHJvl2mgsGo= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8= -github.com/filecoin-project/go-fil-markets v1.15.0 h1:PjoALE+brZTdZCteaj05KXt4lP5eWVWDeZmfwVAXa4w= -github.com/filecoin-project/go-fil-markets v1.15.0/go.mod h1:d6oFs7L6NCIcjY0p31KjbKAEhc0WIn8dguxGGIdTiXo= +github.com/filecoin-project/go-fil-markets v1.15.1-0.20220119073341-c6bf7824c5ae h1:b6ZZPcz6kl2U6K1QBTd9PeNvPKLX5ZZTp12oHweA48w= +github.com/filecoin-project/go-fil-markets v1.15.1-0.20220119073341-c6bf7824c5ae/go.mod h1:VbEWyZhep61wguSaEhXAPX2xLXgSJlcEId4NySjxjaU= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= @@ -372,8 +372,8 @@ github.com/filecoin-project/go-statestore v0.2.0 h1:cRRO0aPLrxKQCZ2UOQbzFGn4WDNd github.com/filecoin-project/go-statestore v0.2.0/go.mod h1:8sjBYbS35HwPzct7iT4lIXjLlYyPor80aU7t7a/Kspo= github.com/filecoin-project/go-storedcounter v0.1.0 h1:Mui6wSUBC+cQGHbDUBcO7rfh5zQkWJM/CpAZa/uOuus= github.com/filecoin-project/go-storedcounter v0.1.0/go.mod h1:4ceukaXi4vFURIoxYMfKzaRF5Xv/Pinh2oTnoxpv+z8= -github.com/filecoin-project/index-provider v0.2.0 h1:r1VPVhtWrU5+6Mo6g2Ozr5NXWMFz1qHt0NKJzV5ELZ8= -github.com/filecoin-project/index-provider v0.2.0/go.mod h1:eYiwZfJNadwn/8Grwn2e4nX2cH4PYl2k8SZqm9k+eCA= +github.com/filecoin-project/index-provider v0.2.1 h1:jM0ZxEsJhx4WmGgFBtC2ctk2pvu50Rd/LBNNNOcWbQQ= +github.com/filecoin-project/index-provider v0.2.1/go.mod h1:T3Ct7dqS7GDtotzFk/cNe0fzhoPLLk8htiXMK+xQfHU= github.com/filecoin-project/specs-actors v0.9.13/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= github.com/filecoin-project/specs-actors v0.9.14 h1:68PVstg2UB3ZsMLF+DKFTAs/YKsqhKWynkr0IqmVRQY= github.com/filecoin-project/specs-actors v0.9.14/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= @@ -397,8 +397,8 @@ github.com/filecoin-project/specs-actors/v7 v7.0.0-20211230214648-aeae366b083a h github.com/filecoin-project/specs-actors/v7 v7.0.0-20211230214648-aeae366b083a/go.mod h1:p6LIOFezA1rgRLMewbvdi3Pp6SAu+q9FtJ9CAleSjrE= github.com/filecoin-project/specs-storage v0.1.1-0.20211228030229-6d460d25a0c9 h1:oUYOvF7EvdXS0Zmk9mNkaB6Bu0l+WXBYPzVodKMiLug= github.com/filecoin-project/specs-storage v0.1.1-0.20211228030229-6d460d25a0c9/go.mod h1:Tb88Zq+IBJbvAn3mS89GYj3jdRThBTE/771HCVZdRJU= -github.com/filecoin-project/storetheindex v0.2.1 h1:jhsMh5O52bBU/NrnjJs2iLPI92T38kjlU9bk/dP0sts= -github.com/filecoin-project/storetheindex v0.2.1/go.mod h1:Tc5mYdAnGUzly40cuo35yITDD3XhF9EX5BO7evGsJ5M= +github.com/filecoin-project/storetheindex v0.2.2 h1:2zQlAtHKOVAfBpqIuQ8Njas3kM0VwgpicUCKC+epPG4= +github.com/filecoin-project/storetheindex v0.2.2/go.mod h1:05vxs5u3vTQFAwGW9+pgWSMc3BgFOK513nPyIQyLwyQ= github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg= github.com/filecoin-project/test-vectors/schema v0.0.5/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= @@ -860,8 +860,9 @@ github.com/ipfs/go-log/v2 v2.1.2-0.20200626104915-0016c0b4b3e4/go.mod h1:2v2nsGf github.com/ipfs/go-log/v2 v2.1.2/go.mod h1:2v2nsGfZsvvAJz13SyFzf9ObaqwHiHxsPLEHntrv9KM= github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g= github.com/ipfs/go-log/v2 v2.3.0/go.mod h1:QqGoj30OTpnKaG/LKTGTxoP2mmQtjVMEnK72gynbe/g= -github.com/ipfs/go-log/v2 v2.4.0 h1:iR/2o9PGWanVJrBgIH5Ff8mPGOwpqLaPIAFqSnsdlzk= github.com/ipfs/go-log/v2 v2.4.0/go.mod h1:nPZnh7Cj7lwS3LpRU5Mwr2ol1c2gXIEXuF6aywqrtmo= +github.com/ipfs/go-log/v2 v2.5.0 h1:+MhAooFd9XZNvR0i9FriKW6HB0ql7HNXUuflWtc0dd4= +github.com/ipfs/go-log/v2 v2.5.0/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI= github.com/ipfs/go-merkledag v0.0.6/go.mod h1:QYPdnlvkOg7GnQRofu9XZimC5ZW5Wi3bKys/4GQQfto= github.com/ipfs/go-merkledag v0.2.3/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= github.com/ipfs/go-merkledag v0.2.4/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= From 8cbf1a3e1b1f4a4d245be76b9a316a70fa87b5a9 Mon Sep 17 00:00:00 2001 From: Cory Schwartz Date: Wed, 19 Jan 2022 12:30:36 -0800 Subject: [PATCH 051/385] undo tmp edits --- .circleci/config.yml | 7 ------- tools/packer/setup-snap.sh | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d967837dc35..1bfe821da83 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1058,13 +1058,6 @@ workflows: tags: only: - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - - publish-snapcraft: - name: publish-snapcraft-temporary - channel: edge - - publish-packer-snap: - name: publish-packer-snap-temporary - requires: - - publish-snapcraft-temporary nightly: triggers: diff --git a/tools/packer/setup-snap.sh b/tools/packer/setup-snap.sh index e4f838d9bed..2e921f8da9f 100644 --- a/tools/packer/setup-snap.sh +++ b/tools/packer/setup-snap.sh @@ -26,7 +26,7 @@ MANAGED_FILES=( apt update apt reinstall snapd -snap install lotus-filecoin --channel=edge +snap install lotus-filecoin snap alias lotus-filecoin.lotus lotus snap alias lotus-file.con.lotus-daemon lotus-daemon From b8bf2af3e336d5150a4ed701a547e20395610349 Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Thu, 20 Jan 2022 16:34:13 +0400 Subject: [PATCH 052/385] upgrade on master --- build/openrpc/full.json.gz | Bin 26594 -> 26596 bytes build/openrpc/miner.json.gz | Bin 12784 -> 13091 bytes build/openrpc/worker.json.gz | Bin 3918 -> 3915 bytes documentation/en/cli-lotus-miner.md | 36 ++-- documentation/en/cli-lotus.md | 36 ++-- .../en/default-lotus-miner-config.toml | 2 +- go.mod | 21 ++- go.sum | 172 ++++++++++++++++-- node/modules/storageminer_idxprov.go | 4 +- 9 files changed, 201 insertions(+), 70 deletions(-) diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index ae8f0b86655688ef335478f8abf47bf58d1ca299..7dec77e7cdd932d36240e255426f41fbff01e78e 100644 GIT binary patch delta 25704 zcmV))K#ITO&jIAm0gxOYarr7ggWl0C^OXjROQdO5P#Z5ZW#U6iu3i8#Tgqy&lgri%&aj5Z3tO98n_FLp z12GQjr(D#4kP{ZIfq9KYn z7WE~|!$D{~`liWz8_bc9RWupLYhpVhrWGp5?>Xht7X_T zf^KT)KW!u2s{2wc-Kv;NL>!}Y1jdkI4+zy0&7l}f0LL`uO8$SP^;*fFs`Xpl?b2tg zEoQTh;n*AOZEcUlVhte|qjj2FmK)E+|5vYLwOI5D)640>t+1D`8&=ri40%`CROz@SA@+YkBxWB&gbVD+P%wF}%8bP- z@-z+T`w?Oc`2eTXHo!3#h*d0R)nN$!P$tz7KyXNXZjgtAu-##rF6g=pi_|Vg77)F@mFAJ|3|v zG!Orxw|{?!@q*67zsBlVnLNdLn4oB|H<)a0ZI5;a!@&jiu8@Ch{g1P^rxB%-N}GH*coQH`w64p1 z8+^v(kj8`$_FfN{Rn8m*xSb>5GbX3>oNL-&z733DuZ9Ep*TI4dqSXXWVI-zvpC4M0 z{EYB)#s_$=b@S&a+06pscrSQG!n%L45a%Te78RBBF_*4(!N=4j4-B=_yTYXriZp;_f&~hS~2(&3{%9%!VQR8VXk^5JorTa`)zvlkNs0e_o?Y;^T>Q3G%EjlZeh$H{curhKP?M z0D1O^P~xEt@Og%aVr>S)5D_-KB$NcoM=-$=OKE~9vTfx~xWRk|0(yfO2V6?Qr)g(A zN*MN0BtD|x9Ni)>7SmFW;HQf>d*I^z@j3YL=HmUQBXIuy)9)uo;M2#Ge}jWJ;P>-4 ze@Ec$r!(;G&Bev>$9LevoAdMicW=(Y@kg)^&QISQ9=|<41P3Rd4u2CAk3NBqpDskb z9NCLcf`VE5@Z|TSH%E%h#qsI+n~O{GJ45MG$mwP_1WLikUg_Ng;L#{TUN$5?O1_-z zp7WzTP(MnutS!B^@t+(7ECa7!z776Jf8vCMnR!7?&&u0~&duK+#nM#;|A0Y^wCms< zWG8rzl^f+9WN#5VgkkpbG(vM6&-H^3GX7|=r<@FOQkIS2;o$K2sBFWJ$Dxm=*U<>? zc$A?VK3lNqi`%Q)@b3xPzL|Lc?9Q*ZXLEYRZ^r)Z6};VHgYRN!&yg2i<@&9Ee@JBX z@P}YHkj9Xb4R&6Lp1;5$_Iq4pZM`4nr0)hi)l6t>u^4lqLsdPeY=Evg$=bG*%txDc z^a8NL-g<6#bzRW*J<)5jb+tqQ^yBDJQ~i8IBa$*ByF2}?o<6t8S1OY zh2;jMZVxwoYh!*W-ALjf&>JG@uf+YnxfI(ys0qLGqItq6DzNK>*Y&MqPIP&j*{_TC zI{Pzrm%G)H_9Fy+iE+~3#Xz;pr*?RJl=`SHi44Cq0xw-m%ER@ge=N&h+X%Bq z;5cY!XFKHWkoUtoYqa%Z*GfmTV{##Z*Q&}oB~+)iP2lw#T08|$zI<)3xYK4DP9UXp z+aEfr?vJ%v&$ugWn5q3Txh3Vrk=%Y#c(*s@T^L>~ZP1g-8U50y1i~;p4g>#_99|pcB53w%5^5&v6-Q4}U(Y!kVWrE0Ybhgoe>GFG!7kemq_Y6XlUeR0Y6Ua%#P1Abmin+9Viq`S zh{y_|0WblbD8ErTM$5U49;VyK!CMD!9lX6eJ@=|9$wVrt(-RA;>A8fAjh@Rpgmq1O zt(P>_sP!t_SV0FGfBm!7fhnJf4vdlq6B=a-u|gB76jnt|2rgzQqoG5Z1I!XHj!-fT zP=cOw`kWG^B6_7#o#)kYqIG2cD^6=5OIlw=7fU7%vF|kU1J=lu%cep<*Ojx<)^Bbx z7h^iu+Z+zg<*xf4hzpP^_7)Bz8ap3E2fIq(| z_Mh;B{ij19JMo0?9~gh{KmGcr+l;v5&4_HxhTCq?R#T{%NT^byxwls1cwwp$?Io2a zr?!)phJbZfrD?Eb(bCebx7qZ51nO^VNxGw&&_7!Rf2gY4Z)3NPz*HrB-ET;FUT#C_ z*3A%1t*dJC9;JQl&p>gau5}QYi)Xz%fwH}ABT)7y97TGBR+B9TCA*B{H9)(gB%oi?w~oL$rD5-tah^6$?E$ht9P0XO}>Y$b1HLHclmbdn9^XW#8t$q#jG03 zwt_ZgZ;7R@Tb7yk8Nd?&voyp2-C~w)Rk{;le~)G(QB2y>$m)m7#gJ&p;6~I#klb@Y z@}lW5>U#wJj$#BszmF5wf=+)hO>@;GH$;1;b1yk>G7~RUFrbnc?x^)WnBBWg$GFZA z^gHWGUD+nCXuROd_i;77#(i8tsQm_R#_1BBnXsS^SK~171DxZ(Rk_tEM3TbHuxATwU3EL;?0T|*e)xip>3r)NMerGz6(1SALr`uio8J7NIyDMn>byM*2 zIfuM6pwN|<01D{{&A`Q{@n53eQgoq-e>b2DO{qP+$oRH!cqV+LS4?uqG2_@{#|N2F_JAWBNhJKMgz<|*VipX6lWzwhN#DadBEf@kHPbQaSjQ9=GCHV~n zY85zS@-UD|qZikGnKi?VTI`etH+ybl_nzZ_^cklUOoY+9v)%H{s;*}fUacB?e{?BP zMq5o`(+VzqUSVg@q+lOCrk)(&=`mTZ1jj&qkbn> z%4gPgmn?q{>-K|n&1q3Hkm*YcQ+IRlm^^W#?YgMb03*T=Vc;Fo`TVrK?8w(&p4vhd zJ6qy<&J*p&0bOFWK{OQF_h8_~e}RMmLLR7xDn1~S4dTP}CK%QuGe+{Q%Fc1)jSWEP z_eMj70Jb)_cUq#1ZZ~K>R=_c;i!0TugLo)7f*f8%kg!PwLbsJ2MM8B##D^SmU1lRG ze0(Hr@(`hDL;gJiV@iW22U|_ED?8ijyOWsag1u&uQ)0@KkA&?Zx(|~6e`lv~)xLWA z{P;*3A@b0c9F^W=QqAz+SuoM)P6CPaM6naCTiZvY-zfe3?w{L#e*4eAuhIMe;o-a8 zeHQ)xUkBdj+xG`=&$r*RH}u`bZS>*f`nUh#lkPtAjP21++9h{B#*?klPF)!l^`iJTgHs)bz zfb;KcEWcB@2q^TG4fT3BkaILK;6~f}L1pHuZbQ-1B+T(=l|J0yx8+UDS=S$*G5NAC z5-gQol@rchc#GcK$1P;suD3c<2q9L@W6!lz^RQ@q?q`|lK4xy(_3JWiv*p4uw^b$jdA z_mItgRljz&<*&g|^ZWrtR{_$u_KUS57WdnT&QHYH9qyl%e^bS1^LOt>OF5v}>~`5? zzGoE~WGZ@-mP$NZRu_aOy|WQi`Ejb?s>?P)XMxt_%hb!+TK@A{`MV!8+0A5pBR|1#+@AdR-T~ECuIVOniA|W;Z30RJRF#d}bc5`0p4+i%*jYik3s_ zq>;u$78$_~f3Vu7bw3<1**!%to22KY8*OMOGc|j2hxFU+n@%Zm43kv9>pr$ zTbe|6HzL+dGHbKGgEKU@0NRe^-3Ia$7Ocx)nMa~Kn{|h9B&d3a$RX?+45TX8p-^q_ zNEDhxe-tk9WGI6DcrsGvY_O$nc!~&$w7NaqKU4mUa$vD|+#hCqEOucdJX?zp%ExA< z?rhhcQqYS+Zf6{m3GFN(QVJFqtS3d6+olHH9>b0E+%DVcF?ld^V8}fm4loh;UM6nW zr}dJgIzEDdvp64w#aS7LUAtz?H&&uPq9J84f9UmMtaA=|Vv!_wD^+=y&$+xfZ|~b6 z`RmKK!AI4_Qt`4RPhY;d4Uxx@e-x`*49X=ABP7Q30!!MPo10tD<$o8On|t!V{|KWj z^p_Vpp;N`@37wYPu^{pN>-Vn`?$T@Q=dHCP$f3~Ed*230G;MVj_d76I!?cwXOF(5NRJL&TX+?>2Yhq`#tv@cNr1``Bfg*{ll9iT> z@Zk&+g7jX%F~J-|wXM?8EIvalq(pt$jwA#xqwi`yq_OnIq>%5`GK-nK1nvN`e!s>s zGloJ9*fBdts$c5&A2jx6sKTLAyXHUfe_3K*cO9B!2&BjqQ=u;zvThQh^&PLdMeuE) zkbw%)N6)!aB65Vu`e|G%Ma_i>yUAvr1idf^+M!tv4vQ(kuF-mS{J|W;vP~t4;aH_G-0M3E3^$7MuQgfch}zeHkdb#nJEL$c^mMIo2eR zR|qT4XN)AFrqs~Pbe`CUTcbbqFG2Nl(72jS)5a?sgBn6hi>Bh-wT zdAwq#y@3#T)bB3}QjOJ}or~Mq?(<+=>h%A~djadZ{&pJA^uLEp20nINdP(&jve)P6 z^_9TB$mFuMmbRZcmv3fB9<0xz!VZs*#N?Ji$-zR0Dm!QVgLTHc9QGxlfAX>}hrL`y z$MY2qH>k=>;sKt5C(l&DGsKpQ6;-syUA~mbWdcRFjOXffgNy};1yU?T1B8%^MZ{@# z%E1K(^l~#!I!(%3Y38dRf7(N}E_XSW-w{w4(zNPbxlA9L74oX_FzN|r-1PT$wM0sE zsxRdD^3^P)P1og8tVF#rf2zKsi4NiQRXu8wccOg8pBd7i4Hh~9FbLAjA3QBfC-P+L z%6EKJ_PipvxVn_x&D(C9?(uBXb&h&=yFfqN8}1z4k7yU@;Rav7ZahgYH8g_3N|;5| zuf;0X5tS*aW?-V}bwwkZ*JUU~F_IvVawMg|B)%*&hdxTKSyCs>e?3WM_4~%M&Q<}C zHi3LDlFvo*xkx@2$>&Uj^^*`Q*a$AD&js~4bIzG_&YW{WeJ-fa1@*b0zQ+^P_prQF zFE$&KRh?j__rh24Q)voyo+|a)&QGODHF~O4nT~#{jMrtJs)UsQGtP9VfKCv=WUvgM zAsm5-QVtG}k5~_Gf2o=X4daECOX@eY80@{+95&_M(TQ?s9C;Ono|q=p0SAZsXH_p& zu(c9`RVub7LrunB#Y@@yyEAW+A$x=_?-yH*`9{Q|N$-?cMV@3t>O@Lf!rlX(5p5JM zIm#VnOpgC$V#eUB-YXtuh3eemJ&2!N-z%h0@x7gYT%{-Of7iEmG}wDl%!E~$%d4F5 zE3vpX8{BM$Yq_JBO|ZbukcaSf;%AeOP9gT+3S=XmTu=@J@kF!c9IDQty3P*O;o!|R zB3z~>?i_xRTLm_1y0Db2+zrm3cz^vW&SmmA{fSz(Sa}F6Ic{_b<#0)dotKr|N!_w7 znhv2VIbi?ke>3FKmWTW41#)>Lo9wz#W3D)vp0yz(u$^I7pi*~|M4x!t(79b@hRH1F z`N+(9-X`ODq4fq6aHX{8c2Y6e4R)i53c#ar{^H7x7+T4V~)afvt zcVpxDXz8^fCb@nt4=FIXELBL3fk^()2}4vbe|l3p*`VB6imw-&eWv(&Y*%W$*c~;m z9mZjlOUuxC36&_-tt20Em?Uf1$ToB&I?Ryb2#hHWEY@17-M*GwRflX{qg8A{&e1&N z3~&k}^&UWV2YWIc;0E)VM2adKU;6y`NP2Ck%pWEOskbFu^EK{lJ&(FB=SCoTFYs^K zf7ke9Qhzx?c(V24Ib^3o`@PmzxzVe<+Bp&nVK9ZMSM(a<$` zUXCYp>sW1YB9(_HjqsDHc#v$?}s}%VZL=_&azwJomct(e|eSf+ApkEUfWOf6Wqy_{-~VpC_ABwuWh7b znp>gevb8@@`OusauNw1~CK~f1T4+ z^vM>bG_hM{gE0<+0Qu&D1xnKE5kn>afTv=|E{WQ2hY#-Ixb7nT($y?(UV$NYpLqbk6E62PKcKSGFMC?-JI`+OAc}zzxJ)M!6Uk z1*c$)fJeoA=KbAAP(5CE=e%^j%kC>|ce62D-MMtIq0Sc$r1k68*0Z$4shnEEY)`{F zml^D7-5xD=ljCIzENefM$N6Pof0!?ROBW;Tdjq;SShlzmayYmLna@58h|p|X%WMmU z-C9Y8<I2XTM*})g?>Rtj&lp(Vem1*5qb`Z|9nEDDdNvFFhT&GOae?)>Rf^M zH71b&g~lAPc+Ak>v7DF@^sX?OI=tfWio+`ouQIC<5mP-0)w(1npDuns|G$I%!{2^C{lA0#^Edx@x_|K= zAaac(O62arHHVZzDQ4e}AOJ(=kDR$R(-p`a8%@@Er5O-fQ_oPo(ta zX@urDo+s9Tl!r1cmbQ@g2LC3(=6}u)W*+&k8T#*k{cA8BRHn-sk3%0#ucHy(@hC$# ze70cI7q?fp;olRoeKYa?*_~f+&*t=s-;Dj+D|oxZ25lpTe^jsAVmYJV9jfZ_v%#z8 zfVK`k(qnJaj{ewop*-q4ejCh@kL45_V*;ba8{$!4NNVvB8QR@3689M92kiiz)%@## zxS6G8&^fN8DV+FjZ!Le_LkM&^mbf6AZF3#=;-e@DfN;cSJR&=ztC!PJOd{m}^Kx=a zcBX&57>)c9f881JzsYvEjlO+ns*=8W}%#?Ayq7-1KjVzSw|^gv|_I+{_@C z7$c0ZhX9+=IPk$3DaAOBv&wm ztu~C_!S?5UDyg(EhM(yl=ZN^{A@XV*_{Ex5sxD)wmr$d+uD0^s8$9LBX1On=4j9CQ zA)cDW(z%aO(BoMhXAe7j*xAGDY!4U3qU9R>e*kaaBDLIFPUfWM4@%zYh4N@~4B{0uP^U8C}JveO0z1?$W&*4rDUChlTuqpBbE;ofDIriiPI zbZ|~%!U3Hm!hZ(2Ox5DWQG^H&79dJ0B^MLvv3a;k!TEiAUePZ%Yf`_cnR$i+1R3g< z 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 delta 25743 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 diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 2cb9ab35a596996089916305611753f621b0d112..111e3892245aaf4e14f3ef40fef994df4cda5e28 100644 GIT binary patch literal 13091 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 literal 12784 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 -- reports the resource usage of a specific service. - - proto: -- reports the resource usage of a specific protocol. - - peer: -- reports the resource usage of a specific peer. - - all -- reports the resource usage for all currently active scopes. - + + The scope can be one of the following: + - system -- reports the system aggregate resource usage. + - transient -- reports the transient resource usage. + - svc: -- reports the resource usage of a specific service. + - proto: -- reports the resource usage of a specific protocol. + - peer: -- reports the resource usage of a specific peer. + - all -- reports the resource usage for all currently active scopes. OPTIONS: --help, -h show help (default: false) @@ -1524,16 +1523,15 @@ USAGE: DESCRIPTION: Get or set resource limits for a scope. - - The scope can be one of the following: - - system -- reports the system aggregate resource usage. - - transient -- reports the transient resource usage. - - svc: -- reports the resource usage of a specific service. - - proto: -- reports the resource usage of a specific protocol. - - peer: -- reports the resource usage of a specific peer. - - The limit is json-formatted, with the same structure as the limits file. - + + The scope can be one of the following: + - system -- reports the system aggregate resource usage. + - transient -- reports the transient resource usage. + - svc: -- reports the resource usage of a specific service. + - proto: -- reports the resource usage of a specific protocol. + - peer: -- reports the resource usage of a specific peer. + + The limit is json-formatted, with the same structure as the limits file. OPTIONS: --set set the limit for a scope (default: false) diff --git a/documentation/en/cli-lotus.md b/documentation/en/cli-lotus.md index f230e61894c..3dd7043bddc 100644 --- a/documentation/en/cli-lotus.md +++ b/documentation/en/cli-lotus.md @@ -2869,15 +2869,14 @@ USAGE: DESCRIPTION: Report resource usage for a scope. - - The scope can be one of the following: - - system -- reports the system aggregate resource usage. - - transient -- reports the transient resource usage. - - svc: -- reports the resource usage of a specific service. - - proto: -- reports the resource usage of a specific protocol. - - peer: -- reports the resource usage of a specific peer. - - all -- reports the resource usage for all currently active scopes. - + + The scope can be one of the following: + - system -- reports the system aggregate resource usage. + - transient -- reports the transient resource usage. + - svc: -- reports the resource usage of a specific service. + - proto: -- reports the resource usage of a specific protocol. + - peer: -- reports the resource usage of a specific peer. + - all -- reports the resource usage for all currently active scopes. OPTIONS: --help, -h show help (default: false) @@ -2894,16 +2893,15 @@ USAGE: DESCRIPTION: Get or set resource limits for a scope. - - The scope can be one of the following: - - system -- reports the system aggregate resource usage. - - transient -- reports the transient resource usage. - - svc: -- reports the resource usage of a specific service. - - proto: -- reports the resource usage of a specific protocol. - - peer: -- reports the resource usage of a specific peer. - - The limit is json-formatted, with the same structure as the limits file. - + + The scope can be one of the following: + - system -- reports the system aggregate resource usage. + - transient -- reports the transient resource usage. + - svc: -- reports the resource usage of a specific service. + - proto: -- reports the resource usage of a specific protocol. + - peer: -- reports the resource usage of a specific peer. + + The limit is json-formatted, with the same structure as the limits file. OPTIONS: --set set the limit for a scope (default: false) diff --git a/documentation/en/default-lotus-miner-config.toml b/documentation/en/default-lotus-miner-config.toml index e1fbd29b4cb..2e9638fabb3 100644 --- a/documentation/en/default-lotus-miner-config.toml +++ b/documentation/en/default-lotus-miner-config.toml @@ -262,7 +262,7 @@ #LinkCacheSize = 1024 # env var: LOTUS_INDEXERPROVIDER_LINKEDCHUNKSIZE - #LinkedChunkSize = 100 + #LinkedChunkSize = 16384 # env var: LOTUS_INDEXERPROVIDER_PUBSUBTOPIC #PubSubTopic = "indexer/ingest" diff --git a/go.mod b/go.mod index 1761efe1483..5806599737a 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/elastic/gosigar v0.14.1 github.com/etclabscore/go-openrpc-reflect v0.0.36 github.com/fatih/color v1.13.0 - github.com/filecoin-project/dagstore v0.4.4 + github.com/filecoin-project/dagstore v0.5.2-0.20220120115845-e07b050f48d3 github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200910194244-f640612a1a1f github.com/filecoin-project/go-address v0.0.6 github.com/filecoin-project/go-bitfield v0.2.4 @@ -36,7 +36,8 @@ require ( github.com/filecoin-project/go-data-transfer v1.14.0 github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 - github.com/filecoin-project/go-fil-markets v1.19.0 + github.com/filecoin-project/go-fil-markets v1.19.1-0.20220120121729-eb2fe1f4df58 + github.com/filecoin-project/go-indexer-core v0.2.7 github.com/filecoin-project/go-jsonrpc v0.1.5 github.com/filecoin-project/go-padreader v0.0.1 github.com/filecoin-project/go-paramfetch v0.0.3-0.20220111000201-e42866db1a53 @@ -44,6 +45,7 @@ require ( github.com/filecoin-project/go-statemachine v1.0.1 github.com/filecoin-project/go-statestore v0.2.0 github.com/filecoin-project/go-storedcounter v0.1.0 + github.com/filecoin-project/index-provider v0.2.1 github.com/filecoin-project/specs-actors v0.9.14 github.com/filecoin-project/specs-actors/v2 v2.3.6 github.com/filecoin-project/specs-actors/v3 v3.1.1 @@ -77,7 +79,7 @@ require ( github.com/ipfs/go-ds-badger2 v0.1.2 github.com/ipfs/go-ds-leveldb v0.5.0 github.com/ipfs/go-ds-measure v0.2.0 - github.com/ipfs/go-fs-lock v0.0.6 + github.com/ipfs/go-fs-lock v0.0.7 github.com/ipfs/go-graphsync v0.12.0 github.com/ipfs/go-ipfs-blockstore v1.1.2 github.com/ipfs/go-ipfs-blocksutil v0.0.1 @@ -96,9 +98,9 @@ require ( github.com/ipfs/go-merkledag v0.5.1 github.com/ipfs/go-metrics-interface v0.0.1 github.com/ipfs/go-metrics-prometheus v0.0.2 - github.com/ipfs/go-path v0.0.7 + github.com/ipfs/go-path v0.2.1 github.com/ipfs/go-unixfs v0.3.1 - github.com/ipfs/interface-go-ipfs-core v0.4.0 + github.com/ipfs/interface-go-ipfs-core v0.5.2 github.com/ipld/go-car v0.3.3 github.com/ipld/go-car/v2 v2.1.1 github.com/ipld/go-codec-dagpb v1.3.0 @@ -143,9 +145,9 @@ require ( github.com/stretchr/testify v1.7.0 github.com/syndtr/goleveldb v1.0.0 github.com/uber/jaeger-client-go v2.25.0+incompatible // indirect - github.com/urfave/cli/v2 v2.2.0 + github.com/urfave/cli/v2 v2.3.0 github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba - github.com/whyrusleeping/cbor-gen v0.0.0-20210713220151-be142a5ae1a8 + github.com/whyrusleeping/cbor-gen v0.0.0-20211110122933-f57984553008 github.com/whyrusleeping/ledger-filecoin-go v0.9.1-0.20201010031517-c3dcc1bddce4 github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 github.com/whyrusleeping/pubsub v0.0.0-20190708150250-92bcb0691325 @@ -155,8 +157,7 @@ require ( go.opentelemetry.io/otel/bridge/opencensus v0.25.0 go.opentelemetry.io/otel/exporters/jaeger v1.2.0 go.opentelemetry.io/otel/sdk v1.2.0 - go.uber.org/dig v1.10.0 // indirect - go.uber.org/fx v1.9.0 + go.uber.org/fx v1.15.0 go.uber.org/multierr v1.7.0 go.uber.org/zap v1.19.1 golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b // indirect @@ -174,3 +175,5 @@ require ( replace github.com/filecoin-project/filecoin-ffi => ./extern/filecoin-ffi replace github.com/filecoin-project/test-vectors => ./extern/test-vectors + +replace github.com/ipfs/go-path => github.com/ipfs/go-path v0.0.7 diff --git a/go.sum b/go.sum index 5615223b234..aec106a7694 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,4 @@ +bazil.org/fuse v0.0.0-20200117225306-7b5117fecadc/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= @@ -87,6 +88,7 @@ github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/akavel/rsrc v0.8.0 h1:zjWn7ukO9Kc5Q62DOJCcxGpXC18RawVtYAGdz2aLlfw= github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= +github.com/akrylysov/pogreb v0.10.1/go.mod h1:pNs6QmpQ1UlTJKDezuRWmaqkgUE2TuU0YTWyqJZ7+lI= github.com/alecthomas/jsonschema v0.0.0-20200530073317-71f438968921 h1:T3+cD5fYvuH36h7EZq+TDpm+d8a6FSD4pQsbmuGGQ8o= github.com/alecthomas/jsonschema v0.0.0-20200530073317-71f438968921/go.mod h1:/n6+1/DWPltRLWL/VKyUxg6tzsl5kHUCcraimt4vr60= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -96,6 +98,7 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a h1:E/8AP5dFtMhl5KPJz66Kt9G0n+7Sn41Fy1wv9/jHOrc= github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= +github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5/go.mod h1:Y2QMoi1vgtOIfc+6DhrMOGkLoGzqSV2rKp4Sm+opsyA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= @@ -129,6 +132,7 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bep/debounce v1.2.0 h1:wXds8Kq8qRfwAOpAxHrJDbCXgC5aHSzgQb/0gKsHQqo= github.com/bep/debounce v1.2.0/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/briandowns/spinner v1.11.1/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ= github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= @@ -159,6 +163,7 @@ github.com/casbin/casbin/v2 v2.37.0/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRt github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/ceramicnetwork/go-dag-jose v0.1.0/go.mod h1:qYA1nYt0X8u4XoMAVoOV3upUVKtrxy/I670Dg5F0wjI= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -166,6 +171,7 @@ github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cb github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= +github.com/cheggaaa/pb v1.0.29/go.mod h1:W40334L7FMC5JKWldsTWbdGjLo0RxUKK73K+TuPxX30= github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= @@ -198,6 +204,7 @@ github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7 github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU= github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= @@ -269,6 +276,7 @@ github.com/elastic/go-windows v1.0.0/go.mod h1:TsU0Nrp7/y3+VwE82FoZF8gC/XFg/Elz6 github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= github.com/elastic/gosigar v0.14.1 h1:T0aQ7n/n2ZA9W7DmAnj60v+qzqKERdBgJBO1CG2W6rc= github.com/elastic/gosigar v0.14.1/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= +github.com/elgris/jsondiff v0.0.0-20160530203242-765b5c24c302/go.mod h1:qBlWZqWeVx9BjvqBsnC/8RUlAYpIFmPvgROcw0n1scE= github.com/ema/qdisc v0.0.0-20190904071900-b82c76788043/go.mod h1:ix4kG2zvdUd8kEKSW0ZTr1XLks0epFpI4j745DXxlNE= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -290,9 +298,8 @@ github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/filecoin-project/dagstore v0.4.3-0.20211211192320-72b849e131d2/go.mod h1:tlV8C11UljvFq3WWlMh2oMViEaVaPb6uT8eL/YQgDfk= -github.com/filecoin-project/dagstore v0.4.4 h1:luolWahhzp3ulRsapGKE7raoLE3n2cFkQUJjPyqUmF4= -github.com/filecoin-project/dagstore v0.4.4/go.mod h1:7BlOvaTJrFJ1Qemt5jHlLJ4VhDIuSIzGS0IwO/0AXPA= +github.com/filecoin-project/dagstore v0.5.2-0.20220120115845-e07b050f48d3 h1:kuZsRFDjyrDAgoHNolJBnO7xX1EETHdJ090sgD3Al5E= +github.com/filecoin-project/dagstore v0.5.2-0.20220120115845-e07b050f48d3/go.mod h1:OdlK3x5m3Mol874WC2bI79H4H2+leN+FabwWdW2D/wY= github.com/filecoin-project/go-address v0.0.3/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= github.com/filecoin-project/go-address v0.0.5/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= github.com/filecoin-project/go-address v0.0.6 h1:DWQtj38ax+ogHwyH3VULRIoT8E6loyXqsk/p81xoY7M= @@ -316,9 +323,14 @@ github.com/filecoin-project/go-commp-utils v0.1.3/go.mod h1:3ENlD1pZySaUout0p9AN github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= github.com/filecoin-project/go-crypto v0.0.1 h1:AcvpSGGCgjaY8y1az6AMfKQWreF/pWO2JJGLl6gCq6o= github.com/filecoin-project/go-crypto v0.0.1/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= +github.com/filecoin-project/go-dagaggregator-unixfs v0.2.0/go.mod h1:WTuJWgBQY0omnQqa8kRPT9O0Uj5wQOgslVMUuTeHdJ8= +github.com/filecoin-project/go-data-transfer v1.11.4/go.mod h1:2MitLI0ebCkLlPKM7NRggP/t9d+gCcREUKkCKqWRCwU= +github.com/filecoin-project/go-data-transfer v1.12.1/go.mod h1:j3HL645YiQFxcM+q7uPlGApILSqeweDABNgZQP7pDYU= +github.com/filecoin-project/go-data-transfer v1.13.0/go.mod h1:TcUtAdQl1ofnLV9oH3gPC93Hjce9yuKnq4O4j2M/BU4= github.com/filecoin-project/go-data-transfer v1.14.0 h1:4pnfJk8FYtqcdAg+QRGzaz57seUC/Tz+HJgPuGB7zdg= github.com/filecoin-project/go-data-transfer v1.14.0/go.mod h1:wNJKhaLLYBJDM3VFvgvYi4iUjPa69pz/1Q5Q4HzX2wE= github.com/filecoin-project/go-ds-versioning v0.0.0-20211206185234-508abd7c2aff/go.mod h1:C9/l9PnB1+mwPa26BBVpCjG/XQCB0yj/q5CK2J8X1I4= +github.com/filecoin-project/go-ds-versioning v0.1.0/go.mod h1:mp16rb4i2QPmxBnmanUx8i/XANp+PFCCJWiAb+VW4/s= github.com/filecoin-project/go-ds-versioning v0.1.1 h1:JiyBqaQlwC+UM0WhcBtVEeT3XrX59mQhT8U3p7nu86o= github.com/filecoin-project/go-ds-versioning v0.1.1/go.mod h1:C9/l9PnB1+mwPa26BBVpCjG/XQCB0yj/q5CK2J8X1I4= github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= @@ -327,8 +339,8 @@ github.com/filecoin-project/go-fil-commcid v0.1.0 h1:3R4ds1A9r6cr8mvZBfMYxTS88Oq github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7LXep5bFEVOVmQWHJvl2mgsGo= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8= -github.com/filecoin-project/go-fil-markets v1.19.0 h1:kap2q2wTM6tfkVO5gMA5DD9GUeTvkDhMfhjCtEwMDM8= -github.com/filecoin-project/go-fil-markets v1.19.0/go.mod h1:qsb3apmo4RSJYCEq40QxVdU7UZospN6nFJLOBHuaIbc= +github.com/filecoin-project/go-fil-markets v1.19.1-0.20220120121729-eb2fe1f4df58 h1:NHX4FXQQQ9dVhQBBM1BThVbYmN3EnM4Dxzvz0DYTOTk= +github.com/filecoin-project/go-fil-markets v1.19.1-0.20220120121729-eb2fe1f4df58/go.mod h1:SmDIzoUwFlej6Ac5ilBMyBImTj/TrmJmZ6wh/ILMfuI= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= @@ -336,8 +348,14 @@ github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0/go.mod h1:7aWZdaQ1b16BVoQUYR+ github.com/filecoin-project/go-hamt-ipld/v3 v3.0.1/go.mod h1:gXpNmr3oQx8l3o7qkGyDjJjYSRX7hp/FGOStdqrWyDI= github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0 h1:rVVNq0x6RGQIzCo1iiJlGFm9AGIZzeifggxtKMU7zmI= github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0/go.mod h1:bxmzgT8tmeVQA1/gvBwFmYdT8SOFUwB3ovSUfG1Ux0g= +github.com/filecoin-project/go-indexer-core v0.2.4/go.mod h1:MSe5aRWmfRB+5syR4yDV+OApgJU+MUJ4rl9VUuzwCfc= +github.com/filecoin-project/go-indexer-core v0.2.7 h1:D0egR6Q3Jkp5r4klxkdDQvjXeLx3cwZMKE55qop2xCI= +github.com/filecoin-project/go-indexer-core v0.2.7/go.mod h1:6YD7KwDOQ+03DdAitviL7h1fksIU6a4j52yPnA/E1PU= github.com/filecoin-project/go-jsonrpc v0.1.5 h1:ckxqZ09ivBAVf5CSmxxrqqNHC7PJm3GYGtYKiNQ+vGk= github.com/filecoin-project/go-jsonrpc v0.1.5/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4= +github.com/filecoin-project/go-legs v0.2.1/go.mod h1:iHDfdqieReblkLoHneB68wvthFtNKB+wkeEWKtiJESk= +github.com/filecoin-project/go-legs v0.2.2 h1:tCCqiXpXw8219/l191phtp7BZbssm7hJcnFFTESs2NI= +github.com/filecoin-project/go-legs v0.2.2/go.mod h1:mdNMISV/bWyZguFM7R4s0mxV1v6Vhda3BiAw9+jv5iE= github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20/go.mod h1:mPn+LRRd5gEKNAtc+r3ScpW2JRU/pj4NBKdADYWHiak= github.com/filecoin-project/go-padreader v0.0.0-20210723183308-812a16dc01b1/go.mod h1:VYVPJqwpsfmtoHnAmPx6MUwmrK6HIcDqZJiuZhtmfLQ= github.com/filecoin-project/go-padreader v0.0.1 h1:8h2tVy5HpoNbr2gBRr+WD6zV6VD6XHig+ynSGJg8ZOs= @@ -361,6 +379,8 @@ github.com/filecoin-project/go-statestore v0.2.0 h1:cRRO0aPLrxKQCZ2UOQbzFGn4WDNd github.com/filecoin-project/go-statestore v0.2.0/go.mod h1:8sjBYbS35HwPzct7iT4lIXjLlYyPor80aU7t7a/Kspo= github.com/filecoin-project/go-storedcounter v0.1.0 h1:Mui6wSUBC+cQGHbDUBcO7rfh5zQkWJM/CpAZa/uOuus= github.com/filecoin-project/go-storedcounter v0.1.0/go.mod h1:4ceukaXi4vFURIoxYMfKzaRF5Xv/Pinh2oTnoxpv+z8= +github.com/filecoin-project/index-provider v0.2.1 h1:jM0ZxEsJhx4WmGgFBtC2ctk2pvu50Rd/LBNNNOcWbQQ= +github.com/filecoin-project/index-provider v0.2.1/go.mod h1:T3Ct7dqS7GDtotzFk/cNe0fzhoPLLk8htiXMK+xQfHU= github.com/filecoin-project/specs-actors v0.9.13/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= github.com/filecoin-project/specs-actors v0.9.14 h1:68PVstg2UB3ZsMLF+DKFTAs/YKsqhKWynkr0IqmVRQY= github.com/filecoin-project/specs-actors v0.9.14/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= @@ -384,9 +404,13 @@ github.com/filecoin-project/specs-actors/v7 v7.0.0-rc1 h1:FuDaXIbcw2hRsFI8SDTmsG github.com/filecoin-project/specs-actors/v7 v7.0.0-rc1/go.mod h1:TA5FwCna+Yi36POaT7SLKXsgEDvJwc0V/L6ZsO19B9M= github.com/filecoin-project/specs-storage v0.1.1-0.20211228030229-6d460d25a0c9 h1:oUYOvF7EvdXS0Zmk9mNkaB6Bu0l+WXBYPzVodKMiLug= github.com/filecoin-project/specs-storage v0.1.1-0.20211228030229-6d460d25a0c9/go.mod h1:Tb88Zq+IBJbvAn3mS89GYj3jdRThBTE/771HCVZdRJU= +github.com/filecoin-project/storetheindex v0.2.2/go.mod h1:05vxs5u3vTQFAwGW9+pgWSMc3BgFOK513nPyIQyLwyQ= +github.com/filecoin-project/storetheindex v0.2.3 h1:YXA1qWQv/tRzvuqcPUt4kQbIgxFdKP32SPjWTefhOGw= +github.com/filecoin-project/storetheindex v0.2.3/go.mod h1:US7ddOKCI+KQFcC3ipKuhK3i46EYlSCt5EvPhxBLfWI= github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg= github.com/filecoin-project/test-vectors/schema v0.0.5/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6/go.mod h1:1i71OnUq3iUe1ma7Lr6yG6/rjvM3emb6yoL7xLFzcVQ= github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ= github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= @@ -399,8 +423,14 @@ github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss= github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= +github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= +github.com/gabriel-vasile/mimetype v1.4.0/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8= +github.com/gammazero/keymutex v0.0.2 h1:cmpLBJHdEwn+WlR5Z/o9/BN92znSZTp5AKPQDpu1QcI= +github.com/gammazero/keymutex v0.0.2/go.mod h1:qtzWCCLMisQUmVa4dvqHVgwfh4BP2YB7JxNDGXnsKrs= +github.com/gammazero/radixtree v0.2.5 h1:muPQ4eEgCkUymFWPiVQRuXOQv4IhWg8YXH2r71MoqPM= +github.com/gammazero/radixtree v0.2.5/go.mod h1:VPqqCDZ3YZZxAzUUsIF/ytFBigVWV7JIV1Stld8hri0= github.com/gbrlsnchs/jwt/v3 v3.0.1 h1:lbUmgAKpxnClrKloyIwpxm4OuWeDl5wLk52G91ODPw4= github.com/gbrlsnchs/jwt/v3 v3.0.1/go.mod h1:AncDcjXz18xetI3A6STfXq2w+LuTx8pQ8bGEwRN8zVM= github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= @@ -409,6 +439,7 @@ github.com/gdamore/tcell/v2 v2.2.0 h1:vSyEgKwraXPSOkvCk7IwOSyX+Pv3V2cV9CikJMXg4U github.com/gdamore/tcell/v2 v2.2.0/go.mod h1:cTTuF84Dlj/RqmaCIV5p4w8uG1zWdk0SF6oBpwHp4fU= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/go-bindata/go-bindata/v3 v3.1.3/go.mod h1:1/zrpXsLD8YDIbhZRqXzm1Ghc7NhEvIN9+Z6R5/xH4I= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -665,6 +696,8 @@ github.com/ipfs/go-bitfield v1.0.0/go.mod h1:N/UiujQy+K+ceU1EF5EkVd1TNqevLrCQMIc github.com/ipfs/go-bitswap v0.0.9/go.mod h1:kAPf5qgn2W2DrgAcscZ3HrM9qh4pH+X8Fkk3UPrwvis= github.com/ipfs/go-bitswap v0.1.0/go.mod h1:FFJEf18E9izuCqUtHxbWEvq+reg7o4CW5wSAE1wsxj0= github.com/ipfs/go-bitswap v0.1.2/go.mod h1:qxSWS4NXGs7jQ6zQvoPY3+NmOfHHG47mhkiLzBpJQIs= +github.com/ipfs/go-bitswap v0.1.8/go.mod h1:TOWoxllhccevbWFUR2N7B1MTSVVge1s6XSMiCSA4MzM= +github.com/ipfs/go-bitswap v0.3.4/go.mod h1:4T7fvNv/LmOys+21tnLzGKncMeeXUYUd1nUiJ2teMvI= github.com/ipfs/go-bitswap v0.5.1 h1:721YAEDBnLIrvcIMkCHCdqp34hA8jwL9yKMkyJpSpco= github.com/ipfs/go-bitswap v0.5.1/go.mod h1:P+ckC87ri1xFLvk74NlXdP0Kj9RmWAh4+H78sC6Qopo= github.com/ipfs/go-block-format v0.0.1/go.mod h1:DK/YYcsSUIVAFNwo/KZCdIIbpN0ROH/baNLgayt4pFc= @@ -673,6 +706,9 @@ github.com/ipfs/go-block-format v0.0.3 h1:r8t66QstRp/pd/or4dpnbVfXT5Gt7lOqRvC+/d github.com/ipfs/go-block-format v0.0.3/go.mod h1:4LmD4ZUw0mhO+JSKdpWwrzATiEfM7WWgQ8H5l6P8MVk= github.com/ipfs/go-blockservice v0.0.7/go.mod h1:EOfb9k/Y878ZTRY/CH0x5+ATtaipfbRhbvNSdgc/7So= github.com/ipfs/go-blockservice v0.1.0/go.mod h1:hzmMScl1kXHg3M2BjTymbVPjv627N7sYcvYaKbop39M= +github.com/ipfs/go-blockservice v0.1.3/go.mod h1:OTZhFpkgY48kNzbgyvcexW9cHrpjBYIjSR0KoDOFOLU= +github.com/ipfs/go-blockservice v0.1.4/go.mod h1:OTZhFpkgY48kNzbgyvcexW9cHrpjBYIjSR0KoDOFOLU= +github.com/ipfs/go-blockservice v0.1.7/go.mod h1:GmS+BAt4hrwBKkzE11AFDQUrnvqjwFatGS2MY7wOjEM= github.com/ipfs/go-blockservice v0.2.1 h1:NJ4j/cwEfIg60rzAWcCIxRtOwbf6ZPK49MewNxObCPQ= github.com/ipfs/go-blockservice v0.2.1/go.mod h1:k6SiwmgyYgs4M/qt+ww6amPeUH9EISLRBnvUurKJhi8= github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= @@ -695,8 +731,11 @@ github.com/ipfs/go-datastore v0.1.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRV github.com/ipfs/go-datastore v0.3.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= github.com/ipfs/go-datastore v0.4.0/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= github.com/ipfs/go-datastore v0.4.1/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= +github.com/ipfs/go-datastore v0.4.2/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= github.com/ipfs/go-datastore v0.4.4/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= github.com/ipfs/go-datastore v0.4.5/go.mod h1:eXTcaaiN6uOlVCLS9GjJUJtlvJfM3xk23w3fyfrmmJs= +github.com/ipfs/go-datastore v0.4.6/go.mod h1:XSipLSc64rFKSFRFGo1ecQl+WhYce3K7frtpHkyPFUc= +github.com/ipfs/go-datastore v0.4.7-0.20211013204805-28a3721c2e66/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk= github.com/ipfs/go-datastore v0.5.0/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk= github.com/ipfs/go-datastore v0.5.1 h1:WkRhLuISI+XPD0uk3OskB0fYFSyqK8Ob5ZYew9Qa1nQ= github.com/ipfs/go-datastore v0.5.1/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk= @@ -707,11 +746,13 @@ github.com/ipfs/go-ds-badger v0.0.5/go.mod h1:g5AuuCGmr7efyzQhLL8MzwqcauPojGPUaH github.com/ipfs/go-ds-badger v0.0.7/go.mod h1:qt0/fWzZDoPW6jpQeqUjR5kBfhDNB65jd9YlmAvpQBk= github.com/ipfs/go-ds-badger v0.2.1/go.mod h1:Tx7l3aTph3FMFrRS838dcSJh+jjA7cX9DrGVwx/NOwE= github.com/ipfs/go-ds-badger v0.2.3/go.mod h1:pEYw0rgg3FIrywKKnL+Snr+w/LjJZVMTBRn4FS6UHUk= +github.com/ipfs/go-ds-badger v0.2.6/go.mod h1:02rnztVKA4aZwDuaRPTf8mpqcKmXP7mLl6JPxd14JHA= github.com/ipfs/go-ds-badger v0.2.7/go.mod h1:02rnztVKA4aZwDuaRPTf8mpqcKmXP7mLl6JPxd14JHA= github.com/ipfs/go-ds-badger v0.3.0 h1:xREL3V0EH9S219kFFueOYJJTcjgNSZ2HY1iSvN7U1Ro= github.com/ipfs/go-ds-badger v0.3.0/go.mod h1:1ke6mXNqeV8K3y5Ak2bAA0osoTfmxUdupVCGm4QUIek= github.com/ipfs/go-ds-badger2 v0.1.2 h1:sQc2q1gaXrv8YFNeUtxil0neuyDf9hnVHfLsi7lpXfE= github.com/ipfs/go-ds-badger2 v0.1.2/go.mod h1:3FtQmDv6fMubygEfU43bsFelYpIiXX/XEYA54l9eCwg= +github.com/ipfs/go-ds-flatfs v0.5.1/go.mod h1:RWTV7oZD/yZYBKdbVIFXTX2fdY2Tbvl94NsWqmoyAX4= github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= github.com/ipfs/go-ds-leveldb v0.1.0/go.mod h1:hqAW8y4bwX5LWcCtku2rFNX3vjDZCy5LZCg+cSZvYb8= github.com/ipfs/go-ds-leveldb v0.4.1/go.mod h1:jpbku/YqBSsBc1qgME8BkWS4AxzF2cEu1Ii2r79Hh9s= @@ -720,15 +761,29 @@ github.com/ipfs/go-ds-leveldb v0.5.0 h1:s++MEBbD3ZKc9/8/njrn4flZLnCuY9I79v94gBUN github.com/ipfs/go-ds-leveldb v0.5.0/go.mod h1:d3XG9RUDzQ6V4SHi8+Xgj9j1XuEk1z82lquxrVbml/Q= github.com/ipfs/go-ds-measure v0.2.0 h1:sG4goQe0KDTccHMyT45CY1XyUbxe5VwTKpg2LjApYyQ= github.com/ipfs/go-ds-measure v0.2.0/go.mod h1:SEUD/rE2PwRa4IQEC5FuNAmjJCyYObZr9UvVh8V3JxE= +github.com/ipfs/go-fetcher v1.5.0/go.mod h1:5pDZ0393oRF/fHiLmtFZtpMNBQfHOYNPtryWedVuSWE= +github.com/ipfs/go-fetcher v1.6.1/go.mod h1:27d/xMV8bodjVs9pugh/RCjjK2OZ68UgAMspMdingNo= +github.com/ipfs/go-filestore v0.1.0/go.mod h1:0KTrzoJnJ3sJDEDM09Vq8nz8H475rRyeq4i0n/bpF00= github.com/ipfs/go-filestore v1.1.0 h1:Pu4tLBi1bucu6/HU9llaOmb9yLFk/sgP+pW764zNDoE= github.com/ipfs/go-filestore v1.1.0/go.mod h1:6e1/5Y6NvLuCRdmda/KA4GUhXJQ3Uat6vcWm2DJfxc8= -github.com/ipfs/go-fs-lock v0.0.6 h1:sn3TWwNVQqSeNjlWy6zQ1uUGAZrV3hPOyEA6y1/N2a0= github.com/ipfs/go-fs-lock v0.0.6/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28L7zESmM= +github.com/ipfs/go-fs-lock v0.0.7 h1:6BR3dajORFrFTkb5EpCUFIAypsoxpGpDSVUdFwzgL9U= +github.com/ipfs/go-fs-lock v0.0.7/go.mod h1:Js8ka+FNYmgQRLrRXzU3CB/+Csr1BwrRilEcvYrHhhc= +github.com/ipfs/go-graphsync v0.10.0/go.mod h1:cKIshzTaa5rCZjryH5xmSKZVGX9uk1wvwGvz2WEha5Y= +github.com/ipfs/go-graphsync v0.11.0/go.mod h1:wC+c8vGVjAHthsVIl8LKr37cUra2GOaMYcQNNmMxDqE= +github.com/ipfs/go-graphsync v0.11.5/go.mod h1:+/sZqRwRCQRrV7NCzgBtufmr5QGpUE98XSa7NlsztmM= github.com/ipfs/go-graphsync v0.12.0 h1:QCsVHVzb9FTkcm3NEa8GjXnUeGit1L9s08HcSVQ4m/g= github.com/ipfs/go-graphsync v0.12.0/go.mod h1:nASYWYETgsnMbQ3+DirNImOHQ8TY0a5AhAqyOY55tUg= +github.com/ipfs/go-ipfs v0.11.0/go.mod h1:g68Thu2Ho11AWoHsN34P5fSK7iA6OWWRy3T/g8HLixc= github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08= github.com/ipfs/go-ipfs-blockstore v0.1.0/go.mod h1:5aD0AvHPi7mZc6Ci1WCAhiBQu2IsfTduLl+422H6Rqw= +github.com/ipfs/go-ipfs-blockstore v0.1.4/go.mod h1:Jxm3XMVjh6R17WvxFEiyKBLUGr86HgIYJW/D/MwqeYQ= +github.com/ipfs/go-ipfs-blockstore v0.1.6/go.mod h1:Jxm3XMVjh6R17WvxFEiyKBLUGr86HgIYJW/D/MwqeYQ= github.com/ipfs/go-ipfs-blockstore v0.2.1/go.mod h1:jGesd8EtCM3/zPgx+qr0/feTXGUeRai6adgwC+Q+JvE= +github.com/ipfs/go-ipfs-blockstore v1.0.1/go.mod h1:MGNZlHNEnR4KGgPHM3/k8lBySIOK2Ve+0KjZubKlaOE= +github.com/ipfs/go-ipfs-blockstore v1.0.4-0.20210205083733-fb07d7bc5aec/go.mod h1:feuklK+m9POeWJzYQO7l05yNEgUiX5oELBNA8/Be33E= +github.com/ipfs/go-ipfs-blockstore v1.0.4/go.mod h1:uL7/gTJ8QIZ3MtA3dWf+s1a0U3fJy2fcEZAsovpRp+w= +github.com/ipfs/go-ipfs-blockstore v1.1.0/go.mod h1:5QDUApRqpgPcfGstCxYeMnjt/DYQtXXdJVCvxHHuWVk= github.com/ipfs/go-ipfs-blockstore v1.1.1/go.mod h1:w51tNR9y5+QXB0wkNcHt4O2aSZjTdqaEWaQdSxEyUOY= github.com/ipfs/go-ipfs-blockstore v1.1.2 h1:WCXoZcMYnvOTmlpX+RSSnhVN0uCmbWTeepTGX5lgiXw= github.com/ipfs/go-ipfs-blockstore v1.1.2/go.mod h1:w51tNR9y5+QXB0wkNcHt4O2aSZjTdqaEWaQdSxEyUOY= @@ -737,15 +792,18 @@ github.com/ipfs/go-ipfs-blocksutil v0.0.1/go.mod h1:Yq4M86uIOmxmGPUHv/uI7uKqZNtL github.com/ipfs/go-ipfs-chunker v0.0.1/go.mod h1:tWewYK0we3+rMbOh7pPFGDyypCtvGcBFymgY4rSDLAw= github.com/ipfs/go-ipfs-chunker v0.0.5 h1:ojCf7HV/m+uS2vhUGWcogIIxiO5ubl5O57Q7NapWLY8= github.com/ipfs/go-ipfs-chunker v0.0.5/go.mod h1:jhgdF8vxRHycr00k13FM8Y0E+6BoalYeobXmUyTreP8= -github.com/ipfs/go-ipfs-cmds v0.3.0 h1:mi9oYrSCox5aBhutqAYqw6/9crlyGbw4E/aJtwS4zI4= github.com/ipfs/go-ipfs-cmds v0.3.0/go.mod h1:ZgYiWVnCk43ChwoH8hAmI1IRbuVtq3GSTHwtRB/Kqhk= -github.com/ipfs/go-ipfs-config v0.5.3 h1:3GpI/xR9FoJNTjU6YvCMRbYyEi0dBVY5UtlUTcNRlSA= +github.com/ipfs/go-ipfs-cmds v0.6.0 h1:yAxdowQZzoFKjcLI08sXVNnqVj3jnABbf9smrPQmBsw= +github.com/ipfs/go-ipfs-cmds v0.6.0/go.mod h1:ZgYiWVnCk43ChwoH8hAmI1IRbuVtq3GSTHwtRB/Kqhk= github.com/ipfs/go-ipfs-config v0.5.3/go.mod h1:nSLCFtlaL+2rbl3F+9D4gQZQbT1LjRKx7TJg/IHz6oM= +github.com/ipfs/go-ipfs-config v0.18.0 h1:Ta1aNGNEq6RIvzbw7dqzCVZJKb7j+Dd35JFnAOCpT8g= +github.com/ipfs/go-ipfs-config v0.18.0/go.mod h1:wz2lKzOjgJeYJa6zx8W9VT7mz+iSd0laBMqS/9wmX6A= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= github.com/ipfs/go-ipfs-delay v0.0.1 h1:r/UXYyRcddO6thwOnhiznIAiSvxMECGgtv35Xs1IeRQ= github.com/ipfs/go-ipfs-delay v0.0.1/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= github.com/ipfs/go-ipfs-ds-help v0.0.1/go.mod h1:gtP9xRaZXqIQRh1HRpp595KbBEdgqWFxefeVKOV8sxo= github.com/ipfs/go-ipfs-ds-help v0.1.1/go.mod h1:SbBafGJuGsPI/QL3j9Fc5YPLeAu+SzOkI0gFwAg+mOs= +github.com/ipfs/go-ipfs-ds-help v1.0.0/go.mod h1:ujAbkeIgkKAWtxxNkoZHWLCyk5JpPoKnGyCcsoF6ueE= github.com/ipfs/go-ipfs-ds-help v1.1.0 h1:yLE2w9RAsl31LtfMt91tRZcrx+e61O5mDxFRR994w4Q= github.com/ipfs/go-ipfs-ds-help v1.1.0/go.mod h1:YR5+6EaebOhfcqVCyqemItCLthrpVNot+rsOU/5IatU= github.com/ipfs/go-ipfs-exchange-interface v0.0.1/go.mod h1:c8MwfHjtQjPoDyiy9cFquVtVHkO9b9Ob3FG91qJnWCM= @@ -761,11 +819,14 @@ github.com/ipfs/go-ipfs-files v0.0.9 h1:OFyOfmuVDu9c5YtjSDORmwXzE6fmZikzZpzsnNkg github.com/ipfs/go-ipfs-files v0.0.9/go.mod h1:aFv2uQ/qxWpL/6lidWvnSQmaVqCrf0TBGoUr+C1Fo84= github.com/ipfs/go-ipfs-http-client v0.0.6 h1:k2QllZyP7Fz5hMgsX5hvHfn1WPG9Ngdy5WknQ7JNhBM= github.com/ipfs/go-ipfs-http-client v0.0.6/go.mod h1:8e2dQbntMZKxLfny+tyXJ7bJHZFERp/2vyzZdvkeLMc= +github.com/ipfs/go-ipfs-keystore v0.0.2/go.mod h1:H49tRmibOEs7gLMgbOsjC4dqh1u5e0R/SWuc2ScfgSo= +github.com/ipfs/go-ipfs-pinner v0.2.1/go.mod h1:l1AtLL5bovb7opnG77sh4Y10waINz3Y1ni6CvTzx7oo= github.com/ipfs/go-ipfs-posinfo v0.0.1 h1:Esoxj+1JgSjX0+ylc0hUmJCOv6V2vFoZiETLR6OtpRs= github.com/ipfs/go-ipfs-posinfo v0.0.1/go.mod h1:SwyeVP+jCwiDu0C313l/8jg6ZxM0qqtlt2a0vILTc1A= github.com/ipfs/go-ipfs-pq v0.0.1/go.mod h1:LWIqQpqfRG3fNc5XsnIhz/wQ2XXGyugQwls7BgUmUfY= github.com/ipfs/go-ipfs-pq v0.0.2 h1:e1vOOW6MuOwG2lqxcLA+wEn93i/9laCY8sXAw76jFOY= github.com/ipfs/go-ipfs-pq v0.0.2/go.mod h1:LWIqQpqfRG3fNc5XsnIhz/wQ2XXGyugQwls7BgUmUfY= +github.com/ipfs/go-ipfs-provider v0.7.1/go.mod h1:QwdDYRYnC5sYGLlOwVDY/0ZB6T3zcMtu+5+GdGeUuw8= github.com/ipfs/go-ipfs-routing v0.0.1/go.mod h1:k76lf20iKFxQTjcJokbPM9iBXVXVZhcOwc360N4nuKs= github.com/ipfs/go-ipfs-routing v0.1.0/go.mod h1:hYoUkJLyAUKhF58tysKpids8RNDPO42BVMgK5dNsoqY= github.com/ipfs/go-ipfs-routing v0.2.1 h1:E+whHWhJkdN9YeoHZNj5itzc+OR292AJ2uE9FFiW0BY= @@ -784,6 +845,7 @@ github.com/ipfs/go-ipld-format v0.0.1/go.mod h1:kyJtbkDALmFHv3QR6et67i35QzO3S0dC github.com/ipfs/go-ipld-format v0.0.2/go.mod h1:4B6+FM2u9OJ9zCV+kSbgFAZlOrv1Hqbf0INGQgiKf9k= github.com/ipfs/go-ipld-format v0.2.0 h1:xGlJKkArkmBvowr+GMCX0FEZtkro71K1AwiKnL37mwA= github.com/ipfs/go-ipld-format v0.2.0/go.mod h1:3l3C1uKoadTPbeNfrDi+xMInYKlx2Cvg1BuydPSdzQs= +github.com/ipfs/go-ipld-git v0.1.1/go.mod h1:+VyMqF5lMcJh4rwEppV0e6g4nCCHXThLYYDpKUkJubI= github.com/ipfs/go-ipld-legacy v0.1.0/go.mod h1:86f5P/srAmh9GcIcWQR9lfFLZPrIyyXQeVlOWeeWEuI= github.com/ipfs/go-ipld-legacy v0.1.1 h1:BvD8PEuqwBHLTKqlGFTHSwrwFOMkVESEvwIYwR2cdcc= github.com/ipfs/go-ipld-legacy v0.1.1/go.mod h1:8AyKFCjgRPsQFf15ZQgDB8Din4DML/fOmKZkkFkrIEg= @@ -814,39 +876,49 @@ github.com/ipfs/go-merkledag v0.0.6/go.mod h1:QYPdnlvkOg7GnQRofu9XZimC5ZW5Wi3bKy github.com/ipfs/go-merkledag v0.2.3/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= github.com/ipfs/go-merkledag v0.2.4/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= github.com/ipfs/go-merkledag v0.3.2/go.mod h1:fvkZNNZixVW6cKSZ/JfLlON5OlgTXNdRLz0p6QG/I2M= +github.com/ipfs/go-merkledag v0.4.0/go.mod h1:XshXBkhyeS63YNGisLL1uDSfuTyrQIxVUOg3ojR5MOE= github.com/ipfs/go-merkledag v0.5.1 h1:tr17GPP5XtPhvPPiWtu20tSGZiZDuTaJRXBLcr79Umk= github.com/ipfs/go-merkledag v0.5.1/go.mod h1:cLMZXx8J08idkp5+id62iVftUQV+HlYJ3PIhDfZsjA4= github.com/ipfs/go-metrics-interface v0.0.1 h1:j+cpbjYvu4R8zbleSs36gvB7jR+wsL2fGD6n0jO4kdg= github.com/ipfs/go-metrics-interface v0.0.1/go.mod h1:6s6euYU4zowdslK0GKHmqaIZ3j/b/tL7HTWtJ4VPgWY= github.com/ipfs/go-metrics-prometheus v0.0.2 h1:9i2iljLg12S78OhC6UAiXi176xvQGiZaGVF1CUVdE+s= github.com/ipfs/go-metrics-prometheus v0.0.2/go.mod h1:ELLU99AQQNi+zX6GCGm2lAgnzdSH3u5UVlCdqSXnEks= +github.com/ipfs/go-mfs v0.2.1/go.mod h1:Woj80iuw4ajDnIP6+seRaoHpPsc9hmL0pk/nDNDWP88= +github.com/ipfs/go-namesys v0.4.0/go.mod h1:jpJwzodyP8DZdWN6DShRjVZw6gaqMr4nQLBSxU5cR6E= github.com/ipfs/go-path v0.0.7 h1:H06hKMquQ0aYtHiHryOMLpQC1qC3QwXwkahcEVD51Ho= github.com/ipfs/go-path v0.0.7/go.mod h1:6KTKmeRnBXgqrTvzFrPV3CamxcgvXX/4z79tfAd2Sno= github.com/ipfs/go-peertaskqueue v0.0.4/go.mod h1:03H8fhyeMfKNFWqzYEVyMbcPUeYrqP1MX6Kd+aN+rMQ= github.com/ipfs/go-peertaskqueue v0.1.0/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= +github.com/ipfs/go-peertaskqueue v0.1.1/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= +github.com/ipfs/go-peertaskqueue v0.2.0/go.mod h1:5/eNrBEbtSKWCG+kQK8K8fGNixoYUnr+P7jivavs9lY= github.com/ipfs/go-peertaskqueue v0.7.0/go.mod h1:M/akTIE/z1jGNXMU7kFB4TeSEFvj68ow0Rrb04donIU= github.com/ipfs/go-peertaskqueue v0.7.1 h1:7PLjon3RZwRQMgOTvYccZ+mjzkmds/7YzSWKFlBAypE= github.com/ipfs/go-peertaskqueue v0.7.1/go.mod h1:M/akTIE/z1jGNXMU7kFB4TeSEFvj68ow0Rrb04donIU= +github.com/ipfs/go-pinning-service-http-client v0.1.0/go.mod h1:tcCKmlkWWH9JUUkKs8CrOZBanacNc1dmKLfjlyXAMu4= github.com/ipfs/go-todocounter v0.0.1/go.mod h1:l5aErvQc8qKE2r7NDMjmq5UNAvuZy0rC8BHOplkWvZ4= github.com/ipfs/go-unixfs v0.2.2-0.20190827150610-868af2e9e5cb/go.mod h1:IwAAgul1UQIcNZzKPYZWOCijryFBeCV79cNubPzol+k= github.com/ipfs/go-unixfs v0.2.4/go.mod h1:SUdisfUjNoSDzzhGVxvCL9QO/nKdwXdr+gbMUdqcbYw= +github.com/ipfs/go-unixfs v0.2.6/go.mod h1:GTTzQvaZsTZARdNkkdjDKFFnBhmO3e5mIM1PkH/x4p0= github.com/ipfs/go-unixfs v0.3.1 h1:LrfED0OGfG98ZEegO4/xiprx2O+yS+krCMQSp7zLVv8= github.com/ipfs/go-unixfs v0.3.1/go.mod h1:h4qfQYzghiIc8ZNFKiLMFWOTzrWIAtzYQ59W/pCFf1o= +github.com/ipfs/go-unixfsnode v1.1.3/go.mod h1:ZZxUM5wXBC+G0Co9FjrYTOm+UlhZTjxLfRYdWY9veZ4= github.com/ipfs/go-unixfsnode v1.2.0 h1:tHHBJftsJyHGa8bS62PpkYNqHy/Sug3c/vxxC8NaGQY= github.com/ipfs/go-unixfsnode v1.2.0/go.mod h1:mQEgLjxkV/1mohkC4p7taRRBYPBeXu97SA3YaerT2q0= github.com/ipfs/go-verifcid v0.0.1 h1:m2HI7zIuR5TFyQ1b79Da5N9dnnCP1vcu2QqawmWlK2E= github.com/ipfs/go-verifcid v0.0.1/go.mod h1:5Hrva5KBeIog4A+UpqlaIU+DEstipcJYQQZc0g37pY0= -github.com/ipfs/interface-go-ipfs-core v0.4.0 h1:+mUiamyHIwedqP8ZgbCIwpy40oX7QcXUbo4CZOeJVJg= github.com/ipfs/interface-go-ipfs-core v0.4.0/go.mod h1:UJBcU6iNennuI05amq3FQ7g0JHUkibHFAfhfUIy927o= +github.com/ipfs/interface-go-ipfs-core v0.5.2 h1:m1/5U+WpOK2ZE7Qzs5iIu80QM1ZA3aWYi2Ilwpi+tdg= +github.com/ipfs/interface-go-ipfs-core v0.5.2/go.mod h1:lNBJrdXHtWS46evMPBdWtDQMDsrKcGbxCOGoKLkztOE= github.com/ipfs/iptb v1.4.0 h1:YFYTrCkLMRwk/35IMyC6+yjoQSHTEcNcefBStLJzgvo= github.com/ipfs/iptb v1.4.0/go.mod h1:1rzHpCYtNp87/+hTxG5TfCVn/yMY3dKnLn8tBiMfdmg= github.com/ipfs/iptb-plugins v0.3.0 h1:C1rpq1o5lUZtaAOkLIox5akh6ba4uk/3RwWc6ttVxw0= github.com/ipfs/iptb-plugins v0.3.0/go.mod h1:5QtOvckeIw4bY86gSH4fgh3p3gCSMn3FmIKr4gaBncA= +github.com/ipfs/tar-utils v0.0.2/go.mod h1:4qlnRWgTVljIMhSG2SqRYn66NT+3wrv/kZt9V+eqxDM= github.com/ipld/go-car v0.1.0/go.mod h1:RCWzaUh2i4mOEkB3W45Vc+9jnS/M6Qay5ooytiBHl3g= +github.com/ipld/go-car v0.3.2/go.mod h1:WEjynkVt04dr0GwJhry0KlaTeSDEiEYyMPOxDBQ17KE= github.com/ipld/go-car v0.3.3-0.20211210032800-e6f244225a16/go.mod h1:/wkKF4908ULT4dFIFIUZYcfjAnj+KFnJvlh8Hsz1FbQ= github.com/ipld/go-car v0.3.3 h1:D6y+jvg9h2ZSv7GLUMWUwg5VTLy1E7Ak+uQw5orOg3I= github.com/ipld/go-car v0.3.3/go.mod h1:/wkKF4908ULT4dFIFIUZYcfjAnj+KFnJvlh8Hsz1FbQ= -github.com/ipld/go-car/v2 v2.1.1-0.20211211000942-be2525f6bf2d/go.mod h1:+2Yvf0Z3wzkv7NeI69i8tuZ+ft7jyjPYIWZzeVNeFcI= github.com/ipld/go-car/v2 v2.1.1 h1:saaKz4nC0AdfCGHLYKeXLGn8ivoPC54fyS55uyOLKwA= github.com/ipld/go-car/v2 v2.1.1/go.mod h1:+2Yvf0Z3wzkv7NeI69i8tuZ+ft7jyjPYIWZzeVNeFcI= github.com/ipld/go-codec-dagpb v1.2.0/go.mod h1:6nBN7X7h8EOsEejZGqC7tej5drsdBAXbMHyBT+Fne5s= @@ -857,8 +929,12 @@ github.com/ipld/go-ipld-prime v0.9.0/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/j github.com/ipld/go-ipld-prime v0.9.1-0.20210324083106-dc342a9917db/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= github.com/ipld/go-ipld-prime v0.10.0/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= github.com/ipld/go-ipld-prime v0.11.0/go.mod h1:+WIAkokurHmZ/KwzDOMUuoeJgaRQktHtEaLglS3ZeV8= +github.com/ipld/go-ipld-prime v0.12.3/go.mod h1:PaeLYq8k6dJLmDUSLrzkEpoGV4PEfe/1OtFN/eALOc8= github.com/ipld/go-ipld-prime v0.14.0/go.mod h1:9ASQLwUFLptCov6lIYc70GRB4V7UTyLD0IJtrDJe6ZM= +github.com/ipld/go-ipld-prime v0.14.1/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= +github.com/ipld/go-ipld-prime v0.14.2/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= github.com/ipld/go-ipld-prime v0.14.3-0.20211207234443-319145880958/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= +github.com/ipld/go-ipld-prime v0.14.3/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= github.com/ipld/go-ipld-prime v0.14.4 h1:bqhmume8+nbNsX4/+J6eohktfZHAI8GKrF3rQ0xgOyc= github.com/ipld/go-ipld-prime v0.14.4/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= github.com/ipld/go-ipld-prime-proto v0.0.0-20191113031812-e32bd156a1e5/go.mod h1:gcvzoEDBjwycpXt3LBE061wT9f46szXGHAmj9uoP6fU= @@ -866,6 +942,9 @@ github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20211210234204-ce2a1c70cd github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20211210234204-ce2a1c70cd73/go.mod h1:2PJ0JgxyB08t0b2WKrcuqI3di0V+5n6RS/LTUJhkoxY= github.com/ipld/go-ipld-selector-text-lite v0.0.1 h1:lNqFsQpBHc3p5xHob2KvEg/iM5dIFn6iw4L/Hh+kS1Y= github.com/ipld/go-ipld-selector-text-lite v0.0.1/go.mod h1:U2CQmFb+uWzfIEF3I1arrDa5rwtj00PrpiwwCO+k1RM= +github.com/ipld/go-storethehash v0.0.0-20210915160027-d72ca9b0968c/go.mod h1:PwE6iq8TiWJRI3zMGA1RtkFAnrDMK93dLA5SUeu0lH8= +github.com/ipld/go-storethehash v0.0.1 h1:U9E9n3dE0IaImSNbRcUmm5Dk9UPiS9H0i+LmCFFGJBI= +github.com/ipld/go-storethehash v0.0.1/go.mod h1:w8cQfWInks8lvvbQTiKbCPusU9v0sqiViBihTHbavpQ= github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52 h1:QG4CGBqCeuBo6aZlGAamSkxWdgWfZGeE49eUOWJPA4c= github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52/go.mod h1:fdg+/X9Gg4AsAIzWpEHwnqd+QY3b7lajxyjE1m4hkq4= github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= @@ -973,6 +1052,7 @@ github.com/libp2p/go-conn-security-multistream v0.2.0/go.mod h1:hZN4MjlNetKD3Rq5 github.com/libp2p/go-conn-security-multistream v0.2.1/go.mod h1:cR1d8gA0Hr59Fj6NhaTpFhJZrjSYuNmhpT2r25zYR70= github.com/libp2p/go-conn-security-multistream v0.3.0 h1:9UCIKlBL1hC9u7nkMXpD1nkc/T53PKMAn3/k9ivBAVc= github.com/libp2p/go-conn-security-multistream v0.3.0/go.mod h1:EEP47t4fw/bTelVmEzIDqSe69hO/ip52xBEhZMLWAHM= +github.com/libp2p/go-doh-resolver v0.3.1/go.mod h1:y5go1ZppAq9N2eppbX0xON01CyPBeUg2yS6BTssssog= github.com/libp2p/go-eventbus v0.0.2/go.mod h1:Hr/yGlwxA/stuLnpMiu82lpNKpvRy3EaJxPu40XYOwk= github.com/libp2p/go-eventbus v0.1.0/go.mod h1:vROgu5cs5T7cv7POWlWxBaVLxfSegC5UGQf8A2eEmx4= github.com/libp2p/go-eventbus v0.2.1 h1:VanAdErQnpTioN2TowqNcOijf6YwhuODe4pPKSDpxGc= @@ -990,8 +1070,12 @@ github.com/libp2p/go-libp2p v0.6.1/go.mod h1:CTFnWXogryAHjXAKEbOf1OWY+VeAP3lDMZk github.com/libp2p/go-libp2p v0.7.0/go.mod h1:hZJf8txWeCduQRDC/WSqBGMxaTHCOYHt2xSU1ivxn0k= github.com/libp2p/go-libp2p v0.7.4/go.mod h1:oXsBlTLF1q7pxr+9w6lqzS1ILpyHsaBPniVO7zIHGMw= github.com/libp2p/go-libp2p v0.8.1/go.mod h1:QRNH9pwdbEBpx5DTJYg+qxcVaDMAz3Ee/qDKwXujH5o= +github.com/libp2p/go-libp2p v0.12.0/go.mod h1:FpHZrfC1q7nA8jitvdjKBDF31hguaC676g/nT9PgQM0= +github.com/libp2p/go-libp2p v0.13.0/go.mod h1:pM0beYdACRfHO1WcJlp65WXyG2A6NqYM+t2DTVAJxMo= +github.com/libp2p/go-libp2p v0.14.0/go.mod h1:dsQrWLAoIn+GkHPN/U+yypizkHiB9tnv79Os+kSgQ4Q= github.com/libp2p/go-libp2p v0.14.3/go.mod h1:d12V4PdKbpL0T1/gsUNN8DfgMuRPDX8bS2QxCZlwRH0= github.com/libp2p/go-libp2p v0.14.4/go.mod h1:EIRU0Of4J5S8rkockZM7eJp2S0UrCyi55m2kJVru3rM= +github.com/libp2p/go-libp2p v0.15.0/go.mod h1:8Ljmwon0cZZYKrOCjFeLwQEK8bqR42dOheUZ1kSKhP0= github.com/libp2p/go-libp2p v0.16.0/go.mod h1:ump42BsirwAWxKzsCiFnTtN1Yc+DuPu76fyMX364/O4= github.com/libp2p/go-libp2p v0.17.0/go.mod h1:Fkin50rsGdv5mm5BshBUtPRZknt9esfmYXBOYcwOTgw= github.com/libp2p/go-libp2p v0.18.0-rc1 h1:CFHROLGmMwe/p8tR3sHahg/1NSaZa2EGbu7nDmdC+RY= @@ -1005,6 +1089,7 @@ github.com/libp2p/go-libp2p-autonat v0.1.1/go.mod h1:OXqkeGOY2xJVWKAGV2inNF5aKN/ github.com/libp2p/go-libp2p-autonat v0.2.0/go.mod h1:DX+9teU4pEEoZUqR1PiMlqliONQdNbfzE1C718tcViI= github.com/libp2p/go-libp2p-autonat v0.2.1/go.mod h1:MWtAhV5Ko1l6QBsHQNSuM6b1sRkXrpk0/LqCr+vCVxI= github.com/libp2p/go-libp2p-autonat v0.2.2/go.mod h1:HsM62HkqZmHR2k1xgX34WuWDzk/nBwNHoeyyT4IWV6A= +github.com/libp2p/go-libp2p-autonat v0.4.0/go.mod h1:YxaJlpr81FhdOv3W3BTconZPfhaYivRdf53g+S2wobk= github.com/libp2p/go-libp2p-autonat v0.4.2/go.mod h1:YxaJlpr81FhdOv3W3BTconZPfhaYivRdf53g+S2wobk= github.com/libp2p/go-libp2p-autonat v0.6.0/go.mod h1:bFC6kY8jwzNNWoqc8iGE57vsfwyJ/lP4O4DOV1e0B2o= github.com/libp2p/go-libp2p-autonat v0.7.0/go.mod h1:uPvPn6J7cN+LCfFwW5tpOYvAz5NvPTc4iBamTV/WDMg= @@ -1075,10 +1160,15 @@ github.com/libp2p/go-libp2p-discovery v0.1.0/go.mod h1:4F/x+aldVHjHDHuX85x1zWoFT github.com/libp2p/go-libp2p-discovery v0.2.0/go.mod h1:s4VGaxYMbw4+4+tsoQTqh7wfxg97AEdo4GYBt6BadWg= github.com/libp2p/go-libp2p-discovery v0.3.0/go.mod h1:o03drFnz9BVAZdzC/QUQ+NeQOu38Fu7LJGEOK2gQltw= github.com/libp2p/go-libp2p-discovery v0.5.0/go.mod h1:+srtPIU9gDaBNu//UHvcdliKBIcr4SfDcm0/PfPJLug= +github.com/libp2p/go-libp2p-discovery v0.5.1/go.mod h1:+srtPIU9gDaBNu//UHvcdliKBIcr4SfDcm0/PfPJLug= github.com/libp2p/go-libp2p-discovery v0.6.0 h1:1XdPmhMJr8Tmj/yUfkJMIi8mgwWrLUsCB3bMxdT+DSo= github.com/libp2p/go-libp2p-discovery v0.6.0/go.mod h1:/u1voHt0tKIe5oIA1RHBKQLVCWPna2dXmPNHc2zR9S8= +github.com/libp2p/go-libp2p-gostream v0.3.0/go.mod h1:pLBQu8db7vBMNINGsAwLL/ZCE8wng5V1FThoaE5rNjc= +github.com/libp2p/go-libp2p-gostream v0.3.1 h1:XlwohsPn6uopGluEWs1Csv1QCEjrTXf2ZQagzZ5paAg= +github.com/libp2p/go-libp2p-gostream v0.3.1/go.mod h1:1V3b+u4Zhaq407UUY9JLCpboaeufAeVQbnvAt12LRsI= github.com/libp2p/go-libp2p-host v0.0.1/go.mod h1:qWd+H1yuU0m5CwzAkvbSjqKairayEHdR5MMl7Cwa7Go= github.com/libp2p/go-libp2p-host v0.0.3/go.mod h1:Y/qPyA6C8j2coYyos1dfRm0I8+nvd4TGrDGt4tA7JR8= +github.com/libp2p/go-libp2p-http v0.2.1/go.mod h1:9KdioZ7XqNH0eZkZG9bulZLzHv11A7/12fT97agqWhg= github.com/libp2p/go-libp2p-interface-connmgr v0.0.1/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k= github.com/libp2p/go-libp2p-interface-connmgr v0.0.4/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k= github.com/libp2p/go-libp2p-interface-connmgr v0.0.5/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k= @@ -1099,6 +1189,7 @@ github.com/libp2p/go-libp2p-mplex v0.2.0/go.mod h1:Ejl9IyjvXJ0T9iqUTE1jpYATQ9NM3 github.com/libp2p/go-libp2p-mplex v0.2.1/go.mod h1:SC99Rxs8Vuzrf/6WhmH41kNn13TiYdAWNYHrwImKLnE= github.com/libp2p/go-libp2p-mplex v0.2.2/go.mod h1:74S9eum0tVQdAfFiKxAyKzNdSuLqw5oadDq7+L/FELo= github.com/libp2p/go-libp2p-mplex v0.2.3/go.mod h1:CK3p2+9qH9x+7ER/gWWDYJ3QW5ZxWDkm+dVvjfuG3ek= +github.com/libp2p/go-libp2p-mplex v0.3.0/go.mod h1:l9QWxRbbb5/hQMECEb908GbS9Sm2UAR2KFZKUJEynEs= github.com/libp2p/go-libp2p-mplex v0.4.0/go.mod h1:yCyWJE2sc6TBTnFpjvLuEJgTSw/u+MamvzILKdX7asw= github.com/libp2p/go-libp2p-mplex v0.4.1/go.mod h1:cmy+3GfqfM1PceHTLL7zQzAAYaryDu6iPSC+CIb094g= github.com/libp2p/go-libp2p-mplex v0.5.0 h1:vt3k4E4HSND9XH4Z8rUpacPJFSAgLOv6HDvG8W9Ks9E= @@ -1113,7 +1204,9 @@ github.com/libp2p/go-libp2p-net v0.0.2/go.mod h1:Yt3zgmlsHOgUWSXmt5V/Jpz9upuJBE8 github.com/libp2p/go-libp2p-netutil v0.0.1/go.mod h1:GdusFvujWZI9Vt0X5BKqwWWmZFxecf9Gt03cKxm2f/Q= github.com/libp2p/go-libp2p-netutil v0.1.0 h1:zscYDNVEcGxyUpMd0JReUZTrpMfia8PmLKcKF72EAMQ= github.com/libp2p/go-libp2p-netutil v0.1.0/go.mod h1:3Qv/aDqtMLTUyQeundkKsA+YCThNdbQD54k3TqjpbFU= +github.com/libp2p/go-libp2p-noise v0.1.1/go.mod h1:QDFLdKX7nluB7DEnlVPbz7xlLHdwHFA9HiohJRr3vwM= github.com/libp2p/go-libp2p-noise v0.2.0/go.mod h1:IEbYhBBzGyvdLBoxxULL/SGbJARhUeqlO8lVSREYu2Q= +github.com/libp2p/go-libp2p-noise v0.2.2/go.mod h1:IEbYhBBzGyvdLBoxxULL/SGbJARhUeqlO8lVSREYu2Q= github.com/libp2p/go-libp2p-noise v0.3.0 h1:NCVH7evhVt9njbTQshzT7N1S3Q6fjj9M11FCgfH5+cA= github.com/libp2p/go-libp2p-noise v0.3.0/go.mod h1:JNjHbociDJKHD64KTkzGnzqJ0FEV5gHJa6AB00kbCNQ= github.com/libp2p/go-libp2p-peer v0.0.1/go.mod h1:nXQvOBbwVqoP+T5Y5nCjeH4sP9IX/J0AMzcDUVruVoo= @@ -1138,9 +1231,11 @@ github.com/libp2p/go-libp2p-pnet v0.2.0/go.mod h1:Qqvq6JH/oMZGwqs3N1Fqhv8NVhrdYc github.com/libp2p/go-libp2p-protocol v0.0.1/go.mod h1:Af9n4PiruirSDjHycM1QuiMi/1VZNHYcK8cLgFJLZ4s= github.com/libp2p/go-libp2p-protocol v0.1.0/go.mod h1:KQPHpAabB57XQxGrXCNvbL6UEXfQqUgC/1adR2Xtflk= github.com/libp2p/go-libp2p-pubsub v0.1.1/go.mod h1:ZwlKzRSe1eGvSIdU5bD7+8RZN/Uzw0t1Bp9R1znpR/Q= +github.com/libp2p/go-libp2p-pubsub v0.5.6/go.mod h1:gVOzwebXVdSMDQBTfH8ACO5EJ4SQrvsHqCmYsCZpD0E= github.com/libp2p/go-libp2p-pubsub v0.6.0/go.mod h1:nJv87QM2cU0w45KPR1rZicq+FmFIOD16zmT+ep1nOmg= github.com/libp2p/go-libp2p-pubsub v0.6.1 h1:wycbV+f4rreCoVY61Do6g/BUk0RIrbNRcYVbn+QkjGk= github.com/libp2p/go-libp2p-pubsub v0.6.1/go.mod h1:nJv87QM2cU0w45KPR1rZicq+FmFIOD16zmT+ep1nOmg= +github.com/libp2p/go-libp2p-pubsub-router v0.5.0/go.mod h1:TRJKskSem3C0aSb3CmRgPwq6IleVFzds6hS09fmZbGM= github.com/libp2p/go-libp2p-quic-transport v0.1.1/go.mod h1:wqG/jzhF3Pu2NrhJEvE+IE0NTHNXslOPn9JQzyCAxzU= github.com/libp2p/go-libp2p-quic-transport v0.10.0/go.mod h1:RfJbZ8IqXIhxBRm5hqUEJqjiiY8xmEuq3HUDS993MkA= github.com/libp2p/go-libp2p-quic-transport v0.11.2/go.mod h1:wlanzKtIh6pHrq+0U3p3DY9PJfGqxMgPaGKaK5LifwQ= @@ -1174,6 +1269,8 @@ github.com/libp2p/go-libp2p-swarm v0.2.2/go.mod h1:fvmtQ0T1nErXym1/aa1uJEyN7JzaT github.com/libp2p/go-libp2p-swarm v0.2.3/go.mod h1:P2VO/EpxRyDxtChXz/VPVXyTnszHvokHKRhfkEgFKNM= github.com/libp2p/go-libp2p-swarm v0.2.8/go.mod h1:JQKMGSth4SMqonruY0a8yjlPVIkb0mdNSwckW7OYziM= github.com/libp2p/go-libp2p-swarm v0.3.0/go.mod h1:hdv95GWCTmzkgeJpP+GK/9D9puJegb7H57B5hWQR5Kk= +github.com/libp2p/go-libp2p-swarm v0.3.1/go.mod h1:hdv95GWCTmzkgeJpP+GK/9D9puJegb7H57B5hWQR5Kk= +github.com/libp2p/go-libp2p-swarm v0.4.0/go.mod h1:XVFcO52VoLoo0eitSxNQWYq4D6sydGOweTOAjJNraCw= github.com/libp2p/go-libp2p-swarm v0.5.0/go.mod h1:sU9i6BoHE0Ve5SKz3y9WfKrh8dUat6JknzUehFx8xW4= github.com/libp2p/go-libp2p-swarm v0.5.3/go.mod h1:NBn7eNW2lu568L7Ns9wdFrOhgRlkRnIDg0FLKbuu3i8= github.com/libp2p/go-libp2p-swarm v0.8.0/go.mod h1:sOMp6dPuqco0r0GHTzfVheVBh6UEL0L1lXUZ5ot2Fvc= @@ -1195,6 +1292,7 @@ github.com/libp2p/go-libp2p-testing v0.6.0/go.mod h1:QBk8fqIL1XNcno/l3/hhaIEn4aL github.com/libp2p/go-libp2p-testing v0.7.0 h1:9bfyhNINizxuLrKsenzGaZalXRXIaAEmx1BP/PzF1gM= github.com/libp2p/go-libp2p-testing v0.7.0/go.mod h1:OLbdn9DbgdMwv00v+tlp1l3oe2Cl+FAjoWIA2pa0X6E= github.com/libp2p/go-libp2p-tls v0.1.3/go.mod h1:wZfuewxOndz5RTnCAxFliGjvYSDA40sKitV4c50uI1M= +github.com/libp2p/go-libp2p-tls v0.2.0/go.mod h1:twrp2Ci4lE2GYspA1AnlYm+boYjqVruxDKJJj7s6xrc= github.com/libp2p/go-libp2p-tls v0.3.0/go.mod h1:fwF5X6PWGxm6IDRwF3V8AVCCj/hOd5oFlg+wo2FxJDY= github.com/libp2p/go-libp2p-tls v0.3.1 h1:lsE2zYte+rZCEOHF72J1Fg3XK3dGQyKvI6i5ehJfEp0= github.com/libp2p/go-libp2p-tls v0.3.1/go.mod h1:fwF5X6PWGxm6IDRwF3V8AVCCj/hOd5oFlg+wo2FxJDY= @@ -1204,6 +1302,7 @@ github.com/libp2p/go-libp2p-transport-upgrader v0.0.4/go.mod h1:RGq+tupk+oj7PzL2 github.com/libp2p/go-libp2p-transport-upgrader v0.1.1/go.mod h1:IEtA6or8JUbsV07qPW4r01GnTenLW4oi3lOPbUMGJJA= github.com/libp2p/go-libp2p-transport-upgrader v0.2.0/go.mod h1:mQcrHj4asu6ArfSoMuyojOdjx73Q47cYD7s5+gZOlns= github.com/libp2p/go-libp2p-transport-upgrader v0.3.0/go.mod h1:i+SKzbRnvXdVbU3D1dwydnTmKRPXiAR/fyvi1dXuL4o= +github.com/libp2p/go-libp2p-transport-upgrader v0.4.0/go.mod h1:J4ko0ObtZSmgn5BX5AmegP+dK3CSnU2lMCKsSq/EY0s= github.com/libp2p/go-libp2p-transport-upgrader v0.4.2/go.mod h1:NR8ne1VwfreD5VIWIU62Agt/J18ekORFU/j1i2y8zvk= github.com/libp2p/go-libp2p-transport-upgrader v0.4.3/go.mod h1:bpkldbOWXMrXhpZbSV1mQxTrefOg2Fi+k1ClDSA4ppw= github.com/libp2p/go-libp2p-transport-upgrader v0.4.6/go.mod h1:JE0WQuQdy+uLZ5zOaI3Nw9dWGYJIA7mywEtP2lMvnyk= @@ -1222,6 +1321,8 @@ github.com/libp2p/go-libp2p-yamux v0.2.7/go.mod h1:X28ENrBMU/nm4I3Nx4sZ4dgjZ6VhL github.com/libp2p/go-libp2p-yamux v0.2.8/go.mod h1:/t6tDqeuZf0INZMTgd0WxIRbtK2EzI2h7HbFm9eAKI4= github.com/libp2p/go-libp2p-yamux v0.4.0/go.mod h1:+DWDjtFMzoAwYLVkNZftoucn7PelNoy5nm3tZ3/Zw30= github.com/libp2p/go-libp2p-yamux v0.5.0/go.mod h1:AyR8k5EzyM2QN9Bbdg6X1SkVVuqLwTGf0L4DFq9g6po= +github.com/libp2p/go-libp2p-yamux v0.5.1/go.mod h1:dowuvDu8CRWmr0iqySMiSxK+W0iL5cMVO9S94Y6gkv4= +github.com/libp2p/go-libp2p-yamux v0.5.3/go.mod h1:Vy3TMonBAfTMXHWopsMc8iX/XGRYrRlpUaMzaeuHV/s= github.com/libp2p/go-libp2p-yamux v0.5.4/go.mod h1:tfrXbyaTqqSU654GTvK3ocnSZL3BuHoeTSqhcel1wsE= github.com/libp2p/go-libp2p-yamux v0.6.0/go.mod h1:MRhd6mAYnFRnSISp4M8i0ClV/j+mWHo2mYLifWGw33k= github.com/libp2p/go-libp2p-yamux v0.7.0/go.mod h1:fMyA0CsPfHkIuBU0wjRGrCjTBFiXTXxG0k5M4ETv+08= @@ -1277,6 +1378,7 @@ github.com/libp2p/go-reuseport-transport v0.1.0/go.mod h1:vev0C0uMkzriDY59yFHD9v github.com/libp2p/go-sockaddr v0.0.2/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= github.com/libp2p/go-sockaddr v0.1.0/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= github.com/libp2p/go-sockaddr v0.1.1/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= +github.com/libp2p/go-socket-activation v0.1.0/go.mod h1:gzda2dNkMG5Ti2OfWNNwW0FDIbj0g/aJJU320FcLfhk= github.com/libp2p/go-stream-muxer v0.0.1/go.mod h1:bAo8x7YkSpadMTbtTaxGVHWUQsR/l5MEaHbKaliuT14= github.com/libp2p/go-stream-muxer v0.1.0/go.mod h1:8JAVsjeRBCWwPoZeH0W1imLOcriqXJyFvB0mR4A04sQ= github.com/libp2p/go-stream-muxer-multistream v0.1.1/go.mod h1:zmGdfkQ1AzOECIAcccoL8L//laqawOsO03zX8Sa+eGw= @@ -1288,9 +1390,11 @@ github.com/libp2p/go-tcp-transport v0.0.4/go.mod h1:+E8HvC8ezEVOxIo3V5vCK9l1y/19 github.com/libp2p/go-tcp-transport v0.1.0/go.mod h1:oJ8I5VXryj493DEJ7OsBieu8fcg2nHGctwtInJVpipc= github.com/libp2p/go-tcp-transport v0.1.1/go.mod h1:3HzGvLbx6etZjnFlERyakbaYPdfjg2pWP97dFZworkY= github.com/libp2p/go-tcp-transport v0.2.0/go.mod h1:vX2U0CnWimU4h0SGSEsg++AzvBcroCGYw28kh94oLe0= +github.com/libp2p/go-tcp-transport v0.2.1/go.mod h1:zskiJ70MEfWz2MKxvFB/Pv+tPIB1PpPUrHIWQ8aFw7M= github.com/libp2p/go-tcp-transport v0.2.3/go.mod h1:9dvr03yqrPyYGIEN6Dy5UvdJZjyPFvl1S/igQ5QD1SU= github.com/libp2p/go-tcp-transport v0.2.4/go.mod h1:9dvr03yqrPyYGIEN6Dy5UvdJZjyPFvl1S/igQ5QD1SU= github.com/libp2p/go-tcp-transport v0.2.7/go.mod h1:lue9p1b3VmZj1MhhEGB/etmvF/nBQ0X9CW2DutBT3MM= +github.com/libp2p/go-tcp-transport v0.2.8/go.mod h1:64rSfVidkYPLqbzpcN2IwHY4pmgirp67h++hZ/rcndQ= github.com/libp2p/go-tcp-transport v0.4.0/go.mod h1:0y52Rwrn4076xdJYu/51/qJIdxz+EWDAOG2S45sV3VI= github.com/libp2p/go-tcp-transport v0.5.0 h1:3ZPW8HAuyRAuFzyabE0hSrCXKKSWzROnZZX7DtcIatY= github.com/libp2p/go-tcp-transport v0.5.0/go.mod h1:UPPL0DIjQqiWRwVAb+CEQlaAG0rp/mCqJfIhFcLHc4Y= @@ -1301,6 +1405,7 @@ github.com/libp2p/go-ws-transport v0.1.0/go.mod h1:rjw1MG1LU9YDC6gzmwObkPd/Sqwhw github.com/libp2p/go-ws-transport v0.1.2/go.mod h1:dsh2Ld8F+XNmzpkaAijmg5Is+e9l6/1tK/6VFOdN69Y= github.com/libp2p/go-ws-transport v0.2.0/go.mod h1:9BHJz/4Q5A9ludYWKoGCFC5gUElzlHoKzu0yY9p/klM= github.com/libp2p/go-ws-transport v0.3.0/go.mod h1:bpgTJmRZAvVHrgHybCVyqoBmyLQ1fiZuEaBYusP5zsk= +github.com/libp2p/go-ws-transport v0.3.1/go.mod h1:bpgTJmRZAvVHrgHybCVyqoBmyLQ1fiZuEaBYusP5zsk= github.com/libp2p/go-ws-transport v0.4.0/go.mod h1:EcIEKqf/7GDjth6ksuS/6p7R49V4CBY6/E7R/iyhYUA= github.com/libp2p/go-ws-transport v0.5.0/go.mod h1:I2juo1dNTbl8BKSBYo98XY85kU2xds1iamArLvl8kNg= github.com/libp2p/go-ws-transport v0.6.0 h1:326XBL6Q+5CQ2KtjXz32+eGu02W/Kz2+Fm4SpXdr0q4= @@ -1315,11 +1420,14 @@ github.com/libp2p/go-yamux v1.3.7/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/h github.com/libp2p/go-yamux v1.4.0/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= github.com/libp2p/go-yamux v1.4.1 h1:P1Fe9vF4th5JOxxgQvfbOHkrGqIZniTLf+ddhZp8YTI= github.com/libp2p/go-yamux v1.4.1/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= +github.com/libp2p/go-yamux/v2 v2.0.0/go.mod h1:NVWira5+sVUIU6tu1JWvaRn1dRnG+cawOJiflsAM+7U= +github.com/libp2p/go-yamux/v2 v2.1.1/go.mod h1:3So6P6TV6r75R9jiBpiIKgU/66lOarCZjqROGxzPpPQ= github.com/libp2p/go-yamux/v2 v2.2.0/go.mod h1:3So6P6TV6r75R9jiBpiIKgU/66lOarCZjqROGxzPpPQ= github.com/libp2p/go-yamux/v2 v2.3.0/go.mod h1:iTU+lOIn/2h0AgKcL49clNTwfEw+WSfDYrXe05EyKIs= github.com/libp2p/go-yamux/v3 v3.0.1/go.mod h1:s2LsDhHbh+RfCsQoICSYt58U2f8ijtPANFD8BmE74Bo= github.com/libp2p/go-yamux/v3 v3.0.2 h1:LW0q5+A1Wy0npEsPJP9wmare2NH4ohNluN5EWVwv2mE= github.com/libp2p/go-yamux/v3 v3.0.2/go.mod h1:s2LsDhHbh+RfCsQoICSYt58U2f8ijtPANFD8BmE74Bo= +github.com/libp2p/zeroconf/v2 v2.0.0/go.mod h1:J85R/d9joD8u8F9aHM8pBXygtG9W02enEwS+wWeL6yo= github.com/libp2p/zeroconf/v2 v2.1.1/go.mod h1:fuJqLnUwZTshS3U/bMRJ3+ow/v9oid1n0DmyYyNO1Xs= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= @@ -1379,6 +1487,7 @@ github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg= github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= @@ -1397,6 +1506,7 @@ github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3N github.com/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.28/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= +github.com/miekg/dns v1.1.31/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= @@ -1464,6 +1574,7 @@ github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/94 github.com/multiformats/go-multiaddr-dns v0.0.3/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.1.0/go.mod h1:01k2RAqtoXIuPa3DCavAE9/6jc6nM0H3EgZyfUhN2oY= github.com/multiformats/go-multiaddr-dns v0.2.0/go.mod h1:TJ5pr5bBO7Y1B18djPuRsVkduhQH2YqYSbxWJzYGdK0= +github.com/multiformats/go-multiaddr-dns v0.3.0/go.mod h1:mNzQ4eTGDg0ll1N9jKPOUogZPoJ30W8a7zk66FQPpdQ= github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A= github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk= github.com/multiformats/go-multiaddr-fmt v0.0.1/go.mod h1:aBYjqL4T/7j4Qx+R73XSv/8JsgnRFlf0w2KGLCmXl3Q= @@ -1483,8 +1594,9 @@ github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPw github.com/multiformats/go-multicodec v0.2.0/go.mod h1:/y4YVwkfMyry5kFbMTbLJKErhycTIftytRV+llXdyS4= github.com/multiformats/go-multicodec v0.3.0/go.mod h1:qGGaQmioCDh+TeFOnxrbU0DaIPw8yFgAZgFG0V7p1qQ= github.com/multiformats/go-multicodec v0.3.1-0.20210902112759-1539a079fd61/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ= -github.com/multiformats/go-multicodec v0.3.1-0.20211210143421-a526f306ed2c h1:VyANTtZ0wsx0IAZnCZhfMmAmfUyzJq/5JQi2hHOtKS0= github.com/multiformats/go-multicodec v0.3.1-0.20211210143421-a526f306ed2c/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ= +github.com/multiformats/go-multicodec v0.4.0 h1:fbqb6ky7erjdD+/zaEBJgZWu1i8D6i/wmPywGK7sdow= +github.com/multiformats/go-multicodec v0.4.0/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ= github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= @@ -1493,12 +1605,14 @@ github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpK github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= github.com/multiformats/go-multihash v0.0.14/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= github.com/multiformats/go-multihash v0.0.15/go.mod h1:D6aZrWNLFTV/ynMpKsNtB40mJzmCl4jb1alC0OvHiHg= +github.com/multiformats/go-multihash v0.0.16/go.mod h1:zhfEIgVnB/rPMfxgFw15ZmGoNaKyNUIE4IWHG/kC+Ag= github.com/multiformats/go-multihash v0.1.0 h1:CgAgwqk3//SVEw3T+6DqI4mWMyRuDwZtOWcJT0q9+EA= github.com/multiformats/go-multihash v0.1.0/go.mod h1:RJlXsxt6vHGaia+S8We0ErjhojtKzPP2AH4+kYM7k84= github.com/multiformats/go-multistream v0.0.1/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= github.com/multiformats/go-multistream v0.0.4/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= github.com/multiformats/go-multistream v0.1.1/go.mod h1:KmHZ40hzVxiaiwlj3MEbYgK9JFk2/9UktWZAF54Du38= +github.com/multiformats/go-multistream v0.2.0/go.mod h1:5GZPQZbkWOLOn3J2y4Y99vVW7vOfsAflxARk3x14o6k= github.com/multiformats/go-multistream v0.2.1/go.mod h1:5GZPQZbkWOLOn3J2y4Y99vVW7vOfsAflxARk3x14o6k= github.com/multiformats/go-multistream v0.2.2 h1:TCYu1BHTDr1F/Qm75qwYISQdzGcRdC21nFgQW7l7GBo= github.com/multiformats/go-multistream v0.2.2/go.mod h1:UIcnm7Zuo8HKG+HkWgfQsGL+/MIEhyTqbODbIUwSXKs= @@ -1781,6 +1895,7 @@ github.com/tj/go-spin v1.1.0 h1:lhdWZsvImxvZ3q1C5OIB7d72DuOwP4O2NdBg9PyzNds= github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= github.com/uber/jaeger-client-go v2.15.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.23.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.25.0+incompatible h1:IxcNZ7WRY1Y3G4poYlx24szfsn/3LvK9QHCq9oQw8+U= @@ -1794,8 +1909,9 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.0.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= -github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4= github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= +github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= +github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.0.1 h1:tY9CJiPnMXf1ERmG2EyK7gNUd+c6RKGD0IfU8WdUSz8= @@ -1803,8 +1919,9 @@ github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPU github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= github.com/wangjia184/sortedset v0.0.0-20160527075905-f5d03557ba30/go.mod h1:YkocrP2K2tcw938x9gCOmT5G5eCD6jsTz0SZuyAqwIE= -github.com/warpfork/go-testmark v0.3.0 h1:Q81c4u7hT+BR5kNfNQhEF0VT2pmL7+Kk0wD+ORYl7iA= github.com/warpfork/go-testmark v0.3.0/go.mod h1:jhEf8FVxd+F17juRubpmut64NEG6I2rgkUhlcqqXwE0= +github.com/warpfork/go-testmark v0.9.0 h1:nc+uaCiv5lFQLYjhuC2LTYeJ7JaC+gdDmsz9r0ISy0Y= +github.com/warpfork/go-testmark v0.9.0/go.mod h1:jhEf8FVxd+F17juRubpmut64NEG6I2rgkUhlcqqXwE0= github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= github.com/warpfork/go-wish v0.0.0-20190328234359-8b3e70f8e830/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a h1:G++j5e0OC488te356JvdhaM8YS6nMsjLAYF7JxCv07w= @@ -1832,8 +1949,9 @@ github.com/whyrusleeping/cbor-gen v0.0.0-20200826160007-0b9f6c5fb163/go.mod h1:f github.com/whyrusleeping/cbor-gen v0.0.0-20210118024343-169e9d70c0c2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20210219115102-f37d292932f2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20210303213153-67a261a1d291/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= -github.com/whyrusleeping/cbor-gen v0.0.0-20210713220151-be142a5ae1a8 h1:TEv7MId88TyIqIUL4hbf9otOookIolMxlEbN0ro671Y= github.com/whyrusleeping/cbor-gen v0.0.0-20210713220151-be142a5ae1a8/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= +github.com/whyrusleeping/cbor-gen v0.0.0-20211110122933-f57984553008 h1:7WtW9D9VGpmRLuQmrPy2JobUNdka95z3MKEVpELtOjo= +github.com/whyrusleeping/cbor-gen v0.0.0-20211110122933-f57984553008/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f/go.mod h1:p9UJB6dDgdPgMJZs7UjUOdulKyRr9fqkS+6JKAInPy8= github.com/whyrusleeping/go-ctrlnet v0.0.0-20180313164037-f564fbbdaa95/go.mod h1:SJqKCCPXRfBFCwXjfNT/skfsceF7+MBFLI2OrvuRA7g= @@ -1842,6 +1960,7 @@ github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= github.com/whyrusleeping/go-logging v0.0.1/go.mod h1:lDPYj54zutzG1XYfHAhcc7oNXEburHQBn+Iqd4yS4vE= github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f/go.mod h1:cZNvX9cFybI01GriPRMXDtczuvUhgbcYr9iCGaNlRv8= +github.com/whyrusleeping/go-sysinfo v0.0.0-20190219211824-4a357d4b90b1/go.mod h1:tKH72zYNt/exx6/5IQO6L9LoQ0rEjd5SbbWaDTs9Zso= github.com/whyrusleeping/ledger-filecoin-go v0.9.1-0.20201010031517-c3dcc1bddce4 h1:NwiwjQDB3CzQ5XH0rdMh1oQqzJH7O2PSLWxif/w3zsY= github.com/whyrusleeping/ledger-filecoin-go v0.9.1-0.20201010031517-c3dcc1bddce4/go.mod h1:K+EVq8d5QcQ2At5VECsA+SNZvWefyBXh8TnIsxo1OvQ= github.com/whyrusleeping/mafmt v1.2.8/go.mod h1:faQJFPbLSxzD9xpA02ttW/tS9vZykNvXwGvqIpk20FA= @@ -1863,6 +1982,7 @@ github.com/xorcare/golden v0.6.0/go.mod h1:7T39/ZMvaSEZlBPoYfVFmsBLmUl3uz9IuzWj/ github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542 h1:oWgZJmC1DorFZDpfMfWg7xk29yEOZiXmo/wZl+utTI8= github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542/go.mod h1:7T39/ZMvaSEZlBPoYfVFmsBLmUl3uz9IuzWj/U6FtvQ= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/ybbus/jsonrpc/v2 v2.1.6/go.mod h1:rIuG1+ORoiqocf9xs/v+ecaAVeo3zcZHQgInyKFMeg0= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1935,14 +2055,15 @@ go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/dig v1.10.0 h1:yLmDDj9/zuDjv3gz8GQGviXMs9TfysIUMUilCpgzUJY= -go.uber.org/dig v1.10.0/go.mod h1:X34SnWGr8Fyla9zQNO2GSO2D+TIuqB14OS8JhYocIyw= -go.uber.org/fx v1.9.0 h1:7OAz8ucp35AU8eydejpYG7QrbE8rLKzGhHbZlJi5LYY= -go.uber.org/fx v1.9.0/go.mod h1:mFdUyAUuJ3w4jAckiKSKbldsxy1ojpAMJ+dVZg5Y0Aw= +go.uber.org/dig v1.12.0 h1:l1GQeZpEbss0/M4l/ZotuBndCrkMdjnygzgcuOjAdaY= +go.uber.org/dig v1.12.0/go.mod h1:X34SnWGr8Fyla9zQNO2GSO2D+TIuqB14OS8JhYocIyw= +go.uber.org/fx v1.15.0 h1:kcfBpAm98n0ksanyyZLFE/Q3T7yPi13Ge2liu3TxR+A= +go.uber.org/fx v1.15.0/go.mod h1:jI3RazQUhGv5KkpZIRv+kuP4CcgX3fnc0qX8bLnzbx8= go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 h1:sHOAIxRGBp443oHZIPB+HsUGaksVCXVQENPxwTfQdH4= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= @@ -1992,6 +2113,7 @@ golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -2007,6 +2129,8 @@ golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210813211128-0a44fdfbc16e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210915214749-c084706c2272/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b h1:QAqMVf3pSa6eeTsuklijukjXBlj7Es2QQplab+/RbQ4= golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -2054,6 +2178,7 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -2113,6 +2238,7 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -2192,6 +2318,7 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191206220618-eeba5f6aabab/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2241,7 +2368,9 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211025112917-711f33c9992c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211209171907-798191bca915 h1:P+8mCzuEpyszAT6T42q0sxU+eveBAF/cJ2Kp0x6/8+0= golang.org/x/sys v0.0.0-20211209171907-798191bca915/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -2328,6 +2457,7 @@ golang.org/x/tools v0.0.0-20201112185108-eeaa07dd7696/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1-0.20210225150353-54dc8c5edb56/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= @@ -2466,6 +2596,7 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= @@ -2515,6 +2646,7 @@ modernc.org/strutil v1.1.0 h1:+1/yCzZxY2pZwwrsbH+4T7BQMoLQ9QiBshRC9eicYsc= modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= modernc.org/xc v1.0.0 h1:7ccXrupWZIS3twbUGrtKmHS2DXY6xegFua+6O3xgAFU= modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= +pgregory.net/rapid v0.4.7/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= diff --git a/node/modules/storageminer_idxprov.go b/node/modules/storageminer_idxprov.go index be07341429a..8a0d2105733 100644 --- a/node/modules/storageminer_idxprov.go +++ b/node/modules/storageminer_idxprov.go @@ -133,14 +133,14 @@ func newIndexerProviderDataTransfer(cfg config.IndexerProviderConfig, mctx helpe // Set up data transfer dtDs := namespace.Wrap(ds, datastore.NewKey("/datatransfer/transfers")) - transport := dtgstransport.NewTransport(h.ID(), gs, net) + transport := dtgstransport.NewTransport(h.ID(), gs) dtPath := filepath.Join(r.Path(), "indexer-provider", "data-transfer") err := os.MkdirAll(dtPath, 0755) //nolint: gosec if err != nil && !os.IsExist(err) { return nil, xerrors.Errorf("creating indexer provider data transfer dir %s: %w", dtPath, err) } - dt, err := dtimpl.NewDataTransfer(dtDs, dtPath, net, transport) + dt, err := dtimpl.NewDataTransfer(dtDs, net, transport) if err != nil { return nil, xerrors.Errorf("creating indexer provider data transfer module: %w", err) } From 7508d96327ebbab1eede2e453ea04fda2e3859a4 Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Thu, 20 Jan 2022 16:47:15 +0400 Subject: [PATCH 053/385] fix lint --- markets/dagstore/wrapper_migration_test.go | 7 ++++++- markets/dagstore/wrapper_test.go | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/markets/dagstore/wrapper_migration_test.go b/markets/dagstore/wrapper_migration_test.go index 437032da943..a08e46e6c16 100644 --- a/markets/dagstore/wrapper_migration_test.go +++ b/markets/dagstore/wrapper_migration_test.go @@ -5,6 +5,8 @@ import ( "io" "testing" + mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" + "github.com/stretchr/testify/require" "github.com/filecoin-project/dagstore" @@ -96,8 +98,11 @@ func TestShardRegistration(t *testing.T) { cfg := config.DefaultStorageMiner().DAGStore cfg.RootDir = t.TempDir() + h, err := mocknet.New().GenPeer() + require.NoError(t, err) + mapi := NewMinerAPI(ps, &wrappedSA{sa}, 10, 5) - dagst, w, err := NewDAGStore(cfg, mapi) + dagst, w, err := NewDAGStore(cfg, mapi, h) require.NoError(t, err) require.NotNil(t, dagst) require.NotNil(t, w) diff --git a/markets/dagstore/wrapper_test.go b/markets/dagstore/wrapper_test.go index 80b559aa08e..5224f000d5d 100644 --- a/markets/dagstore/wrapper_test.go +++ b/markets/dagstore/wrapper_test.go @@ -31,7 +31,7 @@ func TestWrapperAcquireRecovery(t *testing.T) { pieceCid, err := cid.Parse("bafkqaaa") require.NoError(t, err) - h, err := mocknet.New(ctx).GenPeer() + h, err := mocknet.New().GenPeer() require.NoError(t, err) // Create a DAG store wrapper dagst, w, err := NewDAGStore(config.DAGStoreConfig{ @@ -83,7 +83,7 @@ func TestWrapperAcquireRecovery(t *testing.T) { // TestWrapperBackground verifies the behaviour of the background go routine func TestWrapperBackground(t *testing.T) { ctx := context.Background() - h, err := mocknet.New(ctx).GenPeer() + h, err := mocknet.New().GenPeer() require.NoError(t, err) // Create a DAG store wrapper From 8e46b9ea5d294e44035a47fe763c9aba4d07d42e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 4 Jan 2022 20:33:49 +0100 Subject: [PATCH 054/385] paych: API to pre-fund channels --- api/api_full.go | 6 +- api/proxy_gen.go | 8 +-- api/v0api/v1_wrapper.go | 5 ++ markets/retrievaladapter/client.go | 2 +- node/impl/paych/paych.go | 6 +- paychmgr/cbor_gen.go | 54 ++++++++++++++++- paychmgr/manager.go | 4 +- paychmgr/simple.go | 97 +++++++++++++++++++++++++----- paychmgr/store.go | 19 +++--- 9 files changed, 168 insertions(+), 33 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index cf58a3cc6ee..cf9a1f22ef2 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -689,7 +689,11 @@ type FullNode interface { // MethodGroup: Paych // The Paych methods are for interacting with and managing payment channels - PaychGet(ctx context.Context, from, to address.Address, amt types.BigInt) (*ChannelInfo, error) //perm:sign + // PaychGet gets or creates a payment channel between address pair + // - If reserve is false, the specified amount will be added to the channel through on-chain send for future use + // - If reserve is true, the specified amount will be reserved for use. If there aren't enough non-reserved funds + // available, funds will be added through an on-chain message. + PaychGet(ctx context.Context, from, to address.Address, amt types.BigInt, reserve bool) (*ChannelInfo, error) //perm:sign PaychGetWaitReady(context.Context, cid.Cid) (address.Address, error) //perm:sign PaychAvailableFunds(ctx context.Context, ch address.Address) (*ChannelAvailableFunds, error) //perm:sign PaychAvailableFundsByFromTo(ctx context.Context, from, to address.Address) (*ChannelAvailableFunds, error) //perm:sign diff --git a/api/proxy_gen.go b/api/proxy_gen.go index e353a7c6e89..9a134cec91b 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -306,7 +306,7 @@ type FullNodeStruct struct { PaychCollect func(p0 context.Context, p1 address.Address) (cid.Cid, error) `perm:"sign"` - PaychGet func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (*ChannelInfo, error) `perm:"sign"` + PaychGet func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 bool) (*ChannelInfo, error) `perm:"sign"` PaychGetWaitReady func(p0 context.Context, p1 cid.Cid) (address.Address, error) `perm:"sign"` @@ -2179,14 +2179,14 @@ func (s *FullNodeStub) PaychCollect(p0 context.Context, p1 address.Address) (cid return *new(cid.Cid), ErrNotSupported } -func (s *FullNodeStruct) PaychGet(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (*ChannelInfo, error) { +func (s *FullNodeStruct) PaychGet(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 bool) (*ChannelInfo, error) { if s.Internal.PaychGet == nil { return nil, ErrNotSupported } - return s.Internal.PaychGet(p0, p1, p2, p3) + return s.Internal.PaychGet(p0, p1, p2, p3, p4) } -func (s *FullNodeStub) PaychGet(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (*ChannelInfo, error) { +func (s *FullNodeStub) PaychGet(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 bool) (*ChannelInfo, error) { return nil, ErrNotSupported } diff --git a/api/v0api/v1_wrapper.go b/api/v0api/v1_wrapper.go index 7e0d7a94ab6..605b27b0c9f 100644 --- a/api/v0api/v1_wrapper.go +++ b/api/v0api/v1_wrapper.go @@ -337,4 +337,9 @@ func (w *WrapperV1Full) clientRetrieve(ctx context.Context, order RetrievalOrder finish(w.ClientExport(ctx, eref, *ref)) } +func (w *WrapperV1Full) PaychGet(ctx context.Context, from, to address.Address, amt types.BigInt) (*api.ChannelInfo, error) { + // v0 always reserves + return w.FullNode.PaychGet(ctx, from, to, amt, true) +} + var _ FullNode = &WrapperV1Full{} diff --git a/markets/retrievaladapter/client.go b/markets/retrievaladapter/client.go index 1bef23e1296..4ed2e905ab4 100644 --- a/markets/retrievaladapter/client.go +++ b/markets/retrievaladapter/client.go @@ -34,7 +34,7 @@ func NewRetrievalClientNode(payAPI payapi.PaychAPI, chainAPI full.ChainAPI, stat func (rcn *retrievalClientNode) GetOrCreatePaymentChannel(ctx context.Context, clientAddress address.Address, minerAddress address.Address, clientFundsAvailable abi.TokenAmount, tok shared.TipSetToken) (address.Address, cid.Cid, error) { // TODO: respect the provided TipSetToken (a serialized TipSetKey) when // querying the chain - ci, err := rcn.payAPI.PaychGet(ctx, clientAddress, minerAddress, clientFundsAvailable) + ci, err := rcn.payAPI.PaychGet(ctx, clientAddress, minerAddress, clientFundsAvailable, true) if err != nil { return address.Undef, cid.Undef, err } diff --git a/node/impl/paych/paych.go b/node/impl/paych/paych.go index df3b1e3e490..d308f6248ac 100644 --- a/node/impl/paych/paych.go +++ b/node/impl/paych/paych.go @@ -22,8 +22,8 @@ type PaychAPI struct { PaychMgr *paychmgr.Manager } -func (a *PaychAPI) PaychGet(ctx context.Context, from, to address.Address, amt types.BigInt) (*api.ChannelInfo, error) { - ch, mcid, err := a.PaychMgr.GetPaych(ctx, from, to, amt) +func (a *PaychAPI) PaychGet(ctx context.Context, from, to address.Address, amt types.BigInt, reserve bool) (*api.ChannelInfo, error) { + ch, mcid, err := a.PaychMgr.GetPaych(ctx, from, to, amt, reserve) if err != nil { return nil, err } @@ -55,7 +55,7 @@ func (a *PaychAPI) PaychNewPayment(ctx context.Context, from, to address.Address // TODO: Fix free fund tracking in PaychGet // TODO: validate voucher spec before locking funds - ch, err := a.PaychGet(ctx, from, to, amount) + ch, err := a.PaychGet(ctx, from, to, amount, true) if err != nil { return nil, err } diff --git a/paychmgr/cbor_gen.go b/paychmgr/cbor_gen.go index caa4143a257..428c09a9e05 100644 --- a/paychmgr/cbor_gen.go +++ b/paychmgr/cbor_gen.go @@ -196,7 +196,7 @@ func (t *ChannelInfo) MarshalCBOR(w io.Writer) error { _, err := w.Write(cbg.CborNull) return err } - if _, err := w.Write([]byte{172}); err != nil { + if _, err := w.Write([]byte{174}); err != nil { return err } @@ -346,6 +346,38 @@ func (t *ChannelInfo) MarshalCBOR(w io.Writer) error { return err } + // t.AvailableAmount (big.Int) (struct) + if len("AvailableAmount") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"AvailableAmount\" was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("AvailableAmount"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("AvailableAmount")); err != nil { + return err + } + + if err := t.AvailableAmount.MarshalCBOR(w); err != nil { + return err + } + + // t.PendingAvailableAmount (big.Int) (struct) + if len("PendingAvailableAmount") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"PendingAvailableAmount\" was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("PendingAvailableAmount"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("PendingAvailableAmount")); err != nil { + return err + } + + if err := t.PendingAvailableAmount.MarshalCBOR(w); err != nil { + return err + } + // t.PendingAmount (big.Int) (struct) if len("PendingAmount") > cbg.MaxLength { return xerrors.Errorf("Value in field \"PendingAmount\" was too long") @@ -577,6 +609,26 @@ func (t *ChannelInfo) UnmarshalCBOR(r io.Reader) error { return xerrors.Errorf("unmarshaling t.Amount: %w", err) } + } + // t.AvailableAmount (big.Int) (struct) + case "AvailableAmount": + + { + + if err := t.AvailableAmount.UnmarshalCBOR(br); err != nil { + return xerrors.Errorf("unmarshaling t.AvailableAmount: %w", err) + } + + } + // t.PendingAvailableAmount (big.Int) (struct) + case "PendingAvailableAmount": + + { + + if err := t.PendingAvailableAmount.UnmarshalCBOR(br); err != nil { + return xerrors.Errorf("unmarshaling t.PendingAvailableAmount: %w", err) + } + } // t.PendingAmount (big.Int) (struct) case "PendingAmount": diff --git a/paychmgr/manager.go b/paychmgr/manager.go index e0fcd7a754c..eed475547aa 100644 --- a/paychmgr/manager.go +++ b/paychmgr/manager.go @@ -101,13 +101,13 @@ func (pm *Manager) Stop() error { return nil } -func (pm *Manager) GetPaych(ctx context.Context, from, to address.Address, amt types.BigInt) (address.Address, cid.Cid, error) { +func (pm *Manager) GetPaych(ctx context.Context, from, to address.Address, amt types.BigInt, reserve bool) (address.Address, cid.Cid, error) { chanAccessor, err := pm.accessorByFromTo(from, to) if err != nil { return address.Undef, cid.Undef, err } - return chanAccessor.getPaych(ctx, amt) + return chanAccessor.getPaych(ctx, amt, reserve) } func (pm *Manager) AvailableFunds(ctx context.Context, ch address.Address) (*api.ChannelAvailableFunds, error) { diff --git a/paychmgr/simple.go b/paychmgr/simple.go index 502338e2953..fd849d3aed7 100644 --- a/paychmgr/simple.go +++ b/paychmgr/simple.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "fmt" + "sort" "sync" "github.com/ipfs/go-cid" @@ -32,18 +33,20 @@ type fundsReq struct { ctx context.Context promise chan *paychFundsRes amt types.BigInt + reserve bool lk sync.Mutex // merge parent, if this req is part of a merge merge *mergedFundsReq } -func newFundsReq(ctx context.Context, amt types.BigInt) *fundsReq { +func newFundsReq(ctx context.Context, amt types.BigInt, reserve bool) *fundsReq { promise := make(chan *paychFundsRes) return &fundsReq{ ctx: ctx, promise: promise, amt: amt, + reserve: reserve, } } @@ -104,6 +107,15 @@ func newMergedFundsReq(reqs []*fundsReq) *mergedFundsReq { r.setMergeParent(m) } + sort.Slice(m.reqs, func(i, j int) bool { + if m.reqs[i].reserve != m.reqs[j].reserve { // non-reserve first + return m.reqs[j].reserve + } + + // sort by amount asc (reducing latency for smaller requests) + return m.reqs[i].amt.LessThan(m.reqs[j].amt) + }) + // If the requests were all cancelled while being added, cancel the context // immediately m.checkActive() @@ -135,18 +147,24 @@ func (m *mergedFundsReq) onComplete(res *paychFundsRes) { } // sum is the sum of the amounts in all requests in the merge -func (m *mergedFundsReq) sum() types.BigInt { +func (m *mergedFundsReq) sum() (types.BigInt, types.BigInt) { sum := types.NewInt(0) + avail := types.NewInt(0) + for _, r := range m.reqs { if r.isActive() { sum = types.BigAdd(sum, r.amt) + if !r.reserve { + avail = types.BigAdd(avail, r.amt) + } } } - return sum + + return sum, avail } // getPaych ensures that a channel exists between the from and to addresses, -// and adds the given amount of funds. +// and reserves (or adds as available) the given amount of funds. // If the channel does not exist a create channel message is sent and the // message CID is returned. // If the channel does exist an add funds message is sent and both the channel @@ -156,9 +174,9 @@ func (m *mergedFundsReq) sum() types.BigInt { // address and the CID of the new add funds message. // If an operation returns an error, subsequent waiting operations will still // be attempted. -func (ca *channelAccessor) getPaych(ctx context.Context, amt types.BigInt) (address.Address, cid.Cid, error) { +func (ca *channelAccessor) getPaych(ctx context.Context, amt types.BigInt, reserve bool) (address.Address, cid.Cid, error) { // Add the request to add funds to a queue and wait for the result - freq := newFundsReq(ctx, amt) + freq := newFundsReq(ctx, amt, reserve) ca.enqueue(ctx, freq) select { case res := <-freq.promise: @@ -195,14 +213,57 @@ func (ca *channelAccessor) processQueue(ctx context.Context, channelID string) ( // For example if there are pending requests for 3, 2, 4 then // amt = 3 + 2 + 4 = 9 merged := newMergedFundsReq(ca.fundsReqQueue) - amt := merged.sum() + amt, avail := merged.sum() if amt.IsZero() { // Note: The amount can be zero if requests are cancelled as we're // building the mergedFundsReq return ca.currentAvailableFunds(ctx, channelID, amt) } - res := ca.processTask(merged.ctx, amt) + { + toReserve := types.BigSub(amt, avail) + avail := types.NewInt(0) + + // reserve at most what we need + ca.mutateChannelInfo(ctx, channelID, func(ci *ChannelInfo) { + avail = ci.AvailableAmount + if avail.GreaterThan(toReserve) { + avail = toReserve + } + ci.AvailableAmount = big.Sub(ci.AvailableAmount, avail) + }) + + used := types.NewInt(0) + + next := 0 + for i, r := range merged.reqs { + if !r.reserve { + // non-reserving request are put after reserving requests, so we are done here + break + } + + if r.amt.GreaterThan(types.BigSub(avail, used)) { + // requests are sorted by amount ascending, so if we hit this, there aren't any more requests we can fill + } + + // don't try to fill inactive requests + if !r.isActive() { + continue + } + + used = types.BigAdd(used, r.amt) + r.onComplete(&paychFundsRes{}) + next = i + 1 + } + merged.reqs = merged.reqs[next:] + + // return any unused reserved funds (e.g. from cancelled requests) + ca.mutateChannelInfo(ctx, channelID, func(ci *ChannelInfo) { + ci.AvailableAmount = types.BigAdd(ci.AvailableAmount, types.BigSub(avail, used)) + }) + } + + res := ca.processTask(merged.ctx, amt, avail) // If the task is waiting on an external event (eg something to appear on // chain) it will return nil @@ -333,7 +394,7 @@ func (ca *channelAccessor) currentAvailableFunds(ctx context.Context, channelID // Note that processTask may be called repeatedly in the same state, and should // return nil if there is no state change to be made (eg when waiting for a // message to be confirmed on chain) -func (ca *channelAccessor) processTask(ctx context.Context, amt types.BigInt) *paychFundsRes { +func (ca *channelAccessor) processTask(ctx context.Context, amt, avail types.BigInt) *paychFundsRes { // Get the payment channel for the from/to addresses. // Note: It's ok if we get ErrChannelNotTracked. It just means we need to // create a channel. @@ -344,7 +405,7 @@ func (ca *channelAccessor) processTask(ctx context.Context, amt types.BigInt) *p // If a channel has not yet been created, create one. if channelInfo == nil { - mcid, err := ca.createPaych(ctx, amt) + mcid, err := ca.createPaych(ctx, amt, avail) if err != nil { return &paychFundsRes{err: err} } @@ -368,7 +429,7 @@ func (ca *channelAccessor) processTask(ctx context.Context, amt types.BigInt) *p // We need to add more funds, so send an add funds message to // cover the amount for this request - mcid, err := ca.addFunds(ctx, channelInfo, amt) + mcid, err := ca.addFunds(ctx, channelInfo, amt, avail) if err != nil { return &paychFundsRes{err: err} } @@ -376,7 +437,7 @@ func (ca *channelAccessor) processTask(ctx context.Context, amt types.BigInt) *p } // createPaych sends a message to create the channel and returns the message cid -func (ca *channelAccessor) createPaych(ctx context.Context, amt types.BigInt) (cid.Cid, error) { +func (ca *channelAccessor) createPaych(ctx context.Context, amt, avail types.BigInt) (cid.Cid, error) { mb, err := ca.messageBuilder(ctx, ca.from) if err != nil { return cid.Undef, err @@ -393,7 +454,7 @@ func (ca *channelAccessor) createPaych(ctx context.Context, amt types.BigInt) (c mcid := smsg.Cid() // Create a new channel in the store - ci, err := ca.store.CreateChannel(ctx, ca.from, ca.to, mcid, amt) + ci, err := ca.store.CreateChannel(ctx, ca.from, ca.to, mcid, amt, avail) if err != nil { log.Errorf("creating channel: %s", err) return cid.Undef, err @@ -452,7 +513,9 @@ func (ca *channelAccessor) waitPaychCreateMsg(ctx context.Context, channelID str ca.mutateChannelInfo(ctx, channelID, func(channelInfo *ChannelInfo) { channelInfo.Channel = &decodedReturn.RobustAddress channelInfo.Amount = channelInfo.PendingAmount + channelInfo.AvailableAmount = channelInfo.PendingAvailableAmount channelInfo.PendingAmount = big.NewInt(0) + channelInfo.PendingAvailableAmount = big.NewInt(0) channelInfo.CreateMsg = nil }) @@ -460,7 +523,7 @@ func (ca *channelAccessor) waitPaychCreateMsg(ctx context.Context, channelID str } // addFunds sends a message to add funds to the channel and returns the message cid -func (ca *channelAccessor) addFunds(ctx context.Context, channelInfo *ChannelInfo, amt types.BigInt) (*cid.Cid, error) { +func (ca *channelAccessor) addFunds(ctx context.Context, channelInfo *ChannelInfo, amt, avail types.BigInt) (*cid.Cid, error) { msg := &types.Message{ To: *channelInfo.Channel, From: channelInfo.Control, @@ -477,6 +540,7 @@ func (ca *channelAccessor) addFunds(ctx context.Context, channelInfo *ChannelInf // Store the add funds message CID on the channel ca.mutateChannelInfo(ctx, channelInfo.ChannelID, func(ci *ChannelInfo) { ci.PendingAmount = amt + ci.PendingAvailableAmount = avail ci.AddFundsMsg = &mcid }) @@ -492,6 +556,8 @@ func (ca *channelAccessor) addFunds(ctx context.Context, channelInfo *ChannelInf return &mcid, nil } +// TODO func (ca *channelAccessor) freeFunds(ctx context.Context, channelInfo *ChannelInfo, amt, avail types.BigInt) (*cid.Cid, error) { + // waitForAddFundsMsg waits for mcid to appear on chain and returns error, if any func (ca *channelAccessor) waitForAddFundsMsg(ctx context.Context, channelID string, mcid cid.Cid) { err := ca.waitAddFundsMsg(ctx, channelID, mcid) @@ -514,6 +580,7 @@ func (ca *channelAccessor) waitAddFundsMsg(ctx context.Context, channelID string ca.mutateChannelInfo(ctx, channelID, func(channelInfo *ChannelInfo) { channelInfo.PendingAmount = big.NewInt(0) + channelInfo.PendingAvailableAmount = big.NewInt(0) channelInfo.AddFundsMsg = nil }) @@ -526,7 +593,9 @@ func (ca *channelAccessor) waitAddFundsMsg(ctx context.Context, channelID string // Store updated amount ca.mutateChannelInfo(ctx, channelID, func(channelInfo *ChannelInfo) { channelInfo.Amount = types.BigAdd(channelInfo.Amount, channelInfo.PendingAmount) + channelInfo.AvailableAmount = types.BigAdd(channelInfo.AvailableAmount, channelInfo.PendingAvailableAmount) channelInfo.PendingAmount = big.NewInt(0) + channelInfo.PendingAvailableAmount = big.NewInt(0) channelInfo.AddFundsMsg = nil }) diff --git a/paychmgr/store.go b/paychmgr/store.go index 62849e6bedd..bbc549b862c 100644 --- a/paychmgr/store.go +++ b/paychmgr/store.go @@ -74,6 +74,10 @@ type ChannelInfo struct { // has locally been added to the channel. It should reflect the channel's // Balance on chain as long as all operations occur on the same datastore. Amount types.BigInt + // AvailableAmount indicates how much afil is non-reverved + AvailableAmount types.BigInt + // PendingAvailableAmount is available amount that we're awaiting confirmation of + PendingAvailableAmount types.BigInt // PendingAmount is the amount that we're awaiting confirmation of PendingAmount types.BigInt // CreateMsg is the CID of a pending create message (while waiting for confirmation) @@ -416,14 +420,15 @@ func (ps *Store) ByChannelID(ctx context.Context, channelID string) (*ChannelInf } // CreateChannel creates an outbound channel for the given from / to -func (ps *Store) CreateChannel(ctx context.Context, from address.Address, to address.Address, createMsgCid cid.Cid, amt types.BigInt) (*ChannelInfo, error) { +func (ps *Store) CreateChannel(ctx context.Context, from address.Address, to address.Address, createMsgCid cid.Cid, amt, avail types.BigInt) (*ChannelInfo, error) { ci := &ChannelInfo{ - Direction: DirOutbound, - NextLane: 0, - Control: from, - Target: to, - CreateMsg: &createMsgCid, - PendingAmount: amt, + Direction: DirOutbound, + NextLane: 0, + Control: from, + Target: to, + CreateMsg: &createMsgCid, + PendingAmount: amt, + PendingAvailableAmount: avail, } // Save the new channel From 97151138984b312d64d2679fa8d6d536ff84abaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 4 Jan 2022 21:34:27 +0100 Subject: [PATCH 055/385] paych: Test pre-funding --- api/mocks/mock_full.go | 8 +- documentation/en/api-v1-unstable-methods.md | 9 +- paychmgr/paychget_test.go | 319 ++++++++++++++++++-- paychmgr/paychvoucherfunds_test.go | 4 +- paychmgr/settle_test.go | 4 +- paychmgr/simple.go | 101 ++++--- 6 files changed, 360 insertions(+), 85 deletions(-) diff --git a/api/mocks/mock_full.go b/api/mocks/mock_full.go index e985a794d0c..c745f26fcd4 100644 --- a/api/mocks/mock_full.go +++ b/api/mocks/mock_full.go @@ -1976,18 +1976,18 @@ func (mr *MockFullNodeMockRecorder) PaychCollect(arg0, arg1 interface{}) *gomock } // PaychGet mocks base method. -func (m *MockFullNode) PaychGet(arg0 context.Context, arg1, arg2 address.Address, arg3 big.Int) (*api.ChannelInfo, error) { +func (m *MockFullNode) PaychGet(arg0 context.Context, arg1, arg2 address.Address, arg3 big.Int, arg4 bool) (*api.ChannelInfo, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "PaychGet", arg0, arg1, arg2, arg3) + ret := m.ctrl.Call(m, "PaychGet", arg0, arg1, arg2, arg3, arg4) ret0, _ := ret[0].(*api.ChannelInfo) ret1, _ := ret[1].(error) return ret0, ret1 } // PaychGet indicates an expected call of PaychGet. -func (mr *MockFullNodeMockRecorder) PaychGet(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { +func (mr *MockFullNodeMockRecorder) PaychGet(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PaychGet", reflect.TypeOf((*MockFullNode)(nil).PaychGet), arg0, arg1, arg2, arg3) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PaychGet", reflect.TypeOf((*MockFullNode)(nil).PaychGet), arg0, arg1, arg2, arg3, arg4) } // PaychGetWaitReady mocks base method. diff --git a/documentation/en/api-v1-unstable-methods.md b/documentation/en/api-v1-unstable-methods.md index a5fdd999429..ce0ceadcdfd 100644 --- a/documentation/en/api-v1-unstable-methods.md +++ b/documentation/en/api-v1-unstable-methods.md @@ -4509,7 +4509,11 @@ Response: ``` ### PaychGet -There are not yet any comments for this method. +PaychGet gets or creates a payment channel between address pair + - If reserve is false, the specified amount will be added to the channel through on-chain send for future use + - If reserve is true, the specified amount will be reserved for use. If there aren't enough non-reserved funds + available, funds will be added through an on-chain message. + Perms: sign @@ -4518,7 +4522,8 @@ Inputs: [ "f01234", "f01234", - "0" + "0", + true ] ``` diff --git a/paychmgr/paychget_test.go b/paychmgr/paychget_test.go index 2aacaf6c287..31207917721 100644 --- a/paychmgr/paychget_test.go +++ b/paychmgr/paychget_test.go @@ -55,7 +55,7 @@ func TestPaychGetCreateChannelMsg(t *testing.T) { require.NoError(t, err) amt := big.NewInt(10) - ch, mcid, err := mgr.GetPaych(ctx, from, to, amt) + ch, mcid, err := mgr.GetPaych(ctx, from, to, amt, true) require.NoError(t, err) require.Equal(t, address.Undef, ch) @@ -83,7 +83,7 @@ func TestPaychGetCreateChannelThenAddFunds(t *testing.T) { // Send create message for a channel with value 10 amt := big.NewInt(10) - _, createMsgCid, err := mgr.GetPaych(ctx, from, to, amt) + _, createMsgCid, err := mgr.GetPaych(ctx, from, to, amt, true) require.NoError(t, err) // Should have no channels yet (message sent but channel not created) @@ -100,7 +100,7 @@ func TestPaychGetCreateChannelThenAddFunds(t *testing.T) { // 2. Request add funds - should block until create channel has completed amt2 := big.NewInt(5) - ch2, addFundsMsgCid, err := mgr.GetPaych(ctx, from, to, amt2) + ch2, addFundsMsgCid, err := mgr.GetPaych(ctx, from, to, amt2, true) // 4. This GetPaych should return after create channel from first // GetPaych completes @@ -154,6 +154,74 @@ func TestPaychGetCreateChannelThenAddFunds(t *testing.T) { <-done } +func TestPaychGetCreatePrefundedChannelThenAddFunds(t *testing.T) { + ctx := context.Background() + store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore())) + + ch := tutils.NewIDAddr(t, 100) + from := tutils.NewIDAddr(t, 101) + to := tutils.NewIDAddr(t, 102) + + mock := newMockManagerAPI() + defer mock.close() + + mgr, err := newManager(store, mock) + require.NoError(t, err) + + // Send create message for a channel with value 10 + amt := big.NewInt(10) + _, createMsgCid, err := mgr.GetPaych(ctx, from, to, amt, false) + require.NoError(t, err) + + // Should have no channels yet (message sent but channel not created) + cis, err := mgr.ListChannels(ctx) + require.NoError(t, err) + require.Len(t, cis, 0) + + // 1. Set up create channel response (sent in response to WaitForMsg()) + response := testChannelResponse(t, ch) + + done := make(chan struct{}) + go func() { + defer close(done) + + // 2. Request add funds - shouldn't block + amt2 := big.NewInt(3) + ch2, addFundsMsgCid, err := mgr.GetPaych(ctx, from, to, amt2, true) + + // 4. This GetPaych should return after create channel from first + // GetPaych completes + require.NoError(t, err) + + // Expect the channel to be the same + require.Equal(t, ch, ch2) + require.Equal(t, cid.Undef, addFundsMsgCid) + + // Should have one channel, whose address is the channel that was created + cis, err := mgr.ListChannels(ctx) + require.NoError(t, err) + require.Len(t, cis, 1) + require.Equal(t, ch, cis[0]) + + // Amount should be amount sent to first GetPaych (to create + // channel). + // PendingAmount should be zero, AvailableAmount should be Amount minus what we requested + + ci, err := mgr.GetChannelInfo(ctx, ch) + require.NoError(t, err) + require.EqualValues(t, 10, ci.Amount.Int64()) + require.EqualValues(t, 0, ci.PendingAmount.Int64()) + require.EqualValues(t, 7, ci.AvailableAmount.Int64()) + require.Nil(t, ci.CreateMsg) + require.Nil(t, ci.AddFundsMsg) + }() + + // 3. Send create channel response + mock.receiveMsgResponse(createMsgCid, response) + + <-done +} + // TestPaychGetCreateChannelWithErrorThenCreateAgain tests that if an // operation is queued up behind a create channel operation, and the create // channel fails, then the waiting operation can succeed. @@ -172,7 +240,7 @@ func TestPaychGetCreateChannelWithErrorThenCreateAgain(t *testing.T) { // Send create message for a channel amt := big.NewInt(10) - _, mcid1, err := mgr.GetPaych(ctx, from, to, amt) + _, mcid1, err := mgr.GetPaych(ctx, from, to, amt, true) require.NoError(t, err) // 1. Set up create channel response (sent in response to WaitForMsg()) @@ -190,7 +258,7 @@ func TestPaychGetCreateChannelWithErrorThenCreateAgain(t *testing.T) { // Because first channel create fails, this request // should be for channel create again. amt2 := big.NewInt(5) - ch2, mcid2, err := mgr.GetPaych(ctx, from, to, amt2) + ch2, mcid2, err := mgr.GetPaych(ctx, from, to, amt2, true) require.NoError(t, err) require.Equal(t, address.Undef, ch2) @@ -237,7 +305,7 @@ func TestPaychGetRecoverAfterError(t *testing.T) { // Send create message for a channel amt := big.NewInt(10) - _, mcid, err := mgr.GetPaych(ctx, from, to, amt) + _, mcid, err := mgr.GetPaych(ctx, from, to, amt, true) require.NoError(t, err) // Send error create channel response @@ -248,7 +316,7 @@ func TestPaychGetRecoverAfterError(t *testing.T) { // Send create message for a channel again amt2 := big.NewInt(7) - _, mcid2, err := mgr.GetPaych(ctx, from, to, amt2) + _, mcid2, err := mgr.GetPaych(ctx, from, to, amt2, true) require.NoError(t, err) // Send success create channel response @@ -289,7 +357,7 @@ func TestPaychGetRecoverAfterAddFundsError(t *testing.T) { // Send create message for a channel amt := big.NewInt(10) - _, mcid1, err := mgr.GetPaych(ctx, from, to, amt) + _, mcid1, err := mgr.GetPaych(ctx, from, to, amt, true) require.NoError(t, err) // Send success create channel response @@ -298,7 +366,7 @@ func TestPaychGetRecoverAfterAddFundsError(t *testing.T) { // Send add funds message for channel amt2 := big.NewInt(5) - _, mcid2, err := mgr.GetPaych(ctx, from, to, amt2) + _, mcid2, err := mgr.GetPaych(ctx, from, to, amt2, true) require.NoError(t, err) // Send error add funds response @@ -325,7 +393,7 @@ func TestPaychGetRecoverAfterAddFundsError(t *testing.T) { // Send add funds message for channel again amt3 := big.NewInt(2) - _, mcid3, err := mgr.GetPaych(ctx, from, to, amt3) + _, mcid3, err := mgr.GetPaych(ctx, from, to, amt3, true) require.NoError(t, err) // Send success add funds response @@ -370,7 +438,7 @@ func TestPaychGetRestartAfterCreateChannelMsg(t *testing.T) { // Send create message for a channel with value 10 amt := big.NewInt(10) - _, createMsgCid, err := mgr.GetPaych(ctx, from, to, amt) + _, createMsgCid, err := mgr.GetPaych(ctx, from, to, amt, true) require.NoError(t, err) // Simulate shutting down system @@ -397,7 +465,7 @@ func TestPaychGetRestartAfterCreateChannelMsg(t *testing.T) { // 2. Request add funds - should block until create channel has completed amt2 := big.NewInt(5) - ch2, addFundsMsgCid, err := mgr2.GetPaych(ctx, from, to, amt2) + ch2, addFundsMsgCid, err := mgr2.GetPaych(ctx, from, to, amt2, true) // 4. This GetPaych should return after create channel from first // GetPaych completes @@ -449,7 +517,7 @@ func TestPaychGetRestartAfterAddFundsMsg(t *testing.T) { // Send create message for a channel amt := big.NewInt(10) - _, mcid1, err := mgr.GetPaych(ctx, from, to, amt) + _, mcid1, err := mgr.GetPaych(ctx, from, to, amt, true) require.NoError(t, err) // Send success create channel response @@ -458,7 +526,7 @@ func TestPaychGetRestartAfterAddFundsMsg(t *testing.T) { // Send add funds message for channel amt2 := big.NewInt(5) - _, mcid2, err := mgr.GetPaych(ctx, from, to, amt2) + _, mcid2, err := mgr.GetPaych(ctx, from, to, amt2, true) require.NoError(t, err) // Simulate shutting down system @@ -512,7 +580,7 @@ func TestPaychGetWait(t *testing.T) { // 1. Get amt := big.NewInt(10) - _, createMsgCid, err := mgr.GetPaych(ctx, from, to, amt) + _, createMsgCid, err := mgr.GetPaych(ctx, from, to, amt, true) require.NoError(t, err) expch := tutils.NewIDAddr(t, 100) @@ -535,7 +603,7 @@ func TestPaychGetWait(t *testing.T) { // Request add funds amt2 := big.NewInt(15) - _, addFundsMsgCid, err := mgr.GetPaych(ctx, from, to, amt2) + _, addFundsMsgCid, err := mgr.GetPaych(ctx, from, to, amt2, true) require.NoError(t, err) go func() { @@ -569,7 +637,7 @@ func TestPaychGetWaitErr(t *testing.T) { // 1. Create channel amt := big.NewInt(10) - _, mcid, err := mgr.GetPaych(ctx, from, to, amt) + _, mcid, err := mgr.GetPaych(ctx, from, to, amt, true) require.NoError(t, err) done := make(chan address.Address) @@ -615,7 +683,7 @@ func TestPaychGetWaitCtx(t *testing.T) { require.NoError(t, err) amt := big.NewInt(10) - _, mcid, err := mgr.GetPaych(ctx, from, to, amt) + _, mcid, err := mgr.GetPaych(ctx, from, to, amt, true) require.NoError(t, err) // When the context is cancelled, should unblock wait @@ -646,7 +714,7 @@ func TestPaychGetMergeAddFunds(t *testing.T) { // Send create message for a channel with value 10 createAmt := big.NewInt(10) - _, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt) + _, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, true) require.NoError(t, err) // Queue up two add funds requests behind create channel @@ -664,7 +732,103 @@ func TestPaychGetMergeAddFunds(t *testing.T) { // Request add funds - should block until create channel has completed var err error - addFundsCh1, addFundsMcid1, err = mgr.GetPaych(ctx, from, to, addFundsAmt1) + addFundsCh1, addFundsMcid1, err = mgr.GetPaych(ctx, from, to, addFundsAmt1, true) + require.NoError(t, err) + }() + + go func() { + defer addFundsSent.Done() + + // Request add funds again - should merge with waiting add funds request + var err error + addFundsCh2, addFundsMcid2, err = mgr.GetPaych(ctx, from, to, addFundsAmt2, true) + require.NoError(t, err) + }() + // Wait for add funds requests to be queued up + waitForQueueSize(t, mgr, from, to, 2) + + // Send create channel response + response := testChannelResponse(t, ch) + mock.receiveMsgResponse(createMsgCid, response) + + // Wait for create channel response + chres, err := mgr.GetPaychWaitReady(ctx, createMsgCid) + require.NoError(t, err) + require.Equal(t, ch, chres) + + // Wait for add funds requests to be sent + addFundsSent.Wait() + + // Expect add funds requests to have same channel as create channel and + // same message cid as each other (because they should have been merged) + require.Equal(t, ch, addFundsCh1) + require.Equal(t, ch, addFundsCh2) + require.Equal(t, addFundsMcid1, addFundsMcid2) + + // Send success add funds response + mock.receiveMsgResponse(addFundsMcid1, types.MessageReceipt{ + ExitCode: 0, + Return: []byte{}, + }) + + // Wait for add funds response + addFundsCh, err := mgr.GetPaychWaitReady(ctx, addFundsMcid1) + require.NoError(t, err) + require.Equal(t, ch, addFundsCh) + + // Make sure that one create channel message and one add funds message was + // sent + require.Equal(t, 2, mock.pushedMessageCount()) + + // Check create message amount is correct + createMsg := mock.pushedMessages(createMsgCid) + require.Equal(t, from, createMsg.Message.From) + require.Equal(t, lotusinit.Address, createMsg.Message.To) + require.Equal(t, createAmt, createMsg.Message.Value) + + // Check merged add funds amount is the sum of the individual + // amounts + addFundsMsg := mock.pushedMessages(addFundsMcid1) + require.Equal(t, from, addFundsMsg.Message.From) + require.Equal(t, ch, addFundsMsg.Message.To) + require.Equal(t, types.BigAdd(addFundsAmt1, addFundsAmt2), addFundsMsg.Message.Value) +} + +func TestPaychGetMergePrefundAndReserve(t *testing.T) { + ctx := context.Background() + store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore())) + + ch := tutils.NewIDAddr(t, 100) + from := tutils.NewIDAddr(t, 101) + to := tutils.NewIDAddr(t, 102) + + mock := newMockManagerAPI() + defer mock.close() + + mgr, err := newManager(store, mock) + require.NoError(t, err) + + // Send create message for a channel with value 10 + createAmt := big.NewInt(10) + _, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, true) + require.NoError(t, err) + + // Queue up two add funds requests behind create channel + var addFundsSent sync.WaitGroup + addFundsSent.Add(2) + + addFundsAmt1 := big.NewInt(5) // 1 prefunds + addFundsAmt2 := big.NewInt(3) // 2 reserves + var addFundsCh1 address.Address + var addFundsCh2 address.Address + var addFundsMcid1 cid.Cid + var addFundsMcid2 cid.Cid + go func() { + defer addFundsSent.Done() + + // Request add funds - should block until create channel has completed + var err error + addFundsCh1, addFundsMcid1, err = mgr.GetPaych(ctx, from, to, addFundsAmt1, false) require.NoError(t, err) }() @@ -673,7 +837,7 @@ func TestPaychGetMergeAddFunds(t *testing.T) { // Request add funds again - should merge with waiting add funds request var err error - addFundsCh2, addFundsMcid2, err = mgr.GetPaych(ctx, from, to, addFundsAmt2) + addFundsCh2, addFundsMcid2, err = mgr.GetPaych(ctx, from, to, addFundsAmt2, true) require.NoError(t, err) }() // Wait for add funds requests to be queued up @@ -726,6 +890,103 @@ func TestPaychGetMergeAddFunds(t *testing.T) { require.Equal(t, types.BigAdd(addFundsAmt1, addFundsAmt2), addFundsMsg.Message.Value) } +func TestPaychGetMergePrefundAndReservePrefunded(t *testing.T) { + ctx := context.Background() + store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore())) + + ch := tutils.NewIDAddr(t, 100) + from := tutils.NewIDAddr(t, 101) + to := tutils.NewIDAddr(t, 102) + + mock := newMockManagerAPI() + defer mock.close() + + mgr, err := newManager(store, mock) + require.NoError(t, err) + + // Send create message for a channel with value 10 + createAmt := big.NewInt(10) + _, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, false) + require.NoError(t, err) + + // Queue up two add funds requests behind create channel + var addFundsSent sync.WaitGroup + addFundsSent.Add(2) + + addFundsAmt1 := big.NewInt(5) // 1 prefunds + addFundsAmt2 := big.NewInt(3) // 2 reserves + var addFundsCh1 address.Address + var addFundsCh2 address.Address + var addFundsMcid1 cid.Cid + var addFundsMcid2 cid.Cid + go func() { + defer addFundsSent.Done() + + // Request add funds - should block until create channel has completed + var err error + addFundsCh1, addFundsMcid1, err = mgr.GetPaych(ctx, from, to, addFundsAmt1, false) + require.NoError(t, err) + }() + + go func() { + defer addFundsSent.Done() + + // Request add funds again - should merge with waiting add funds request + var err error + addFundsCh2, addFundsMcid2, err = mgr.GetPaych(ctx, from, to, addFundsAmt2, true) + require.NoError(t, err) + }() + // Wait for add funds requests to be queued up + waitForQueueSize(t, mgr, from, to, 2) + + // Send create channel response + response := testChannelResponse(t, ch) + mock.receiveMsgResponse(createMsgCid, response) + + // Wait for create channel response + chres, err := mgr.GetPaychWaitReady(ctx, createMsgCid) + require.NoError(t, err) + require.Equal(t, ch, chres) + + // Wait for add funds requests to be sent + addFundsSent.Wait() + + // Expect add funds requests to have same channel as create channel and + // same message cid as each other (because they should have been merged) + require.Equal(t, ch, addFundsCh1) + require.Equal(t, ch, addFundsCh2) + require.NotEqual(t, cid.Undef, addFundsMcid1) + require.Equal(t, cid.Undef, addFundsMcid2) + + // Send success add funds response + mock.receiveMsgResponse(addFundsMcid1, types.MessageReceipt{ + ExitCode: 0, + Return: []byte{}, + }) + + // Wait for add funds response + addFundsCh, err := mgr.GetPaychWaitReady(ctx, addFundsMcid1) + require.NoError(t, err) + require.Equal(t, ch, addFundsCh) + + // Make sure that one create channel message and one add funds message was + // sent + require.Equal(t, 2, mock.pushedMessageCount()) + + // Check create message amount is correct + createMsg := mock.pushedMessages(createMsgCid) + require.Equal(t, from, createMsg.Message.From) + require.Equal(t, lotusinit.Address, createMsg.Message.To) + require.Equal(t, createAmt, createMsg.Message.Value) + + // Check merged add funds amount is the sum of the individual + // amounts + addFundsMsg := mock.pushedMessages(addFundsMcid1) + require.Equal(t, from, addFundsMsg.Message.From) + require.Equal(t, ch, addFundsMsg.Message.To) + require.Equal(t, addFundsAmt1, addFundsMsg.Message.Value) +} + // TestPaychGetMergeAddFundsCtxCancelOne tests that when a queued add funds // request is cancelled, its amount is removed from the total merged add funds func TestPaychGetMergeAddFundsCtxCancelOne(t *testing.T) { @@ -744,7 +1005,7 @@ func TestPaychGetMergeAddFundsCtxCancelOne(t *testing.T) { // Send create message for a channel with value 10 createAmt := big.NewInt(10) - _, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt) + _, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, true) require.NoError(t, err) // Queue up two add funds requests behind create channel @@ -761,7 +1022,7 @@ func TestPaychGetMergeAddFundsCtxCancelOne(t *testing.T) { defer addFundsSent.Done() // Request add funds - should block until create channel has completed - _, _, addFundsErr1 = mgr.GetPaych(addFundsCtx1, from, to, addFundsAmt1) + _, _, addFundsErr1 = mgr.GetPaych(addFundsCtx1, from, to, addFundsAmt1, true) }() go func() { @@ -769,7 +1030,7 @@ func TestPaychGetMergeAddFundsCtxCancelOne(t *testing.T) { // Request add funds again - should merge with waiting add funds request var err error - addFundsCh2, addFundsMcid2, err = mgr.GetPaych(ctx, from, to, addFundsAmt2) + addFundsCh2, addFundsMcid2, err = mgr.GetPaych(ctx, from, to, addFundsAmt2, true) require.NoError(t, err) }() // Wait for add funds requests to be queued up @@ -841,7 +1102,7 @@ func TestPaychGetMergeAddFundsCtxCancelAll(t *testing.T) { // Send create message for a channel with value 10 createAmt := big.NewInt(10) - _, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt) + _, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, true) require.NoError(t, err) // Queue up two add funds requests behind create channel @@ -856,14 +1117,14 @@ func TestPaychGetMergeAddFundsCtxCancelAll(t *testing.T) { defer addFundsSent.Done() // Request add funds - should block until create channel has completed - _, _, addFundsErr1 = mgr.GetPaych(addFundsCtx1, from, to, big.NewInt(5)) + _, _, addFundsErr1 = mgr.GetPaych(addFundsCtx1, from, to, big.NewInt(5), true) }() go func() { defer addFundsSent.Done() // Request add funds again - should merge with waiting add funds request - _, _, addFundsErr2 = mgr.GetPaych(addFundsCtx2, from, to, big.NewInt(3)) + _, _, addFundsErr2 = mgr.GetPaych(addFundsCtx2, from, to, big.NewInt(3), true) }() // Wait for add funds requests to be queued up waitForQueueSize(t, mgr, from, to, 2) @@ -928,7 +1189,7 @@ func TestPaychAvailableFunds(t *testing.T) { // Send create message for a channel with value 10 createAmt := big.NewInt(10) - _, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt) + _, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, true) require.NoError(t, err) // Available funds should reflect create channel message sent @@ -953,7 +1214,7 @@ func TestPaychAvailableFunds(t *testing.T) { // Request add funds - should block until create channel has completed var err error - _, addFundsMcid, err = mgr.GetPaych(ctx, from, to, addFundsAmt) + _, addFundsMcid, err = mgr.GetPaych(ctx, from, to, addFundsAmt, true) require.NoError(t, err) }() diff --git a/paychmgr/paychvoucherfunds_test.go b/paychmgr/paychvoucherfunds_test.go index f83a7cd623e..d13a5815eb4 100644 --- a/paychmgr/paychvoucherfunds_test.go +++ b/paychmgr/paychvoucherfunds_test.go @@ -46,7 +46,7 @@ func TestPaychAddVoucherAfterAddFunds(t *testing.T) { // Send create message for a channel with value 10 createAmt := big.NewInt(10) - _, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt) + _, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, true) require.NoError(t, err) // Send create channel response @@ -82,7 +82,7 @@ func TestPaychAddVoucherAfterAddFunds(t *testing.T) { require.Equal(t, res.Shortfall, excessAmt) // Add funds so as to cover the voucher shortfall - _, addFundsMsgCid, err := mgr.GetPaych(ctx, from, to, excessAmt) + _, addFundsMsgCid, err := mgr.GetPaych(ctx, from, to, excessAmt, true) require.NoError(t, err) // Trigger add funds confirmation diff --git a/paychmgr/settle_test.go b/paychmgr/settle_test.go index 43a0062000b..e674d63f4e0 100644 --- a/paychmgr/settle_test.go +++ b/paychmgr/settle_test.go @@ -29,7 +29,7 @@ func TestPaychSettle(t *testing.T) { require.NoError(t, err) amt := big.NewInt(10) - _, mcid, err := mgr.GetPaych(ctx, from, to, amt) + _, mcid, err := mgr.GetPaych(ctx, from, to, amt, true) require.NoError(t, err) // Send channel create response @@ -49,7 +49,7 @@ func TestPaychSettle(t *testing.T) { // (should create a new channel because the previous channel // is settling) amt2 := big.NewInt(5) - _, mcid2, err := mgr.GetPaych(ctx, from, to, amt2) + _, mcid2, err := mgr.GetPaych(ctx, from, to, amt2, true) require.NoError(t, err) require.NotEqual(t, cid.Undef, mcid2) diff --git a/paychmgr/simple.go b/paychmgr/simple.go index fd849d3aed7..b9c70a7f3fd 100644 --- a/paychmgr/simple.go +++ b/paychmgr/simple.go @@ -109,7 +109,7 @@ func newMergedFundsReq(reqs []*fundsReq) *mergedFundsReq { sort.Slice(m.reqs, func(i, j int) bool { if m.reqs[i].reserve != m.reqs[j].reserve { // non-reserve first - return m.reqs[j].reserve + return m.reqs[i].reserve } // sort by amount asc (reducing latency for smaller requests) @@ -220,50 +220,7 @@ func (ca *channelAccessor) processQueue(ctx context.Context, channelID string) ( return ca.currentAvailableFunds(ctx, channelID, amt) } - { - toReserve := types.BigSub(amt, avail) - avail := types.NewInt(0) - - // reserve at most what we need - ca.mutateChannelInfo(ctx, channelID, func(ci *ChannelInfo) { - avail = ci.AvailableAmount - if avail.GreaterThan(toReserve) { - avail = toReserve - } - ci.AvailableAmount = big.Sub(ci.AvailableAmount, avail) - }) - - used := types.NewInt(0) - - next := 0 - for i, r := range merged.reqs { - if !r.reserve { - // non-reserving request are put after reserving requests, so we are done here - break - } - - if r.amt.GreaterThan(types.BigSub(avail, used)) { - // requests are sorted by amount ascending, so if we hit this, there aren't any more requests we can fill - } - - // don't try to fill inactive requests - if !r.isActive() { - continue - } - - used = types.BigAdd(used, r.amt) - r.onComplete(&paychFundsRes{}) - next = i + 1 - } - merged.reqs = merged.reqs[next:] - - // return any unused reserved funds (e.g. from cancelled requests) - ca.mutateChannelInfo(ctx, channelID, func(ci *ChannelInfo) { - ci.AvailableAmount = types.BigAdd(ci.AvailableAmount, types.BigSub(avail, used)) - }) - } - - res := ca.processTask(merged.ctx, amt, avail) + res := ca.processTask(merged, amt, avail) // If the task is waiting on an external event (eg something to appear on // chain) it will return nil @@ -394,7 +351,9 @@ func (ca *channelAccessor) currentAvailableFunds(ctx context.Context, channelID // Note that processTask may be called repeatedly in the same state, and should // return nil if there is no state change to be made (eg when waiting for a // message to be confirmed on chain) -func (ca *channelAccessor) processTask(ctx context.Context, amt, avail types.BigInt) *paychFundsRes { +func (ca *channelAccessor) processTask(merged *mergedFundsReq, amt, avail types.BigInt) *paychFundsRes { + ctx := merged.ctx + // Get the payment channel for the from/to addresses. // Note: It's ok if we get ErrChannelNotTracked. It just means we need to // create a channel. @@ -427,6 +386,56 @@ func (ca *channelAccessor) processTask(ctx context.Context, amt, avail types.Big return nil } + { + toReserve := types.BigSub(amt, avail) + avail := types.NewInt(0) + + // reserve at most what we need + ca.mutateChannelInfo(ctx, channelInfo.ChannelID, func(ci *ChannelInfo) { + avail = ci.AvailableAmount + if avail.GreaterThan(toReserve) { + avail = toReserve + } + ci.AvailableAmount = big.Sub(ci.AvailableAmount, avail) + }) + + used := types.NewInt(0) + + next := 0 + for i, r := range merged.reqs { + if !r.reserve { + // non-reserving request are put after reserving requests, so we are done here + break + } + + if r.amt.GreaterThan(types.BigSub(avail, used)) { + // requests are sorted by amount ascending, so if we hit this, there aren't any more requests we can fill + break + } + + // don't try to fill inactive requests + if !r.isActive() { + continue + } + + used = types.BigAdd(used, r.amt) + r.onComplete(&paychFundsRes{channel: *channelInfo.Channel}) + next = i + 1 + } + merged.reqs = merged.reqs[next:] + + // return any unused reserved funds (e.g. from cancelled requests) + ca.mutateChannelInfo(ctx, channelInfo.ChannelID, func(ci *ChannelInfo) { + ci.AvailableAmount = types.BigAdd(ci.AvailableAmount, types.BigSub(avail, used)) + }) + + amt = types.BigSub(amt, used) + } + + if amt.LessThanEqual(types.NewInt(0)) { + return nil + } + // We need to add more funds, so send an add funds message to // cover the amount for this request mcid, err := ca.addFunds(ctx, channelInfo, amt, avail) From 2e76375e8aa230a2a2182c0737ec6eb63b3b1896 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 4 Jan 2022 21:41:57 +0100 Subject: [PATCH 056/385] Fix paych itests --- itests/paych_api_test.go | 2 +- testplans/lotus-soup/deals_e2e.go | 4 ++-- testplans/lotus-soup/paych/stress.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/itests/paych_api_test.go b/itests/paych_api_test.go index 49c23545b44..fb2233d9043 100644 --- a/itests/paych_api_test.go +++ b/itests/paych_api_test.go @@ -58,7 +58,7 @@ func TestPaymentChannelsAPI(t *testing.T) { require.NoError(t, err) channelAmt := int64(7000) - channelInfo, err := paymentCreator.PaychGet(ctx, createrAddr, receiverAddr, abi.NewTokenAmount(channelAmt)) + channelInfo, err := paymentCreator.PaychGet(ctx, createrAddr, receiverAddr, abi.NewTokenAmount(channelAmt), true) require.NoError(t, err) channel, err := paymentCreator.PaychGetWaitReady(ctx, channelInfo.WaitSentinel) diff --git a/testplans/lotus-soup/deals_e2e.go b/testplans/lotus-soup/deals_e2e.go index 6737bdae226..bc970350837 100644 --- a/testplans/lotus-soup/deals_e2e.go +++ b/testplans/lotus-soup/deals_e2e.go @@ -207,7 +207,7 @@ func initPaymentChannel(t *testkit.TestEnvironment, ctx context.Context, cl *tes t.RecordMessage("my balance: %d", balance) t.RecordMessage("creating payment channel; from=%s, to=%s, funds=%d", cl.Wallet.Address, recv.WalletAddr, balance) - channel, err := cl.FullApi.PaychGet(ctx, cl.Wallet.Address, recv.WalletAddr, balance) + channel, err := cl.FullApi.PaychGet(ctx, cl.Wallet.Address, recv.WalletAddr, balance, true) if err != nil { return fmt.Errorf("failed to create payment channel: %w", err) } @@ -230,7 +230,7 @@ func initPaymentChannel(t *testkit.TestEnvironment, ctx context.Context, cl *tes // we wait for 2 confirmations, so we have the assurance the channel is tracked. t.RecordMessage("reloading paych; now it should have an address") - channel, err = cl.FullApi.PaychGet(ctx, cl.Wallet.Address, recv.WalletAddr, big.Zero()) + channel, err = cl.FullApi.PaychGet(ctx, cl.Wallet.Address, recv.WalletAddr, big.Zero(), true) if err != nil { return fmt.Errorf("failed to reload payment channel: %w", err) } diff --git a/testplans/lotus-soup/paych/stress.go b/testplans/lotus-soup/paych/stress.go index 85246603f0f..e0d324f03e9 100644 --- a/testplans/lotus-soup/paych/stress.go +++ b/testplans/lotus-soup/paych/stress.go @@ -124,7 +124,7 @@ func runSender(ctx context.Context, t *testkit.TestEnvironment, clients []*testk time.Sleep(20 * time.Second) - channel, err := cl.FullApi.PaychGet(ctx, cl.Wallet.Address, recv.WalletAddr, channelAmt) + channel, err := cl.FullApi.PaychGet(ctx, cl.Wallet.Address, recv.WalletAddr, channelAmt, true) if err != nil { return fmt.Errorf("failed to create payment channel: %w", err) } From 7a938b2dea63793c35598e239385ad0a46baef21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 4 Jan 2022 22:53:59 +0100 Subject: [PATCH 057/385] paych: Output FIL in cli --- cli/paych.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cli/paych.go b/cli/paych.go index 1d5e304c383..03fd1cd6e5b 100644 --- a/cli/paych.go +++ b/cli/paych.go @@ -169,7 +169,7 @@ func paychStatus(writer io.Writer, avail *api.ChannelAvailableFunds) { fmt.Fprint(writer, "Creating channel\n") fmt.Fprintf(writer, " From: %s\n", avail.From) fmt.Fprintf(writer, " To: %s\n", avail.To) - fmt.Fprintf(writer, " Pending Amt: %d\n", avail.PendingAmt) + fmt.Fprintf(writer, " Pending Amt: %s\n", types.FIL(avail.PendingAmt)) fmt.Fprintf(writer, " Wait Sentinel: %s\n", avail.PendingWaitSentinel) return } @@ -189,10 +189,10 @@ func paychStatus(writer io.Writer, avail *api.ChannelAvailableFunds) { {"Channel", avail.Channel.String()}, {"From", avail.From.String()}, {"To", avail.To.String()}, - {"Confirmed Amt", fmt.Sprintf("%d", avail.ConfirmedAmt)}, - {"Pending Amt", fmt.Sprintf("%d", avail.PendingAmt)}, - {"Queued Amt", fmt.Sprintf("%d", avail.QueuedAmt)}, - {"Voucher Redeemed Amt", fmt.Sprintf("%d", avail.VoucherReedeemedAmt)}, + {"Confirmed Amt", fmt.Sprintf("%s", types.FIL(avail.ConfirmedAmt))}, + {"Pending Amt", fmt.Sprintf("%s", types.FIL(avail.PendingAmt))}, + {"Queued Amt", fmt.Sprintf("%s", types.FIL(avail.QueuedAmt))}, + {"Voucher Redeemed Amt", fmt.Sprintf("%s", types.FIL(avail.VoucherReedeemedAmt))}, } if avail.PendingWaitSentinel != nil { nameValues = append(nameValues, []string{ @@ -576,7 +576,7 @@ func outputVoucher(w io.Writer, v *paych.SignedVoucher, export bool) error { } } - fmt.Fprintf(w, "Lane %d, Nonce %d: %s", v.Lane, v.Nonce, v.Amount.String()) + fmt.Fprintf(w, "Lane %d, Nonce %d: %s", v.Lane, v.Nonce, types.FIL(v.Amount)) if export { fmt.Fprintf(w, "; %s", enc) } From 8f6f21c94cee6b3bc0c596ee87bbd5b21ee45edd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 4 Jan 2022 23:20:11 +0100 Subject: [PATCH 058/385] paych: Print available amounts in paych status --- api/api_full.go | 4 ++++ cli/paych.go | 2 ++ paychmgr/manager.go | 2 ++ paychmgr/simple.go | 2 ++ 4 files changed, 10 insertions(+) diff --git a/api/api_full.go b/api/api_full.go index cf9a1f22ef2..47f05fb7976 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -854,6 +854,10 @@ type ChannelAvailableFunds struct { ConfirmedAmt types.BigInt // PendingAmt is the amount of funds that are pending confirmation on-chain PendingAmt types.BigInt + // AvailableAmt is part of ConfirmedAmt that is available for use (pre-allocated) + AvailableAmt types.BigInt + // PendingAvailableAmt is the amount of available funds that are pending confirmation on-chain + PendingAvailableAmt types.BigInt // PendingWaitSentinel can be used with PaychGetWaitReady to wait for // confirmation of pending funds PendingWaitSentinel *cid.Cid diff --git a/cli/paych.go b/cli/paych.go index 03fd1cd6e5b..eef26227231 100644 --- a/cli/paych.go +++ b/cli/paych.go @@ -191,6 +191,8 @@ func paychStatus(writer io.Writer, avail *api.ChannelAvailableFunds) { {"To", avail.To.String()}, {"Confirmed Amt", fmt.Sprintf("%s", types.FIL(avail.ConfirmedAmt))}, {"Pending Amt", fmt.Sprintf("%s", types.FIL(avail.PendingAmt))}, + {"Available Amt", fmt.Sprintf("%s", types.FIL(avail.AvailableAmt))}, + {"Pending Available Amt", fmt.Sprintf("%s", types.FIL(avail.PendingAvailableAmt))}, {"Queued Amt", fmt.Sprintf("%s", types.FIL(avail.QueuedAmt))}, {"Voucher Redeemed Amt", fmt.Sprintf("%s", types.FIL(avail.VoucherReedeemedAmt))}, } diff --git a/paychmgr/manager.go b/paychmgr/manager.go index eed475547aa..612cb6678a8 100644 --- a/paychmgr/manager.go +++ b/paychmgr/manager.go @@ -142,6 +142,8 @@ func (pm *Manager) AvailableFundsByFromTo(ctx context.Context, from address.Addr To: to, ConfirmedAmt: types.NewInt(0), PendingAmt: types.NewInt(0), + AvailableAmt: types.NewInt(0), + PendingAvailableAmt: types.NewInt(0), PendingWaitSentinel: nil, QueuedAmt: types.NewInt(0), VoucherReedeemedAmt: types.NewInt(0), diff --git a/paychmgr/simple.go b/paychmgr/simple.go index b9c70a7f3fd..45a522ba41d 100644 --- a/paychmgr/simple.go +++ b/paychmgr/simple.go @@ -340,6 +340,8 @@ func (ca *channelAccessor) currentAvailableFunds(ctx context.Context, channelID To: channelInfo.to(), ConfirmedAmt: channelInfo.Amount, PendingAmt: channelInfo.PendingAmount, + AvailableAmt: channelInfo.AvailableAmount, + PendingAvailableAmt: channelInfo.PendingAvailableAmount, PendingWaitSentinel: waitSentinel, QueuedAmt: queuedAmt, VoucherReedeemedAmt: totalRedeemed, From ff8b95df934264f9c85bb0ecb82bb7cf7b277176 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 4 Jan 2022 23:31:22 +0100 Subject: [PATCH 059/385] paych: Reserve flag for add-funds cli --- cli/paych.go | 9 ++++++--- paychmgr/store.go | 6 ++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/cli/paych.go b/cli/paych.go index eef26227231..171ab38abfc 100644 --- a/cli/paych.go +++ b/cli/paych.go @@ -39,12 +39,15 @@ var paychAddFundsCmd = &cli.Command{ Usage: "Add funds to the payment channel between fromAddress and toAddress. Creates the payment channel if it doesn't already exist.", ArgsUsage: "[fromAddress toAddress amount]", Flags: []cli.Flag{ - &cli.BoolFlag{ Name: "restart-retrievals", Usage: "restart stalled retrieval deals on this payment channel", Value: true, }, + &cli.BoolFlag{ + Name: "reserve", + Usage: "mark funds as reserved", + }, }, Action: func(cctx *cli.Context) error { if cctx.Args().Len() != 3 { @@ -66,7 +69,7 @@ var paychAddFundsCmd = &cli.Command{ return ShowHelp(cctx, fmt.Errorf("parsing amount failed: %s", err)) } - api, closer, err := GetFullNodeAPI(cctx) + api, closer, err := GetFullNodeAPIV1(cctx) if err != nil { return err } @@ -76,7 +79,7 @@ var paychAddFundsCmd = &cli.Command{ // Send a message to chain to create channel / add funds to existing // channel - info, err := api.PaychGet(ctx, from, to, types.BigInt(amt)) + info, err := api.PaychGet(ctx, from, to, types.BigInt(amt), cctx.Bool("reserve")) if err != nil { return err } diff --git a/paychmgr/store.go b/paychmgr/store.go index bbc549b862c..d5c8e198049 100644 --- a/paychmgr/store.go +++ b/paychmgr/store.go @@ -502,5 +502,11 @@ func unmarshallChannelInfo(stored *ChannelInfo, value []byte) (*ChannelInfo, err stored.Channel = nil } + // backwards compat + if stored.AvailableAmount.Int == nil { + stored.AvailableAmount = types.NewInt(0) + stored.PendingAvailableAmount = types.NewInt(0) + } + return stored, nil } From 1f2621b57430e024910a33bf6da3d19c92fdcdb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 5 Jan 2022 00:09:19 +0100 Subject: [PATCH 060/385] Make retrieval work with reused channels --- markets/retrievaladapter/client.go | 34 ++++++++++++++++++++++++++++++ paychmgr/simple.go | 2 +- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/markets/retrievaladapter/client.go b/markets/retrievaladapter/client.go index 4ed2e905ab4..88fcb7ba1e3 100644 --- a/markets/retrievaladapter/client.go +++ b/markets/retrievaladapter/client.go @@ -9,6 +9,8 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" "github.com/multiformats/go-multiaddr" + mh "github.com/multiformats/go-multihash" + "golang.org/x/xerrors" "github.com/filecoin-project/lotus/chain/actors/builtin/paych" "github.com/filecoin-project/lotus/chain/types" @@ -16,6 +18,27 @@ import ( payapi "github.com/filecoin-project/lotus/node/impl/paych" ) +func mkPaychReusedCid(addr address.Address) cid.Cid { + c, err := cid.V1Builder{Codec: cid.Raw, MhType: mh.IDENTITY}.Sum(addr.Bytes()) + if err != nil { + panic(err) + } + return c +} + +func extractPaychReusedCid(c cid.Cid) (address.Address, error) { + if c.Prefix().Codec != cid.Raw { + return address.Undef, nil + } + + h, err := mh.Decode(c.Hash()) + if err != nil { + return address.Address{}, err + } + + return address.NewFromBytes(h.Digest) +} + type retrievalClientNode struct { chainAPI full.ChainAPI payAPI payapi.PaychAPI @@ -38,6 +61,10 @@ func (rcn *retrievalClientNode) GetOrCreatePaymentChannel(ctx context.Context, c if err != nil { return address.Undef, cid.Undef, err } + if ci.WaitSentinel == cid.Undef { + return ci.Channel, mkPaychReusedCid(ci.Channel), nil + } + return ci.Channel, ci.WaitSentinel, nil } @@ -74,6 +101,13 @@ func (rcn *retrievalClientNode) GetChainHead(ctx context.Context) (shared.TipSet } func (rcn *retrievalClientNode) WaitForPaymentChannelReady(ctx context.Context, messageCID cid.Cid) (address.Address, error) { + maybeAddr, err := extractPaychReusedCid(messageCID) + if err != nil { + return address.Address{}, xerrors.Errorf("extract paych reused CID: %w", err) + } + if maybeAddr != address.Undef { + return maybeAddr, nil + } return rcn.payAPI.PaychGetWaitReady(ctx, messageCID) } diff --git a/paychmgr/simple.go b/paychmgr/simple.go index 45a522ba41d..d06cb870df4 100644 --- a/paychmgr/simple.go +++ b/paychmgr/simple.go @@ -41,7 +41,7 @@ type fundsReq struct { } func newFundsReq(ctx context.Context, amt types.BigInt, reserve bool) *fundsReq { - promise := make(chan *paychFundsRes) + promise := make(chan *paychFundsRes, 1) return &fundsReq{ ctx: ctx, promise: promise, From eab8fecd2631766e29a5e1f7bce8d3eac858f321 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 5 Jan 2022 00:17:03 +0100 Subject: [PATCH 061/385] gen stuff --- documentation/en/api-v0-methods.md | 4 ++++ documentation/en/api-v1-unstable-methods.md | 4 ++++ documentation/en/cli-lotus.md | 1 + 3 files changed, 9 insertions(+) diff --git a/documentation/en/api-v0-methods.md b/documentation/en/api-v0-methods.md index 883d4d27499..2061d7fadb7 100644 --- a/documentation/en/api-v0-methods.md +++ b/documentation/en/api-v0-methods.md @@ -4061,6 +4061,8 @@ Response: "To": "f01234", "ConfirmedAmt": "0", "PendingAmt": "0", + "AvailableAmt": "0", + "PendingAvailableAmt": "0", "PendingWaitSentinel": null, "QueuedAmt": "0", "VoucherReedeemedAmt": "0" @@ -4088,6 +4090,8 @@ Response: "To": "f01234", "ConfirmedAmt": "0", "PendingAmt": "0", + "AvailableAmt": "0", + "PendingAvailableAmt": "0", "PendingWaitSentinel": null, "QueuedAmt": "0", "VoucherReedeemedAmt": "0" diff --git a/documentation/en/api-v1-unstable-methods.md b/documentation/en/api-v1-unstable-methods.md index ce0ceadcdfd..b84877b97a5 100644 --- a/documentation/en/api-v1-unstable-methods.md +++ b/documentation/en/api-v1-unstable-methods.md @@ -4456,6 +4456,8 @@ Response: "To": "f01234", "ConfirmedAmt": "0", "PendingAmt": "0", + "AvailableAmt": "0", + "PendingAvailableAmt": "0", "PendingWaitSentinel": null, "QueuedAmt": "0", "VoucherReedeemedAmt": "0" @@ -4483,6 +4485,8 @@ Response: "To": "f01234", "ConfirmedAmt": "0", "PendingAmt": "0", + "AvailableAmt": "0", + "PendingAvailableAmt": "0", "PendingWaitSentinel": null, "QueuedAmt": "0", "VoucherReedeemedAmt": "0" diff --git a/documentation/en/cli-lotus.md b/documentation/en/cli-lotus.md index 54c0d36dfe6..46e481b0879 100644 --- a/documentation/en/cli-lotus.md +++ b/documentation/en/cli-lotus.md @@ -1347,6 +1347,7 @@ USAGE: OPTIONS: --restart-retrievals restart stalled retrieval deals on this payment channel (default: true) + --reserve mark funds as reserved (default: false) --help, -h show help (default: false) ``` From 533349cc0d0d13de84531e2deb822b2f3a51a210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 5 Jan 2022 12:11:19 +0100 Subject: [PATCH 062/385] paych: Fix cli tests --- cli/paych.go | 4 ++-- itests/paych_cli_test.go | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cli/paych.go b/cli/paych.go index 171ab38abfc..29e8c640719 100644 --- a/cli/paych.go +++ b/cli/paych.go @@ -193,11 +193,11 @@ func paychStatus(writer io.Writer, avail *api.ChannelAvailableFunds) { {"From", avail.From.String()}, {"To", avail.To.String()}, {"Confirmed Amt", fmt.Sprintf("%s", types.FIL(avail.ConfirmedAmt))}, - {"Pending Amt", fmt.Sprintf("%s", types.FIL(avail.PendingAmt))}, {"Available Amt", fmt.Sprintf("%s", types.FIL(avail.AvailableAmt))}, + {"Voucher Redeemed Amt", fmt.Sprintf("%s", types.FIL(avail.VoucherReedeemedAmt))}, + {"Pending Amt", fmt.Sprintf("%s", types.FIL(avail.PendingAmt))}, {"Pending Available Amt", fmt.Sprintf("%s", types.FIL(avail.PendingAvailableAmt))}, {"Queued Amt", fmt.Sprintf("%s", types.FIL(avail.QueuedAmt))}, - {"Voucher Redeemed Amt", fmt.Sprintf("%s", types.FIL(avail.VoucherReedeemedAmt))}, } if avail.PendingWaitSentinel != nil { nameValues = append(nameValues, []string{ diff --git a/itests/paych_cli_test.go b/itests/paych_cli_test.go index a4ad1920b6e..f964d781384 100644 --- a/itests/paych_cli_test.go +++ b/itests/paych_cli_test.go @@ -133,10 +133,10 @@ func TestPaymentChannelStatus(t *testing.T) { require.True(t, stateCreating || stateCreated) channelAmtAtto := types.BigMul(types.NewInt(channelAmt), types.NewInt(build.FilecoinPrecision)) - channelAmtStr := fmt.Sprintf("%d", channelAmtAtto) + channelAmtStr := fmt.Sprintf("%s", types.FIL(channelAmtAtto)) if stateCreating { // If we're in the creating state (most likely) the amount should be pending - require.Regexp(t, regexp.MustCompile("Pending.*"+channelAmtStr), out) + require.Regexp(t, regexp.MustCompile("Pending Amt.*"+channelAmtStr), out) } // Wait for create channel to complete @@ -159,7 +159,7 @@ func TestPaymentChannelStatus(t *testing.T) { out = creatorCLI.RunCmd("paych", "status", chstr) fmt.Println(out) voucherAmtAtto := types.BigMul(types.NewInt(voucherAmt), types.NewInt(build.FilecoinPrecision)) - voucherAmtStr := fmt.Sprintf("%d", voucherAmtAtto) + voucherAmtStr := fmt.Sprintf("%s", types.FIL(voucherAmtAtto)) // Output should include voucher amount require.Regexp(t, regexp.MustCompile("Voucher.*"+voucherAmtStr), out) } From b0e7bc15c2f664dc96053ed4f70c61e3421bfe68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 5 Jan 2022 16:11:32 +0100 Subject: [PATCH 063/385] paych: Cleanup available fund logic --- paychmgr/simple.go | 100 +++++++++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 45 deletions(-) diff --git a/paychmgr/simple.go b/paychmgr/simple.go index d06cb870df4..747eac58509 100644 --- a/paychmgr/simple.go +++ b/paychmgr/simple.go @@ -163,6 +163,35 @@ func (m *mergedFundsReq) sum() (types.BigInt, types.BigInt) { return sum, avail } +// completeAmount completes first non-reserving requests up to the available amount +func (m *mergedFundsReq) completeAmount(avail types.BigInt, channelInfo *ChannelInfo) types.BigInt { + used := types.NewInt(0) + next := 0 + for i, r := range m.reqs { + if !r.reserve { + // non-reserving request are put after reserving requests, so we are done here + break + } + + if r.amt.GreaterThan(types.BigSub(avail, used)) { + // requests are sorted by amount ascending, so if we hit this, there aren't any more requests we can fill + break + } + + // don't try to fill inactive requests + if !r.isActive() { + continue + } + + used = types.BigAdd(used, r.amt) + r.onComplete(&paychFundsRes{channel: *channelInfo.Channel}) + next = i + 1 + } + + m.reqs = m.reqs[next:] + return used +} + // getPaych ensures that a channel exists between the from and to addresses, // and reserves (or adds as available) the given amount of funds. // If the channel does not exist a create channel message is sent and the @@ -388,51 +417,8 @@ func (ca *channelAccessor) processTask(merged *mergedFundsReq, amt, avail types. return nil } - { - toReserve := types.BigSub(amt, avail) - avail := types.NewInt(0) - - // reserve at most what we need - ca.mutateChannelInfo(ctx, channelInfo.ChannelID, func(ci *ChannelInfo) { - avail = ci.AvailableAmount - if avail.GreaterThan(toReserve) { - avail = toReserve - } - ci.AvailableAmount = big.Sub(ci.AvailableAmount, avail) - }) - - used := types.NewInt(0) - - next := 0 - for i, r := range merged.reqs { - if !r.reserve { - // non-reserving request are put after reserving requests, so we are done here - break - } - - if r.amt.GreaterThan(types.BigSub(avail, used)) { - // requests are sorted by amount ascending, so if we hit this, there aren't any more requests we can fill - break - } - - // don't try to fill inactive requests - if !r.isActive() { - continue - } - - used = types.BigAdd(used, r.amt) - r.onComplete(&paychFundsRes{channel: *channelInfo.Channel}) - next = i + 1 - } - merged.reqs = merged.reqs[next:] - - // return any unused reserved funds (e.g. from cancelled requests) - ca.mutateChannelInfo(ctx, channelInfo.ChannelID, func(ci *ChannelInfo) { - ci.AvailableAmount = types.BigAdd(ci.AvailableAmount, types.BigSub(avail, used)) - }) - - amt = types.BigSub(amt, used) - } + // Try to fill requests using available funds, without going to the chain + amt = ca.completeAvailable(ctx, merged, channelInfo, amt, avail) if amt.LessThanEqual(types.NewInt(0)) { return nil @@ -533,6 +519,30 @@ func (ca *channelAccessor) waitPaychCreateMsg(ctx context.Context, channelID str return nil } +// completeAvailable fills reserving fund requests using already available funds, without interacting with the chain +func (ca *channelAccessor) completeAvailable(ctx context.Context, merged *mergedFundsReq, channelInfo *ChannelInfo, amt, av types.BigInt) types.BigInt { + toReserve := types.BigSub(amt, av) + avail := types.NewInt(0) + + // reserve at most what we need + ca.mutateChannelInfo(ctx, channelInfo.ChannelID, func(ci *ChannelInfo) { + avail = ci.AvailableAmount + if avail.GreaterThan(toReserve) { + avail = toReserve + } + ci.AvailableAmount = big.Sub(ci.AvailableAmount, avail) + }) + + used := merged.completeAmount(avail, channelInfo) + + // return any unused reserved funds (e.g. from cancelled requests) + ca.mutateChannelInfo(ctx, channelInfo.ChannelID, func(ci *ChannelInfo) { + ci.AvailableAmount = types.BigAdd(ci.AvailableAmount, types.BigSub(avail, used)) + }) + + return types.BigSub(amt, used) +} + // addFunds sends a message to add funds to the channel and returns the message cid func (ca *channelAccessor) addFunds(ctx context.Context, channelInfo *ChannelInfo, amt, avail types.BigInt) (*cid.Cid, error) { msg := &types.Message{ From 5b585c0285f22d26d8c50db909b12cf2cd479f49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 5 Jan 2022 21:49:26 +0100 Subject: [PATCH 064/385] paych: reset fundsReqQueue correctly --- paychmgr/simple.go | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/paychmgr/simple.go b/paychmgr/simple.go index 747eac58509..def24d1cf5c 100644 --- a/paychmgr/simple.go +++ b/paychmgr/simple.go @@ -164,7 +164,7 @@ func (m *mergedFundsReq) sum() (types.BigInt, types.BigInt) { } // completeAmount completes first non-reserving requests up to the available amount -func (m *mergedFundsReq) completeAmount(avail types.BigInt, channelInfo *ChannelInfo) types.BigInt { +func (m *mergedFundsReq) completeAmount(avail types.BigInt, channelInfo *ChannelInfo) (*paychFundsRes, types.BigInt) { used := types.NewInt(0) next := 0 for i, r := range m.reqs { @@ -189,7 +189,10 @@ func (m *mergedFundsReq) completeAmount(avail types.BigInt, channelInfo *Channel } m.reqs = m.reqs[next:] - return used + if len(m.reqs) == 0 { + return &paychFundsRes{channel: *channelInfo.Channel}, used + } + return nil, used } // getPaych ensures that a channel exists between the from and to addresses, @@ -418,10 +421,10 @@ func (ca *channelAccessor) processTask(merged *mergedFundsReq, amt, avail types. } // Try to fill requests using available funds, without going to the chain - amt = ca.completeAvailable(ctx, merged, channelInfo, amt, avail) + res, amt := ca.completeAvailable(ctx, merged, channelInfo, amt, avail) - if amt.LessThanEqual(types.NewInt(0)) { - return nil + if res != nil || amt.LessThanEqual(types.NewInt(0)) { + return res } // We need to add more funds, so send an add funds message to @@ -520,7 +523,7 @@ func (ca *channelAccessor) waitPaychCreateMsg(ctx context.Context, channelID str } // completeAvailable fills reserving fund requests using already available funds, without interacting with the chain -func (ca *channelAccessor) completeAvailable(ctx context.Context, merged *mergedFundsReq, channelInfo *ChannelInfo, amt, av types.BigInt) types.BigInt { +func (ca *channelAccessor) completeAvailable(ctx context.Context, merged *mergedFundsReq, channelInfo *ChannelInfo, amt, av types.BigInt) (*paychFundsRes, types.BigInt) { toReserve := types.BigSub(amt, av) avail := types.NewInt(0) @@ -533,14 +536,14 @@ func (ca *channelAccessor) completeAvailable(ctx context.Context, merged *merged ci.AvailableAmount = big.Sub(ci.AvailableAmount, avail) }) - used := merged.completeAmount(avail, channelInfo) + res, used := merged.completeAmount(avail, channelInfo) // return any unused reserved funds (e.g. from cancelled requests) ca.mutateChannelInfo(ctx, channelInfo.ChannelID, func(ci *ChannelInfo) { ci.AvailableAmount = types.BigAdd(ci.AvailableAmount, types.BigSub(avail, used)) }) - return types.BigSub(amt, used) + return res, types.BigSub(amt, used) } // addFunds sends a message to add funds to the channel and returns the message cid From 8b19b84140ee432eb5ea0c93f8c5a8c1dd5dbf19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 6 Jan 2022 16:04:39 +0100 Subject: [PATCH 065/385] paych: option to force off-chain get --- api/api_full.go | 15 +- api/mocks/mock_full.go | 2 +- api/proxy_gen.go | 6 +- api/v0api/v1_wrapper.go | 6 +- cli/paych.go | 9 +- documentation/en/api-v1-unstable-methods.md | 13 +- itests/paych_api_test.go | 5 +- markets/retrievaladapter/client.go | 6 +- node/impl/paych/paych.go | 9 +- paychmgr/manager.go | 8 +- paychmgr/paychget_test.go | 369 ++++++++++++++++++-- paychmgr/paychvoucherfunds_test.go | 4 +- paychmgr/settle_test.go | 4 +- paychmgr/simple.go | 78 ++++- testplans/lotus-soup/deals_e2e.go | 10 +- testplans/lotus-soup/paych/stress.go | 5 +- 16 files changed, 468 insertions(+), 81 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index 47f05fb7976..853d4928390 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -690,10 +690,14 @@ type FullNode interface { // The Paych methods are for interacting with and managing payment channels // PaychGet gets or creates a payment channel between address pair - // - If reserve is false, the specified amount will be added to the channel through on-chain send for future use - // - If reserve is true, the specified amount will be reserved for use. If there aren't enough non-reserved funds + // - If opts.Reserve is false, the specified amount will be added to the channel through on-chain send for future use + // - If opts.Reserve is true, the specified amount will be reserved for use. If there aren't enough non-reserved funds // available, funds will be added through an on-chain message. - PaychGet(ctx context.Context, from, to address.Address, amt types.BigInt, reserve bool) (*ChannelInfo, error) //perm:sign + // - When opts.OffChain is true, this call will not cause any messages to be sent to the chain (no automatic + // channel creation/funds adding). If the operation can't be performed without sending a message an error will be + // returned. Note that even when this option is specified, this call can be blocked by previous operations on the + // channel waiting for on-chain operations. + PaychGet(ctx context.Context, from, to address.Address, amt types.BigInt, opts PaychGetOpts) (*ChannelInfo, error) //perm:sign PaychGetWaitReady(context.Context, cid.Cid) (address.Address, error) //perm:sign PaychAvailableFunds(ctx context.Context, ch address.Address) (*ChannelAvailableFunds, error) //perm:sign PaychAvailableFundsByFromTo(ctx context.Context, from, to address.Address) (*ChannelAvailableFunds, error) //perm:sign @@ -832,6 +836,11 @@ const ( PCHOutbound ) +type PaychGetOpts struct { + Reserve bool + OffChain bool +} + type PaychStatus struct { ControlAddr address.Address Direction PCHDir diff --git a/api/mocks/mock_full.go b/api/mocks/mock_full.go index c745f26fcd4..5d42ba3c918 100644 --- a/api/mocks/mock_full.go +++ b/api/mocks/mock_full.go @@ -1976,7 +1976,7 @@ func (mr *MockFullNodeMockRecorder) PaychCollect(arg0, arg1 interface{}) *gomock } // PaychGet mocks base method. -func (m *MockFullNode) PaychGet(arg0 context.Context, arg1, arg2 address.Address, arg3 big.Int, arg4 bool) (*api.ChannelInfo, error) { +func (m *MockFullNode) PaychGet(arg0 context.Context, arg1, arg2 address.Address, arg3 big.Int, arg4 api.PaychGetOpts) (*api.ChannelInfo, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "PaychGet", arg0, arg1, arg2, arg3, arg4) ret0, _ := ret[0].(*api.ChannelInfo) diff --git a/api/proxy_gen.go b/api/proxy_gen.go index 9a134cec91b..9615181f58c 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -306,7 +306,7 @@ type FullNodeStruct struct { PaychCollect func(p0 context.Context, p1 address.Address) (cid.Cid, error) `perm:"sign"` - PaychGet func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 bool) (*ChannelInfo, error) `perm:"sign"` + PaychGet func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 PaychGetOpts) (*ChannelInfo, error) `perm:"sign"` PaychGetWaitReady func(p0 context.Context, p1 cid.Cid) (address.Address, error) `perm:"sign"` @@ -2179,14 +2179,14 @@ func (s *FullNodeStub) PaychCollect(p0 context.Context, p1 address.Address) (cid return *new(cid.Cid), ErrNotSupported } -func (s *FullNodeStruct) PaychGet(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 bool) (*ChannelInfo, error) { +func (s *FullNodeStruct) PaychGet(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 PaychGetOpts) (*ChannelInfo, error) { if s.Internal.PaychGet == nil { return nil, ErrNotSupported } return s.Internal.PaychGet(p0, p1, p2, p3, p4) } -func (s *FullNodeStub) PaychGet(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 bool) (*ChannelInfo, error) { +func (s *FullNodeStub) PaychGet(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 PaychGetOpts) (*ChannelInfo, error) { return nil, ErrNotSupported } diff --git a/api/v0api/v1_wrapper.go b/api/v0api/v1_wrapper.go index 605b27b0c9f..1c22eb920ad 100644 --- a/api/v0api/v1_wrapper.go +++ b/api/v0api/v1_wrapper.go @@ -338,8 +338,10 @@ func (w *WrapperV1Full) clientRetrieve(ctx context.Context, order RetrievalOrder } func (w *WrapperV1Full) PaychGet(ctx context.Context, from, to address.Address, amt types.BigInt) (*api.ChannelInfo, error) { - // v0 always reserves - return w.FullNode.PaychGet(ctx, from, to, amt, true) + return w.FullNode.PaychGet(ctx, from, to, amt, api.PaychGetOpts{ + Reserve: true, // v0 always reserves + OffChain: false, + }) } var _ FullNode = &WrapperV1Full{} diff --git a/cli/paych.go b/cli/paych.go index 29e8c640719..78e661d155f 100644 --- a/cli/paych.go +++ b/cli/paych.go @@ -8,7 +8,7 @@ import ( "sort" "strings" - "github.com/filecoin-project/lotus/api" + lapi "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/paychmgr" @@ -79,7 +79,10 @@ var paychAddFundsCmd = &cli.Command{ // Send a message to chain to create channel / add funds to existing // channel - info, err := api.PaychGet(ctx, from, to, types.BigInt(amt), cctx.Bool("reserve")) + info, err := api.PaychGet(ctx, from, to, types.BigInt(amt), lapi.PaychGetOpts{ + Reserve: cctx.Bool("reserve"), + OffChain: false, + }) if err != nil { return err } @@ -166,7 +169,7 @@ var paychStatusCmd = &cli.Command{ }, } -func paychStatus(writer io.Writer, avail *api.ChannelAvailableFunds) { +func paychStatus(writer io.Writer, avail *lapi.ChannelAvailableFunds) { if avail.Channel == nil { if avail.PendingWaitSentinel != nil { fmt.Fprint(writer, "Creating channel\n") diff --git a/documentation/en/api-v1-unstable-methods.md b/documentation/en/api-v1-unstable-methods.md index b84877b97a5..2926faab7c8 100644 --- a/documentation/en/api-v1-unstable-methods.md +++ b/documentation/en/api-v1-unstable-methods.md @@ -4514,9 +4514,13 @@ Response: ### PaychGet PaychGet gets or creates a payment channel between address pair - - If reserve is false, the specified amount will be added to the channel through on-chain send for future use - - If reserve is true, the specified amount will be reserved for use. If there aren't enough non-reserved funds + - If opts.Reserve is false, the specified amount will be added to the channel through on-chain send for future use + - If opts.Reserve is true, the specified amount will be reserved for use. If there aren't enough non-reserved funds available, funds will be added through an on-chain message. + - When opts.OffChain is true, this call will not cause any messages to be sent to the chain (no automatic + channel creation/funds adding). If the operation can't be performed without sending a message an error will be + returned. Note that even when this option is specified, this call can be blocked by previous operations on the + channel waiting for on-chain operations. Perms: sign @@ -4527,7 +4531,10 @@ Inputs: "f01234", "f01234", "0", - true + { + "Reserve": true, + "OffChain": true + } ] ``` diff --git a/itests/paych_api_test.go b/itests/paych_api_test.go index fb2233d9043..c2d14aeb8cb 100644 --- a/itests/paych_api_test.go +++ b/itests/paych_api_test.go @@ -58,7 +58,10 @@ func TestPaymentChannelsAPI(t *testing.T) { require.NoError(t, err) channelAmt := int64(7000) - channelInfo, err := paymentCreator.PaychGet(ctx, createrAddr, receiverAddr, abi.NewTokenAmount(channelAmt), true) + channelInfo, err := paymentCreator.PaychGet(ctx, createrAddr, receiverAddr, abi.NewTokenAmount(channelAmt), api.PaychGetOpts{ + Reserve: true, + OffChain: false, + }) require.NoError(t, err) channel, err := paymentCreator.PaychGetWaitReady(ctx, channelInfo.WaitSentinel) diff --git a/markets/retrievaladapter/client.go b/markets/retrievaladapter/client.go index 88fcb7ba1e3..601f9f2550f 100644 --- a/markets/retrievaladapter/client.go +++ b/markets/retrievaladapter/client.go @@ -12,6 +12,7 @@ import ( mh "github.com/multiformats/go-multihash" "golang.org/x/xerrors" + "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/actors/builtin/paych" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/node/impl/full" @@ -57,7 +58,10 @@ func NewRetrievalClientNode(payAPI payapi.PaychAPI, chainAPI full.ChainAPI, stat func (rcn *retrievalClientNode) GetOrCreatePaymentChannel(ctx context.Context, clientAddress address.Address, minerAddress address.Address, clientFundsAvailable abi.TokenAmount, tok shared.TipSetToken) (address.Address, cid.Cid, error) { // TODO: respect the provided TipSetToken (a serialized TipSetKey) when // querying the chain - ci, err := rcn.payAPI.PaychGet(ctx, clientAddress, minerAddress, clientFundsAvailable, true) + ci, err := rcn.payAPI.PaychGet(ctx, clientAddress, minerAddress, clientFundsAvailable, api.PaychGetOpts{ + Reserve: true, + OffChain: false, + }) if err != nil { return address.Undef, cid.Undef, err } diff --git a/node/impl/paych/paych.go b/node/impl/paych/paych.go index d308f6248ac..2d8777dbb9a 100644 --- a/node/impl/paych/paych.go +++ b/node/impl/paych/paych.go @@ -22,8 +22,8 @@ type PaychAPI struct { PaychMgr *paychmgr.Manager } -func (a *PaychAPI) PaychGet(ctx context.Context, from, to address.Address, amt types.BigInt, reserve bool) (*api.ChannelInfo, error) { - ch, mcid, err := a.PaychMgr.GetPaych(ctx, from, to, amt, reserve) +func (a *PaychAPI) PaychGet(ctx context.Context, from, to address.Address, amt types.BigInt, opts api.PaychGetOpts) (*api.ChannelInfo, error) { + ch, mcid, err := a.PaychMgr.GetPaych(ctx, from, to, amt, opts) if err != nil { return nil, err } @@ -55,7 +55,10 @@ func (a *PaychAPI) PaychNewPayment(ctx context.Context, from, to address.Address // TODO: Fix free fund tracking in PaychGet // TODO: validate voucher spec before locking funds - ch, err := a.PaychGet(ctx, from, to, amount, true) + ch, err := a.PaychGet(ctx, from, to, amount, api.PaychGetOpts{ + Reserve: true, + OffChain: false, + }) if err != nil { return nil, err } diff --git a/paychmgr/manager.go b/paychmgr/manager.go index 612cb6678a8..7045a7dcd23 100644 --- a/paychmgr/manager.go +++ b/paychmgr/manager.go @@ -101,13 +101,17 @@ func (pm *Manager) Stop() error { return nil } -func (pm *Manager) GetPaych(ctx context.Context, from, to address.Address, amt types.BigInt, reserve bool) (address.Address, cid.Cid, error) { +func (pm *Manager) GetPaych(ctx context.Context, from, to address.Address, amt types.BigInt, opts api.PaychGetOpts) (address.Address, cid.Cid, error) { + if !opts.Reserve && opts.OffChain { + return address.Undef, cid.Undef, xerrors.Errorf("can't fund payment channels without on-chain operations") + } + chanAccessor, err := pm.accessorByFromTo(from, to) if err != nil { return address.Undef, cid.Undef, err } - return chanAccessor.getPaych(ctx, amt, reserve) + return chanAccessor.getPaych(ctx, amt, opts) } func (pm *Manager) AvailableFunds(ctx context.Context, ch address.Address) (*api.ChannelAvailableFunds, error) { diff --git a/paychmgr/paychget_test.go b/paychmgr/paychget_test.go index 31207917721..f16b146f627 100644 --- a/paychmgr/paychget_test.go +++ b/paychmgr/paychget_test.go @@ -19,12 +19,30 @@ import ( init2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/init" tutils "github.com/filecoin-project/specs-actors/v2/support/testing" + "github.com/filecoin-project/lotus/api" lotusinit "github.com/filecoin-project/lotus/chain/actors/builtin/init" "github.com/filecoin-project/lotus/chain/actors/builtin/paych" paychmock "github.com/filecoin-project/lotus/chain/actors/builtin/paych/mock" "github.com/filecoin-project/lotus/chain/types" ) +var onChainReserve = api.PaychGetOpts{ + Reserve: true, + OffChain: false, +} +var onChainNoReserve = api.PaychGetOpts{ + Reserve: false, + OffChain: false, +} +var offChainReserve = api.PaychGetOpts{ + Reserve: true, + OffChain: true, +} +var offChainNoReserve = api.PaychGetOpts{ + Reserve: false, + OffChain: true, +} + func testChannelResponse(t *testing.T, ch address.Address) types.MessageReceipt { createChannelRet := init2.ExecReturn{ IDAddress: ch, @@ -55,7 +73,7 @@ func TestPaychGetCreateChannelMsg(t *testing.T) { require.NoError(t, err) amt := big.NewInt(10) - ch, mcid, err := mgr.GetPaych(ctx, from, to, amt, true) + ch, mcid, err := mgr.GetPaych(ctx, from, to, amt, onChainReserve) require.NoError(t, err) require.Equal(t, address.Undef, ch) @@ -65,6 +83,42 @@ func TestPaychGetCreateChannelMsg(t *testing.T) { require.Equal(t, amt, pushedMsg.Message.Value) } +func TestPaychGetOffchainNoReserveFails(t *testing.T) { + ctx := context.Background() + store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore())) + + from := tutils.NewIDAddr(t, 101) + to := tutils.NewIDAddr(t, 102) + + mock := newMockManagerAPI() + defer mock.close() + + mgr, err := newManager(store, mock) + require.NoError(t, err) + + amt := big.NewInt(10) + _, _, err = mgr.GetPaych(ctx, from, to, amt, offChainNoReserve) + require.Error(t, err) +} + +func TestPaychGetCreateOffchainReserveFails(t *testing.T) { + ctx := context.Background() + store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore())) + + from := tutils.NewIDAddr(t, 101) + to := tutils.NewIDAddr(t, 102) + + mock := newMockManagerAPI() + defer mock.close() + + mgr, err := newManager(store, mock) + require.NoError(t, err) + + amt := big.NewInt(10) + _, _, err = mgr.GetPaych(ctx, from, to, amt, offChainReserve) + require.Error(t, err) +} + // TestPaychGetCreateChannelThenAddFunds tests creating a channel and then // adding funds to it func TestPaychGetCreateChannelThenAddFunds(t *testing.T) { @@ -83,7 +137,7 @@ func TestPaychGetCreateChannelThenAddFunds(t *testing.T) { // Send create message for a channel with value 10 amt := big.NewInt(10) - _, createMsgCid, err := mgr.GetPaych(ctx, from, to, amt, true) + _, createMsgCid, err := mgr.GetPaych(ctx, from, to, amt, onChainReserve) require.NoError(t, err) // Should have no channels yet (message sent but channel not created) @@ -100,7 +154,7 @@ func TestPaychGetCreateChannelThenAddFunds(t *testing.T) { // 2. Request add funds - should block until create channel has completed amt2 := big.NewInt(5) - ch2, addFundsMsgCid, err := mgr.GetPaych(ctx, from, to, amt2, true) + ch2, addFundsMsgCid, err := mgr.GetPaych(ctx, from, to, amt2, onChainReserve) // 4. This GetPaych should return after create channel from first // GetPaych completes @@ -170,7 +224,7 @@ func TestPaychGetCreatePrefundedChannelThenAddFunds(t *testing.T) { // Send create message for a channel with value 10 amt := big.NewInt(10) - _, createMsgCid, err := mgr.GetPaych(ctx, from, to, amt, false) + _, createMsgCid, err := mgr.GetPaych(ctx, from, to, amt, onChainNoReserve) require.NoError(t, err) // Should have no channels yet (message sent but channel not created) @@ -187,7 +241,7 @@ func TestPaychGetCreatePrefundedChannelThenAddFunds(t *testing.T) { // 2. Request add funds - shouldn't block amt2 := big.NewInt(3) - ch2, addFundsMsgCid, err := mgr.GetPaych(ctx, from, to, amt2, true) + ch2, addFundsMsgCid, err := mgr.GetPaych(ctx, from, to, amt2, offChainReserve) // 4. This GetPaych should return after create channel from first // GetPaych completes @@ -240,7 +294,7 @@ func TestPaychGetCreateChannelWithErrorThenCreateAgain(t *testing.T) { // Send create message for a channel amt := big.NewInt(10) - _, mcid1, err := mgr.GetPaych(ctx, from, to, amt, true) + _, mcid1, err := mgr.GetPaych(ctx, from, to, amt, onChainReserve) require.NoError(t, err) // 1. Set up create channel response (sent in response to WaitForMsg()) @@ -258,7 +312,7 @@ func TestPaychGetCreateChannelWithErrorThenCreateAgain(t *testing.T) { // Because first channel create fails, this request // should be for channel create again. amt2 := big.NewInt(5) - ch2, mcid2, err := mgr.GetPaych(ctx, from, to, amt2, true) + ch2, mcid2, err := mgr.GetPaych(ctx, from, to, amt2, onChainReserve) require.NoError(t, err) require.Equal(t, address.Undef, ch2) @@ -305,7 +359,7 @@ func TestPaychGetRecoverAfterError(t *testing.T) { // Send create message for a channel amt := big.NewInt(10) - _, mcid, err := mgr.GetPaych(ctx, from, to, amt, true) + _, mcid, err := mgr.GetPaych(ctx, from, to, amt, onChainReserve) require.NoError(t, err) // Send error create channel response @@ -316,7 +370,7 @@ func TestPaychGetRecoverAfterError(t *testing.T) { // Send create message for a channel again amt2 := big.NewInt(7) - _, mcid2, err := mgr.GetPaych(ctx, from, to, amt2, true) + _, mcid2, err := mgr.GetPaych(ctx, from, to, amt2, onChainReserve) require.NoError(t, err) // Send success create channel response @@ -357,7 +411,7 @@ func TestPaychGetRecoverAfterAddFundsError(t *testing.T) { // Send create message for a channel amt := big.NewInt(10) - _, mcid1, err := mgr.GetPaych(ctx, from, to, amt, true) + _, mcid1, err := mgr.GetPaych(ctx, from, to, amt, onChainReserve) require.NoError(t, err) // Send success create channel response @@ -366,7 +420,7 @@ func TestPaychGetRecoverAfterAddFundsError(t *testing.T) { // Send add funds message for channel amt2 := big.NewInt(5) - _, mcid2, err := mgr.GetPaych(ctx, from, to, amt2, true) + _, mcid2, err := mgr.GetPaych(ctx, from, to, amt2, onChainReserve) require.NoError(t, err) // Send error add funds response @@ -393,7 +447,7 @@ func TestPaychGetRecoverAfterAddFundsError(t *testing.T) { // Send add funds message for channel again amt3 := big.NewInt(2) - _, mcid3, err := mgr.GetPaych(ctx, from, to, amt3, true) + _, mcid3, err := mgr.GetPaych(ctx, from, to, amt3, onChainReserve) require.NoError(t, err) // Send success add funds response @@ -438,7 +492,7 @@ func TestPaychGetRestartAfterCreateChannelMsg(t *testing.T) { // Send create message for a channel with value 10 amt := big.NewInt(10) - _, createMsgCid, err := mgr.GetPaych(ctx, from, to, amt, true) + _, createMsgCid, err := mgr.GetPaych(ctx, from, to, amt, onChainReserve) require.NoError(t, err) // Simulate shutting down system @@ -465,7 +519,7 @@ func TestPaychGetRestartAfterCreateChannelMsg(t *testing.T) { // 2. Request add funds - should block until create channel has completed amt2 := big.NewInt(5) - ch2, addFundsMsgCid, err := mgr2.GetPaych(ctx, from, to, amt2, true) + ch2, addFundsMsgCid, err := mgr2.GetPaych(ctx, from, to, amt2, onChainReserve) // 4. This GetPaych should return after create channel from first // GetPaych completes @@ -517,7 +571,7 @@ func TestPaychGetRestartAfterAddFundsMsg(t *testing.T) { // Send create message for a channel amt := big.NewInt(10) - _, mcid1, err := mgr.GetPaych(ctx, from, to, amt, true) + _, mcid1, err := mgr.GetPaych(ctx, from, to, amt, onChainReserve) require.NoError(t, err) // Send success create channel response @@ -526,7 +580,7 @@ func TestPaychGetRestartAfterAddFundsMsg(t *testing.T) { // Send add funds message for channel amt2 := big.NewInt(5) - _, mcid2, err := mgr.GetPaych(ctx, from, to, amt2, true) + _, mcid2, err := mgr.GetPaych(ctx, from, to, amt2, onChainReserve) require.NoError(t, err) // Simulate shutting down system @@ -580,7 +634,7 @@ func TestPaychGetWait(t *testing.T) { // 1. Get amt := big.NewInt(10) - _, createMsgCid, err := mgr.GetPaych(ctx, from, to, amt, true) + _, createMsgCid, err := mgr.GetPaych(ctx, from, to, amt, onChainReserve) require.NoError(t, err) expch := tutils.NewIDAddr(t, 100) @@ -603,7 +657,7 @@ func TestPaychGetWait(t *testing.T) { // Request add funds amt2 := big.NewInt(15) - _, addFundsMsgCid, err := mgr.GetPaych(ctx, from, to, amt2, true) + _, addFundsMsgCid, err := mgr.GetPaych(ctx, from, to, amt2, onChainReserve) require.NoError(t, err) go func() { @@ -637,7 +691,7 @@ func TestPaychGetWaitErr(t *testing.T) { // 1. Create channel amt := big.NewInt(10) - _, mcid, err := mgr.GetPaych(ctx, from, to, amt, true) + _, mcid, err := mgr.GetPaych(ctx, from, to, amt, onChainReserve) require.NoError(t, err) done := make(chan address.Address) @@ -683,7 +737,7 @@ func TestPaychGetWaitCtx(t *testing.T) { require.NoError(t, err) amt := big.NewInt(10) - _, mcid, err := mgr.GetPaych(ctx, from, to, amt, true) + _, mcid, err := mgr.GetPaych(ctx, from, to, amt, onChainReserve) require.NoError(t, err) // When the context is cancelled, should unblock wait @@ -714,7 +768,7 @@ func TestPaychGetMergeAddFunds(t *testing.T) { // Send create message for a channel with value 10 createAmt := big.NewInt(10) - _, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, true) + _, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, onChainReserve) require.NoError(t, err) // Queue up two add funds requests behind create channel @@ -732,7 +786,7 @@ func TestPaychGetMergeAddFunds(t *testing.T) { // Request add funds - should block until create channel has completed var err error - addFundsCh1, addFundsMcid1, err = mgr.GetPaych(ctx, from, to, addFundsAmt1, true) + addFundsCh1, addFundsMcid1, err = mgr.GetPaych(ctx, from, to, addFundsAmt1, onChainReserve) require.NoError(t, err) }() @@ -741,7 +795,7 @@ func TestPaychGetMergeAddFunds(t *testing.T) { // Request add funds again - should merge with waiting add funds request var err error - addFundsCh2, addFundsMcid2, err = mgr.GetPaych(ctx, from, to, addFundsAmt2, true) + addFundsCh2, addFundsMcid2, err = mgr.GetPaych(ctx, from, to, addFundsAmt2, onChainReserve) require.NoError(t, err) }() // Wait for add funds requests to be queued up @@ -810,7 +864,7 @@ func TestPaychGetMergePrefundAndReserve(t *testing.T) { // Send create message for a channel with value 10 createAmt := big.NewInt(10) - _, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, true) + _, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, onChainReserve) require.NoError(t, err) // Queue up two add funds requests behind create channel @@ -828,7 +882,7 @@ func TestPaychGetMergePrefundAndReserve(t *testing.T) { // Request add funds - should block until create channel has completed var err error - addFundsCh1, addFundsMcid1, err = mgr.GetPaych(ctx, from, to, addFundsAmt1, false) + addFundsCh1, addFundsMcid1, err = mgr.GetPaych(ctx, from, to, addFundsAmt1, onChainNoReserve) require.NoError(t, err) }() @@ -837,7 +891,7 @@ func TestPaychGetMergePrefundAndReserve(t *testing.T) { // Request add funds again - should merge with waiting add funds request var err error - addFundsCh2, addFundsMcid2, err = mgr.GetPaych(ctx, from, to, addFundsAmt2, true) + addFundsCh2, addFundsMcid2, err = mgr.GetPaych(ctx, from, to, addFundsAmt2, onChainReserve) require.NoError(t, err) }() // Wait for add funds requests to be queued up @@ -906,7 +960,7 @@ func TestPaychGetMergePrefundAndReservePrefunded(t *testing.T) { // Send create message for a channel with value 10 createAmt := big.NewInt(10) - _, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, false) + _, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, onChainNoReserve) require.NoError(t, err) // Queue up two add funds requests behind create channel @@ -924,7 +978,7 @@ func TestPaychGetMergePrefundAndReservePrefunded(t *testing.T) { // Request add funds - should block until create channel has completed var err error - addFundsCh1, addFundsMcid1, err = mgr.GetPaych(ctx, from, to, addFundsAmt1, false) + addFundsCh1, addFundsMcid1, err = mgr.GetPaych(ctx, from, to, addFundsAmt1, onChainNoReserve) require.NoError(t, err) }() @@ -933,7 +987,7 @@ func TestPaychGetMergePrefundAndReservePrefunded(t *testing.T) { // Request add funds again - should merge with waiting add funds request var err error - addFundsCh2, addFundsMcid2, err = mgr.GetPaych(ctx, from, to, addFundsAmt2, true) + addFundsCh2, addFundsMcid2, err = mgr.GetPaych(ctx, from, to, addFundsAmt2, onChainReserve) require.NoError(t, err) }() // Wait for add funds requests to be queued up @@ -987,6 +1041,247 @@ func TestPaychGetMergePrefundAndReservePrefunded(t *testing.T) { require.Equal(t, addFundsAmt1, addFundsMsg.Message.Value) } +func TestPaychGetMergePrefundAndReservePrefundedOneOffchain(t *testing.T) { + ctx := context.Background() + store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore())) + + ch := tutils.NewIDAddr(t, 100) + from := tutils.NewIDAddr(t, 101) + to := tutils.NewIDAddr(t, 102) + + mock := newMockManagerAPI() + defer mock.close() + + mgr, err := newManager(store, mock) + require.NoError(t, err) + + // Send create message for a channel with value 10 + createAmt := big.NewInt(10) + _, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, onChainNoReserve) + require.NoError(t, err) + + // Queue up two add funds requests behind create channel + var addFundsSent sync.WaitGroup + addFundsSent.Add(2) + + addFundsAmt1 := big.NewInt(5) // 1 reserves + addFundsAmt2 := big.NewInt(3) // 2 reserves + var addFundsCh1 address.Address + var addFundsCh2 address.Address + var addFundsMcid1 cid.Cid + var addFundsMcid2 cid.Cid + go func() { + defer addFundsSent.Done() + + // Request add funds - should block until create channel has completed + var err error + addFundsCh1, addFundsMcid1, err = mgr.GetPaych(ctx, from, to, addFundsAmt1, offChainReserve) + require.NoError(t, err) + }() + + go func() { + defer addFundsSent.Done() + + // Request add funds again - should merge with waiting add funds request + var err error + addFundsCh2, addFundsMcid2, err = mgr.GetPaych(ctx, from, to, addFundsAmt2, onChainReserve) + require.NoError(t, err) + }() + // Wait for add funds requests to be queued up + waitForQueueSize(t, mgr, from, to, 2) + + // Send create channel response + response := testChannelResponse(t, ch) + mock.receiveMsgResponse(createMsgCid, response) + + // Wait for create channel response + chres, err := mgr.GetPaychWaitReady(ctx, createMsgCid) + require.NoError(t, err) + require.Equal(t, ch, chres) + + // Wait for add funds requests to be sent + addFundsSent.Wait() + + // Expect add funds requests to have same channel as create channel and + // same message cid as each other (because they should have been merged) + require.Equal(t, ch, addFundsCh1) + require.Equal(t, ch, addFundsCh2) + require.Equal(t, cid.Undef, addFundsMcid1) + require.Equal(t, cid.Undef, addFundsMcid2) + + // Make sure that one create channel message was sent + require.Equal(t, 1, mock.pushedMessageCount()) + + // Check create message amount is correct + createMsg := mock.pushedMessages(createMsgCid) + require.Equal(t, from, createMsg.Message.From) + require.Equal(t, lotusinit.Address, createMsg.Message.To) + require.Equal(t, createAmt, createMsg.Message.Value) +} + +func TestPaychGetMergePrefundAndReservePrefundedBothOffchainOneFail(t *testing.T) { + ctx := context.Background() + store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore())) + + ch := tutils.NewIDAddr(t, 100) + from := tutils.NewIDAddr(t, 101) + to := tutils.NewIDAddr(t, 102) + + mock := newMockManagerAPI() + defer mock.close() + + mgr, err := newManager(store, mock) + require.NoError(t, err) + + // Send create message for a channel with value 10 + createAmt := big.NewInt(10) + _, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, onChainNoReserve) + require.NoError(t, err) + + // Queue up two add funds requests behind create channel + var addFundsSent sync.WaitGroup + addFundsSent.Add(2) + + addFundsAmt1 := big.NewInt(5) // 1 reserves + addFundsAmt2 := big.NewInt(6) // 2 reserves too much + var addFundsCh1 address.Address + var addFundsCh2 address.Address + var addFundsMcid1 cid.Cid + var addFundsMcid2 cid.Cid + go func() { + defer addFundsSent.Done() + + // Request add funds - should block until create channel has completed + var err error + addFundsCh1, addFundsMcid1, err = mgr.GetPaych(ctx, from, to, addFundsAmt1, offChainReserve) + require.NoError(t, err) + }() + + go func() { + defer addFundsSent.Done() + + // Request add funds again - should merge with waiting add funds request + var err error + addFundsCh2, addFundsMcid2, err = mgr.GetPaych(ctx, from, to, addFundsAmt2, offChainReserve) + require.Error(t, err) + }() + // Wait for add funds requests to be queued up + waitForQueueSize(t, mgr, from, to, 2) + + // Send create channel response + response := testChannelResponse(t, ch) + mock.receiveMsgResponse(createMsgCid, response) + + // Wait for create channel response + chres, err := mgr.GetPaychWaitReady(ctx, createMsgCid) + require.NoError(t, err) + require.Equal(t, ch, chres) + + // Wait for add funds requests to be sent + addFundsSent.Wait() + + // Expect add funds requests to have same channel as create channel and + // same message cid as each other (because they should have been merged) + require.Equal(t, ch, addFundsCh1) + require.Equal(t, ch, addFundsCh2) + require.Equal(t, cid.Undef, addFundsMcid1) + require.Equal(t, cid.Undef, addFundsMcid2) + + // Make sure that one create channel message was sent + require.Equal(t, 1, mock.pushedMessageCount()) + + // Check create message amount is correct + createMsg := mock.pushedMessages(createMsgCid) + require.Equal(t, from, createMsg.Message.From) + require.Equal(t, lotusinit.Address, createMsg.Message.To) + require.Equal(t, createAmt, createMsg.Message.Value) +} + +func TestPaychGetMergePrefundAndReserveOneOffchainOneFail(t *testing.T) { + ctx := context.Background() + store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore())) + + ch := tutils.NewIDAddr(t, 100) + from := tutils.NewIDAddr(t, 101) + to := tutils.NewIDAddr(t, 102) + + mock := newMockManagerAPI() + defer mock.close() + + mgr, err := newManager(store, mock) + require.NoError(t, err) + + // Send create message for a channel with value 10 + createAmt := big.NewInt(10) + _, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, onChainReserve) + require.NoError(t, err) + + // Queue up two add funds requests behind create channel + var addFundsSent sync.WaitGroup + addFundsSent.Add(2) + + addFundsAmt1 := big.NewInt(5) // 1 reserves + addFundsAmt2 := big.NewInt(6) // 2 reserves + var addFundsCh1 address.Address + var addFundsCh2 address.Address + var addFundsMcid1 cid.Cid + var addFundsMcid2 cid.Cid + go func() { + defer addFundsSent.Done() + + // Request add funds - should block until create channel has completed + var err error + addFundsCh1, addFundsMcid1, err = mgr.GetPaych(ctx, from, to, addFundsAmt1, onChainReserve) + require.NoError(t, err) + }() + + go func() { + defer addFundsSent.Done() + + // Request add funds again - should merge with waiting add funds request + var err error + addFundsCh2, addFundsMcid2, err = mgr.GetPaych(ctx, from, to, addFundsAmt2, offChainReserve) + require.Error(t, err) + }() + // Wait for add funds requests to be queued up + waitForQueueSize(t, mgr, from, to, 2) + + // Send create channel response + response := testChannelResponse(t, ch) + mock.receiveMsgResponse(createMsgCid, response) + + // Wait for create channel response + chres, err := mgr.GetPaychWaitReady(ctx, createMsgCid) + require.NoError(t, err) + require.Equal(t, ch, chres) + + // Wait for add funds requests to be sent + addFundsSent.Wait() + + // Expect add funds requests to have same channel as create channel and + // same message cid as each other (because they should have been merged) + require.Equal(t, ch, addFundsCh1) + require.Equal(t, ch, addFundsCh2) + require.NotEqual(t, cid.Undef, addFundsMcid1) + require.Equal(t, cid.Undef, addFundsMcid2) + + // Make sure that one create channel message was sent + require.Equal(t, 2, mock.pushedMessageCount()) + + // Check create message amount is correct + createMsg := mock.pushedMessages(createMsgCid) + require.Equal(t, from, createMsg.Message.From) + require.Equal(t, lotusinit.Address, createMsg.Message.To) + require.Equal(t, createAmt, createMsg.Message.Value) + + // Check merged add funds amount is the sum of the individual + // amounts + addFundsMsg := mock.pushedMessages(addFundsMcid1) + require.Equal(t, from, addFundsMsg.Message.From) + require.Equal(t, ch, addFundsMsg.Message.To) + require.Equal(t, addFundsAmt1, addFundsMsg.Message.Value) +} + // TestPaychGetMergeAddFundsCtxCancelOne tests that when a queued add funds // request is cancelled, its amount is removed from the total merged add funds func TestPaychGetMergeAddFundsCtxCancelOne(t *testing.T) { @@ -1005,7 +1300,7 @@ func TestPaychGetMergeAddFundsCtxCancelOne(t *testing.T) { // Send create message for a channel with value 10 createAmt := big.NewInt(10) - _, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, true) + _, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, onChainReserve) require.NoError(t, err) // Queue up two add funds requests behind create channel @@ -1022,7 +1317,7 @@ func TestPaychGetMergeAddFundsCtxCancelOne(t *testing.T) { defer addFundsSent.Done() // Request add funds - should block until create channel has completed - _, _, addFundsErr1 = mgr.GetPaych(addFundsCtx1, from, to, addFundsAmt1, true) + _, _, addFundsErr1 = mgr.GetPaych(addFundsCtx1, from, to, addFundsAmt1, onChainReserve) }() go func() { @@ -1030,7 +1325,7 @@ func TestPaychGetMergeAddFundsCtxCancelOne(t *testing.T) { // Request add funds again - should merge with waiting add funds request var err error - addFundsCh2, addFundsMcid2, err = mgr.GetPaych(ctx, from, to, addFundsAmt2, true) + addFundsCh2, addFundsMcid2, err = mgr.GetPaych(ctx, from, to, addFundsAmt2, onChainReserve) require.NoError(t, err) }() // Wait for add funds requests to be queued up @@ -1102,7 +1397,7 @@ func TestPaychGetMergeAddFundsCtxCancelAll(t *testing.T) { // Send create message for a channel with value 10 createAmt := big.NewInt(10) - _, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, true) + _, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, onChainReserve) require.NoError(t, err) // Queue up two add funds requests behind create channel @@ -1117,14 +1412,14 @@ func TestPaychGetMergeAddFundsCtxCancelAll(t *testing.T) { defer addFundsSent.Done() // Request add funds - should block until create channel has completed - _, _, addFundsErr1 = mgr.GetPaych(addFundsCtx1, from, to, big.NewInt(5), true) + _, _, addFundsErr1 = mgr.GetPaych(addFundsCtx1, from, to, big.NewInt(5), onChainReserve) }() go func() { defer addFundsSent.Done() // Request add funds again - should merge with waiting add funds request - _, _, addFundsErr2 = mgr.GetPaych(addFundsCtx2, from, to, big.NewInt(3), true) + _, _, addFundsErr2 = mgr.GetPaych(addFundsCtx2, from, to, big.NewInt(3), onChainReserve) }() // Wait for add funds requests to be queued up waitForQueueSize(t, mgr, from, to, 2) @@ -1189,7 +1484,7 @@ func TestPaychAvailableFunds(t *testing.T) { // Send create message for a channel with value 10 createAmt := big.NewInt(10) - _, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, true) + _, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, onChainReserve) require.NoError(t, err) // Available funds should reflect create channel message sent @@ -1214,7 +1509,7 @@ func TestPaychAvailableFunds(t *testing.T) { // Request add funds - should block until create channel has completed var err error - _, addFundsMcid, err = mgr.GetPaych(ctx, from, to, addFundsAmt, true) + _, addFundsMcid, err = mgr.GetPaych(ctx, from, to, addFundsAmt, onChainReserve) require.NoError(t, err) }() diff --git a/paychmgr/paychvoucherfunds_test.go b/paychmgr/paychvoucherfunds_test.go index d13a5815eb4..4a2f7e31a83 100644 --- a/paychmgr/paychvoucherfunds_test.go +++ b/paychmgr/paychvoucherfunds_test.go @@ -46,7 +46,7 @@ func TestPaychAddVoucherAfterAddFunds(t *testing.T) { // Send create message for a channel with value 10 createAmt := big.NewInt(10) - _, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, true) + _, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, onChainReserve) require.NoError(t, err) // Send create channel response @@ -82,7 +82,7 @@ func TestPaychAddVoucherAfterAddFunds(t *testing.T) { require.Equal(t, res.Shortfall, excessAmt) // Add funds so as to cover the voucher shortfall - _, addFundsMsgCid, err := mgr.GetPaych(ctx, from, to, excessAmt, true) + _, addFundsMsgCid, err := mgr.GetPaych(ctx, from, to, excessAmt, onChainReserve) require.NoError(t, err) // Trigger add funds confirmation diff --git a/paychmgr/settle_test.go b/paychmgr/settle_test.go index e674d63f4e0..bc88df2f0d6 100644 --- a/paychmgr/settle_test.go +++ b/paychmgr/settle_test.go @@ -29,7 +29,7 @@ func TestPaychSettle(t *testing.T) { require.NoError(t, err) amt := big.NewInt(10) - _, mcid, err := mgr.GetPaych(ctx, from, to, amt, true) + _, mcid, err := mgr.GetPaych(ctx, from, to, amt, onChainReserve) require.NoError(t, err) // Send channel create response @@ -49,7 +49,7 @@ func TestPaychSettle(t *testing.T) { // (should create a new channel because the previous channel // is settling) amt2 := big.NewInt(5) - _, mcid2, err := mgr.GetPaych(ctx, from, to, amt2, true) + _, mcid2, err := mgr.GetPaych(ctx, from, to, amt2, onChainReserve) require.NoError(t, err) require.NotEqual(t, cid.Undef, mcid2) diff --git a/paychmgr/simple.go b/paychmgr/simple.go index def24d1cf5c..ffb13b6c233 100644 --- a/paychmgr/simple.go +++ b/paychmgr/simple.go @@ -33,20 +33,20 @@ type fundsReq struct { ctx context.Context promise chan *paychFundsRes amt types.BigInt - reserve bool + opts api.PaychGetOpts lk sync.Mutex // merge parent, if this req is part of a merge merge *mergedFundsReq } -func newFundsReq(ctx context.Context, amt types.BigInt, reserve bool) *fundsReq { +func newFundsReq(ctx context.Context, amt types.BigInt, opts api.PaychGetOpts) *fundsReq { promise := make(chan *paychFundsRes, 1) return &fundsReq{ ctx: ctx, promise: promise, amt: amt, - reserve: reserve, + opts: opts, } } @@ -108,8 +108,12 @@ func newMergedFundsReq(reqs []*fundsReq) *mergedFundsReq { } sort.Slice(m.reqs, func(i, j int) bool { - if m.reqs[i].reserve != m.reqs[j].reserve { // non-reserve first - return m.reqs[i].reserve + if m.reqs[i].opts.OffChain != m.reqs[j].opts.OffChain { // off-chain first + return m.reqs[i].opts.OffChain + } + + if m.reqs[i].opts.Reserve != m.reqs[j].opts.Reserve { // non-reserve after off-chain + return m.reqs[i].opts.Reserve } // sort by amount asc (reducing latency for smaller requests) @@ -154,7 +158,7 @@ func (m *mergedFundsReq) sum() (types.BigInt, types.BigInt) { for _, r := range m.reqs { if r.isActive() { sum = types.BigAdd(sum, r.amt) - if !r.reserve { + if !r.opts.Reserve { avail = types.BigAdd(avail, r.amt) } } @@ -164,17 +168,30 @@ func (m *mergedFundsReq) sum() (types.BigInt, types.BigInt) { } // completeAmount completes first non-reserving requests up to the available amount -func (m *mergedFundsReq) completeAmount(avail types.BigInt, channelInfo *ChannelInfo) (*paychFundsRes, types.BigInt) { - used := types.NewInt(0) +func (m *mergedFundsReq) completeAmount(avail types.BigInt, channelInfo *ChannelInfo) (*paychFundsRes, types.BigInt, types.BigInt) { + used, failed := types.NewInt(0), types.NewInt(0) next := 0 + + // order: [offchain+reserve, !offchain+reserve, !offchain+!reserve] for i, r := range m.reqs { - if !r.reserve { + if !r.opts.Reserve { // non-reserving request are put after reserving requests, so we are done here break } if r.amt.GreaterThan(types.BigSub(avail, used)) { // requests are sorted by amount ascending, so if we hit this, there aren't any more requests we can fill + + if r.opts.OffChain { + // can't fill, so OffChain want an error + if r.isActive() { + failed = types.BigAdd(failed, r.amt) + r.onComplete(&paychFundsRes{channel: *channelInfo.Channel, err: xerrors.Errorf("not enough available funds in the payment channel")}) + } + next = i + 1 + continue + } + break } @@ -190,9 +207,34 @@ func (m *mergedFundsReq) completeAmount(avail types.BigInt, channelInfo *Channel m.reqs = m.reqs[next:] if len(m.reqs) == 0 { - return &paychFundsRes{channel: *channelInfo.Channel}, used + return &paychFundsRes{channel: *channelInfo.Channel}, used, failed } - return nil, used + return nil, used, failed +} + +func (m *mergedFundsReq) failOffChain(msg string) (*paychFundsRes, types.BigInt) { + next := 0 + freed := types.NewInt(0) + + for i, r := range m.reqs { + if !r.opts.OffChain { + break + } + + freed = types.BigAdd(freed, r.amt) + if !r.isActive() { + continue + } + r.onComplete(&paychFundsRes{err: xerrors.New(msg)}) + next = i + 1 + } + + m.reqs = m.reqs[next:] + if len(m.reqs) == 0 { + return &paychFundsRes{err: xerrors.New(msg)}, freed + } + + return nil, freed } // getPaych ensures that a channel exists between the from and to addresses, @@ -206,9 +248,9 @@ func (m *mergedFundsReq) completeAmount(avail types.BigInt, channelInfo *Channel // address and the CID of the new add funds message. // If an operation returns an error, subsequent waiting operations will still // be attempted. -func (ca *channelAccessor) getPaych(ctx context.Context, amt types.BigInt, reserve bool) (address.Address, cid.Cid, error) { +func (ca *channelAccessor) getPaych(ctx context.Context, amt types.BigInt, opts api.PaychGetOpts) (address.Address, cid.Cid, error) { // Add the request to add funds to a queue and wait for the result - freq := newFundsReq(ctx, amt, reserve) + freq := newFundsReq(ctx, amt, opts) ca.enqueue(ctx, freq) select { case res := <-freq.promise: @@ -398,6 +440,12 @@ func (ca *channelAccessor) processTask(merged *mergedFundsReq, amt, avail types. // If a channel has not yet been created, create one. if channelInfo == nil { + res, freed := merged.failOffChain("payment channel doesn't exist") + if res != nil { + return res + } + amt = types.BigSub(amt, freed) + mcid, err := ca.createPaych(ctx, amt, avail) if err != nil { return &paychFundsRes{err: err} @@ -536,14 +584,14 @@ func (ca *channelAccessor) completeAvailable(ctx context.Context, merged *merged ci.AvailableAmount = big.Sub(ci.AvailableAmount, avail) }) - res, used := merged.completeAmount(avail, channelInfo) + res, used, failed := merged.completeAmount(avail, channelInfo) // return any unused reserved funds (e.g. from cancelled requests) ca.mutateChannelInfo(ctx, channelInfo.ChannelID, func(ci *ChannelInfo) { ci.AvailableAmount = types.BigAdd(ci.AvailableAmount, types.BigSub(avail, used)) }) - return res, types.BigSub(amt, used) + return res, types.BigSub(amt, types.BigAdd(used, failed)) } // addFunds sends a message to add funds to the channel and returns the message cid diff --git a/testplans/lotus-soup/deals_e2e.go b/testplans/lotus-soup/deals_e2e.go index bc970350837..d9be97f6cae 100644 --- a/testplans/lotus-soup/deals_e2e.go +++ b/testplans/lotus-soup/deals_e2e.go @@ -207,7 +207,10 @@ func initPaymentChannel(t *testkit.TestEnvironment, ctx context.Context, cl *tes t.RecordMessage("my balance: %d", balance) t.RecordMessage("creating payment channel; from=%s, to=%s, funds=%d", cl.Wallet.Address, recv.WalletAddr, balance) - channel, err := cl.FullApi.PaychGet(ctx, cl.Wallet.Address, recv.WalletAddr, balance, true) + channel, err := cl.FullApi.PaychGet(ctx, cl.Wallet.Address, recv.WalletAddr, balance, api.PaychGetOpts{ + Reserve: true, + OffChain: false, + }) if err != nil { return fmt.Errorf("failed to create payment channel: %w", err) } @@ -230,7 +233,10 @@ func initPaymentChannel(t *testkit.TestEnvironment, ctx context.Context, cl *tes // we wait for 2 confirmations, so we have the assurance the channel is tracked. t.RecordMessage("reloading paych; now it should have an address") - channel, err = cl.FullApi.PaychGet(ctx, cl.Wallet.Address, recv.WalletAddr, big.Zero(), true) + channel, err = cl.FullApi.PaychGet(ctx, cl.Wallet.Address, recv.WalletAddr, big.Zero(), api.PaychGetOpts{ + Reserve: true, + OffChain: false, + }) if err != nil { return fmt.Errorf("failed to reload payment channel: %w", err) } diff --git a/testplans/lotus-soup/paych/stress.go b/testplans/lotus-soup/paych/stress.go index e0d324f03e9..2f90308d8ee 100644 --- a/testplans/lotus-soup/paych/stress.go +++ b/testplans/lotus-soup/paych/stress.go @@ -124,7 +124,10 @@ func runSender(ctx context.Context, t *testkit.TestEnvironment, clients []*testk time.Sleep(20 * time.Second) - channel, err := cl.FullApi.PaychGet(ctx, cl.Wallet.Address, recv.WalletAddr, channelAmt, true) + channel, err := cl.FullApi.PaychGet(ctx, cl.Wallet.Address, recv.WalletAddr, channelAmt, api.PaychGetOpts{ + Reserve: true, + OffChain: false, + }) if err != nil { return fmt.Errorf("failed to create payment channel: %w", err) } From 4235a97cf4f7f485c02b090cee9f5b70cdcdf77c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 6 Jan 2022 16:26:25 +0100 Subject: [PATCH 066/385] retrieval: OffChainRetrieval config --- markets/retrievaladapter/client.go | 13 ++++++--- node/builder_chain.go | 4 ++- node/config/doc_gen.go | 8 ++++++ node/config/types.go | 5 ++++ node/modules/client.go | 42 ++++++++++++++++-------------- 5 files changed, 48 insertions(+), 24 deletions(-) diff --git a/markets/retrievaladapter/client.go b/markets/retrievaladapter/client.go index 601f9f2550f..60f41ca296d 100644 --- a/markets/retrievaladapter/client.go +++ b/markets/retrievaladapter/client.go @@ -41,6 +41,8 @@ func extractPaychReusedCid(c cid.Cid) (address.Address, error) { } type retrievalClientNode struct { + forceOffChain bool + chainAPI full.ChainAPI payAPI payapi.PaychAPI stateAPI full.StateAPI @@ -48,8 +50,13 @@ type retrievalClientNode struct { // NewRetrievalClientNode returns a new node adapter for a retrieval client that talks to the // Lotus Node -func NewRetrievalClientNode(payAPI payapi.PaychAPI, chainAPI full.ChainAPI, stateAPI full.StateAPI) retrievalmarket.RetrievalClientNode { - return &retrievalClientNode{payAPI: payAPI, chainAPI: chainAPI, stateAPI: stateAPI} +func NewRetrievalClientNode(forceOffChain bool, payAPI payapi.PaychAPI, chainAPI full.ChainAPI, stateAPI full.StateAPI) retrievalmarket.RetrievalClientNode { + return &retrievalClientNode{ + forceOffChain: forceOffChain, + chainAPI: chainAPI, + payAPI: payAPI, + stateAPI: stateAPI, + } } // GetOrCreatePaymentChannel sets up a new payment channel if one does not exist @@ -60,7 +67,7 @@ func (rcn *retrievalClientNode) GetOrCreatePaymentChannel(ctx context.Context, c // querying the chain ci, err := rcn.payAPI.PaychGet(ctx, clientAddress, minerAddress, clientFundsAvailable, api.PaychGetOpts{ Reserve: true, - OffChain: false, + OffChain: rcn.forceOffChain, }) if err != nil { return address.Undef, cid.Undef, err diff --git a/node/builder_chain.go b/node/builder_chain.go index 11283ec3a09..0d10dcb9b22 100644 --- a/node/builder_chain.go +++ b/node/builder_chain.go @@ -121,7 +121,7 @@ var ChainNode = Options( // Markets (retrieval) Override(new(discovery.PeerResolver), modules.RetrievalResolver), Override(new(retrievalmarket.BlockstoreAccessor), modules.RetrievalBlockstoreAccessor), - Override(new(retrievalmarket.RetrievalClient), modules.RetrievalClient), + Override(new(retrievalmarket.RetrievalClient), modules.RetrievalClient(false)), Override(new(dtypes.ClientDataTransfer), modules.NewClientGraphsyncDataTransfer), // Markets (storage) @@ -221,6 +221,8 @@ func ConfigFullNode(c interface{}) Option { ), Override(new(dtypes.Graphsync), modules.Graphsync(cfg.Client.SimultaneousTransfersForStorage, cfg.Client.SimultaneousTransfersForRetrieval)), + Override(new(retrievalmarket.RetrievalClient), modules.RetrievalClient(cfg.Client.OffChainRetrieval)), + If(cfg.Wallet.RemoteBackend != "", Override(new(*remotewallet.RemoteWallet), remotewallet.SetupRemoteWallet(cfg.Wallet.RemoteBackend)), ), diff --git a/node/config/doc_gen.go b/node/config/doc_gen.go index c3730cbace6..59181f9f625 100644 --- a/node/config/doc_gen.go +++ b/node/config/doc_gen.go @@ -105,6 +105,14 @@ and storage providers for storage deals`, Comment: `The maximum number of simultaneous data transfers between the client and storage providers for retrieval deals`, }, + { + Name: "OffChainRetrieval", + Type: "bool", + + Comment: `Require that retrievals perform no on-chain retrievals. Paid retrievals +without existing payment channels with available funds will fail instead +of automatically performing on-chain operations.`, + }, }, "Common": []DocField{ { diff --git a/node/config/types.go b/node/config/types.go index 715f4824861..7e9064614f5 100644 --- a/node/config/types.go +++ b/node/config/types.go @@ -383,6 +383,11 @@ type Client struct { // The maximum number of simultaneous data transfers between the client // and storage providers for retrieval deals SimultaneousTransfersForRetrieval uint64 + + // Require that retrievals perform no on-chain retrievals. Paid retrievals + // without existing payment channels with available funds will fail instead + // of automatically performing on-chain operations. + OffChainRetrieval bool } type Wallet struct { diff --git a/node/modules/client.go b/node/modules/client.go index 48f9dc3d778..1e74182041d 100644 --- a/node/modules/client.go +++ b/node/modules/client.go @@ -202,26 +202,28 @@ func StorageClient(lc fx.Lifecycle, h host.Host, dataTransfer dtypes.ClientDataT } // RetrievalClient creates a new retrieval client attached to the client blockstore -func RetrievalClient(lc fx.Lifecycle, h host.Host, r repo.LockedRepo, dt dtypes.ClientDataTransfer, payAPI payapi.PaychAPI, resolver discovery.PeerResolver, +func RetrievalClient(forceOffChain bool) func(lc fx.Lifecycle, h host.Host, r repo.LockedRepo, dt dtypes.ClientDataTransfer, payAPI payapi.PaychAPI, resolver discovery.PeerResolver, ds dtypes.MetadataDS, chainAPI full.ChainAPI, stateAPI full.StateAPI, accessor retrievalmarket.BlockstoreAccessor, j journal.Journal) (retrievalmarket.RetrievalClient, error) { - - adapter := retrievaladapter.NewRetrievalClientNode(payAPI, chainAPI, stateAPI) - network := rmnet.NewFromLibp2pHost(h) - ds = namespace.Wrap(ds, datastore.NewKey("/retrievals/client")) - client, err := retrievalimpl.NewClient(network, dt, adapter, resolver, ds, accessor) - if err != nil { - return nil, err + return func(lc fx.Lifecycle, h host.Host, r repo.LockedRepo, dt dtypes.ClientDataTransfer, payAPI payapi.PaychAPI, resolver discovery.PeerResolver, + ds dtypes.MetadataDS, chainAPI full.ChainAPI, stateAPI full.StateAPI, accessor retrievalmarket.BlockstoreAccessor, j journal.Journal) (retrievalmarket.RetrievalClient, error) { + adapter := retrievaladapter.NewRetrievalClientNode(forceOffChain, payAPI, chainAPI, stateAPI) + network := rmnet.NewFromLibp2pHost(h) + ds = namespace.Wrap(ds, datastore.NewKey("/retrievals/client")) + client, err := retrievalimpl.NewClient(network, dt, adapter, resolver, ds, accessor) + if err != nil { + return nil, err + } + client.OnReady(marketevents.ReadyLogger("retrieval client")) + lc.Append(fx.Hook{ + OnStart: func(ctx context.Context) error { + client.SubscribeToEvents(marketevents.RetrievalClientLogger) + + evtType := j.RegisterEventType("markets/retrieval/client", "state_change") + client.SubscribeToEvents(markets.RetrievalClientJournaler(j, evtType)) + + return client.Start(ctx) + }, + }) + return client, nil } - client.OnReady(marketevents.ReadyLogger("retrieval client")) - lc.Append(fx.Hook{ - OnStart: func(ctx context.Context) error { - client.SubscribeToEvents(marketevents.RetrievalClientLogger) - - evtType := j.RegisterEventType("markets/retrieval/client", "state_change") - client.SubscribeToEvents(markets.RetrievalClientJournaler(j, evtType)) - - return client.Start(ctx) - }, - }) - return client, nil } From 8f9e730ad66d7d3d973dc4204a6645cb09f31c01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 6 Jan 2022 18:02:34 +0100 Subject: [PATCH 067/385] paych: Better off-chain errors --- markets/retrievaladapter/client.go | 1 + paychmgr/simple.go | 13 ++++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/markets/retrievaladapter/client.go b/markets/retrievaladapter/client.go index 60f41ca296d..97a157b19cd 100644 --- a/markets/retrievaladapter/client.go +++ b/markets/retrievaladapter/client.go @@ -70,6 +70,7 @@ func (rcn *retrievalClientNode) GetOrCreatePaymentChannel(ctx context.Context, c OffChain: rcn.forceOffChain, }) if err != nil { + log.Errorw("paych get failed", "error", err) return address.Undef, cid.Undef, err } if ci.WaitSentinel == cid.Undef { diff --git a/paychmgr/simple.go b/paychmgr/simple.go index ffb13b6c233..ef0f81b8748 100644 --- a/paychmgr/simple.go +++ b/paychmgr/simple.go @@ -186,7 +186,10 @@ func (m *mergedFundsReq) completeAmount(avail types.BigInt, channelInfo *Channel // can't fill, so OffChain want an error if r.isActive() { failed = types.BigAdd(failed, r.amt) - r.onComplete(&paychFundsRes{channel: *channelInfo.Channel, err: xerrors.Errorf("not enough available funds in the payment channel")}) + r.onComplete(&paychFundsRes{ + channel: *channelInfo.Channel, + err: xerrors.Errorf("not enough funds available in the payment channel %s; add funds with 'lotus paych add-funds %s %s %s'", channelInfo.Channel, channelInfo.from(), channelInfo.to(), types.FIL(r.amt).Unitless()), + }) } next = i + 1 continue @@ -212,7 +215,7 @@ func (m *mergedFundsReq) completeAmount(avail types.BigInt, channelInfo *Channel return nil, used, failed } -func (m *mergedFundsReq) failOffChain(msg string) (*paychFundsRes, types.BigInt) { +func (m *mergedFundsReq) failOffChainNoChannel(from, to address.Address) (*paychFundsRes, types.BigInt) { next := 0 freed := types.NewInt(0) @@ -225,13 +228,13 @@ func (m *mergedFundsReq) failOffChain(msg string) (*paychFundsRes, types.BigInt) if !r.isActive() { continue } - r.onComplete(&paychFundsRes{err: xerrors.New(msg)}) + r.onComplete(&paychFundsRes{err: xerrors.Errorf("payment channel doesn't exist, create with 'lotus paych add-funds %s %s %s'", from, to, types.FIL(r.amt).Unitless())}) next = i + 1 } m.reqs = m.reqs[next:] if len(m.reqs) == 0 { - return &paychFundsRes{err: xerrors.New(msg)}, freed + return &paychFundsRes{err: xerrors.Errorf("payment channel doesn't exist, create with 'lotus paych add-funds %s %s 0'", from, to)}, freed } return nil, freed @@ -440,7 +443,7 @@ func (ca *channelAccessor) processTask(merged *mergedFundsReq, amt, avail types. // If a channel has not yet been created, create one. if channelInfo == nil { - res, freed := merged.failOffChain("payment channel doesn't exist") + res, freed := merged.failOffChainNoChannel(ca.from, ca.to) if res != nil { return res } From 550e2743d727f5322ccfc7261d42c7509a2b185d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 6 Jan 2022 19:51:26 +0100 Subject: [PATCH 068/385] paych: Don't return settling/collected chennals from OutboundActiveByFromTo --- build/openrpc/full.json.gz | Bin 26594 -> 26976 bytes documentation/en/default-lotus-config.toml | 8 ++ paychmgr/paych.go | 2 +- paychmgr/paych_test.go | 12 +-- paychmgr/paychget_test.go | 108 ++++++++++++++++++++- paychmgr/simple.go | 2 +- paychmgr/store.go | 20 +++- 7 files changed, 140 insertions(+), 12 deletions(-) diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index ae8f0b86655688ef335478f8abf47bf58d1ca299..55e96a3aa48e38cb9febb44d3c03b0c3bbc5f34b 100644 GIT binary patch literal 26976 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 GVE+e$XyMKP diff --git a/documentation/en/default-lotus-config.toml b/documentation/en/default-lotus-config.toml index 3cb8977b290..016e1290cb9 100644 --- a/documentation/en/default-lotus-config.toml +++ b/documentation/en/default-lotus-config.toml @@ -121,6 +121,14 @@ # env var: LOTUS_CLIENT_SIMULTANEOUSTRANSFERSFORRETRIEVAL #SimultaneousTransfersForRetrieval = 20 + # Require that retrievals perform no on-chain retrievals. Paid retrievals + # without existing payment channels with available funds will fail instead + # of automatically performing on-chain operations. + # + # type: bool + # env var: LOTUS_CLIENT_OFFCHAINRETRIEVAL + #OffChainRetrieval = false + [Wallet] # type: string diff --git a/paychmgr/paych.go b/paychmgr/paych.go index 16c6604c6ca..5fdb4d8842e 100644 --- a/paychmgr/paych.go +++ b/paychmgr/paych.go @@ -106,7 +106,7 @@ func (ca *channelAccessor) outboundActiveByFromTo(ctx context.Context, from, to ca.lk.Lock() defer ca.lk.Unlock() - return ca.store.OutboundActiveByFromTo(ctx, from, to) + return ca.store.OutboundActiveByFromTo(ctx, ca.api, from, to) } // createVoucher creates a voucher with the given specification, setting its diff --git a/paychmgr/paych_test.go b/paychmgr/paych_test.go index 165c945b8cb..24214d1b585 100644 --- a/paychmgr/paych_test.go +++ b/paychmgr/paych_test.go @@ -465,18 +465,18 @@ func TestAddVoucherInboundWalletKey(t *testing.T) { toAcct := tutils.NewActorAddr(t, "toAct") // Create an actor for the channel in state - act := &types.Actor{ - Code: builtin.AccountActorCodeID, - Head: cid.Cid{}, - Nonce: 0, - Balance: types.NewInt(20), - } mock := newMockManagerAPI() mock.setAccountAddress(fromAcct, from) mock.setAccountAddress(toAcct, to) + act := &types.Actor{ + Code: builtin.AccountActorCodeID, + Head: cid.Cid{}, + Nonce: 0, + Balance: types.NewInt(20), + } mock.setPaychState(ch, act, paychmock.NewMockPayChState(fromAcct, toAcct, abi.ChainEpoch(0), make(map[uint64]paych.LaneState))) // Create a manager diff --git a/paychmgr/paychget_test.go b/paychmgr/paychget_test.go index f16b146f627..c53a85d86a0 100644 --- a/paychmgr/paychget_test.go +++ b/paychmgr/paychget_test.go @@ -132,6 +132,14 @@ func TestPaychGetCreateChannelThenAddFunds(t *testing.T) { mock := newMockManagerAPI() defer mock.close() + act := &types.Actor{ + Code: builtin.AccountActorCodeID, + Head: cid.Cid{}, + Nonce: 0, + Balance: types.NewInt(20), + } + mock.setPaychState(ch, act, paychmock.NewMockPayChState(from, to, abi.ChainEpoch(0), make(map[uint64]paych.LaneState))) + mgr, err := newManager(store, mock) require.NoError(t, err) @@ -219,6 +227,14 @@ func TestPaychGetCreatePrefundedChannelThenAddFunds(t *testing.T) { mock := newMockManagerAPI() defer mock.close() + act := &types.Actor{ + Code: builtin.AccountActorCodeID, + Head: cid.Cid{}, + Nonce: 0, + Balance: types.NewInt(20), + } + mock.setPaychState(ch, act, paychmock.NewMockPayChState(from, to, abi.ChainEpoch(0), make(map[uint64]paych.LaneState))) + mgr, err := newManager(store, mock) require.NoError(t, err) @@ -406,6 +422,14 @@ func TestPaychGetRecoverAfterAddFundsError(t *testing.T) { mock := newMockManagerAPI() defer mock.close() + act := &types.Actor{ + Code: builtin.AccountActorCodeID, + Head: cid.Cid{}, + Nonce: 0, + Balance: types.NewInt(20), + } + mock.setPaychState(ch, act, paychmock.NewMockPayChState(from, to, abi.ChainEpoch(0), make(map[uint64]paych.LaneState))) + mgr, err := newManager(store, mock) require.NoError(t, err) @@ -502,6 +526,14 @@ func TestPaychGetRestartAfterCreateChannelMsg(t *testing.T) { mock2 := newMockManagerAPI() defer mock2.close() + act := &types.Actor{ + Code: builtin.AccountActorCodeID, + Head: cid.Cid{}, + Nonce: 0, + Balance: types.NewInt(20), + } + mock2.setPaychState(ch, act, paychmock.NewMockPayChState(from, to, abi.ChainEpoch(0), make(map[uint64]paych.LaneState))) + mgr2, err := newManager(store, mock2) require.NoError(t, err) @@ -566,6 +598,14 @@ func TestPaychGetRestartAfterAddFundsMsg(t *testing.T) { mock := newMockManagerAPI() + act := &types.Actor{ + Code: builtin.AccountActorCodeID, + Head: cid.Cid{}, + Nonce: 0, + Balance: types.NewInt(20), + } + mock.setPaychState(ch, act, paychmock.NewMockPayChState(from, to, abi.ChainEpoch(0), make(map[uint64]paych.LaneState))) + mgr, err := newManager(store, mock) require.NoError(t, err) @@ -590,6 +630,8 @@ func TestPaychGetRestartAfterAddFundsMsg(t *testing.T) { mock2 := newMockManagerAPI() defer mock2.close() + mock2.setPaychState(ch, act, paychmock.NewMockPayChState(from, to, abi.ChainEpoch(0), make(map[uint64]paych.LaneState))) + mgr2, err := newManager(store, mock2) require.NoError(t, err) @@ -625,10 +667,19 @@ func TestPaychGetWait(t *testing.T) { from := tutils.NewIDAddr(t, 101) to := tutils.NewIDAddr(t, 102) + expch := tutils.NewIDAddr(t, 100) mock := newMockManagerAPI() defer mock.close() + act := &types.Actor{ + Code: builtin.AccountActorCodeID, + Head: cid.Cid{}, + Nonce: 0, + Balance: types.NewInt(20), + } + mock.setPaychState(expch, act, paychmock.NewMockPayChState(from, to, abi.ChainEpoch(0), make(map[uint64]paych.LaneState))) + mgr, err := newManager(store, mock) require.NoError(t, err) @@ -637,7 +688,6 @@ func TestPaychGetWait(t *testing.T) { _, createMsgCid, err := mgr.GetPaych(ctx, from, to, amt, onChainReserve) require.NoError(t, err) - expch := tutils.NewIDAddr(t, 100) go func() { // 3. Send response response := testChannelResponse(t, expch) @@ -763,6 +813,14 @@ func TestPaychGetMergeAddFunds(t *testing.T) { mock := newMockManagerAPI() defer mock.close() + act := &types.Actor{ + Code: builtin.AccountActorCodeID, + Head: cid.Cid{}, + Nonce: 0, + Balance: types.NewInt(20), + } + mock.setPaychState(ch, act, paychmock.NewMockPayChState(from, to, abi.ChainEpoch(0), make(map[uint64]paych.LaneState))) + mgr, err := newManager(store, mock) require.NoError(t, err) @@ -859,6 +917,14 @@ func TestPaychGetMergePrefundAndReserve(t *testing.T) { mock := newMockManagerAPI() defer mock.close() + act := &types.Actor{ + Code: builtin.AccountActorCodeID, + Head: cid.Cid{}, + Nonce: 0, + Balance: types.NewInt(20), + } + mock.setPaychState(ch, act, paychmock.NewMockPayChState(from, to, abi.ChainEpoch(0), make(map[uint64]paych.LaneState))) + mgr, err := newManager(store, mock) require.NoError(t, err) @@ -955,6 +1021,14 @@ func TestPaychGetMergePrefundAndReservePrefunded(t *testing.T) { mock := newMockManagerAPI() defer mock.close() + act := &types.Actor{ + Code: builtin.AccountActorCodeID, + Head: cid.Cid{}, + Nonce: 0, + Balance: types.NewInt(20), + } + mock.setPaychState(ch, act, paychmock.NewMockPayChState(from, to, abi.ChainEpoch(0), make(map[uint64]paych.LaneState))) + mgr, err := newManager(store, mock) require.NoError(t, err) @@ -1052,6 +1126,14 @@ func TestPaychGetMergePrefundAndReservePrefundedOneOffchain(t *testing.T) { mock := newMockManagerAPI() defer mock.close() + act := &types.Actor{ + Code: builtin.AccountActorCodeID, + Head: cid.Cid{}, + Nonce: 0, + Balance: types.NewInt(20), + } + mock.setPaychState(ch, act, paychmock.NewMockPayChState(from, to, abi.ChainEpoch(0), make(map[uint64]paych.LaneState))) + mgr, err := newManager(store, mock) require.NoError(t, err) @@ -1130,6 +1212,14 @@ func TestPaychGetMergePrefundAndReservePrefundedBothOffchainOneFail(t *testing.T mock := newMockManagerAPI() defer mock.close() + act := &types.Actor{ + Code: builtin.AccountActorCodeID, + Head: cid.Cid{}, + Nonce: 0, + Balance: types.NewInt(20), + } + mock.setPaychState(ch, act, paychmock.NewMockPayChState(from, to, abi.ChainEpoch(0), make(map[uint64]paych.LaneState))) + mgr, err := newManager(store, mock) require.NoError(t, err) @@ -1208,6 +1298,14 @@ func TestPaychGetMergePrefundAndReserveOneOffchainOneFail(t *testing.T) { mock := newMockManagerAPI() defer mock.close() + act := &types.Actor{ + Code: builtin.AccountActorCodeID, + Head: cid.Cid{}, + Nonce: 0, + Balance: types.NewInt(20), + } + mock.setPaychState(ch, act, paychmock.NewMockPayChState(from, to, abi.ChainEpoch(0), make(map[uint64]paych.LaneState))) + mgr, err := newManager(store, mock) require.NoError(t, err) @@ -1295,6 +1393,14 @@ func TestPaychGetMergeAddFundsCtxCancelOne(t *testing.T) { mock := newMockManagerAPI() defer mock.close() + act := &types.Actor{ + Code: builtin.AccountActorCodeID, + Head: cid.Cid{}, + Nonce: 0, + Balance: types.NewInt(20), + } + mock.setPaychState(ch, act, paychmock.NewMockPayChState(from, to, abi.ChainEpoch(0), make(map[uint64]paych.LaneState))) + mgr, err := newManager(store, mock) require.NoError(t, err) diff --git a/paychmgr/simple.go b/paychmgr/simple.go index ef0f81b8748..56bea0d27f8 100644 --- a/paychmgr/simple.go +++ b/paychmgr/simple.go @@ -436,7 +436,7 @@ func (ca *channelAccessor) processTask(merged *mergedFundsReq, amt, avail types. // Get the payment channel for the from/to addresses. // Note: It's ok if we get ErrChannelNotTracked. It just means we need to // create a channel. - channelInfo, err := ca.store.OutboundActiveByFromTo(ctx, ca.from, ca.to) + channelInfo, err := ca.store.OutboundActiveByFromTo(ctx, ca.api, ca.from, ca.to) if err != nil && err != ErrChannelNotTracked { return &paychFundsRes{err: err} } diff --git a/paychmgr/store.go b/paychmgr/store.go index d5c8e198049..7d6ee32be67 100644 --- a/paychmgr/store.go +++ b/paychmgr/store.go @@ -6,9 +6,8 @@ import ( "errors" "fmt" - "golang.org/x/xerrors" - "github.com/google/uuid" + "golang.org/x/xerrors" "github.com/filecoin-project/lotus/chain/types" @@ -380,7 +379,7 @@ func (ps *Store) GetMessage(ctx context.Context, mcid cid.Cid) (*MsgInfo, error) // OutboundActiveByFromTo looks for outbound channels that have not been // settled, with the given from / to addresses -func (ps *Store) OutboundActiveByFromTo(ctx context.Context, from address.Address, to address.Address) (*ChannelInfo, error) { +func (ps *Store) OutboundActiveByFromTo(ctx context.Context, sma stateManagerAPI, from address.Address, to address.Address) (*ChannelInfo, error) { return ps.findChan(ctx, func(ci *ChannelInfo) bool { if ci.Direction != DirOutbound { return false @@ -388,6 +387,21 @@ func (ps *Store) OutboundActiveByFromTo(ctx context.Context, from address.Addres if ci.Settling { return false } + + if ci.Channel != nil { + _, st, err := sma.GetPaychState(ctx, *ci.Channel, nil) + if err != nil { + return false + } + sat, err := st.SettlingAt() + if err != nil { + return false + } + if sat != 0 { + return false + } + } + return ci.Control == from && ci.Target == to }) } From 8d062bc880c697766c0e5ee8330ceafdd04671bc Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Mon, 24 Jan 2022 14:26:17 +0400 Subject: [PATCH 069/385] update index provider --- go.mod | 2 +- go.sum | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c8312a261ee..b7f8121acde 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,7 @@ require ( github.com/filecoin-project/go-statemachine v1.0.1 github.com/filecoin-project/go-statestore v0.2.0 github.com/filecoin-project/go-storedcounter v0.1.0 - github.com/filecoin-project/index-provider v0.2.1 + github.com/filecoin-project/index-provider v0.2.2 github.com/filecoin-project/specs-actors v0.9.14 github.com/filecoin-project/specs-actors/v2 v2.3.6 github.com/filecoin-project/specs-actors/v3 v3.1.1 diff --git a/go.sum b/go.sum index 4488b876930..724391a8875 100644 --- a/go.sum +++ b/go.sum @@ -354,8 +354,9 @@ github.com/filecoin-project/go-indexer-core v0.2.7/go.mod h1:6YD7KwDOQ+03DdAitvi github.com/filecoin-project/go-jsonrpc v0.1.5 h1:ckxqZ09ivBAVf5CSmxxrqqNHC7PJm3GYGtYKiNQ+vGk= github.com/filecoin-project/go-jsonrpc v0.1.5/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4= github.com/filecoin-project/go-legs v0.2.1/go.mod h1:iHDfdqieReblkLoHneB68wvthFtNKB+wkeEWKtiJESk= -github.com/filecoin-project/go-legs v0.2.2 h1:tCCqiXpXw8219/l191phtp7BZbssm7hJcnFFTESs2NI= github.com/filecoin-project/go-legs v0.2.2/go.mod h1:mdNMISV/bWyZguFM7R4s0mxV1v6Vhda3BiAw9+jv5iE= +github.com/filecoin-project/go-legs v0.2.3 h1:sNEUF+Cw4mpGp8hX4oZO/lIAiZpbJy55ih2GxXhj+V0= +github.com/filecoin-project/go-legs v0.2.3/go.mod h1:mdNMISV/bWyZguFM7R4s0mxV1v6Vhda3BiAw9+jv5iE= github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20/go.mod h1:mPn+LRRd5gEKNAtc+r3ScpW2JRU/pj4NBKdADYWHiak= github.com/filecoin-project/go-padreader v0.0.0-20210723183308-812a16dc01b1/go.mod h1:VYVPJqwpsfmtoHnAmPx6MUwmrK6HIcDqZJiuZhtmfLQ= github.com/filecoin-project/go-padreader v0.0.1 h1:8h2tVy5HpoNbr2gBRr+WD6zV6VD6XHig+ynSGJg8ZOs= @@ -379,8 +380,9 @@ github.com/filecoin-project/go-statestore v0.2.0 h1:cRRO0aPLrxKQCZ2UOQbzFGn4WDNd github.com/filecoin-project/go-statestore v0.2.0/go.mod h1:8sjBYbS35HwPzct7iT4lIXjLlYyPor80aU7t7a/Kspo= github.com/filecoin-project/go-storedcounter v0.1.0 h1:Mui6wSUBC+cQGHbDUBcO7rfh5zQkWJM/CpAZa/uOuus= github.com/filecoin-project/go-storedcounter v0.1.0/go.mod h1:4ceukaXi4vFURIoxYMfKzaRF5Xv/Pinh2oTnoxpv+z8= -github.com/filecoin-project/index-provider v0.2.1 h1:jM0ZxEsJhx4WmGgFBtC2ctk2pvu50Rd/LBNNNOcWbQQ= github.com/filecoin-project/index-provider v0.2.1/go.mod h1:T3Ct7dqS7GDtotzFk/cNe0fzhoPLLk8htiXMK+xQfHU= +github.com/filecoin-project/index-provider v0.2.2 h1:t4+Q+Bu4yw9LdRAdH85rxPcoY8yKZlm2LdQxiST9UUY= +github.com/filecoin-project/index-provider v0.2.2/go.mod h1:QkOSa6WlNFTdbdGLDS4w5k3pMsz/fLZFoorAGgM7e0Y= github.com/filecoin-project/specs-actors v0.9.13/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= github.com/filecoin-project/specs-actors v0.9.14 h1:68PVstg2UB3ZsMLF+DKFTAs/YKsqhKWynkr0IqmVRQY= github.com/filecoin-project/specs-actors v0.9.14/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= From 5da2995bcdd6feb16f0ecc964d307860cae96949 Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Tue, 25 Jan 2022 09:37:44 +0000 Subject: [PATCH 070/385] Upgrade to `index-provider` v0.2.3 Upgrade index provider to latest so that on engine restart the head advertisement is published. --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index b7f8121acde..bc16eddf05e 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,7 @@ require ( github.com/filecoin-project/go-statemachine v1.0.1 github.com/filecoin-project/go-statestore v0.2.0 github.com/filecoin-project/go-storedcounter v0.1.0 - github.com/filecoin-project/index-provider v0.2.2 + github.com/filecoin-project/index-provider v0.2.3 github.com/filecoin-project/specs-actors v0.9.14 github.com/filecoin-project/specs-actors/v2 v2.3.6 github.com/filecoin-project/specs-actors/v3 v3.1.1 diff --git a/go.sum b/go.sum index 724391a8875..9915e47af7e 100644 --- a/go.sum +++ b/go.sum @@ -383,6 +383,8 @@ github.com/filecoin-project/go-storedcounter v0.1.0/go.mod h1:4ceukaXi4vFURIoxYM github.com/filecoin-project/index-provider v0.2.1/go.mod h1:T3Ct7dqS7GDtotzFk/cNe0fzhoPLLk8htiXMK+xQfHU= github.com/filecoin-project/index-provider v0.2.2 h1:t4+Q+Bu4yw9LdRAdH85rxPcoY8yKZlm2LdQxiST9UUY= github.com/filecoin-project/index-provider v0.2.2/go.mod h1:QkOSa6WlNFTdbdGLDS4w5k3pMsz/fLZFoorAGgM7e0Y= +github.com/filecoin-project/index-provider v0.2.3 h1:F4zM+hetYYXt0dXgUSejN9SadAHUjvzakfWFbC6HUa4= +github.com/filecoin-project/index-provider v0.2.3/go.mod h1:QkOSa6WlNFTdbdGLDS4w5k3pMsz/fLZFoorAGgM7e0Y= github.com/filecoin-project/specs-actors v0.9.13/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= github.com/filecoin-project/specs-actors v0.9.14 h1:68PVstg2UB3ZsMLF+DKFTAs/YKsqhKWynkr0IqmVRQY= github.com/filecoin-project/specs-actors v0.9.14/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= From 4dd93e5bbbfaa99fc0786f0033c12e0e2b323b4d Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Wed, 26 Jan 2022 10:58:44 +0400 Subject: [PATCH 071/385] update deps --- go.mod | 2 +- go.sum | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index bc16eddf05e..bcd7d1421a3 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,7 @@ require ( github.com/filecoin-project/go-data-transfer v1.14.0 github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 - github.com/filecoin-project/go-fil-markets v1.19.1-0.20220120121729-eb2fe1f4df58 + github.com/filecoin-project/go-fil-markets v1.19.1-0.20220126065420-3d2e3c81e8e4 github.com/filecoin-project/go-indexer-core v0.2.7 github.com/filecoin-project/go-jsonrpc v0.1.5 github.com/filecoin-project/go-padreader v0.0.1 diff --git a/go.sum b/go.sum index 9915e47af7e..9d2868de43b 100644 --- a/go.sum +++ b/go.sum @@ -339,8 +339,8 @@ github.com/filecoin-project/go-fil-commcid v0.1.0 h1:3R4ds1A9r6cr8mvZBfMYxTS88Oq github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7LXep5bFEVOVmQWHJvl2mgsGo= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8= -github.com/filecoin-project/go-fil-markets v1.19.1-0.20220120121729-eb2fe1f4df58 h1:NHX4FXQQQ9dVhQBBM1BThVbYmN3EnM4Dxzvz0DYTOTk= -github.com/filecoin-project/go-fil-markets v1.19.1-0.20220120121729-eb2fe1f4df58/go.mod h1:SmDIzoUwFlej6Ac5ilBMyBImTj/TrmJmZ6wh/ILMfuI= +github.com/filecoin-project/go-fil-markets v1.19.1-0.20220126065420-3d2e3c81e8e4 h1:h8neqftyFIA2kFG9nIEESSwARjixPdD0L3OZZhE9XjQ= +github.com/filecoin-project/go-fil-markets v1.19.1-0.20220126065420-3d2e3c81e8e4/go.mod h1:SmDIzoUwFlej6Ac5ilBMyBImTj/TrmJmZ6wh/ILMfuI= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= @@ -381,8 +381,6 @@ github.com/filecoin-project/go-statestore v0.2.0/go.mod h1:8sjBYbS35HwPzct7iT4lI github.com/filecoin-project/go-storedcounter v0.1.0 h1:Mui6wSUBC+cQGHbDUBcO7rfh5zQkWJM/CpAZa/uOuus= github.com/filecoin-project/go-storedcounter v0.1.0/go.mod h1:4ceukaXi4vFURIoxYMfKzaRF5Xv/Pinh2oTnoxpv+z8= github.com/filecoin-project/index-provider v0.2.1/go.mod h1:T3Ct7dqS7GDtotzFk/cNe0fzhoPLLk8htiXMK+xQfHU= -github.com/filecoin-project/index-provider v0.2.2 h1:t4+Q+Bu4yw9LdRAdH85rxPcoY8yKZlm2LdQxiST9UUY= -github.com/filecoin-project/index-provider v0.2.2/go.mod h1:QkOSa6WlNFTdbdGLDS4w5k3pMsz/fLZFoorAGgM7e0Y= github.com/filecoin-project/index-provider v0.2.3 h1:F4zM+hetYYXt0dXgUSejN9SadAHUjvzakfWFbC6HUa4= github.com/filecoin-project/index-provider v0.2.3/go.mod h1:QkOSa6WlNFTdbdGLDS4w5k3pMsz/fLZFoorAGgM7e0Y= github.com/filecoin-project/specs-actors v0.9.13/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= From 211ad166af7ec8f0ba59c858c821fa7e179557fd Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Wed, 26 Jan 2022 15:53:27 +0400 Subject: [PATCH 072/385] update markets deps --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index bcd7d1421a3..fcdbbc0793c 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,7 @@ require ( github.com/filecoin-project/go-data-transfer v1.14.0 github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 - github.com/filecoin-project/go-fil-markets v1.19.1-0.20220126065420-3d2e3c81e8e4 + github.com/filecoin-project/go-fil-markets v1.19.1-0.20220126115144-06ec15036195 github.com/filecoin-project/go-indexer-core v0.2.7 github.com/filecoin-project/go-jsonrpc v0.1.5 github.com/filecoin-project/go-padreader v0.0.1 diff --git a/go.sum b/go.sum index 9d2868de43b..b39380ad236 100644 --- a/go.sum +++ b/go.sum @@ -339,8 +339,8 @@ github.com/filecoin-project/go-fil-commcid v0.1.0 h1:3R4ds1A9r6cr8mvZBfMYxTS88Oq github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7LXep5bFEVOVmQWHJvl2mgsGo= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8= -github.com/filecoin-project/go-fil-markets v1.19.1-0.20220126065420-3d2e3c81e8e4 h1:h8neqftyFIA2kFG9nIEESSwARjixPdD0L3OZZhE9XjQ= -github.com/filecoin-project/go-fil-markets v1.19.1-0.20220126065420-3d2e3c81e8e4/go.mod h1:SmDIzoUwFlej6Ac5ilBMyBImTj/TrmJmZ6wh/ILMfuI= +github.com/filecoin-project/go-fil-markets v1.19.1-0.20220126115144-06ec15036195 h1:IgKgvwi63bhOGvg+2BmYVRK+XEgS/YaEJMzSbY/RAiM= +github.com/filecoin-project/go-fil-markets v1.19.1-0.20220126115144-06ec15036195/go.mod h1:SmDIzoUwFlej6Ac5ilBMyBImTj/TrmJmZ6wh/ILMfuI= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= From 5d72ebe0cc818443820e55bd3c288841bad49a3b Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Thu, 27 Jan 2022 09:48:10 +0000 Subject: [PATCH 073/385] Upgrade `index-provider` and update topic name Update the topic name to be consistent with default configured in storetheindex. Upgrade to the latest `index-provider`. --- documentation/en/default-lotus-miner-config.toml | 2 +- go.mod | 2 +- go.sum | 10 ++++++---- node/config/def_test.go | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/documentation/en/default-lotus-miner-config.toml b/documentation/en/default-lotus-miner-config.toml index 2e9638fabb3..345a2b91cdb 100644 --- a/documentation/en/default-lotus-miner-config.toml +++ b/documentation/en/default-lotus-miner-config.toml @@ -265,7 +265,7 @@ #LinkedChunkSize = 16384 # env var: LOTUS_INDEXERPROVIDER_PUBSUBTOPIC - #PubSubTopic = "indexer/ingest" + #PubSubTopic = "/indexer/ingest/mainnet" # env var: LOTUS_INDEXERPROVIDER_PURGELINKCACHE #PurgeLinkCache = false diff --git a/go.mod b/go.mod index fcdbbc0793c..ce44409381c 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,7 @@ require ( github.com/filecoin-project/go-statemachine v1.0.1 github.com/filecoin-project/go-statestore v0.2.0 github.com/filecoin-project/go-storedcounter v0.1.0 - github.com/filecoin-project/index-provider v0.2.3 + github.com/filecoin-project/index-provider v0.2.4 github.com/filecoin-project/specs-actors v0.9.14 github.com/filecoin-project/specs-actors/v2 v2.3.6 github.com/filecoin-project/specs-actors/v3 v3.1.1 diff --git a/go.sum b/go.sum index b39380ad236..1bc52d803ae 100644 --- a/go.sum +++ b/go.sum @@ -355,8 +355,9 @@ github.com/filecoin-project/go-jsonrpc v0.1.5 h1:ckxqZ09ivBAVf5CSmxxrqqNHC7PJm3G github.com/filecoin-project/go-jsonrpc v0.1.5/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4= github.com/filecoin-project/go-legs v0.2.1/go.mod h1:iHDfdqieReblkLoHneB68wvthFtNKB+wkeEWKtiJESk= github.com/filecoin-project/go-legs v0.2.2/go.mod h1:mdNMISV/bWyZguFM7R4s0mxV1v6Vhda3BiAw9+jv5iE= -github.com/filecoin-project/go-legs v0.2.3 h1:sNEUF+Cw4mpGp8hX4oZO/lIAiZpbJy55ih2GxXhj+V0= github.com/filecoin-project/go-legs v0.2.3/go.mod h1:mdNMISV/bWyZguFM7R4s0mxV1v6Vhda3BiAw9+jv5iE= +github.com/filecoin-project/go-legs v0.2.4 h1:2U4Zg2NMO76YxMMFhAWscvDBatqOlbUYDNKB70cLNl4= +github.com/filecoin-project/go-legs v0.2.4/go.mod h1:mdNMISV/bWyZguFM7R4s0mxV1v6Vhda3BiAw9+jv5iE= github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20/go.mod h1:mPn+LRRd5gEKNAtc+r3ScpW2JRU/pj4NBKdADYWHiak= github.com/filecoin-project/go-padreader v0.0.0-20210723183308-812a16dc01b1/go.mod h1:VYVPJqwpsfmtoHnAmPx6MUwmrK6HIcDqZJiuZhtmfLQ= github.com/filecoin-project/go-padreader v0.0.1 h1:8h2tVy5HpoNbr2gBRr+WD6zV6VD6XHig+ynSGJg8ZOs= @@ -381,8 +382,8 @@ github.com/filecoin-project/go-statestore v0.2.0/go.mod h1:8sjBYbS35HwPzct7iT4lI github.com/filecoin-project/go-storedcounter v0.1.0 h1:Mui6wSUBC+cQGHbDUBcO7rfh5zQkWJM/CpAZa/uOuus= github.com/filecoin-project/go-storedcounter v0.1.0/go.mod h1:4ceukaXi4vFURIoxYMfKzaRF5Xv/Pinh2oTnoxpv+z8= github.com/filecoin-project/index-provider v0.2.1/go.mod h1:T3Ct7dqS7GDtotzFk/cNe0fzhoPLLk8htiXMK+xQfHU= -github.com/filecoin-project/index-provider v0.2.3 h1:F4zM+hetYYXt0dXgUSejN9SadAHUjvzakfWFbC6HUa4= -github.com/filecoin-project/index-provider v0.2.3/go.mod h1:QkOSa6WlNFTdbdGLDS4w5k3pMsz/fLZFoorAGgM7e0Y= +github.com/filecoin-project/index-provider v0.2.4 h1:UNiT7mgln51nliy39t4JwoUNfttYeju3OEW+MIZVfbw= +github.com/filecoin-project/index-provider v0.2.4/go.mod h1:XTRE4AJglEpSlJwSZFVcm6zs3vsDvyfDwLkjTFSB5Po= github.com/filecoin-project/specs-actors v0.9.13/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= github.com/filecoin-project/specs-actors v0.9.14 h1:68PVstg2UB3ZsMLF+DKFTAs/YKsqhKWynkr0IqmVRQY= github.com/filecoin-project/specs-actors v0.9.14/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= @@ -407,8 +408,9 @@ github.com/filecoin-project/specs-actors/v7 v7.0.0-rc1/go.mod h1:TA5FwCna+Yi36PO github.com/filecoin-project/specs-storage v0.1.1-0.20211228030229-6d460d25a0c9 h1:oUYOvF7EvdXS0Zmk9mNkaB6Bu0l+WXBYPzVodKMiLug= github.com/filecoin-project/specs-storage v0.1.1-0.20211228030229-6d460d25a0c9/go.mod h1:Tb88Zq+IBJbvAn3mS89GYj3jdRThBTE/771HCVZdRJU= github.com/filecoin-project/storetheindex v0.2.2/go.mod h1:05vxs5u3vTQFAwGW9+pgWSMc3BgFOK513nPyIQyLwyQ= -github.com/filecoin-project/storetheindex v0.2.3 h1:YXA1qWQv/tRzvuqcPUt4kQbIgxFdKP32SPjWTefhOGw= github.com/filecoin-project/storetheindex v0.2.3/go.mod h1:US7ddOKCI+KQFcC3ipKuhK3i46EYlSCt5EvPhxBLfWI= +github.com/filecoin-project/storetheindex v0.2.5 h1:upSoyl1ostX2DxyXoR5U8FSRqvT1pHeYEfO3irobYZw= +github.com/filecoin-project/storetheindex v0.2.5/go.mod h1:Izc9PdivlQ+he1J8R1DD8978P8Yna0xQbf61L2UKxFc= github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg= github.com/filecoin-project/test-vectors/schema v0.0.5/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= diff --git a/node/config/def_test.go b/node/config/def_test.go index 85264358b54..e6ad1a68719 100644 --- a/node/config/def_test.go +++ b/node/config/def_test.go @@ -55,5 +55,5 @@ func TestDefaultMinerRoundtrip(t *testing.T) { func TestDefaultStorageMiner_SetsIndexIngestTopic(t *testing.T) { subject := DefaultStorageMiner() - require.Equal(t, "indexer/ingest", subject.IndexerProvider.PubSubTopic) + require.Equal(t, "/indexer/ingest/mainnet", subject.IndexerProvider.PubSubTopic) } From ad348c8e2f01e487794d8f259bdd56d9ca8e1bba Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Tue, 1 Feb 2022 09:52:45 +0000 Subject: [PATCH 074/385] Upgrade to the latest index provider Upgrade to the latest index provider which rolls out a more compact ad signature mechanism along with dependency updates. --- go.mod | 4 ++-- go.sum | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index ce44409381c..3344036dffa 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,7 @@ require ( github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 github.com/filecoin-project/go-fil-markets v1.19.1-0.20220126115144-06ec15036195 - github.com/filecoin-project/go-indexer-core v0.2.7 + github.com/filecoin-project/go-indexer-core v0.2.8 github.com/filecoin-project/go-jsonrpc v0.1.5 github.com/filecoin-project/go-padreader v0.0.1 github.com/filecoin-project/go-paramfetch v0.0.3-0.20220111000201-e42866db1a53 @@ -45,7 +45,7 @@ require ( github.com/filecoin-project/go-statemachine v1.0.1 github.com/filecoin-project/go-statestore v0.2.0 github.com/filecoin-project/go-storedcounter v0.1.0 - github.com/filecoin-project/index-provider v0.2.4 + github.com/filecoin-project/index-provider v0.2.6 github.com/filecoin-project/specs-actors v0.9.14 github.com/filecoin-project/specs-actors/v2 v2.3.6 github.com/filecoin-project/specs-actors/v3 v3.1.1 diff --git a/go.sum b/go.sum index 1bc52d803ae..b4cb47ca405 100644 --- a/go.sum +++ b/go.sum @@ -349,15 +349,15 @@ github.com/filecoin-project/go-hamt-ipld/v3 v3.0.1/go.mod h1:gXpNmr3oQx8l3o7qkGy github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0 h1:rVVNq0x6RGQIzCo1iiJlGFm9AGIZzeifggxtKMU7zmI= github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0/go.mod h1:bxmzgT8tmeVQA1/gvBwFmYdT8SOFUwB3ovSUfG1Ux0g= github.com/filecoin-project/go-indexer-core v0.2.4/go.mod h1:MSe5aRWmfRB+5syR4yDV+OApgJU+MUJ4rl9VUuzwCfc= -github.com/filecoin-project/go-indexer-core v0.2.7 h1:D0egR6Q3Jkp5r4klxkdDQvjXeLx3cwZMKE55qop2xCI= github.com/filecoin-project/go-indexer-core v0.2.7/go.mod h1:6YD7KwDOQ+03DdAitviL7h1fksIU6a4j52yPnA/E1PU= +github.com/filecoin-project/go-indexer-core v0.2.8 h1:h1SRdZKTVcaXlzex3UevHh4OWDAhgpMzL4tHNAA7MQI= +github.com/filecoin-project/go-indexer-core v0.2.8/go.mod h1:IagNfTdFuX4057kla43PjRCn3yBuUiZgIxuA0hTUamY= github.com/filecoin-project/go-jsonrpc v0.1.5 h1:ckxqZ09ivBAVf5CSmxxrqqNHC7PJm3GYGtYKiNQ+vGk= github.com/filecoin-project/go-jsonrpc v0.1.5/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4= github.com/filecoin-project/go-legs v0.2.1/go.mod h1:iHDfdqieReblkLoHneB68wvthFtNKB+wkeEWKtiJESk= github.com/filecoin-project/go-legs v0.2.2/go.mod h1:mdNMISV/bWyZguFM7R4s0mxV1v6Vhda3BiAw9+jv5iE= -github.com/filecoin-project/go-legs v0.2.3/go.mod h1:mdNMISV/bWyZguFM7R4s0mxV1v6Vhda3BiAw9+jv5iE= -github.com/filecoin-project/go-legs v0.2.4 h1:2U4Zg2NMO76YxMMFhAWscvDBatqOlbUYDNKB70cLNl4= -github.com/filecoin-project/go-legs v0.2.4/go.mod h1:mdNMISV/bWyZguFM7R4s0mxV1v6Vhda3BiAw9+jv5iE= +github.com/filecoin-project/go-legs v0.2.7 h1:+b1BQv4QKkRNsDUE8Z4sEhLXhfVQ+iGpHhANpYqxJlA= +github.com/filecoin-project/go-legs v0.2.7/go.mod h1:NrdELuDbtAH8/xqRMgyOYms67aliQajExInLS6g8zFM= github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20/go.mod h1:mPn+LRRd5gEKNAtc+r3ScpW2JRU/pj4NBKdADYWHiak= github.com/filecoin-project/go-padreader v0.0.0-20210723183308-812a16dc01b1/go.mod h1:VYVPJqwpsfmtoHnAmPx6MUwmrK6HIcDqZJiuZhtmfLQ= github.com/filecoin-project/go-padreader v0.0.1 h1:8h2tVy5HpoNbr2gBRr+WD6zV6VD6XHig+ynSGJg8ZOs= @@ -382,8 +382,8 @@ github.com/filecoin-project/go-statestore v0.2.0/go.mod h1:8sjBYbS35HwPzct7iT4lI github.com/filecoin-project/go-storedcounter v0.1.0 h1:Mui6wSUBC+cQGHbDUBcO7rfh5zQkWJM/CpAZa/uOuus= github.com/filecoin-project/go-storedcounter v0.1.0/go.mod h1:4ceukaXi4vFURIoxYMfKzaRF5Xv/Pinh2oTnoxpv+z8= github.com/filecoin-project/index-provider v0.2.1/go.mod h1:T3Ct7dqS7GDtotzFk/cNe0fzhoPLLk8htiXMK+xQfHU= -github.com/filecoin-project/index-provider v0.2.4 h1:UNiT7mgln51nliy39t4JwoUNfttYeju3OEW+MIZVfbw= -github.com/filecoin-project/index-provider v0.2.4/go.mod h1:XTRE4AJglEpSlJwSZFVcm6zs3vsDvyfDwLkjTFSB5Po= +github.com/filecoin-project/index-provider v0.2.6 h1:JodDoTiLjDPifRxKSgoyDwD8qzbSZDcyn5IPF0osVAg= +github.com/filecoin-project/index-provider v0.2.6/go.mod h1:y87dsIQdcmQS5PWIcifQdRb454ViVxjjFEccMDswIjQ= github.com/filecoin-project/specs-actors v0.9.13/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= github.com/filecoin-project/specs-actors v0.9.14 h1:68PVstg2UB3ZsMLF+DKFTAs/YKsqhKWynkr0IqmVRQY= github.com/filecoin-project/specs-actors v0.9.14/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= @@ -409,8 +409,8 @@ github.com/filecoin-project/specs-storage v0.1.1-0.20211228030229-6d460d25a0c9 h github.com/filecoin-project/specs-storage v0.1.1-0.20211228030229-6d460d25a0c9/go.mod h1:Tb88Zq+IBJbvAn3mS89GYj3jdRThBTE/771HCVZdRJU= github.com/filecoin-project/storetheindex v0.2.2/go.mod h1:05vxs5u3vTQFAwGW9+pgWSMc3BgFOK513nPyIQyLwyQ= github.com/filecoin-project/storetheindex v0.2.3/go.mod h1:US7ddOKCI+KQFcC3ipKuhK3i46EYlSCt5EvPhxBLfWI= -github.com/filecoin-project/storetheindex v0.2.5 h1:upSoyl1ostX2DxyXoR5U8FSRqvT1pHeYEfO3irobYZw= -github.com/filecoin-project/storetheindex v0.2.5/go.mod h1:Izc9PdivlQ+he1J8R1DD8978P8Yna0xQbf61L2UKxFc= +github.com/filecoin-project/storetheindex v0.3.0 h1:M9C4BFLCKn6FJn2N/8q0VbX00hEjEWUuvJpscqKwqzQ= +github.com/filecoin-project/storetheindex v0.3.0/go.mod h1:GhUmP8+nINxDRUqxQvTc3Fqc7Yp6w0dW/uTaYYIzd68= github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg= github.com/filecoin-project/test-vectors/schema v0.0.5/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= From db5e4da268329952fd6d1ccc1454a50fcbe796a2 Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Wed, 2 Feb 2022 10:51:53 +0100 Subject: [PATCH 075/385] add fullnodeApi to StorageProvider --- node/modules/storageminer.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index c8822b28e29..2a6b61b69c0 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -590,6 +590,7 @@ func StorageProvider(minerAddress dtypes.MinerAddress, spn storagemarket.StorageProviderNode, df dtypes.StorageDealFilter, dsw *dagstore.Wrapper, + fullnodeApi v1api.FullNode, ) (storagemarket.StorageProvider, error) { net := smnet.NewFromLibp2pHost(h) @@ -620,6 +621,7 @@ func StorageProvider(minerAddress dtypes.MinerAddress, spn, address.Address(minerAddress), storedAsk, + fullnodeApi, opt, ) } From f9b63c5f8c61836411efb20147882f4ee3c5e90a Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Wed, 2 Feb 2022 11:36:08 +0100 Subject: [PATCH 076/385] add idxProvHost to StorageProvider --- node/builder_miner.go | 1 + node/modules/storageminer.go | 2 ++ node/modules/storageminer_idxprov.go | 21 ++++++++++++++++++--- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/node/builder_miner.go b/node/builder_miner.go index de22ef8aa60..e45e8d19a79 100644 --- a/node/builder_miner.go +++ b/node/builder_miner.go @@ -168,6 +168,7 @@ func ConfigStorageMiner(c interface{}) Option { Override(new(dtypes.ProviderTransferNetwork), modules.NewProviderTransferNetwork), Override(new(dtypes.ProviderTransport), modules.NewProviderTransport), Override(new(dtypes.ProviderDataTransfer), modules.NewProviderDataTransfer), + Override(new(*modules.IdxProvHost), modules.IndexerProviderHost(cfg.IndexerProvider)), Override(new(provider.Interface), modules.IndexerProvider(cfg.IndexerProvider)), Override(new(*storedask.StoredAsk), modules.NewStorageAsk), Override(new(dtypes.StorageDealFilter), modules.BasicDealFilter(cfg.Dealmaking, nil)), diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index 2a6b61b69c0..34b27d9d75f 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -591,6 +591,7 @@ func StorageProvider(minerAddress dtypes.MinerAddress, df dtypes.StorageDealFilter, dsw *dagstore.Wrapper, fullnodeApi v1api.FullNode, + idxProvHost *IdxProvHost, ) (storagemarket.StorageProvider, error) { net := smnet.NewFromLibp2pHost(h) @@ -622,6 +623,7 @@ func StorageProvider(minerAddress dtypes.MinerAddress, address.Address(minerAddress), storedAsk, fullnodeApi, + idxProvHost.Host, opt, ) } diff --git a/node/modules/storageminer_idxprov.go b/node/modules/storageminer_idxprov.go index 8a0d2105733..b200d23eb6a 100644 --- a/node/modules/storageminer_idxprov.go +++ b/node/modules/storageminer_idxprov.go @@ -48,10 +48,12 @@ type IdxProv struct { peerstore.Peerstore } -func IndexerProvider(cfg config.IndexerProviderConfig) func(params IdxProv, marketHost host.Host) (provider.Interface, error) { - return func(args IdxProv, marketHost host.Host) (provider.Interface, error) { - ipds := namespace.Wrap(args.Datastore, datastore.NewKey("/indexer-provider")) +type IdxProvHost struct { + host.Host +} +func IndexerProviderHost(cfg config.IndexerProviderConfig) func(IdxProv) (*IdxProvHost, error) { + return func(args IdxProv) (*IdxProvHost, error) { pkey := args.Peerstore.PrivKey(args.PeerID) if pkey == nil { return nil, fmt.Errorf("missing private key for node ID: %s", args.PeerID.Pretty()) @@ -62,6 +64,19 @@ func IndexerProvider(cfg config.IndexerProviderConfig) func(params IdxProv, mark return nil, xerrors.Errorf("creating indexer provider host: %w", err) } + return &IdxProvHost{h}, nil + } +} + +func IndexerProvider(cfg config.IndexerProviderConfig) func(params IdxProv, marketHost host.Host, h *IdxProvHost) (provider.Interface, error) { + return func(args IdxProv, marketHost host.Host, h *IdxProvHost) (provider.Interface, error) { + ipds := namespace.Wrap(args.Datastore, datastore.NewKey("/indexer-provider")) + + pkey := args.Peerstore.PrivKey(args.PeerID) + if pkey == nil { + return nil, fmt.Errorf("missing private key for node ID: %s", args.PeerID.Pretty()) + } + dt, err := newIndexerProviderDataTransfer(cfg, args.MetricsCtx, args.Lifecycle, args.Repo, h, ipds) if err != nil { return nil, err From 2790cf35af1cacfee6994895f3b9082e366dd7f2 Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Wed, 2 Feb 2022 13:06:53 +0100 Subject: [PATCH 077/385] change fullnodeApi to listen addrs --- go.mod | 4 +--- go.sum | 36 +++--------------------------------- node/modules/storageminer.go | 7 ++++++- 3 files changed, 10 insertions(+), 37 deletions(-) diff --git a/go.mod b/go.mod index 3344036dffa..970e0d1647c 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,7 @@ require ( github.com/filecoin-project/go-data-transfer v1.14.0 github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 - github.com/filecoin-project/go-fil-markets v1.19.1-0.20220126115144-06ec15036195 + github.com/filecoin-project/go-fil-markets v1.19.1-0.20220202115512-c1c9ba8722ac github.com/filecoin-project/go-indexer-core v0.2.8 github.com/filecoin-project/go-jsonrpc v0.1.5 github.com/filecoin-project/go-padreader v0.0.1 @@ -160,7 +160,6 @@ require ( go.uber.org/fx v1.15.0 go.uber.org/multierr v1.7.0 go.uber.org/zap v1.19.1 - golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b // indirect golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sys v0.0.0-20211209171907-798191bca915 @@ -169,7 +168,6 @@ require ( golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 gopkg.in/cheggaaa/pb.v1 v1.0.28 gotest.tools v2.2.0+incompatible - lukechampine.com/blake3 v1.1.7 // indirect ) replace github.com/filecoin-project/filecoin-ffi => ./extern/filecoin-ffi diff --git a/go.sum b/go.sum index b4cb47ca405..5ba5e5e6432 100644 --- a/go.sum +++ b/go.sum @@ -298,6 +298,7 @@ github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/filecoin-project/dagstore v0.5.1/go.mod h1:OdlK3x5m3Mol874WC2bI79H4H2+leN+FabwWdW2D/wY= github.com/filecoin-project/dagstore v0.5.2-0.20220120115845-e07b050f48d3 h1:kuZsRFDjyrDAgoHNolJBnO7xX1EETHdJ090sgD3Al5E= github.com/filecoin-project/dagstore v0.5.2-0.20220120115845-e07b050f48d3/go.mod h1:OdlK3x5m3Mol874WC2bI79H4H2+leN+FabwWdW2D/wY= github.com/filecoin-project/go-address v0.0.3/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= @@ -324,13 +325,9 @@ github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod github.com/filecoin-project/go-crypto v0.0.1 h1:AcvpSGGCgjaY8y1az6AMfKQWreF/pWO2JJGLl6gCq6o= github.com/filecoin-project/go-crypto v0.0.1/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= github.com/filecoin-project/go-dagaggregator-unixfs v0.2.0/go.mod h1:WTuJWgBQY0omnQqa8kRPT9O0Uj5wQOgslVMUuTeHdJ8= -github.com/filecoin-project/go-data-transfer v1.11.4/go.mod h1:2MitLI0ebCkLlPKM7NRggP/t9d+gCcREUKkCKqWRCwU= -github.com/filecoin-project/go-data-transfer v1.12.1/go.mod h1:j3HL645YiQFxcM+q7uPlGApILSqeweDABNgZQP7pDYU= -github.com/filecoin-project/go-data-transfer v1.13.0/go.mod h1:TcUtAdQl1ofnLV9oH3gPC93Hjce9yuKnq4O4j2M/BU4= github.com/filecoin-project/go-data-transfer v1.14.0 h1:4pnfJk8FYtqcdAg+QRGzaz57seUC/Tz+HJgPuGB7zdg= github.com/filecoin-project/go-data-transfer v1.14.0/go.mod h1:wNJKhaLLYBJDM3VFvgvYi4iUjPa69pz/1Q5Q4HzX2wE= github.com/filecoin-project/go-ds-versioning v0.0.0-20211206185234-508abd7c2aff/go.mod h1:C9/l9PnB1+mwPa26BBVpCjG/XQCB0yj/q5CK2J8X1I4= -github.com/filecoin-project/go-ds-versioning v0.1.0/go.mod h1:mp16rb4i2QPmxBnmanUx8i/XANp+PFCCJWiAb+VW4/s= github.com/filecoin-project/go-ds-versioning v0.1.1 h1:JiyBqaQlwC+UM0WhcBtVEeT3XrX59mQhT8U3p7nu86o= github.com/filecoin-project/go-ds-versioning v0.1.1/go.mod h1:C9/l9PnB1+mwPa26BBVpCjG/XQCB0yj/q5CK2J8X1I4= github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= @@ -339,8 +336,8 @@ github.com/filecoin-project/go-fil-commcid v0.1.0 h1:3R4ds1A9r6cr8mvZBfMYxTS88Oq github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7LXep5bFEVOVmQWHJvl2mgsGo= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8= -github.com/filecoin-project/go-fil-markets v1.19.1-0.20220126115144-06ec15036195 h1:IgKgvwi63bhOGvg+2BmYVRK+XEgS/YaEJMzSbY/RAiM= -github.com/filecoin-project/go-fil-markets v1.19.1-0.20220126115144-06ec15036195/go.mod h1:SmDIzoUwFlej6Ac5ilBMyBImTj/TrmJmZ6wh/ILMfuI= +github.com/filecoin-project/go-fil-markets v1.19.1-0.20220202115512-c1c9ba8722ac h1:5k1TVKQzIcI+/ZA9i7u2Lq4JVRlWxYj7qKAWO4ltZZA= +github.com/filecoin-project/go-fil-markets v1.19.1-0.20220202115512-c1c9ba8722ac/go.mod h1:gnZw2JAtaGcAwGA7ASD3cvO7Laz1N06VLP9FVEQfnRg= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= @@ -349,17 +346,13 @@ github.com/filecoin-project/go-hamt-ipld/v3 v3.0.1/go.mod h1:gXpNmr3oQx8l3o7qkGy github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0 h1:rVVNq0x6RGQIzCo1iiJlGFm9AGIZzeifggxtKMU7zmI= github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0/go.mod h1:bxmzgT8tmeVQA1/gvBwFmYdT8SOFUwB3ovSUfG1Ux0g= github.com/filecoin-project/go-indexer-core v0.2.4/go.mod h1:MSe5aRWmfRB+5syR4yDV+OApgJU+MUJ4rl9VUuzwCfc= -github.com/filecoin-project/go-indexer-core v0.2.7/go.mod h1:6YD7KwDOQ+03DdAitviL7h1fksIU6a4j52yPnA/E1PU= github.com/filecoin-project/go-indexer-core v0.2.8 h1:h1SRdZKTVcaXlzex3UevHh4OWDAhgpMzL4tHNAA7MQI= github.com/filecoin-project/go-indexer-core v0.2.8/go.mod h1:IagNfTdFuX4057kla43PjRCn3yBuUiZgIxuA0hTUamY= github.com/filecoin-project/go-jsonrpc v0.1.5 h1:ckxqZ09ivBAVf5CSmxxrqqNHC7PJm3GYGtYKiNQ+vGk= github.com/filecoin-project/go-jsonrpc v0.1.5/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4= -github.com/filecoin-project/go-legs v0.2.1/go.mod h1:iHDfdqieReblkLoHneB68wvthFtNKB+wkeEWKtiJESk= -github.com/filecoin-project/go-legs v0.2.2/go.mod h1:mdNMISV/bWyZguFM7R4s0mxV1v6Vhda3BiAw9+jv5iE= github.com/filecoin-project/go-legs v0.2.7 h1:+b1BQv4QKkRNsDUE8Z4sEhLXhfVQ+iGpHhANpYqxJlA= github.com/filecoin-project/go-legs v0.2.7/go.mod h1:NrdELuDbtAH8/xqRMgyOYms67aliQajExInLS6g8zFM= github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20/go.mod h1:mPn+LRRd5gEKNAtc+r3ScpW2JRU/pj4NBKdADYWHiak= -github.com/filecoin-project/go-padreader v0.0.0-20210723183308-812a16dc01b1/go.mod h1:VYVPJqwpsfmtoHnAmPx6MUwmrK6HIcDqZJiuZhtmfLQ= github.com/filecoin-project/go-padreader v0.0.1 h1:8h2tVy5HpoNbr2gBRr+WD6zV6VD6XHig+ynSGJg8ZOs= github.com/filecoin-project/go-padreader v0.0.1/go.mod h1:VYVPJqwpsfmtoHnAmPx6MUwmrK6HIcDqZJiuZhtmfLQ= github.com/filecoin-project/go-paramfetch v0.0.3-0.20220111000201-e42866db1a53 h1:+nripp+UI/rhl01w9Gs4V0XDGaVPYPMGU/D/gNVLue0= @@ -368,7 +361,6 @@ github.com/filecoin-project/go-state-types v0.0.0-20200903145444-247639ffa6ad/go github.com/filecoin-project/go-state-types v0.0.0-20200928172055-2df22083d8ab/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-state-types v0.0.0-20201102161440-c8033295a1fc/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-state-types v0.1.0/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= -github.com/filecoin-project/go-state-types v0.1.1-0.20210506134452-99b279731c48/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-state-types v0.1.1-0.20210810190654-139e0e79e69e/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-state-types v0.1.1/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-state-types v0.1.3 h1:rzIJyQo5HO2ptc8Jcu8P0qTutnI7NWwTle54eAHoNO0= @@ -381,7 +373,6 @@ github.com/filecoin-project/go-statestore v0.2.0 h1:cRRO0aPLrxKQCZ2UOQbzFGn4WDNd github.com/filecoin-project/go-statestore v0.2.0/go.mod h1:8sjBYbS35HwPzct7iT4lIXjLlYyPor80aU7t7a/Kspo= github.com/filecoin-project/go-storedcounter v0.1.0 h1:Mui6wSUBC+cQGHbDUBcO7rfh5zQkWJM/CpAZa/uOuus= github.com/filecoin-project/go-storedcounter v0.1.0/go.mod h1:4ceukaXi4vFURIoxYMfKzaRF5Xv/Pinh2oTnoxpv+z8= -github.com/filecoin-project/index-provider v0.2.1/go.mod h1:T3Ct7dqS7GDtotzFk/cNe0fzhoPLLk8htiXMK+xQfHU= github.com/filecoin-project/index-provider v0.2.6 h1:JodDoTiLjDPifRxKSgoyDwD8qzbSZDcyn5IPF0osVAg= github.com/filecoin-project/index-provider v0.2.6/go.mod h1:y87dsIQdcmQS5PWIcifQdRb454ViVxjjFEccMDswIjQ= github.com/filecoin-project/specs-actors v0.9.13/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= @@ -407,8 +398,6 @@ github.com/filecoin-project/specs-actors/v7 v7.0.0-rc1 h1:FuDaXIbcw2hRsFI8SDTmsG github.com/filecoin-project/specs-actors/v7 v7.0.0-rc1/go.mod h1:TA5FwCna+Yi36POaT7SLKXsgEDvJwc0V/L6ZsO19B9M= github.com/filecoin-project/specs-storage v0.1.1-0.20211228030229-6d460d25a0c9 h1:oUYOvF7EvdXS0Zmk9mNkaB6Bu0l+WXBYPzVodKMiLug= github.com/filecoin-project/specs-storage v0.1.1-0.20211228030229-6d460d25a0c9/go.mod h1:Tb88Zq+IBJbvAn3mS89GYj3jdRThBTE/771HCVZdRJU= -github.com/filecoin-project/storetheindex v0.2.2/go.mod h1:05vxs5u3vTQFAwGW9+pgWSMc3BgFOK513nPyIQyLwyQ= -github.com/filecoin-project/storetheindex v0.2.3/go.mod h1:US7ddOKCI+KQFcC3ipKuhK3i46EYlSCt5EvPhxBLfWI= github.com/filecoin-project/storetheindex v0.3.0 h1:M9C4BFLCKn6FJn2N/8q0VbX00hEjEWUuvJpscqKwqzQ= github.com/filecoin-project/storetheindex v0.3.0/go.mod h1:GhUmP8+nINxDRUqxQvTc3Fqc7Yp6w0dW/uTaYYIzd68= github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg= @@ -710,7 +699,6 @@ github.com/ipfs/go-block-format v0.0.3 h1:r8t66QstRp/pd/or4dpnbVfXT5Gt7lOqRvC+/d github.com/ipfs/go-block-format v0.0.3/go.mod h1:4LmD4ZUw0mhO+JSKdpWwrzATiEfM7WWgQ8H5l6P8MVk= github.com/ipfs/go-blockservice v0.0.7/go.mod h1:EOfb9k/Y878ZTRY/CH0x5+ATtaipfbRhbvNSdgc/7So= github.com/ipfs/go-blockservice v0.1.0/go.mod h1:hzmMScl1kXHg3M2BjTymbVPjv627N7sYcvYaKbop39M= -github.com/ipfs/go-blockservice v0.1.3/go.mod h1:OTZhFpkgY48kNzbgyvcexW9cHrpjBYIjSR0KoDOFOLU= github.com/ipfs/go-blockservice v0.1.4/go.mod h1:OTZhFpkgY48kNzbgyvcexW9cHrpjBYIjSR0KoDOFOLU= github.com/ipfs/go-blockservice v0.1.7/go.mod h1:GmS+BAt4hrwBKkzE11AFDQUrnvqjwFatGS2MY7wOjEM= github.com/ipfs/go-blockservice v0.2.1 h1:NJ4j/cwEfIg60rzAWcCIxRtOwbf6ZPK49MewNxObCPQ= @@ -738,8 +726,6 @@ github.com/ipfs/go-datastore v0.4.1/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13X github.com/ipfs/go-datastore v0.4.2/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= github.com/ipfs/go-datastore v0.4.4/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= github.com/ipfs/go-datastore v0.4.5/go.mod h1:eXTcaaiN6uOlVCLS9GjJUJtlvJfM3xk23w3fyfrmmJs= -github.com/ipfs/go-datastore v0.4.6/go.mod h1:XSipLSc64rFKSFRFGo1ecQl+WhYce3K7frtpHkyPFUc= -github.com/ipfs/go-datastore v0.4.7-0.20211013204805-28a3721c2e66/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk= github.com/ipfs/go-datastore v0.5.0/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk= github.com/ipfs/go-datastore v0.5.1 h1:WkRhLuISI+XPD0uk3OskB0fYFSyqK8Ob5ZYew9Qa1nQ= github.com/ipfs/go-datastore v0.5.1/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk= @@ -750,7 +736,6 @@ github.com/ipfs/go-ds-badger v0.0.5/go.mod h1:g5AuuCGmr7efyzQhLL8MzwqcauPojGPUaH github.com/ipfs/go-ds-badger v0.0.7/go.mod h1:qt0/fWzZDoPW6jpQeqUjR5kBfhDNB65jd9YlmAvpQBk= github.com/ipfs/go-ds-badger v0.2.1/go.mod h1:Tx7l3aTph3FMFrRS838dcSJh+jjA7cX9DrGVwx/NOwE= github.com/ipfs/go-ds-badger v0.2.3/go.mod h1:pEYw0rgg3FIrywKKnL+Snr+w/LjJZVMTBRn4FS6UHUk= -github.com/ipfs/go-ds-badger v0.2.6/go.mod h1:02rnztVKA4aZwDuaRPTf8mpqcKmXP7mLl6JPxd14JHA= github.com/ipfs/go-ds-badger v0.2.7/go.mod h1:02rnztVKA4aZwDuaRPTf8mpqcKmXP7mLl6JPxd14JHA= github.com/ipfs/go-ds-badger v0.3.0 h1:xREL3V0EH9S219kFFueOYJJTcjgNSZ2HY1iSvN7U1Ro= github.com/ipfs/go-ds-badger v0.3.0/go.mod h1:1ke6mXNqeV8K3y5Ak2bAA0osoTfmxUdupVCGm4QUIek= @@ -773,9 +758,7 @@ github.com/ipfs/go-filestore v1.1.0/go.mod h1:6e1/5Y6NvLuCRdmda/KA4GUhXJQ3Uat6vc github.com/ipfs/go-fs-lock v0.0.6/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28L7zESmM= github.com/ipfs/go-fs-lock v0.0.7 h1:6BR3dajORFrFTkb5EpCUFIAypsoxpGpDSVUdFwzgL9U= github.com/ipfs/go-fs-lock v0.0.7/go.mod h1:Js8ka+FNYmgQRLrRXzU3CB/+Csr1BwrRilEcvYrHhhc= -github.com/ipfs/go-graphsync v0.10.0/go.mod h1:cKIshzTaa5rCZjryH5xmSKZVGX9uk1wvwGvz2WEha5Y= github.com/ipfs/go-graphsync v0.11.0/go.mod h1:wC+c8vGVjAHthsVIl8LKr37cUra2GOaMYcQNNmMxDqE= -github.com/ipfs/go-graphsync v0.11.5/go.mod h1:+/sZqRwRCQRrV7NCzgBtufmr5QGpUE98XSa7NlsztmM= github.com/ipfs/go-graphsync v0.12.0 h1:QCsVHVzb9FTkcm3NEa8GjXnUeGit1L9s08HcSVQ4m/g= github.com/ipfs/go-graphsync v0.12.0/go.mod h1:nASYWYETgsnMbQ3+DirNImOHQ8TY0a5AhAqyOY55tUg= github.com/ipfs/go-ipfs v0.11.0/go.mod h1:g68Thu2Ho11AWoHsN34P5fSK7iA6OWWRy3T/g8HLixc= @@ -784,10 +767,8 @@ github.com/ipfs/go-ipfs-blockstore v0.1.0/go.mod h1:5aD0AvHPi7mZc6Ci1WCAhiBQu2Is github.com/ipfs/go-ipfs-blockstore v0.1.4/go.mod h1:Jxm3XMVjh6R17WvxFEiyKBLUGr86HgIYJW/D/MwqeYQ= github.com/ipfs/go-ipfs-blockstore v0.1.6/go.mod h1:Jxm3XMVjh6R17WvxFEiyKBLUGr86HgIYJW/D/MwqeYQ= github.com/ipfs/go-ipfs-blockstore v0.2.1/go.mod h1:jGesd8EtCM3/zPgx+qr0/feTXGUeRai6adgwC+Q+JvE= -github.com/ipfs/go-ipfs-blockstore v1.0.1/go.mod h1:MGNZlHNEnR4KGgPHM3/k8lBySIOK2Ve+0KjZubKlaOE= github.com/ipfs/go-ipfs-blockstore v1.0.4-0.20210205083733-fb07d7bc5aec/go.mod h1:feuklK+m9POeWJzYQO7l05yNEgUiX5oELBNA8/Be33E= github.com/ipfs/go-ipfs-blockstore v1.0.4/go.mod h1:uL7/gTJ8QIZ3MtA3dWf+s1a0U3fJy2fcEZAsovpRp+w= -github.com/ipfs/go-ipfs-blockstore v1.1.0/go.mod h1:5QDUApRqpgPcfGstCxYeMnjt/DYQtXXdJVCvxHHuWVk= github.com/ipfs/go-ipfs-blockstore v1.1.1/go.mod h1:w51tNR9y5+QXB0wkNcHt4O2aSZjTdqaEWaQdSxEyUOY= github.com/ipfs/go-ipfs-blockstore v1.1.2 h1:WCXoZcMYnvOTmlpX+RSSnhVN0uCmbWTeepTGX5lgiXw= github.com/ipfs/go-ipfs-blockstore v1.1.2/go.mod h1:w51tNR9y5+QXB0wkNcHt4O2aSZjTdqaEWaQdSxEyUOY= @@ -938,7 +919,6 @@ github.com/ipld/go-ipld-prime v0.14.0/go.mod h1:9ASQLwUFLptCov6lIYc70GRB4V7UTyLD github.com/ipld/go-ipld-prime v0.14.1/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= github.com/ipld/go-ipld-prime v0.14.2/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= github.com/ipld/go-ipld-prime v0.14.3-0.20211207234443-319145880958/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= -github.com/ipld/go-ipld-prime v0.14.3/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= github.com/ipld/go-ipld-prime v0.14.4 h1:bqhmume8+nbNsX4/+J6eohktfZHAI8GKrF3rQ0xgOyc= github.com/ipld/go-ipld-prime v0.14.4/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= github.com/ipld/go-ipld-prime-proto v0.0.0-20191113031812-e32bd156a1e5/go.mod h1:gcvzoEDBjwycpXt3LBE061wT9f46szXGHAmj9uoP6fU= @@ -1079,7 +1059,6 @@ github.com/libp2p/go-libp2p v0.13.0/go.mod h1:pM0beYdACRfHO1WcJlp65WXyG2A6NqYM+t github.com/libp2p/go-libp2p v0.14.0/go.mod h1:dsQrWLAoIn+GkHPN/U+yypizkHiB9tnv79Os+kSgQ4Q= github.com/libp2p/go-libp2p v0.14.3/go.mod h1:d12V4PdKbpL0T1/gsUNN8DfgMuRPDX8bS2QxCZlwRH0= github.com/libp2p/go-libp2p v0.14.4/go.mod h1:EIRU0Of4J5S8rkockZM7eJp2S0UrCyi55m2kJVru3rM= -github.com/libp2p/go-libp2p v0.15.0/go.mod h1:8Ljmwon0cZZYKrOCjFeLwQEK8bqR42dOheUZ1kSKhP0= github.com/libp2p/go-libp2p v0.16.0/go.mod h1:ump42BsirwAWxKzsCiFnTtN1Yc+DuPu76fyMX364/O4= github.com/libp2p/go-libp2p v0.17.0/go.mod h1:Fkin50rsGdv5mm5BshBUtPRZknt9esfmYXBOYcwOTgw= github.com/libp2p/go-libp2p v0.18.0-rc1/go.mod h1:RgYlH7IIWHXREimC92bw5Lg1V2R5XmSzuLHb5fTnr+8= @@ -1165,7 +1144,6 @@ github.com/libp2p/go-libp2p-discovery v0.1.0/go.mod h1:4F/x+aldVHjHDHuX85x1zWoFT github.com/libp2p/go-libp2p-discovery v0.2.0/go.mod h1:s4VGaxYMbw4+4+tsoQTqh7wfxg97AEdo4GYBt6BadWg= github.com/libp2p/go-libp2p-discovery v0.3.0/go.mod h1:o03drFnz9BVAZdzC/QUQ+NeQOu38Fu7LJGEOK2gQltw= github.com/libp2p/go-libp2p-discovery v0.5.0/go.mod h1:+srtPIU9gDaBNu//UHvcdliKBIcr4SfDcm0/PfPJLug= -github.com/libp2p/go-libp2p-discovery v0.5.1/go.mod h1:+srtPIU9gDaBNu//UHvcdliKBIcr4SfDcm0/PfPJLug= github.com/libp2p/go-libp2p-discovery v0.6.0 h1:1XdPmhMJr8Tmj/yUfkJMIi8mgwWrLUsCB3bMxdT+DSo= github.com/libp2p/go-libp2p-discovery v0.6.0/go.mod h1:/u1voHt0tKIe5oIA1RHBKQLVCWPna2dXmPNHc2zR9S8= github.com/libp2p/go-libp2p-gostream v0.3.0/go.mod h1:pLBQu8db7vBMNINGsAwLL/ZCE8wng5V1FThoaE5rNjc= @@ -1211,7 +1189,6 @@ github.com/libp2p/go-libp2p-netutil v0.1.0 h1:zscYDNVEcGxyUpMd0JReUZTrpMfia8PmLK github.com/libp2p/go-libp2p-netutil v0.1.0/go.mod h1:3Qv/aDqtMLTUyQeundkKsA+YCThNdbQD54k3TqjpbFU= github.com/libp2p/go-libp2p-noise v0.1.1/go.mod h1:QDFLdKX7nluB7DEnlVPbz7xlLHdwHFA9HiohJRr3vwM= github.com/libp2p/go-libp2p-noise v0.2.0/go.mod h1:IEbYhBBzGyvdLBoxxULL/SGbJARhUeqlO8lVSREYu2Q= -github.com/libp2p/go-libp2p-noise v0.2.2/go.mod h1:IEbYhBBzGyvdLBoxxULL/SGbJARhUeqlO8lVSREYu2Q= github.com/libp2p/go-libp2p-noise v0.3.0 h1:NCVH7evhVt9njbTQshzT7N1S3Q6fjj9M11FCgfH5+cA= github.com/libp2p/go-libp2p-noise v0.3.0/go.mod h1:JNjHbociDJKHD64KTkzGnzqJ0FEV5gHJa6AB00kbCNQ= github.com/libp2p/go-libp2p-peer v0.0.1/go.mod h1:nXQvOBbwVqoP+T5Y5nCjeH4sP9IX/J0AMzcDUVruVoo= @@ -1236,7 +1213,6 @@ github.com/libp2p/go-libp2p-pnet v0.2.0/go.mod h1:Qqvq6JH/oMZGwqs3N1Fqhv8NVhrdYc github.com/libp2p/go-libp2p-protocol v0.0.1/go.mod h1:Af9n4PiruirSDjHycM1QuiMi/1VZNHYcK8cLgFJLZ4s= github.com/libp2p/go-libp2p-protocol v0.1.0/go.mod h1:KQPHpAabB57XQxGrXCNvbL6UEXfQqUgC/1adR2Xtflk= github.com/libp2p/go-libp2p-pubsub v0.1.1/go.mod h1:ZwlKzRSe1eGvSIdU5bD7+8RZN/Uzw0t1Bp9R1znpR/Q= -github.com/libp2p/go-libp2p-pubsub v0.5.6/go.mod h1:gVOzwebXVdSMDQBTfH8ACO5EJ4SQrvsHqCmYsCZpD0E= github.com/libp2p/go-libp2p-pubsub v0.6.0/go.mod h1:nJv87QM2cU0w45KPR1rZicq+FmFIOD16zmT+ep1nOmg= github.com/libp2p/go-libp2p-pubsub v0.6.1 h1:wycbV+f4rreCoVY61Do6g/BUk0RIrbNRcYVbn+QkjGk= github.com/libp2p/go-libp2p-pubsub v0.6.1/go.mod h1:nJv87QM2cU0w45KPR1rZicq+FmFIOD16zmT+ep1nOmg= @@ -1298,7 +1274,6 @@ github.com/libp2p/go-libp2p-testing v0.6.0/go.mod h1:QBk8fqIL1XNcno/l3/hhaIEn4aL github.com/libp2p/go-libp2p-testing v0.7.0 h1:9bfyhNINizxuLrKsenzGaZalXRXIaAEmx1BP/PzF1gM= github.com/libp2p/go-libp2p-testing v0.7.0/go.mod h1:OLbdn9DbgdMwv00v+tlp1l3oe2Cl+FAjoWIA2pa0X6E= github.com/libp2p/go-libp2p-tls v0.1.3/go.mod h1:wZfuewxOndz5RTnCAxFliGjvYSDA40sKitV4c50uI1M= -github.com/libp2p/go-libp2p-tls v0.2.0/go.mod h1:twrp2Ci4lE2GYspA1AnlYm+boYjqVruxDKJJj7s6xrc= github.com/libp2p/go-libp2p-tls v0.3.0/go.mod h1:fwF5X6PWGxm6IDRwF3V8AVCCj/hOd5oFlg+wo2FxJDY= github.com/libp2p/go-libp2p-tls v0.3.1 h1:lsE2zYte+rZCEOHF72J1Fg3XK3dGQyKvI6i5ehJfEp0= github.com/libp2p/go-libp2p-tls v0.3.1/go.mod h1:fwF5X6PWGxm6IDRwF3V8AVCCj/hOd5oFlg+wo2FxJDY= @@ -1401,7 +1376,6 @@ github.com/libp2p/go-tcp-transport v0.2.1/go.mod h1:zskiJ70MEfWz2MKxvFB/Pv+tPIB1 github.com/libp2p/go-tcp-transport v0.2.3/go.mod h1:9dvr03yqrPyYGIEN6Dy5UvdJZjyPFvl1S/igQ5QD1SU= github.com/libp2p/go-tcp-transport v0.2.4/go.mod h1:9dvr03yqrPyYGIEN6Dy5UvdJZjyPFvl1S/igQ5QD1SU= github.com/libp2p/go-tcp-transport v0.2.7/go.mod h1:lue9p1b3VmZj1MhhEGB/etmvF/nBQ0X9CW2DutBT3MM= -github.com/libp2p/go-tcp-transport v0.2.8/go.mod h1:64rSfVidkYPLqbzpcN2IwHY4pmgirp67h++hZ/rcndQ= github.com/libp2p/go-tcp-transport v0.4.0/go.mod h1:0y52Rwrn4076xdJYu/51/qJIdxz+EWDAOG2S45sV3VI= github.com/libp2p/go-tcp-transport v0.5.0 h1:3ZPW8HAuyRAuFzyabE0hSrCXKKSWzROnZZX7DtcIatY= github.com/libp2p/go-tcp-transport v0.5.0/go.mod h1:UPPL0DIjQqiWRwVAb+CEQlaAG0rp/mCqJfIhFcLHc4Y= @@ -1434,7 +1408,6 @@ github.com/libp2p/go-yamux/v2 v2.3.0/go.mod h1:iTU+lOIn/2h0AgKcL49clNTwfEw+WSfDY github.com/libp2p/go-yamux/v3 v3.0.1/go.mod h1:s2LsDhHbh+RfCsQoICSYt58U2f8ijtPANFD8BmE74Bo= github.com/libp2p/go-yamux/v3 v3.0.2 h1:LW0q5+A1Wy0npEsPJP9wmare2NH4ohNluN5EWVwv2mE= github.com/libp2p/go-yamux/v3 v3.0.2/go.mod h1:s2LsDhHbh+RfCsQoICSYt58U2f8ijtPANFD8BmE74Bo= -github.com/libp2p/zeroconf/v2 v2.0.0/go.mod h1:J85R/d9joD8u8F9aHM8pBXygtG9W02enEwS+wWeL6yo= github.com/libp2p/zeroconf/v2 v2.1.1/go.mod h1:fuJqLnUwZTshS3U/bMRJ3+ow/v9oid1n0DmyYyNO1Xs= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= @@ -1956,7 +1929,6 @@ github.com/whyrusleeping/cbor-gen v0.0.0-20200826160007-0b9f6c5fb163/go.mod h1:f github.com/whyrusleeping/cbor-gen v0.0.0-20210118024343-169e9d70c0c2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20210219115102-f37d292932f2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20210303213153-67a261a1d291/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= -github.com/whyrusleeping/cbor-gen v0.0.0-20210713220151-be142a5ae1a8/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20211110122933-f57984553008 h1:7WtW9D9VGpmRLuQmrPy2JobUNdka95z3MKEVpELtOjo= github.com/whyrusleeping/cbor-gen v0.0.0-20211110122933-f57984553008/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E= @@ -2185,7 +2157,6 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -2464,7 +2435,6 @@ golang.org/x/tools v0.0.0-20201112185108-eeaa07dd7696/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1-0.20210225150353-54dc8c5edb56/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index 34b27d9d75f..c8a30b9d656 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -611,6 +611,11 @@ func StorageProvider(minerAddress dtypes.MinerAddress, opt := storageimpl.CustomDealDecisionLogic(storageimpl.DealDeciderFunc(df)) + ai, err := fullnodeApi.NetAddrsListen(context.Background()) + if err != nil { + return nil, err + } + return storageimpl.NewProvider( net, namespace.Wrap(ds, datastore.NewKey("/deals/provider")), @@ -622,7 +627,7 @@ func StorageProvider(minerAddress dtypes.MinerAddress, spn, address.Address(minerAddress), storedAsk, - fullnodeApi, + ai, idxProvHost.Host, opt, ) From 79403f169e44da63cbf493e7d1ef0f8f0d542429 Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Wed, 2 Feb 2022 13:18:53 +0100 Subject: [PATCH 078/385] fix autogenerated docs --- documentation/en/default-lotus-miner-config.toml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/documentation/en/default-lotus-miner-config.toml b/documentation/en/default-lotus-miner-config.toml index 345a2b91cdb..f6f3e1d689a 100644 --- a/documentation/en/default-lotus-miner-config.toml +++ b/documentation/en/default-lotus-miner-config.toml @@ -270,6 +270,9 @@ # env var: LOTUS_INDEXERPROVIDER_PURGELINKCACHE #PurgeLinkCache = false + # env var: LOTUS_INDEXERPROVIDER_PUBLISHERKIND + #PublisherKind = "dtsync" + # Binding address for the libp2p host - 0 means random port. # Format: multiaddress; see https://multiformats.io/multiaddr/ # @@ -292,6 +295,10 @@ # env var: LOTUS_INDEXERPROVIDER_MAXSIMULTANEOUSTRANSFERS #MaxSimultaneousTransfers = 20 + [IndexerProvider.HttpPublisher] + # env var: LOTUS_INDEXERPROVIDER_HTTPPUBLISHER_LISTENMULTIADDR + #ListenMultiaddr = "/ip4/0.0.0.0/tcp/3104/http" + [Sealing] # Upper bound on how many sectors can be waiting for more deals to be packed in it before it begins sealing at any given time. From 03dd33dbbe784e9d759c625446ca14757190e342 Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Wed, 2 Feb 2022 14:07:41 +0100 Subject: [PATCH 079/385] upgrade go-fil-markets --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 970e0d1647c..cf587739217 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,7 @@ require ( github.com/filecoin-project/go-data-transfer v1.14.0 github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 - github.com/filecoin-project/go-fil-markets v1.19.1-0.20220202115512-c1c9ba8722ac + github.com/filecoin-project/go-fil-markets v1.19.1-0.20220202130458-93e4c64218c2 github.com/filecoin-project/go-indexer-core v0.2.8 github.com/filecoin-project/go-jsonrpc v0.1.5 github.com/filecoin-project/go-padreader v0.0.1 diff --git a/go.sum b/go.sum index 5ba5e5e6432..bc1d2b46acc 100644 --- a/go.sum +++ b/go.sum @@ -338,6 +338,8 @@ github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7L github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8= github.com/filecoin-project/go-fil-markets v1.19.1-0.20220202115512-c1c9ba8722ac h1:5k1TVKQzIcI+/ZA9i7u2Lq4JVRlWxYj7qKAWO4ltZZA= github.com/filecoin-project/go-fil-markets v1.19.1-0.20220202115512-c1c9ba8722ac/go.mod h1:gnZw2JAtaGcAwGA7ASD3cvO7Laz1N06VLP9FVEQfnRg= +github.com/filecoin-project/go-fil-markets v1.19.1-0.20220202130458-93e4c64218c2 h1:00InEPicixNXm0Ovvy0u8EpWrNgXkxLQ64SImOn9MR4= +github.com/filecoin-project/go-fil-markets v1.19.1-0.20220202130458-93e4c64218c2/go.mod h1:gnZw2JAtaGcAwGA7ASD3cvO7Laz1N06VLP9FVEQfnRg= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= From faa3a79a5f0fd734703bac4686127673f0b08437 Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Wed, 2 Feb 2022 16:01:19 +0100 Subject: [PATCH 080/385] use NetAddrListener iface --- node/modules/storageminer.go | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index c8a30b9d656..34b27d9d75f 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -611,11 +611,6 @@ func StorageProvider(minerAddress dtypes.MinerAddress, opt := storageimpl.CustomDealDecisionLogic(storageimpl.DealDeciderFunc(df)) - ai, err := fullnodeApi.NetAddrsListen(context.Background()) - if err != nil { - return nil, err - } - return storageimpl.NewProvider( net, namespace.Wrap(ds, datastore.NewKey("/deals/provider")), @@ -627,7 +622,7 @@ func StorageProvider(minerAddress dtypes.MinerAddress, spn, address.Address(minerAddress), storedAsk, - ai, + fullnodeApi, idxProvHost.Host, opt, ) From c3d41d4e17a07fb38e5fb2ebbb15f29abcab9047 Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Wed, 2 Feb 2022 16:12:28 +0100 Subject: [PATCH 081/385] upgrade go-fil-markets --- go.mod | 2 +- go.sum | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index cf587739217..b1720761287 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,7 @@ require ( github.com/filecoin-project/go-data-transfer v1.14.0 github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 - github.com/filecoin-project/go-fil-markets v1.19.1-0.20220202130458-93e4c64218c2 + github.com/filecoin-project/go-fil-markets v1.19.1-0.20220202151058-ea0c8f1c8630 github.com/filecoin-project/go-indexer-core v0.2.8 github.com/filecoin-project/go-jsonrpc v0.1.5 github.com/filecoin-project/go-padreader v0.0.1 diff --git a/go.sum b/go.sum index bc1d2b46acc..a3753f8d1f1 100644 --- a/go.sum +++ b/go.sum @@ -336,10 +336,8 @@ github.com/filecoin-project/go-fil-commcid v0.1.0 h1:3R4ds1A9r6cr8mvZBfMYxTS88Oq github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7LXep5bFEVOVmQWHJvl2mgsGo= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8= -github.com/filecoin-project/go-fil-markets v1.19.1-0.20220202115512-c1c9ba8722ac h1:5k1TVKQzIcI+/ZA9i7u2Lq4JVRlWxYj7qKAWO4ltZZA= -github.com/filecoin-project/go-fil-markets v1.19.1-0.20220202115512-c1c9ba8722ac/go.mod h1:gnZw2JAtaGcAwGA7ASD3cvO7Laz1N06VLP9FVEQfnRg= -github.com/filecoin-project/go-fil-markets v1.19.1-0.20220202130458-93e4c64218c2 h1:00InEPicixNXm0Ovvy0u8EpWrNgXkxLQ64SImOn9MR4= -github.com/filecoin-project/go-fil-markets v1.19.1-0.20220202130458-93e4c64218c2/go.mod h1:gnZw2JAtaGcAwGA7ASD3cvO7Laz1N06VLP9FVEQfnRg= +github.com/filecoin-project/go-fil-markets v1.19.1-0.20220202151058-ea0c8f1c8630 h1:h46LVtyElHCjLt7JtIPHjLId+H65izL0ytZ9EC/hA44= +github.com/filecoin-project/go-fil-markets v1.19.1-0.20220202151058-ea0c8f1c8630/go.mod h1:gnZw2JAtaGcAwGA7ASD3cvO7Laz1N06VLP9FVEQfnRg= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= From 008fbbd652326a878e6848d3a922eb8efbd0f171 Mon Sep 17 00:00:00 2001 From: Darko Brdareski Date: Wed, 2 Feb 2022 17:08:50 +0100 Subject: [PATCH 082/385] Add unit and integration tests for mempool --- chain/messagepool/check_test.go | 224 +++++++++++++ chain/messagepool/messagepool_test.go | 299 +++++++++++++++++ chain/messagepool/repub_test.go | 3 + chain/messagepool/selection_test.go | 26 ++ itests/mempool_test.go | 455 ++++++++++++++++++++++++++ 5 files changed, 1007 insertions(+) create mode 100644 chain/messagepool/check_test.go create mode 100644 itests/mempool_test.go diff --git a/chain/messagepool/check_test.go b/chain/messagepool/check_test.go new file mode 100644 index 00000000000..ffcac74e5d0 --- /dev/null +++ b/chain/messagepool/check_test.go @@ -0,0 +1,224 @@ +//stm: #unit +package messagepool + +import ( + "context" + "fmt" + "testing" + + "github.com/ipfs/go-datastore" + logging "github.com/ipfs/go-log/v2" + "github.com/stretchr/testify/assert" + + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/consensus/filcns" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/chain/types/mock" + "github.com/filecoin-project/lotus/chain/wallet" + _ "github.com/filecoin-project/lotus/lib/sigs/bls" + _ "github.com/filecoin-project/lotus/lib/sigs/secp" +) + +func init() { + _ = logging.SetLogLevel("*", "INFO") +} + +func getCheckMessageStatus(statusCode api.CheckStatusCode, msgStatuses []api.MessageCheckStatus) (*api.MessageCheckStatus, error) { + for i := 0; i < len(msgStatuses); i++ { + iMsgStatuses := msgStatuses[i] + if iMsgStatuses.CheckStatus.Code == statusCode { + return &iMsgStatuses, nil + } + } + return nil, fmt.Errorf("Could not find CheckStatusCode %s", statusCode) +} + +func TestCheckMessages(t *testing.T) { + //stm: @CHAIN_MEMPOOL_CHECK_MESSAGES_001 + tma := newTestMpoolAPI() + + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + if err != nil { + t.Fatal(err) + } + + ds := datastore.NewMapDatastore() + + mp, err := New(context.Background(), tma, ds, filcns.DefaultUpgradeSchedule(), "mptest", nil) + if err != nil { + t.Fatal(err) + } + + sender, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + + tma.setBalance(sender, 1000e15) + target := mock.Address(1001) + + var protos []*api.MessagePrototype + for i := 0; i < 5; i++ { + msg := &types.Message{ + To: target, + From: sender, + Value: types.NewInt(1), + Nonce: uint64(i), + GasLimit: 50000000, + GasFeeCap: types.NewInt(minimumBaseFee.Uint64()), + GasPremium: types.NewInt(1), + Params: make([]byte, 2<<10), + } + proto := &api.MessagePrototype{ + Message: *msg, + ValidNonce: true, + } + protos = append(protos, proto) + } + + messageStatuses, err := mp.CheckMessages(context.TODO(), protos) + assert.NoError(t, err) + for i := 0; i < len(messageStatuses); i++ { + iMsgStatuses := messageStatuses[i] + for j := 0; j < len(iMsgStatuses); j++ { + jStatus := iMsgStatuses[i] + assert.True(t, jStatus.OK) + } + } +} + +func TestCheckPendingMessages(t *testing.T) { + //stm: @CHAIN_MEMPOOL_CHECK_PENDING_MESSAGES_001 + tma := newTestMpoolAPI() + + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + if err != nil { + t.Fatal(err) + } + + ds := datastore.NewMapDatastore() + + mp, err := New(context.Background(), tma, ds, filcns.DefaultUpgradeSchedule(), "mptest", nil) + if err != nil { + t.Fatal(err) + } + + sender, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + + tma.setBalance(sender, 1000e15) + target := mock.Address(1001) + + // add a valid message to the pool + msg := &types.Message{ + To: target, + From: sender, + Value: types.NewInt(1), + Nonce: 0, + GasLimit: 50000000, + GasFeeCap: types.NewInt(minimumBaseFee.Uint64()), + GasPremium: types.NewInt(1), + Params: make([]byte, 2<<10), + } + + sig, err := w.WalletSign(context.TODO(), sender, msg.Cid().Bytes(), api.MsgMeta{}) + if err != nil { + panic(err) + } + sm := &types.SignedMessage{ + Message: *msg, + Signature: *sig, + } + mustAdd(t, mp, sm) + + messageStatuses, err := mp.CheckPendingMessages(context.TODO(), sender) + assert.NoError(t, err) + for i := 0; i < len(messageStatuses); i++ { + iMsgStatuses := messageStatuses[i] + for j := 0; j < len(iMsgStatuses); j++ { + jStatus := iMsgStatuses[i] + assert.True(t, jStatus.OK) + } + } +} + +func TestCheckReplaceMessages(t *testing.T) { + //stm: @CHAIN_MEMPOOL_CHECK_REPLACE_MESSAGES_001 + tma := newTestMpoolAPI() + + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + if err != nil { + t.Fatal(err) + } + + ds := datastore.NewMapDatastore() + + mp, err := New(context.Background(), tma, ds, filcns.DefaultUpgradeSchedule(), "mptest", nil) + if err != nil { + t.Fatal(err) + } + + sender, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + + tma.setBalance(sender, 1000e15) + target := mock.Address(1001) + + // add a valid message to the pool + msg := &types.Message{ + To: target, + From: sender, + Value: types.NewInt(1), + Nonce: 0, + GasLimit: 50000000, + GasFeeCap: types.NewInt(minimumBaseFee.Uint64()), + GasPremium: types.NewInt(1), + Params: make([]byte, 2<<10), + } + + sig, err := w.WalletSign(context.TODO(), sender, msg.Cid().Bytes(), api.MsgMeta{}) + if err != nil { + panic(err) + } + sm := &types.SignedMessage{ + Message: *msg, + Signature: *sig, + } + mustAdd(t, mp, sm) + + // create a new message with the same data, except that it is too big + var msgs []*types.Message + invalidmsg := &types.Message{ + To: target, + From: sender, + Value: types.NewInt(1), + Nonce: 0, + GasLimit: 50000000, + GasFeeCap: types.NewInt(minimumBaseFee.Uint64()), + GasPremium: types.NewInt(1), + Params: make([]byte, 128<<10), + } + msgs = append(msgs, invalidmsg) + + { + messageStatuses, err := mp.CheckReplaceMessages(context.TODO(), msgs) + if err != nil { + t.Fatal(err) + } + for i := 0; i < len(messageStatuses); i++ { + iMsgStatuses := messageStatuses[i] + + status, err := getCheckMessageStatus(api.CheckStatusMessageSize, iMsgStatuses) + if err != nil { + t.Fatal(err) + } + // the replacement message should cause a status error + assert.False(t, status.OK) + } + } + +} diff --git a/chain/messagepool/messagepool_test.go b/chain/messagepool/messagepool_test.go index 6bd60da34b1..86c3a49d147 100644 --- a/chain/messagepool/messagepool_test.go +++ b/chain/messagepool/messagepool_test.go @@ -9,6 +9,7 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/crypto" "github.com/ipfs/go-cid" "github.com/ipfs/go-datastore" logging "github.com/ipfs/go-log/v2" @@ -226,6 +227,8 @@ func mustAdd(t *testing.T, mp *MessagePool, msg *types.SignedMessage) { } func TestMessagePool(t *testing.T) { + //stm: @CHAIN_MEMPOOL_GET_NONCE_001 + tma := newTestMpoolAPI() w, err := wallet.NewWallet(wallet.NewMemKeyStore()) @@ -327,6 +330,7 @@ func TestCheckMessageBig(t *testing.T) { Message: *msg, Signature: *sig, } + //stm: @CHAIN_MEMPOOL_PUSH_001 err = mp.Add(context.TODO(), sm) assert.ErrorIs(t, err, ErrMessageTooBig) } @@ -760,3 +764,298 @@ func TestUpdates(t *testing.T) { t.Fatal("expected closed channel, but got an update instead") } } + +func TestMessageBelowMinGasFee(t *testing.T) { + //stm: @CHAIN_MEMPOOL_PUSH_001 + tma := newTestMpoolAPI() + + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + assert.NoError(t, err) + + from, err := w.WalletNew(context.Background(), types.KTBLS) + assert.NoError(t, err) + + tma.setBalance(from, 1000e9) + + ds := datastore.NewMapDatastore() + + mp, err := New(context.Background(), tma, ds, filcns.DefaultUpgradeSchedule(), "mptest", nil) + assert.NoError(t, err) + + to := mock.Address(1001) + + // fee is just below minimum gas fee + fee := minimumBaseFee.Uint64() - 1 + { + msg := &types.Message{ + To: to, + From: from, + Value: types.NewInt(1), + Nonce: 0, + GasLimit: 50000000, + GasFeeCap: types.NewInt(fee), + GasPremium: types.NewInt(1), + Params: make([]byte, 32<<10), + } + + sig, err := w.WalletSign(context.TODO(), from, msg.Cid().Bytes(), api.MsgMeta{}) + if err != nil { + panic(err) + } + sm := &types.SignedMessage{ + Message: *msg, + Signature: *sig, + } + err = mp.Add(context.TODO(), sm) + assert.ErrorIs(t, err, ErrGasFeeCapTooLow) + } +} + +func TestMessageValueTooHigh(t *testing.T) { + //stm: @CHAIN_MEMPOOL_PUSH_001 + tma := newTestMpoolAPI() + + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + assert.NoError(t, err) + + from, err := w.WalletNew(context.Background(), types.KTBLS) + assert.NoError(t, err) + + tma.setBalance(from, 1000e9) + + ds := datastore.NewMapDatastore() + + mp, err := New(context.Background(), tma, ds, filcns.DefaultUpgradeSchedule(), "mptest", nil) + assert.NoError(t, err) + + to := mock.Address(1001) + + totalFil := types.TotalFilecoinInt + extra := types.NewInt(1) + + value := types.BigAdd(totalFil, extra) + { + msg := &types.Message{ + To: to, + From: from, + Value: value, + Nonce: 0, + GasLimit: 50000000, + GasFeeCap: types.NewInt(minimumBaseFee.Uint64()), + GasPremium: types.NewInt(1), + Params: make([]byte, 32<<10), + } + + sig, err := w.WalletSign(context.TODO(), from, msg.Cid().Bytes(), api.MsgMeta{}) + if err != nil { + panic(err) + } + sm := &types.SignedMessage{ + Message: *msg, + Signature: *sig, + } + + err = mp.Add(context.TODO(), sm) + assert.Error(t, err) + } +} + +func TestMessageSignatureInvalid(t *testing.T) { + //stm: @CHAIN_MEMPOOL_PUSH_001 + tma := newTestMpoolAPI() + + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + assert.NoError(t, err) + + from, err := w.WalletNew(context.Background(), types.KTBLS) + assert.NoError(t, err) + + tma.setBalance(from, 1000e9) + + ds := datastore.NewMapDatastore() + + mp, err := New(context.Background(), tma, ds, filcns.DefaultUpgradeSchedule(), "mptest", nil) + assert.NoError(t, err) + + to := mock.Address(1001) + + { + msg := &types.Message{ + To: to, + From: from, + Value: types.NewInt(1), + Nonce: 0, + GasLimit: 50000000, + GasFeeCap: types.NewInt(minimumBaseFee.Uint64()), + GasPremium: types.NewInt(1), + Params: make([]byte, 32<<10), + } + + badSig := &crypto.Signature{ + Type: crypto.SigTypeSecp256k1, + Data: make([]byte, 0), + } + sm := &types.SignedMessage{ + Message: *msg, + Signature: *badSig, + } + err = mp.Add(context.TODO(), sm) + assert.Error(t, err) + assert.Contains(t, err.Error(), "invalid signature length") + } +} + +func TestAddMessageTwice(t *testing.T) { + //stm: @CHAIN_MEMPOOL_PUSH_001 + tma := newTestMpoolAPI() + + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + assert.NoError(t, err) + + from, err := w.WalletNew(context.Background(), types.KTBLS) + assert.NoError(t, err) + + tma.setBalance(from, 1000e9) + + ds := datastore.NewMapDatastore() + + mp, err := New(context.Background(), tma, ds, filcns.DefaultUpgradeSchedule(), "mptest", nil) + assert.NoError(t, err) + + to := mock.Address(1001) + + { + // create a valid messages + sm := makeTestMessage(w, from, to, 0, 50_000_000, minimumBaseFee.Uint64()) + mustAdd(t, mp, sm) + + // try to add it twice + err = mp.Add(context.TODO(), sm) + assert.Contains(t, err.Error(), "with nonce 0 already in mpool") + } +} + +func TestAddMessageTwiceNonceGap(t *testing.T) { + //stm: @CHAIN_MEMPOOL_PUSH_001 + tma := newTestMpoolAPI() + + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + assert.NoError(t, err) + + from, err := w.WalletNew(context.Background(), types.KTBLS) + assert.NoError(t, err) + + tma.setBalance(from, 1000e9) + + ds := datastore.NewMapDatastore() + + mp, err := New(context.Background(), tma, ds, filcns.DefaultUpgradeSchedule(), "mptest", nil) + assert.NoError(t, err) + + to := mock.Address(1001) + + { + // create message with invalid nonce (1) + sm := makeTestMessage(w, from, to, 1, 50_000_000, minimumBaseFee.Uint64()) + mustAdd(t, mp, sm) + + // then try to add message again + err = mp.Add(context.TODO(), sm) + assert.Contains(t, err.Error(), "unfulfilled nonce gap") + } +} + +func TestAddMessageTwiceCidDiff(t *testing.T) { + tma := newTestMpoolAPI() + + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + assert.NoError(t, err) + + from, err := w.WalletNew(context.Background(), types.KTBLS) + assert.NoError(t, err) + + tma.setBalance(from, 1000e9) + + ds := datastore.NewMapDatastore() + + mp, err := New(context.Background(), tma, ds, filcns.DefaultUpgradeSchedule(), "mptest", nil) + assert.NoError(t, err) + + to := mock.Address(1001) + + { + sm := makeTestMessage(w, from, to, 0, 50_000_000, minimumBaseFee.Uint64()) + mustAdd(t, mp, sm) + + // Create message with different data, so CID is different + sm2 := makeTestMessage(w, from, to, 0, 50_000_001, minimumBaseFee.Uint64()) + + //stm: @CHAIN_MEMPOOL_PUSH_001 + // then try to add message again + err = mp.Add(context.TODO(), sm2) + assert.Contains(t, err.Error(), "replace by fee has too low GasPremium") + } +} + +func TestAddMessageTwiceCidDiffReplaced(t *testing.T) { + //stm: @CHAIN_MEMPOOL_PUSH_001 + tma := newTestMpoolAPI() + + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + assert.NoError(t, err) + + from, err := w.WalletNew(context.Background(), types.KTBLS) + assert.NoError(t, err) + + tma.setBalance(from, 1000e9) + + ds := datastore.NewMapDatastore() + + mp, err := New(context.Background(), tma, ds, filcns.DefaultUpgradeSchedule(), "mptest", nil) + assert.NoError(t, err) + + to := mock.Address(1001) + + { + sm := makeTestMessage(w, from, to, 0, 50_000_000, minimumBaseFee.Uint64()) + mustAdd(t, mp, sm) + + // Create message with different data, so CID is different + sm2 := makeTestMessage(w, from, to, 0, 50_000_000, minimumBaseFee.Uint64()*2) + mustAdd(t, mp, sm2) + } +} + +func TestRemoveMessage(t *testing.T) { + //stm: @CHAIN_MEMPOOL_PUSH_001 + tma := newTestMpoolAPI() + + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + assert.NoError(t, err) + + from, err := w.WalletNew(context.Background(), types.KTBLS) + assert.NoError(t, err) + + tma.setBalance(from, 1000e9) + + ds := datastore.NewMapDatastore() + + mp, err := New(context.Background(), tma, ds, filcns.DefaultUpgradeSchedule(), "mptest", nil) + assert.NoError(t, err) + + to := mock.Address(1001) + + { + sm := makeTestMessage(w, from, to, 0, 50_000_000, minimumBaseFee.Uint64()) + mustAdd(t, mp, sm) + + //stm: @CHAIN_MEMPOOL_REMOVE_001 + // remove message for sender + mp.Remove(context.TODO(), from, sm.Message.Nonce, true) + + //stm: @CHAIN_MEMPOOL_PENDING_FOR_001 + // check messages in pool: should be none present + msgs := mp.pendingFor(context.TODO(), from) + assert.Len(t, msgs, 0) + } +} diff --git a/chain/messagepool/repub_test.go b/chain/messagepool/repub_test.go index de32eaa6bd4..18a75d88181 100644 --- a/chain/messagepool/repub_test.go +++ b/chain/messagepool/repub_test.go @@ -1,3 +1,4 @@ +//stm: #unit package messagepool import ( @@ -16,6 +17,7 @@ import ( ) func TestRepubMessages(t *testing.T) { + //stm: @TOKEN_WALLET_NEW_001 oldRepublishBatchDelay := RepublishBatchDelay RepublishBatchDelay = time.Microsecond defer func() { @@ -57,6 +59,7 @@ func TestRepubMessages(t *testing.T) { for i := 0; i < 10; i++ { m := makeTestMessage(w1, a1, a2, uint64(i), gasLimit, uint64(i+1)) + //stm: @CHAIN_MEMPOOL_PUSH_001 _, err := mp.Push(context.TODO(), m) if err != nil { t.Fatal(err) diff --git a/chain/messagepool/selection_test.go b/chain/messagepool/selection_test.go index 2ae99cd779f..e97d5208ef1 100644 --- a/chain/messagepool/selection_test.go +++ b/chain/messagepool/selection_test.go @@ -1,3 +1,4 @@ +//stm: #unit package messagepool import ( @@ -74,6 +75,8 @@ func makeTestMpool() (*MessagePool, *testMpoolAPI) { } func TestMessageChains(t *testing.T) { + //stm: @TOKEN_WALLET_NEW_001 + //stm: @CHAIN_MEMPOOL_CREATE_MSG_CHAINS_001 mp, tma := makeTestMpool() // the actors @@ -310,6 +313,8 @@ func TestMessageChains(t *testing.T) { } func TestMessageChainSkipping(t *testing.T) { + //stm: @TOKEN_WALLET_NEW_001, @CHAIN_MEMPOOL_CREATE_MSG_CHAINS_001 + // regression test for chain skip bug mp, tma := makeTestMpool() @@ -382,6 +387,7 @@ func TestMessageChainSkipping(t *testing.T) { } func TestBasicMessageSelection(t *testing.T) { + //stm: @TOKEN_WALLET_NEW_001, @CHAIN_MEMPOOL_SELECT_001 oldMaxNonceGap := MaxNonceGap MaxNonceGap = 1000 defer func() { @@ -532,6 +538,7 @@ func TestBasicMessageSelection(t *testing.T) { } func TestMessageSelectionTrimmingGas(t *testing.T) { + //stm: @TOKEN_WALLET_NEW_001, @CHAIN_MEMPOOL_SELECT_001 mp, tma := makeTestMpool() // the actors @@ -595,6 +602,7 @@ func TestMessageSelectionTrimmingGas(t *testing.T) { } func TestMessageSelectionTrimmingMsgsBasic(t *testing.T) { + //stm: @TOKEN_WALLET_NEW_001, @CHAIN_MEMPOOL_SELECT_001 mp, tma := makeTestMpool() // the actors @@ -641,6 +649,7 @@ func TestMessageSelectionTrimmingMsgsBasic(t *testing.T) { } func TestMessageSelectionTrimmingMsgsTwoSendersBasic(t *testing.T) { + //stm: @TOKEN_WALLET_NEW_001, @CHAIN_MEMPOOL_SELECT_001 mp, tma := makeTestMpool() // the actors @@ -707,6 +716,7 @@ func TestMessageSelectionTrimmingMsgsTwoSendersBasic(t *testing.T) { } func TestMessageSelectionTrimmingMsgsTwoSendersAdvanced(t *testing.T) { + //stm: @TOKEN_WALLET_NEW_001, @CHAIN_MEMPOOL_SELECT_001 mp, tma := makeTestMpool() // the actors @@ -788,6 +798,7 @@ func TestMessageSelectionTrimmingMsgsTwoSendersAdvanced(t *testing.T) { } func TestPriorityMessageSelection(t *testing.T) { + //stm: @TOKEN_WALLET_NEW_001, @CHAIN_MEMPOOL_SELECT_001 mp, tma := makeTestMpool() // the actors @@ -867,6 +878,7 @@ func TestPriorityMessageSelection(t *testing.T) { } func TestPriorityMessageSelection2(t *testing.T) { + //stm: @TOKEN_WALLET_NEW_001, @CHAIN_MEMPOOL_SELECT_001 mp, tma := makeTestMpool() // the actors @@ -934,6 +946,7 @@ func TestPriorityMessageSelection2(t *testing.T) { } func TestPriorityMessageSelection3(t *testing.T) { + //stm: @TOKEN_WALLET_NEW_001, @CHAIN_MEMPOOL_SELECT_001 mp, tma := makeTestMpool() // the actors @@ -1028,6 +1041,8 @@ func TestPriorityMessageSelection3(t *testing.T) { } func TestOptimalMessageSelection1(t *testing.T) { + //stm: @TOKEN_WALLET_NEW_001, @CHAIN_MEMPOOL_SELECT_001 + // this test uses just a single actor sending messages with a low tq // the chain depenent merging algorithm should pick messages from the actor // from the start @@ -1094,6 +1109,8 @@ func TestOptimalMessageSelection1(t *testing.T) { } func TestOptimalMessageSelection2(t *testing.T) { + //stm: @TOKEN_WALLET_NEW_001, @CHAIN_MEMPOOL_SELECT_001 + // this test uses two actors sending messages to each other, with the first // actor paying (much) higher gas premium than the second. // We select with a low ticket quality; the chain depenent merging algorithm should pick @@ -1173,6 +1190,8 @@ func TestOptimalMessageSelection2(t *testing.T) { } func TestOptimalMessageSelection3(t *testing.T) { + //stm: @TOKEN_WALLET_NEW_001, @CHAIN_MEMPOOL_SELECT_001 + // this test uses 10 actors sending a block of messages to each other, with the the first // actors paying higher gas premium than the subsequent actors. // We select with a low ticket quality; the chain dependent merging algorithm should pick @@ -1416,6 +1435,8 @@ func makeZipfPremiumDistribution(rng *rand.Rand) func() uint64 { } func TestCompetitiveMessageSelectionExp(t *testing.T) { + //stm: @TOKEN_WALLET_NEW_001, @CHAIN_MEMPOOL_SELECT_001 + if testing.Short() { t.Skip("skipping in short mode") } @@ -1439,6 +1460,8 @@ func TestCompetitiveMessageSelectionExp(t *testing.T) { } func TestCompetitiveMessageSelectionZipf(t *testing.T) { + //stm: @TOKEN_WALLET_NEW_001, @CHAIN_MEMPOOL_SELECT_001 + if testing.Short() { t.Skip("skipping in short mode") } @@ -1462,6 +1485,7 @@ func TestCompetitiveMessageSelectionZipf(t *testing.T) { } func TestGasReward(t *testing.T) { + //stm: @CHAIN_MEMPOOL_GET_GAS_REWARD_001 tests := []struct { Premium uint64 FeeCap uint64 @@ -1494,6 +1518,8 @@ func TestGasReward(t *testing.T) { } func TestRealWorldSelection(t *testing.T) { + //stm: @TOKEN_WALLET_NEW_001, @TOKEN_WALLET_SIGN_001, @CHAIN_MEMPOOL_SELECT_001 + // load test-messages.json.gz and rewrite the messages so that // 1) we map each real actor to a test actor so that we can sign the messages // 2) adjust the nonces so that they start from 0 diff --git a/itests/mempool_test.go b/itests/mempool_test.go new file mode 100644 index 00000000000..f5fb408e0aa --- /dev/null +++ b/itests/mempool_test.go @@ -0,0 +1,455 @@ +//stm: #integration +package itests + +import ( + "context" + "testing" + "time" + + "github.com/filecoin-project/go-state-types/big" + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/itests/kit" + "github.com/stretchr/testify/require" +) + +func TestMemPoolPushSingleNode(t *testing.T) { + //stm: @CHAIN_MEMPOOL_CREATE_MSG_CHAINS_001, @CHAIN_MEMPOOL_SELECT_001 + //stm: @CHAIN_MEMPOOL_PENDING_001, @CHAIN_STATE_WAIT_MSG_001, @CHAIN_MEMPOOL_CAP_GAS_FEE_001 + //stm: @CHAIN_MEMPOOL_PUSH_002 + ctx := context.Background() + const blockTime = 100 * time.Millisecond + firstNode, _, _, ens := kit.EnsembleTwoOne(t, kit.MockProofs()) + ens.InterconnectAll().BeginMining(blockTime) + kit.QuietMiningLogs() + + sender := firstNode.DefaultKey.Address + + addr, err := firstNode.WalletNew(ctx, types.KTBLS) + require.NoError(t, err) + + const totalMessages = 10 + + bal, err := firstNode.WalletBalance(ctx, sender) + require.NoError(t, err) + toSend := big.Div(bal, big.NewInt(10)) + each := big.Div(toSend, big.NewInt(totalMessages)) + + // add messages to be mined/published + var sms []*types.SignedMessage + for i := 0; i < totalMessages; i++ { + msg := &types.Message{ + From: sender, + To: addr, + Value: each, + } + + sm, err := firstNode.MpoolPushMessage(ctx, msg, nil) + require.NoError(t, err) + require.EqualValues(t, i, sm.Message.Nonce) + + sms = append(sms, sm) + } + + // check pending messages for address + msgStatuses, _ := firstNode.MpoolCheckPendingMessages(ctx, sender) + require.Equal(t, totalMessages, len(msgStatuses)) + for _, msgStatusList := range msgStatuses { + for _, status := range msgStatusList { + require.True(t, status.OK) + } + } + + // verify messages should be the ones included in the next block + selected, _ := firstNode.MpoolSelect(ctx, types.EmptyTSK, 0) + for _, msg := range sms { + found := false + for _, selectedMsg := range selected { + if selectedMsg.Cid() == msg.Cid() { + found = true + break + } + } + require.True(t, found) + } + + time.Sleep(10 * blockTime) + + // pool pending list should be empty + pending, err := firstNode.MpoolPending(context.TODO(), types.EmptyTSK) + require.NoError(t, err) + require.Equal(t, 0, len(pending)) + + // all messages should be added to the chain + for _, lookMsg := range sms { + msgLookup, err := firstNode.StateWaitMsg(ctx, lookMsg.Cid(), 3, api.LookbackNoLimit, true) + require.NoError(t, err) + require.NotNil(t, msgLookup) + } +} + +func TestMemPoolPushTwoNodes(t *testing.T) { + //stm: @CHAIN_MEMPOOL_CREATE_MSG_CHAINS_001, @CHAIN_MEMPOOL_SELECT_001 + //stm: @CHAIN_MEMPOOL_PENDING_001, @CHAIN_STATE_WAIT_MSG_001, @CHAIN_MEMPOOL_CAP_GAS_FEE_001 + //stm: @CHAIN_MEMPOOL_PUSH_002 + ctx := context.Background() + const blockTime = 100 * time.Millisecond + firstNode, secondNode, _, ens := kit.EnsembleTwoOne(t, kit.MockProofs()) + ens.InterconnectAll().BeginMining(blockTime) + kit.QuietMiningLogs() + + sender := firstNode.DefaultKey.Address + sender2 := secondNode.DefaultKey.Address + + addr, _ := firstNode.WalletNew(ctx, types.KTBLS) + addr2, _ := secondNode.WalletNew(ctx, types.KTBLS) + + bal, err := firstNode.WalletBalance(ctx, sender) + require.NoError(t, err) + + const totalMessages = 10 + + toSend := big.Div(bal, big.NewInt(10)) + each := big.Div(toSend, big.NewInt(totalMessages)) + + var sms []*types.SignedMessage + // push messages to message pools of both nodes + for i := 0; i < totalMessages; i++ { + // first + msg1 := &types.Message{ + From: sender, + To: addr, + Value: each, + } + + sm1, err := firstNode.MpoolPushMessage(ctx, msg1, nil) + require.NoError(t, err) + require.EqualValues(t, i, sm1.Message.Nonce) + sms = append(sms, sm1) + + // second + msg2 := &types.Message{ + From: sender2, + To: addr2, + Value: each, + } + + sm2, err := secondNode.MpoolPushMessage(ctx, msg2, nil) + require.NoError(t, err) + require.EqualValues(t, i, sm2.Message.Nonce) + sms = append(sms, sm2) + } + + time.Sleep(10 * blockTime) + + pending1, err := firstNode.MpoolPending(context.TODO(), types.EmptyTSK) + require.NoError(t, err) + require.Equal(t, 0, len(pending1)) + + pending2, err := secondNode.MpoolPending(context.TODO(), types.EmptyTSK) + require.NoError(t, err) + require.Equal(t, 0, len(pending2)) + + // Check messages on both nodes + for _, lookMsg := range sms { + msgLookup1, err := firstNode.StateWaitMsg(ctx, lookMsg.Cid(), 3, api.LookbackNoLimit, true) + require.NoError(t, err) + require.NotNil(t, msgLookup1) + + msgLookup2, err := secondNode.StateWaitMsg(ctx, lookMsg.Cid(), 3, api.LookbackNoLimit, true) + require.NoError(t, err) + require.NotNil(t, msgLookup2) + } +} + +func TestMemPoolClearPending(t *testing.T) { + //stm: @CHAIN_MEMPOOL_PUSH_001, @CHAIN_MEMPOOL_PENDING_001 + //stm: @CHAIN_STATE_WAIT_MSG_001, @CHAIN_MEMPOOL_CLEAR_001, @CHAIN_MEMPOOL_CAP_GAS_FEE_001 + ctx := context.Background() + const blockTime = 100 * time.Millisecond + firstNode, _, _, ens := kit.EnsembleTwoOne(t, kit.MockProofs()) + ens.InterconnectAll().BeginMining(blockTime) + kit.QuietMiningLogs() + + sender := firstNode.DefaultKey.Address + + addr, _ := firstNode.WalletNew(ctx, types.KTBLS) + + const totalMessages = 10 + + bal, err := firstNode.WalletBalance(ctx, sender) + require.NoError(t, err) + toSend := big.Div(bal, big.NewInt(10)) + each := big.Div(toSend, big.NewInt(totalMessages)) + + // Add single message, then clear the pool + msg := &types.Message{ + From: sender, + To: addr, + Value: each, + } + _, err = firstNode.MpoolPushMessage(ctx, msg, nil) + require.NoError(t, err) + + err = firstNode.MpoolClear(ctx, true) + require.NoError(t, err) + + // pool should be empty now + pending, err := firstNode.MpoolPending(context.TODO(), types.EmptyTSK) + require.NoError(t, err) + require.Equal(t, 0, len(pending)) + + time.Sleep(2 * blockTime) + + // waiting for the message should produce nothing + _, err = firstNode.StateWaitMsg(ctx, msg.Cid(), 3, api.LookbackNoLimit, true) + require.Error(t, err) +} + +func TestMemPoolBatchPush(t *testing.T) { + //stm: @CHAIN_MEMPOOL_CREATE_MSG_CHAINS_001, @CHAIN_MEMPOOL_SELECT_001, @CHAIN_MEMPOOL_CAP_GAS_FEE_001 + //stm: @CHAIN_MEMPOOL_CHECK_PENDING_MESSAGES_001, @CHAIN_MEMPOOL_SELECT_001 + //stm: @CHAIN_MEMPOOL_PENDING_001, @CHAIN_STATE_WAIT_MSG_001 + //stm: @CHAIN_MEMPOOL_BATCH_PUSH_001 + ctx := context.Background() + const blockTime = 100 * time.Millisecond + firstNode, _, _, ens := kit.EnsembleTwoOne(t, kit.MockProofs()) + ens.InterconnectAll().BeginMining(blockTime) + kit.QuietMiningLogs() + + sender := firstNode.DefaultKey.Address + + addr, _ := firstNode.WalletNew(ctx, types.KTBLS) + + const totalMessages = 10 + + bal, err := firstNode.WalletBalance(ctx, sender) + require.NoError(t, err) + toSend := big.Div(bal, big.NewInt(10)) + each := big.Div(toSend, big.NewInt(totalMessages)) + + // add messages to be mined/published + var sms []*types.SignedMessage + for i := 0; i < totalMessages; i++ { + msg := &types.Message{ + From: sender, + To: addr, + Value: each, + Nonce: uint64(i), + GasLimit: 50_000_000, + GasFeeCap: types.NewInt(100_000_000), + GasPremium: types.NewInt(1), + } + + signedMessage, err := firstNode.WalletSignMessage(ctx, sender, msg) + require.NoError(t, err) + + sms = append(sms, signedMessage) + } + + _, err = firstNode.MpoolBatchPush(ctx, sms) + require.NoError(t, err) + + // check pending messages for address + msgStatuses, err := firstNode.MpoolCheckPendingMessages(ctx, sender) + require.NoError(t, err) + require.Equal(t, totalMessages, len(msgStatuses)) + for _, msgStatusList := range msgStatuses { + for _, status := range msgStatusList { + require.True(t, status.OK) + } + } + + // verify messages should be the ones included in the next block + selected, _ := firstNode.MpoolSelect(ctx, types.EmptyTSK, 0) + require.NoError(t, err) + for _, msg := range sms { + found := false + for _, selectedMsg := range selected { + if selectedMsg.Cid() == msg.Cid() { + found = true + break + } + } + require.True(t, found) + } + + time.Sleep(10 * blockTime) + + // pool pending list should be empty + pending, err := firstNode.MpoolPending(context.TODO(), types.EmptyTSK) + require.NoError(t, err) + require.Equal(t, 0, len(pending)) + + // all messages should be added to the chain + for _, lookMsg := range sms { + msgLookup, err := firstNode.StateWaitMsg(ctx, lookMsg.Cid(), 3, api.LookbackNoLimit, true) + require.NoError(t, err) + require.NotNil(t, msgLookup) + } +} + +func TestMemPoolPushSingleNodeUntrusted(t *testing.T) { + //stm: @CHAIN_MEMPOOL_CREATE_MSG_CHAINS_001, @CHAIN_MEMPOOL_SELECT_001, @CHAIN_MEMPOOL_CAP_GAS_FEE_001 + //stm: @CHAIN_MEMPOOL_CHECK_PENDING_MESSAGES_001, @CHAIN_MEMPOOL_SELECT_001 + //stm: @CHAIN_MEMPOOL_PENDING_001, @CHAIN_STATE_WAIT_MSG_001 + //stm: @CHAIN_MEMPOOL_PUSH_003 + ctx := context.Background() + const blockTime = 100 * time.Millisecond + firstNode, _, _, ens := kit.EnsembleTwoOne(t, kit.MockProofs()) + ens.InterconnectAll().BeginMining(blockTime) + kit.QuietMiningLogs() + + sender := firstNode.DefaultKey.Address + + addr, _ := firstNode.WalletNew(ctx, types.KTBLS) + + const totalMessages = 10 + + bal, err := firstNode.WalletBalance(ctx, sender) + require.NoError(t, err) + toSend := big.Div(bal, big.NewInt(10)) + each := big.Div(toSend, big.NewInt(totalMessages)) + + // add messages to be mined/published + var sms []*types.SignedMessage + for i := 0; i < totalMessages; i++ { + msg := &types.Message{ + From: sender, + To: addr, + Value: each, + Nonce: uint64(i), + GasLimit: 50_000_000, + GasFeeCap: types.NewInt(100_000_000), + GasPremium: types.NewInt(1), + } + + signedMessage, err := firstNode.WalletSignMessage(ctx, sender, msg) + require.NoError(t, err) + + // push untrusted messages + pushedCid, err := firstNode.MpoolPushUntrusted(ctx, signedMessage) + require.NoError(t, err) + require.Equal(t, msg.Cid(), pushedCid) + + sms = append(sms, signedMessage) + } + + // check pending messages for address + msgStatuses, _ := firstNode.MpoolCheckPendingMessages(ctx, sender) + require.Equal(t, totalMessages, len(msgStatuses)) + for _, msgStatusList := range msgStatuses { + for _, status := range msgStatusList { + require.True(t, status.OK) + } + } + + // verify messages should be the ones included in the next block + selected, _ := firstNode.MpoolSelect(ctx, types.EmptyTSK, 0) + for _, msg := range sms { + found := false + for _, selectedMsg := range selected { + if selectedMsg.Cid() == msg.Cid() { + found = true + break + } + } + require.True(t, found) + } + + time.Sleep(10 * blockTime) + + // pool pending list should be empty + pending, err := firstNode.MpoolPending(context.TODO(), types.EmptyTSK) + require.NoError(t, err) + require.Equal(t, 0, len(pending)) + + // all messages should be added to the chain + for _, lookMsg := range sms { + msgLookup, err := firstNode.StateWaitMsg(ctx, lookMsg.Cid(), 3, api.LookbackNoLimit, true) + require.NoError(t, err) + require.NotNil(t, msgLookup) + } +} + +func TestMemPoolBatchPushUntrusted(t *testing.T) { + //stm: @CHAIN_MEMPOOL_CREATE_MSG_CHAINS_001, @CHAIN_MEMPOOL_SELECT_001, @CHAIN_MEMPOOL_CAP_GAS_FEE_001 + //stm: @CHAIN_MEMPOOL_CHECK_PENDING_MESSAGES_001, @CHAIN_MEMPOOL_SELECT_001 + //stm: @CHAIN_MEMPOOL_PENDING_001, @CHAIN_STATE_WAIT_MSG_001 + //stm: @CHAIN_MEMPOOL_BATCH_PUSH_002 + ctx := context.Background() + const blockTime = 100 * time.Millisecond + firstNode, _, _, ens := kit.EnsembleTwoOne(t, kit.MockProofs()) + ens.InterconnectAll().BeginMining(blockTime) + kit.QuietMiningLogs() + + sender := firstNode.DefaultKey.Address + + addr, _ := firstNode.WalletNew(ctx, types.KTBLS) + + const totalMessages = 10 + + bal, err := firstNode.WalletBalance(ctx, sender) + require.NoError(t, err) + toSend := big.Div(bal, big.NewInt(10)) + each := big.Div(toSend, big.NewInt(totalMessages)) + + // add messages to be mined/published + var sms []*types.SignedMessage + for i := 0; i < totalMessages; i++ { + msg := &types.Message{ + From: sender, + To: addr, + Value: each, + Nonce: uint64(i), + GasLimit: 50_000_000, + GasFeeCap: types.NewInt(100_000_000), + GasPremium: types.NewInt(1), + } + + signedMessage, err := firstNode.WalletSignMessage(ctx, sender, msg) + require.NoError(t, err) + + sms = append(sms, signedMessage) + } + + _, err = firstNode.MpoolBatchPushUntrusted(ctx, sms) + require.NoError(t, err) + + // check pending messages for address + msgStatuses, err := firstNode.MpoolCheckPendingMessages(ctx, sender) + require.NoError(t, err) + require.Equal(t, totalMessages, len(msgStatuses)) + for _, msgStatusList := range msgStatuses { + for _, status := range msgStatusList { + require.True(t, status.OK) + } + } + + // verify messages should be the ones included in the next block + selected, _ := firstNode.MpoolSelect(ctx, types.EmptyTSK, 0) + for _, msg := range sms { + found := false + for _, selectedMsg := range selected { + if selectedMsg.Cid() == msg.Cid() { + found = true + break + } + } + require.True(t, found) + } + + time.Sleep(10 * blockTime) + + // pool pending list should be empty + pending, err := firstNode.MpoolPending(context.TODO(), types.EmptyTSK) + require.NoError(t, err) + require.Equal(t, 0, len(pending)) + + // all messages should be added to the chain + for _, lookMsg := range sms { + msgLookup, err := firstNode.StateWaitMsg(ctx, lookMsg.Cid(), 3, api.LookbackNoLimit, true) + require.NoError(t, err) + require.NotNil(t, msgLookup) + } +} From 235377585d45c3e1b478aa4518da3f81dc1ea79f Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Thu, 3 Feb 2022 11:51:01 +0000 Subject: [PATCH 083/385] Clarify the purpose of `MaxSimultaneousTransfers` config Clarify the documentation of `MaxSimultaneousTransfers` to state that the "transfer" refers to multihash syncing only and not the data itself. --- documentation/en/default-lotus-miner-config.toml | 4 ++-- node/config/doc_gen.go | 3 +-- node/config/types.go | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/documentation/en/default-lotus-miner-config.toml b/documentation/en/default-lotus-miner-config.toml index 345a2b91cdb..07328bb7794 100644 --- a/documentation/en/default-lotus-miner-config.toml +++ b/documentation/en/default-lotus-miner-config.toml @@ -285,8 +285,8 @@ # env var: LOTUS_INDEXERPROVIDER_ANNOUNCEADDRESSES #AnnounceAddresses = [] - # The maximum number of simultaneous data transfers between the indexers - # and the indexer provider + # The maximum number of simultaneous requests syncing the list of advertised multihashes between + # the indexers and the index provider. # # type: uint64 # env var: LOTUS_INDEXERPROVIDER_MAXSIMULTANEOUSTRANSFERS diff --git a/node/config/doc_gen.go b/node/config/doc_gen.go index 1b7c20b6394..8e7a1a963d4 100644 --- a/node/config/doc_gen.go +++ b/node/config/doc_gen.go @@ -378,8 +378,7 @@ Format: multiaddress`, Name: "MaxSimultaneousTransfers", Type: "uint64", - Comment: `The maximum number of simultaneous data transfers between the indexers -and the indexer provider`, + Comment: `The maximum number of simultaneous requests syncing the list of advertised multihashes between the indexers and the index provider.`, }, }, "Libp2p": []DocField{ diff --git a/node/config/types.go b/node/config/types.go index 428f1d59bee..18f27feeac3 100644 --- a/node/config/types.go +++ b/node/config/types.go @@ -173,8 +173,8 @@ type IndexerProviderConfig struct { // Format: multiaddress AnnounceAddresses []string - // The maximum number of simultaneous data transfers between the indexers - // and the indexer provider + // The maximum number of simultaneous requests syncing the list of advertised multihashes + // between the indexers and the index provider. MaxSimultaneousTransfers uint64 } From 575e6add435b3eac6daab80522cba44b5e827a59 Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Thu, 3 Feb 2022 11:51:01 +0000 Subject: [PATCH 084/385] Rename `IndexerProvider` to `IndexProvider` and add more docs Rename the config section corresponding to indexing to `IndexProvider` for better readability. Update existing docs for better clarity and add docs for config parameters embedded from `index-provider` `Ingest` config library. --- .../en/default-lotus-miner-config.toml | 45 +++++++++++++------ itests/deals_concurrent_test.go | 10 ++--- itests/kit/deals.go | 6 +-- node/builder_miner.go | 2 +- node/config/def.go | 4 +- node/config/def_test.go | 2 +- node/config/doc_gen.go | 21 +++++---- node/config/types.go | 34 +++++++------- node/modules/storageminer_idxprov.go | 14 +++--- 9 files changed, 81 insertions(+), 57 deletions(-) diff --git a/documentation/en/default-lotus-miner-config.toml b/documentation/en/default-lotus-miner-config.toml index 07328bb7794..79b4efb87af 100644 --- a/documentation/en/default-lotus-miner-config.toml +++ b/documentation/en/default-lotus-miner-config.toml @@ -257,39 +257,58 @@ #Path = "" -[IndexerProvider] - # env var: LOTUS_INDEXERPROVIDER_LINKCACHESIZE +[IndexProvider] + # The maximum number of multihash chunk links that index provider cash can store before + # LRU eviction. If chunks belonging to a single advertisement are larger than the cache can + # hold, the cache is resized to be able to hold all links. The actual disk usaed depends on + # LinkedChunkSize and the length of multihashes. For example, for 128-bit long multihashes + # with the default LinkedChunkSize, and LinkCacheSize the cache size can grow to 256MiB. + # + # type int + # env var: LOTUS_INDEXPROVIDER_LINKCACHESIZE #LinkCacheSize = 1024 - # env var: LOTUS_INDEXERPROVIDER_LINKEDCHUNKSIZE + # The number of multihashes in each chunk of the + # advertised multihash entries linked list. If multihashes are 128-bit, then + # setting LinkedChunkSize = 16384 will result in blocks of 0.25MiB when + # full. + # + # type int + # env var: LOTUS_INDEXPROVIDER_LINKEDCHUNKSIZE #LinkedChunkSize = 16384 - # env var: LOTUS_INDEXERPROVIDER_PUBSUBTOPIC + # The gossipsub topic name used to publish change to the advertised content. + # + # env var: LOTUS_INDEXPROVIDER_PUBSUBTOPIC #PubSubTopic = "/indexer/ingest/mainnet" - # env var: LOTUS_INDEXERPROVIDER_PURGELINKCACHE + # Whether to purge all cached entries on start-up. + # + # env var: LOTUS_INDEXPROVIDER_PURGELINKCACHE #PurgeLinkCache = false - # Binding address for the libp2p host - 0 means random port. - # Format: multiaddress; see https://multiformats.io/multiaddr/ + # Binding address for the libp2p host contacted by indexer nodes to sync the list of advertised + # multihashes. Note that when port is set to 0 a random port is generated at runtime and may be + # different on every restart. The format of the strings specified must conform to multiaddress; + # see https://multiformats.io/multiaddr/ # # type: []string - # env var: LOTUS_INDEXERPROVIDER_LISTENADDRESSES + # env var: LOTUS_INDEXPROVIDER_LISTENADDRESSES #ListenAddresses = ["/ip4/0.0.0.0/tcp/0", "/ip6/::/tcp/0"] - # Addresses to explicitly announce to other peers. If not specified, - # all interface addresses are announced - # Format: multiaddress + # The address the endpoints at which the data associated to the advertised + # multihashes can be retrieved. If not specified, the ListenAddresses are used instead. The format + # of the strings specified must conform to multiaddress; see https://multiformats.io/multiaddr/ # # type: []string - # env var: LOTUS_INDEXERPROVIDER_ANNOUNCEADDRESSES + # env var: LOTUS_INDEXPROVIDER_ANNOUNCEADDRESSES #AnnounceAddresses = [] # The maximum number of simultaneous requests syncing the list of advertised multihashes between # the indexers and the index provider. # # type: uint64 - # env var: LOTUS_INDEXERPROVIDER_MAXSIMULTANEOUSTRANSFERS + # env var: LOTUS_INDEXPROVIDER_MAXSIMULTANEOUSTRANSFERS #MaxSimultaneousTransfers = 20 diff --git a/itests/deals_concurrent_test.go b/itests/deals_concurrent_test.go index 3bc5e4813cf..624e253b441 100644 --- a/itests/deals_concurrent_test.go +++ b/itests/deals_concurrent_test.go @@ -55,11 +55,11 @@ func TestDealWithMarketAndMinerNode(t *testing.T) { dh := kit.NewDealHarness(t, client, main, market) dh.RunConcurrentDeals(kit.RunConcurrentDealsOpts{ - N: n, - FastRetrieval: fastRetrieval, - CarExport: carExport, - StartEpoch: startEpoch, - IndexerProvider: idxProv, + N: n, + FastRetrieval: fastRetrieval, + CarExport: carExport, + StartEpoch: startEpoch, + IndexProvider: idxProv, }) } diff --git a/itests/kit/deals.go b/itests/kit/deals.go index ca3848c588b..44f785d3df3 100644 --- a/itests/kit/deals.go +++ b/itests/kit/deals.go @@ -406,7 +406,7 @@ type RunConcurrentDealsOpts struct { CarExport bool StartEpoch abi.ChainEpoch UseCARFileForStorageDeal bool - IndexerProvider *shared_testutil.MockIndexProvider + IndexProvider *shared_testutil.MockIndexProvider } func (dh *DealHarness) RunConcurrentDeals(opts RunConcurrentDealsOpts) { @@ -434,8 +434,8 @@ func (dh *DealHarness) RunConcurrentDeals(opts RunConcurrentDealsOpts) { }) // Check that the storage provider announced the deal to indexers - if opts.IndexerProvider != nil { - notifs := opts.IndexerProvider.GetNotifs() + if opts.IndexProvider != nil { + notifs := opts.IndexProvider.GetNotifs() _, ok := notifs[string(deal.Bytes())] require.True(dh.t, ok) } diff --git a/node/builder_miner.go b/node/builder_miner.go index de22ef8aa60..afac1e8280a 100644 --- a/node/builder_miner.go +++ b/node/builder_miner.go @@ -168,7 +168,7 @@ func ConfigStorageMiner(c interface{}) Option { Override(new(dtypes.ProviderTransferNetwork), modules.NewProviderTransferNetwork), Override(new(dtypes.ProviderTransport), modules.NewProviderTransport), Override(new(dtypes.ProviderDataTransfer), modules.NewProviderDataTransfer), - Override(new(provider.Interface), modules.IndexerProvider(cfg.IndexerProvider)), + Override(new(provider.Interface), modules.IndexProvider(cfg.IndexProvider)), Override(new(*storedask.StoredAsk), modules.NewStorageAsk), Override(new(dtypes.StorageDealFilter), modules.BasicDealFilter(cfg.Dealmaking, nil)), Override(new(storagemarket.StorageProvider), modules.StorageProvider), diff --git a/node/config/def.go b/node/config/def.go index d6fedc7539e..75e2a08a3d2 100644 --- a/node/config/def.go +++ b/node/config/def.go @@ -181,7 +181,7 @@ func DefaultStorageMiner() *StorageMiner { }, }, - IndexerProvider: IndexerProviderConfig{ + IndexProvider: IndexProviderConfig{ ListenAddresses: []string{ "/ip4/0.0.0.0/tcp/0", "/ip6/::/tcp/0", @@ -234,7 +234,7 @@ func DefaultStorageMiner() *StorageMiner { // TODO: Remove hardcoded defaults once provider library exposes them. // See: https://github.com/filecoin-project/index-provider/issues/108 - cfg.IndexerProvider.Ingest = ipconfig.NewIngest() + cfg.IndexProvider.Ingest = ipconfig.NewIngest() cfg.Common.API.ListenAddress = "/ip4/127.0.0.1/tcp/2345/http" cfg.Common.API.RemoteListenAddress = "127.0.0.1:2345" diff --git a/node/config/def_test.go b/node/config/def_test.go index e6ad1a68719..c25b255bfd3 100644 --- a/node/config/def_test.go +++ b/node/config/def_test.go @@ -55,5 +55,5 @@ func TestDefaultMinerRoundtrip(t *testing.T) { func TestDefaultStorageMiner_SetsIndexIngestTopic(t *testing.T) { subject := DefaultStorageMiner() - require.Equal(t, "/indexer/ingest/mainnet", subject.IndexerProvider.PubSubTopic) + require.Equal(t, "/indexer/ingest/mainnet", subject.IndexProvider.PubSubTopic) } diff --git a/node/config/doc_gen.go b/node/config/doc_gen.go index 8e7a1a963d4..d7c500e6716 100644 --- a/node/config/doc_gen.go +++ b/node/config/doc_gen.go @@ -358,27 +358,30 @@ see https://docs.filecoin.io/mine/lotus/miner-configuration/#using-filters-for-f Comment: ``, }, }, - "IndexerProviderConfig": []DocField{ + "IndexProviderConfig": []DocField{ { Name: "ListenAddresses", Type: "[]string", - Comment: `Binding address for the libp2p host - 0 means random port. -Format: multiaddress; see https://multiformats.io/multiaddr/`, + Comment: `Binding address for the libp2p host contacted by indexer nodes to sync the list of advertised +multihashes. Note that when port is set to 0 a random port is generated at runtime and may be +different on every restart. The format of the strings specified must conform to multiaddress; +see https://multiformats.io/multiaddr/`, }, { Name: "AnnounceAddresses", Type: "[]string", - Comment: `Addresses to explicitly announce to other peers. If not specified, -all interface addresses are announced -Format: multiaddress`, + Comment: `The address the endpoints at which the data associated to the advertised +multihashes can be retrieved. If not specified, the ListenAddresses are used instead. The format +of the strings specified must conform to multiaddress; see https://multiformats.io/multiaddr/`, }, { Name: "MaxSimultaneousTransfers", Type: "uint64", - Comment: `The maximum number of simultaneous requests syncing the list of advertised multihashes between the indexers and the index provider.`, + Comment: `The maximum number of simultaneous requests syncing the list of advertised multihashes between +the indexers and the index provider.`, }, }, "Libp2p": []DocField{ @@ -857,8 +860,8 @@ Default is 20 (about once a week).`, Comment: ``, }, { - Name: "IndexerProvider", - Type: "IndexerProviderConfig", + Name: "IndexProvider", + Type: "IndexProviderConfig", Comment: ``, }, diff --git a/node/config/types.go b/node/config/types.go index 18f27feeac3..b73e957f600 100644 --- a/node/config/types.go +++ b/node/config/types.go @@ -45,14 +45,14 @@ type Backup struct { type StorageMiner struct { Common - Subsystems MinerSubsystemConfig - Dealmaking DealmakingConfig - IndexerProvider IndexerProviderConfig - Sealing SealingConfig - Storage sectorstorage.SealerConfig - Fees MinerFeeConfig - Addresses MinerAddressConfig - DAGStore DAGStoreConfig + Subsystems MinerSubsystemConfig + Dealmaking DealmakingConfig + IndexProvider IndexProviderConfig + Sealing SealingConfig + Storage sectorstorage.SealerConfig + Fees MinerFeeConfig + Addresses MinerAddressConfig + DAGStore DAGStoreConfig } type DAGStoreConfig struct { @@ -161,20 +161,22 @@ type DealmakingConfig struct { RetrievalPricing *RetrievalPricing } -type IndexerProviderConfig struct { +type IndexProviderConfig struct { config.Ingest - // Binding address for the libp2p host - 0 means random port. - // Format: multiaddress; see https://multiformats.io/multiaddr/ + // Binding address for the libp2p host contacted by indexer nodes to sync the list of advertised + // multihashes. Note that when port is set to 0 a random port is generated at runtime and may be + // different on every restart. The format of the strings specified must conform to multiaddress; + // see https://multiformats.io/multiaddr/ ListenAddresses []string - // Addresses to explicitly announce to other peers. If not specified, - // all interface addresses are announced - // Format: multiaddress + // The address the endpoints at which the data associated to the advertised + // multihashes can be retrieved. If not specified, the ListenAddresses are used instead. The format + // of the strings specified must conform to multiaddress; see https://multiformats.io/multiaddr/ AnnounceAddresses []string - // The maximum number of simultaneous requests syncing the list of advertised multihashes - // between the indexers and the index provider. + // The maximum number of simultaneous requests syncing the list of advertised multihashes between + // the indexers and the index provider. MaxSimultaneousTransfers uint64 } diff --git a/node/modules/storageminer_idxprov.go b/node/modules/storageminer_idxprov.go index 8a0d2105733..b5caf3e59c4 100644 --- a/node/modules/storageminer_idxprov.go +++ b/node/modules/storageminer_idxprov.go @@ -48,7 +48,7 @@ type IdxProv struct { peerstore.Peerstore } -func IndexerProvider(cfg config.IndexerProviderConfig) func(params IdxProv, marketHost host.Host) (provider.Interface, error) { +func IndexProvider(cfg config.IndexProviderConfig) func(params IdxProv, marketHost host.Host) (provider.Interface, error) { return func(args IdxProv, marketHost host.Host) (provider.Interface, error) { ipds := namespace.Wrap(args.Datastore, datastore.NewKey("/indexer-provider")) @@ -57,12 +57,12 @@ func IndexerProvider(cfg config.IndexerProviderConfig) func(params IdxProv, mark return nil, fmt.Errorf("missing private key for node ID: %s", args.PeerID.Pretty()) } - h, err := createIndexerProviderHost(args.MetricsCtx, args.Lifecycle, pkey, args.Peerstore, cfg.ListenAddresses, cfg.AnnounceAddresses) + h, err := createIndexProviderHost(args.MetricsCtx, args.Lifecycle, pkey, args.Peerstore, cfg.ListenAddresses, cfg.AnnounceAddresses) if err != nil { return nil, xerrors.Errorf("creating indexer provider host: %w", err) } - dt, err := newIndexerProviderDataTransfer(cfg, args.MetricsCtx, args.Lifecycle, args.Repo, h, ipds) + dt, err := newIndexProviderDataTransfer(cfg, args.MetricsCtx, args.Lifecycle, args.Repo, h, ipds) if err != nil { return nil, err } @@ -96,7 +96,7 @@ func IndexerProvider(cfg config.IndexerProviderConfig) func(params IdxProv, mark } } -func createIndexerProviderHost(mctx helpers.MetricsCtx, lc fx.Lifecycle, pkey ci.PrivKey, pstore peerstore.Peerstore, listenAddrs []string, announceAddrs []string) (host.Host, error) { +func createIndexProviderHost(mctx helpers.MetricsCtx, lc fx.Lifecycle, pkey ci.PrivKey, pstore peerstore.Peerstore, listenAddrs []string, announceAddrs []string) (host.Host, error) { addrsFactory, err := lp2p.MakeAddrsFactory(announceAddrs, nil) if err != nil { return nil, err @@ -125,11 +125,11 @@ func createIndexerProviderHost(mctx helpers.MetricsCtx, lc fx.Lifecycle, pkey ci return h, nil } -func newIndexerProviderDataTransfer(cfg config.IndexerProviderConfig, mctx helpers.MetricsCtx, lc fx.Lifecycle, r repo.LockedRepo, h host.Host, ds datastore.Batching) (datatransfer.Manager, error) { +func newIndexProviderDataTransfer(cfg config.IndexProviderConfig, mctx helpers.MetricsCtx, lc fx.Lifecycle, r repo.LockedRepo, h host.Host, ds datastore.Batching) (datatransfer.Manager, error) { net := dtnet.NewFromLibp2pHost(h) // Set up graphsync - gs := newIndexerProviderGraphsync(cfg, mctx, lc, h) + gs := newIndexProviderGraphsync(cfg, mctx, lc, h) // Set up data transfer dtDs := namespace.Wrap(ds, datastore.NewKey("/datatransfer/transfers")) @@ -153,7 +153,7 @@ func newIndexerProviderDataTransfer(cfg config.IndexerProviderConfig, mctx helpe return dt, nil } -func newIndexerProviderGraphsync(cfg config.IndexerProviderConfig, mctx helpers.MetricsCtx, lc fx.Lifecycle, h host.Host) graphsync.GraphExchange { +func newIndexProviderGraphsync(cfg config.IndexProviderConfig, mctx helpers.MetricsCtx, lc fx.Lifecycle, h host.Host) graphsync.GraphExchange { graphsyncNetwork := gsnet.NewFromLibp2pHost(h) return graphsyncimpl.New(helpers.LifecycleCtx(mctx, lc), graphsyncNetwork, From 6ef0c382c3445595406b14e22f56d1ec4c4056b3 Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Thu, 3 Feb 2022 13:24:46 +0000 Subject: [PATCH 085/385] Fix typos in default miner config --- documentation/en/default-lotus-miner-config.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/en/default-lotus-miner-config.toml b/documentation/en/default-lotus-miner-config.toml index 79b4efb87af..6fad2700c09 100644 --- a/documentation/en/default-lotus-miner-config.toml +++ b/documentation/en/default-lotus-miner-config.toml @@ -258,9 +258,9 @@ [IndexProvider] - # The maximum number of multihash chunk links that index provider cash can store before + # The maximum number of multihash chunk links that index provider cache can store before # LRU eviction. If chunks belonging to a single advertisement are larger than the cache can - # hold, the cache is resized to be able to hold all links. The actual disk usaed depends on + # hold, the cache is resized to be able to hold all links. The actual disk usage depends on # LinkedChunkSize and the length of multihashes. For example, for 128-bit long multihashes # with the default LinkedChunkSize, and LinkCacheSize the cache size can grow to 256MiB. # From 20fc5ffa387669dd077793685e6e876029c0c0a7 Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Thu, 3 Feb 2022 14:43:20 +0100 Subject: [PATCH 086/385] fixing tests --- itests/kit/ensemble.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/itests/kit/ensemble.go b/itests/kit/ensemble.go index 0227ee81e70..56569ceaeff 100644 --- a/itests/kit/ensemble.go +++ b/itests/kit/ensemble.go @@ -541,6 +541,12 @@ func (n *Ensemble) Start() *Ensemble { node.Override(new(stmgr.UpgradeSchedule), n.options.upgradeSchedule), } + if m.options.subsystems.Has(SMarkets) { + opts = append(opts, + node.Override(new(*modules.IdxProvHost), node.MockHost(n.mn)), + ) + } + // append any node builder options. opts = append(opts, m.options.extraNodeOpts...) From 595ad44ee71e743e626b7144c2755eb28095faee Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Thu, 3 Feb 2022 15:44:18 +0100 Subject: [PATCH 087/385] refactor indexprovider libp2p host connection to fullnode with meshcreator --- .../en/default-lotus-miner-config.toml | 22 +++++----- go.mod | 2 +- go.sum | 2 + itests/deals_concurrent_test.go | 10 ++--- itests/kit/deals.go | 6 +-- itests/kit/ensemble.go | 4 +- markets/idxprov/host.go | 5 +++ markets/idxprov/idxprov_test/noop.go | 16 ++++++++ markets/idxprov/mesh.go | 40 +++++++++++++++++++ node/builder_miner.go | 6 ++- node/config/def.go | 4 +- node/config/def_test.go | 2 +- node/config/doc_gen.go | 6 +-- node/config/types.go | 18 ++++----- node/modules/storageminer.go | 9 +++-- node/modules/storageminer_idxprov.go | 27 ++++++------- 16 files changed, 122 insertions(+), 57 deletions(-) create mode 100644 markets/idxprov/host.go create mode 100644 markets/idxprov/idxprov_test/noop.go create mode 100644 markets/idxprov/mesh.go diff --git a/documentation/en/default-lotus-miner-config.toml b/documentation/en/default-lotus-miner-config.toml index f6f3e1d689a..0bc5cfe1e6f 100644 --- a/documentation/en/default-lotus-miner-config.toml +++ b/documentation/en/default-lotus-miner-config.toml @@ -257,27 +257,27 @@ #Path = "" -[IndexerProvider] - # env var: LOTUS_INDEXERPROVIDER_LINKCACHESIZE +[IndexProvider] + # env var: LOTUS_INDEXPROVIDER_LINKCACHESIZE #LinkCacheSize = 1024 - # env var: LOTUS_INDEXERPROVIDER_LINKEDCHUNKSIZE + # env var: LOTUS_INDEXPROVIDER_LINKEDCHUNKSIZE #LinkedChunkSize = 16384 - # env var: LOTUS_INDEXERPROVIDER_PUBSUBTOPIC + # env var: LOTUS_INDEXPROVIDER_PUBSUBTOPIC #PubSubTopic = "/indexer/ingest/mainnet" - # env var: LOTUS_INDEXERPROVIDER_PURGELINKCACHE + # env var: LOTUS_INDEXPROVIDER_PURGELINKCACHE #PurgeLinkCache = false - # env var: LOTUS_INDEXERPROVIDER_PUBLISHERKIND + # env var: LOTUS_INDEXPROVIDER_PUBLISHERKIND #PublisherKind = "dtsync" # Binding address for the libp2p host - 0 means random port. # Format: multiaddress; see https://multiformats.io/multiaddr/ # # type: []string - # env var: LOTUS_INDEXERPROVIDER_LISTENADDRESSES + # env var: LOTUS_INDEXPROVIDER_LISTENADDRESSES #ListenAddresses = ["/ip4/0.0.0.0/tcp/0", "/ip6/::/tcp/0"] # Addresses to explicitly announce to other peers. If not specified, @@ -285,18 +285,18 @@ # Format: multiaddress # # type: []string - # env var: LOTUS_INDEXERPROVIDER_ANNOUNCEADDRESSES + # env var: LOTUS_INDEXPROVIDER_ANNOUNCEADDRESSES #AnnounceAddresses = [] # The maximum number of simultaneous data transfers between the indexers # and the indexer provider # # type: uint64 - # env var: LOTUS_INDEXERPROVIDER_MAXSIMULTANEOUSTRANSFERS + # env var: LOTUS_INDEXPROVIDER_MAXSIMULTANEOUSTRANSFERS #MaxSimultaneousTransfers = 20 - [IndexerProvider.HttpPublisher] - # env var: LOTUS_INDEXERPROVIDER_HTTPPUBLISHER_LISTENMULTIADDR + [IndexProvider.HttpPublisher] + # env var: LOTUS_INDEXPROVIDER_HTTPPUBLISHER_LISTENMULTIADDR #ListenMultiaddr = "/ip4/0.0.0.0/tcp/3104/http" diff --git a/go.mod b/go.mod index b1720761287..d26187b7d5e 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,7 @@ require ( github.com/filecoin-project/go-data-transfer v1.14.0 github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 - github.com/filecoin-project/go-fil-markets v1.19.1-0.20220202151058-ea0c8f1c8630 + github.com/filecoin-project/go-fil-markets v1.19.1-0.20220203143446-7ec33d5dc6ee github.com/filecoin-project/go-indexer-core v0.2.8 github.com/filecoin-project/go-jsonrpc v0.1.5 github.com/filecoin-project/go-padreader v0.0.1 diff --git a/go.sum b/go.sum index a3753f8d1f1..88ba59b5bc0 100644 --- a/go.sum +++ b/go.sum @@ -338,6 +338,8 @@ github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7L github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8= github.com/filecoin-project/go-fil-markets v1.19.1-0.20220202151058-ea0c8f1c8630 h1:h46LVtyElHCjLt7JtIPHjLId+H65izL0ytZ9EC/hA44= github.com/filecoin-project/go-fil-markets v1.19.1-0.20220202151058-ea0c8f1c8630/go.mod h1:gnZw2JAtaGcAwGA7ASD3cvO7Laz1N06VLP9FVEQfnRg= +github.com/filecoin-project/go-fil-markets v1.19.1-0.20220203143446-7ec33d5dc6ee h1:mL4jV1+c5jA9823E4DUfUVSSqPS/jGz75QuIOXVLqvE= +github.com/filecoin-project/go-fil-markets v1.19.1-0.20220203143446-7ec33d5dc6ee/go.mod h1:gnZw2JAtaGcAwGA7ASD3cvO7Laz1N06VLP9FVEQfnRg= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= diff --git a/itests/deals_concurrent_test.go b/itests/deals_concurrent_test.go index 3bc5e4813cf..624e253b441 100644 --- a/itests/deals_concurrent_test.go +++ b/itests/deals_concurrent_test.go @@ -55,11 +55,11 @@ func TestDealWithMarketAndMinerNode(t *testing.T) { dh := kit.NewDealHarness(t, client, main, market) dh.RunConcurrentDeals(kit.RunConcurrentDealsOpts{ - N: n, - FastRetrieval: fastRetrieval, - CarExport: carExport, - StartEpoch: startEpoch, - IndexerProvider: idxProv, + N: n, + FastRetrieval: fastRetrieval, + CarExport: carExport, + StartEpoch: startEpoch, + IndexProvider: idxProv, }) } diff --git a/itests/kit/deals.go b/itests/kit/deals.go index ca3848c588b..44f785d3df3 100644 --- a/itests/kit/deals.go +++ b/itests/kit/deals.go @@ -406,7 +406,7 @@ type RunConcurrentDealsOpts struct { CarExport bool StartEpoch abi.ChainEpoch UseCARFileForStorageDeal bool - IndexerProvider *shared_testutil.MockIndexProvider + IndexProvider *shared_testutil.MockIndexProvider } func (dh *DealHarness) RunConcurrentDeals(opts RunConcurrentDealsOpts) { @@ -434,8 +434,8 @@ func (dh *DealHarness) RunConcurrentDeals(opts RunConcurrentDealsOpts) { }) // Check that the storage provider announced the deal to indexers - if opts.IndexerProvider != nil { - notifs := opts.IndexerProvider.GetNotifs() + if opts.IndexProvider != nil { + notifs := opts.IndexProvider.GetNotifs() _, ok := notifs[string(deal.Bytes())] require.True(dh.t, ok) } diff --git a/itests/kit/ensemble.go b/itests/kit/ensemble.go index 56569ceaeff..e0a549c2b06 100644 --- a/itests/kit/ensemble.go +++ b/itests/kit/ensemble.go @@ -36,6 +36,8 @@ import ( "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" "github.com/filecoin-project/lotus/extern/sector-storage/mock" "github.com/filecoin-project/lotus/genesis" + "github.com/filecoin-project/lotus/markets/idxprov" + idxprov_test "github.com/filecoin-project/lotus/markets/idxprov/idxprov_test" lotusminer "github.com/filecoin-project/lotus/miner" "github.com/filecoin-project/lotus/node" "github.com/filecoin-project/lotus/node/config" @@ -543,7 +545,7 @@ func (n *Ensemble) Start() *Ensemble { if m.options.subsystems.Has(SMarkets) { opts = append(opts, - node.Override(new(*modules.IdxProvHost), node.MockHost(n.mn)), + node.Override(new(idxprov.MeshCreator), idxprov_test.NewNoopMeshCreator), ) } diff --git a/markets/idxprov/host.go b/markets/idxprov/host.go new file mode 100644 index 00000000000..5e901a560f4 --- /dev/null +++ b/markets/idxprov/host.go @@ -0,0 +1,5 @@ +package idxprov + +import "github.com/libp2p/go-libp2p-core/host" + +type Host host.Host diff --git a/markets/idxprov/idxprov_test/noop.go b/markets/idxprov/idxprov_test/noop.go new file mode 100644 index 00000000000..535c13d2522 --- /dev/null +++ b/markets/idxprov/idxprov_test/noop.go @@ -0,0 +1,16 @@ +package idxprov_test + +import ( + "context" +) + +type NoopMeshCreator struct { +} + +func NewNoopMeshCreator() *NoopMeshCreator { + return &NoopMeshCreator{} +} + +func (mc NoopMeshCreator) Connect(ctx context.Context) error { + return nil +} diff --git a/markets/idxprov/mesh.go b/markets/idxprov/mesh.go new file mode 100644 index 00000000000..d073bbb1e07 --- /dev/null +++ b/markets/idxprov/mesh.go @@ -0,0 +1,40 @@ +package idxprov + +import ( + "context" + "fmt" + + "github.com/filecoin-project/lotus/api/v1api" + + logging "github.com/ipfs/go-log/v2" +) + +var log = logging.Logger("idxprov") + +type MeshCreator interface { + Connect(ctx context.Context) error +} + +type Libp2pMeshCreator struct { + fullnodeApi v1api.FullNode + idxProvHost Host +} + +func (mc Libp2pMeshCreator) Connect(ctx context.Context) error { + addrs, err := mc.fullnodeApi.NetAddrsListen(ctx) + if err != nil { + return err + } + + if err := mc.idxProvHost.Connect(ctx, addrs); err != nil { + return fmt.Errorf("failed to connect index provider host with the full node: %w", err) + } + mc.idxProvHost.ConnManager().Protect(addrs.ID, "markets") + log.Debugw("successfully connected to full node", "fullNodeInfo", addrs.String()) + + return nil +} + +func NewMeshCreator(fullnodeApi v1api.FullNode, idxProvHost Host) MeshCreator { + return Libp2pMeshCreator{fullnodeApi, idxProvHost} +} diff --git a/node/builder_miner.go b/node/builder_miner.go index e45e8d19a79..351a65be79e 100644 --- a/node/builder_miner.go +++ b/node/builder_miner.go @@ -26,6 +26,7 @@ import ( sealing "github.com/filecoin-project/lotus/extern/storage-sealing" "github.com/filecoin-project/lotus/markets/dagstore" "github.com/filecoin-project/lotus/markets/dealfilter" + "github.com/filecoin-project/lotus/markets/idxprov" "github.com/filecoin-project/lotus/markets/retrievaladapter" "github.com/filecoin-project/lotus/markets/sectoraccessor" "github.com/filecoin-project/lotus/markets/storageadapter" @@ -168,8 +169,9 @@ func ConfigStorageMiner(c interface{}) Option { Override(new(dtypes.ProviderTransferNetwork), modules.NewProviderTransferNetwork), Override(new(dtypes.ProviderTransport), modules.NewProviderTransport), Override(new(dtypes.ProviderDataTransfer), modules.NewProviderDataTransfer), - Override(new(*modules.IdxProvHost), modules.IndexerProviderHost(cfg.IndexerProvider)), - Override(new(provider.Interface), modules.IndexerProvider(cfg.IndexerProvider)), + Override(new(idxprov.MeshCreator), idxprov.NewMeshCreator), + Override(new(idxprov.Host), modules.IndexProviderHost(cfg.IndexProvider)), + Override(new(provider.Interface), modules.IndexProvider(cfg.IndexProvider)), Override(new(*storedask.StoredAsk), modules.NewStorageAsk), Override(new(dtypes.StorageDealFilter), modules.BasicDealFilter(cfg.Dealmaking, nil)), Override(new(storagemarket.StorageProvider), modules.StorageProvider), diff --git a/node/config/def.go b/node/config/def.go index d6fedc7539e..75e2a08a3d2 100644 --- a/node/config/def.go +++ b/node/config/def.go @@ -181,7 +181,7 @@ func DefaultStorageMiner() *StorageMiner { }, }, - IndexerProvider: IndexerProviderConfig{ + IndexProvider: IndexProviderConfig{ ListenAddresses: []string{ "/ip4/0.0.0.0/tcp/0", "/ip6/::/tcp/0", @@ -234,7 +234,7 @@ func DefaultStorageMiner() *StorageMiner { // TODO: Remove hardcoded defaults once provider library exposes them. // See: https://github.com/filecoin-project/index-provider/issues/108 - cfg.IndexerProvider.Ingest = ipconfig.NewIngest() + cfg.IndexProvider.Ingest = ipconfig.NewIngest() cfg.Common.API.ListenAddress = "/ip4/127.0.0.1/tcp/2345/http" cfg.Common.API.RemoteListenAddress = "127.0.0.1:2345" diff --git a/node/config/def_test.go b/node/config/def_test.go index e6ad1a68719..c25b255bfd3 100644 --- a/node/config/def_test.go +++ b/node/config/def_test.go @@ -55,5 +55,5 @@ func TestDefaultMinerRoundtrip(t *testing.T) { func TestDefaultStorageMiner_SetsIndexIngestTopic(t *testing.T) { subject := DefaultStorageMiner() - require.Equal(t, "/indexer/ingest/mainnet", subject.IndexerProvider.PubSubTopic) + require.Equal(t, "/indexer/ingest/mainnet", subject.IndexProvider.PubSubTopic) } diff --git a/node/config/doc_gen.go b/node/config/doc_gen.go index 1b7c20b6394..55392a9f30f 100644 --- a/node/config/doc_gen.go +++ b/node/config/doc_gen.go @@ -358,7 +358,7 @@ see https://docs.filecoin.io/mine/lotus/miner-configuration/#using-filters-for-f Comment: ``, }, }, - "IndexerProviderConfig": []DocField{ + "IndexProviderConfig": []DocField{ { Name: "ListenAddresses", Type: "[]string", @@ -858,8 +858,8 @@ Default is 20 (about once a week).`, Comment: ``, }, { - Name: "IndexerProvider", - Type: "IndexerProviderConfig", + Name: "IndexProvider", + Type: "IndexProviderConfig", Comment: ``, }, diff --git a/node/config/types.go b/node/config/types.go index 428f1d59bee..35b6646c641 100644 --- a/node/config/types.go +++ b/node/config/types.go @@ -45,14 +45,14 @@ type Backup struct { type StorageMiner struct { Common - Subsystems MinerSubsystemConfig - Dealmaking DealmakingConfig - IndexerProvider IndexerProviderConfig - Sealing SealingConfig - Storage sectorstorage.SealerConfig - Fees MinerFeeConfig - Addresses MinerAddressConfig - DAGStore DAGStoreConfig + Subsystems MinerSubsystemConfig + Dealmaking DealmakingConfig + IndexProvider IndexProviderConfig + Sealing SealingConfig + Storage sectorstorage.SealerConfig + Fees MinerFeeConfig + Addresses MinerAddressConfig + DAGStore DAGStoreConfig } type DAGStoreConfig struct { @@ -161,7 +161,7 @@ type DealmakingConfig struct { RetrievalPricing *RetrievalPricing } -type IndexerProviderConfig struct { +type IndexProviderConfig struct { config.Ingest // Binding address for the libp2p host - 0 means random port. diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index 34b27d9d75f..1df076ff027 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -62,6 +62,7 @@ import ( "github.com/filecoin-project/lotus/journal" "github.com/filecoin-project/lotus/markets" "github.com/filecoin-project/lotus/markets/dagstore" + "github.com/filecoin-project/lotus/markets/idxprov" marketevents "github.com/filecoin-project/lotus/markets/loggers" "github.com/filecoin-project/lotus/markets/pricing" lotusminer "github.com/filecoin-project/lotus/miner" @@ -590,8 +591,7 @@ func StorageProvider(minerAddress dtypes.MinerAddress, spn storagemarket.StorageProviderNode, df dtypes.StorageDealFilter, dsw *dagstore.Wrapper, - fullnodeApi v1api.FullNode, - idxProvHost *IdxProvHost, + meshCreator idxprov.MeshCreator, ) (storagemarket.StorageProvider, error) { net := smnet.NewFromLibp2pHost(h) @@ -622,8 +622,9 @@ func StorageProvider(minerAddress dtypes.MinerAddress, spn, address.Address(minerAddress), storedAsk, - fullnodeApi, - idxProvHost.Host, + meshCreator, + //fullnodeApi, + //idxProvHost, opt, ) } diff --git a/node/modules/storageminer_idxprov.go b/node/modules/storageminer_idxprov.go index b200d23eb6a..e9ee94c57d9 100644 --- a/node/modules/storageminer_idxprov.go +++ b/node/modules/storageminer_idxprov.go @@ -29,6 +29,7 @@ import ( "github.com/libp2p/go-libp2p-core/host" "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/markets/idxprov" marketevents "github.com/filecoin-project/lotus/markets/loggers" "github.com/filecoin-project/lotus/node/config" "github.com/filecoin-project/lotus/node/modules/dtypes" @@ -48,28 +49,24 @@ type IdxProv struct { peerstore.Peerstore } -type IdxProvHost struct { - host.Host -} - -func IndexerProviderHost(cfg config.IndexerProviderConfig) func(IdxProv) (*IdxProvHost, error) { - return func(args IdxProv) (*IdxProvHost, error) { +func IndexProviderHost(cfg config.IndexProviderConfig) func(IdxProv) (idxprov.Host, error) { + return func(args IdxProv) (idxprov.Host, error) { pkey := args.Peerstore.PrivKey(args.PeerID) if pkey == nil { return nil, fmt.Errorf("missing private key for node ID: %s", args.PeerID.Pretty()) } - h, err := createIndexerProviderHost(args.MetricsCtx, args.Lifecycle, pkey, args.Peerstore, cfg.ListenAddresses, cfg.AnnounceAddresses) + h, err := createIndexProviderHost(args.MetricsCtx, args.Lifecycle, pkey, args.Peerstore, cfg.ListenAddresses, cfg.AnnounceAddresses) if err != nil { return nil, xerrors.Errorf("creating indexer provider host: %w", err) } - return &IdxProvHost{h}, nil + return h, nil } } -func IndexerProvider(cfg config.IndexerProviderConfig) func(params IdxProv, marketHost host.Host, h *IdxProvHost) (provider.Interface, error) { - return func(args IdxProv, marketHost host.Host, h *IdxProvHost) (provider.Interface, error) { +func IndexProvider(cfg config.IndexProviderConfig) func(params IdxProv, marketHost host.Host, h idxprov.Host) (provider.Interface, error) { + return func(args IdxProv, marketHost host.Host, h idxprov.Host) (provider.Interface, error) { ipds := namespace.Wrap(args.Datastore, datastore.NewKey("/indexer-provider")) pkey := args.Peerstore.PrivKey(args.PeerID) @@ -77,7 +74,7 @@ func IndexerProvider(cfg config.IndexerProviderConfig) func(params IdxProv, mark return nil, fmt.Errorf("missing private key for node ID: %s", args.PeerID.Pretty()) } - dt, err := newIndexerProviderDataTransfer(cfg, args.MetricsCtx, args.Lifecycle, args.Repo, h, ipds) + dt, err := newIndexProviderDataTransfer(cfg, args.MetricsCtx, args.Lifecycle, args.Repo, h, ipds) if err != nil { return nil, err } @@ -111,7 +108,7 @@ func IndexerProvider(cfg config.IndexerProviderConfig) func(params IdxProv, mark } } -func createIndexerProviderHost(mctx helpers.MetricsCtx, lc fx.Lifecycle, pkey ci.PrivKey, pstore peerstore.Peerstore, listenAddrs []string, announceAddrs []string) (host.Host, error) { +func createIndexProviderHost(mctx helpers.MetricsCtx, lc fx.Lifecycle, pkey ci.PrivKey, pstore peerstore.Peerstore, listenAddrs []string, announceAddrs []string) (host.Host, error) { addrsFactory, err := lp2p.MakeAddrsFactory(announceAddrs, nil) if err != nil { return nil, err @@ -140,11 +137,11 @@ func createIndexerProviderHost(mctx helpers.MetricsCtx, lc fx.Lifecycle, pkey ci return h, nil } -func newIndexerProviderDataTransfer(cfg config.IndexerProviderConfig, mctx helpers.MetricsCtx, lc fx.Lifecycle, r repo.LockedRepo, h host.Host, ds datastore.Batching) (datatransfer.Manager, error) { +func newIndexProviderDataTransfer(cfg config.IndexProviderConfig, mctx helpers.MetricsCtx, lc fx.Lifecycle, r repo.LockedRepo, h host.Host, ds datastore.Batching) (datatransfer.Manager, error) { net := dtnet.NewFromLibp2pHost(h) // Set up graphsync - gs := newIndexerProviderGraphsync(cfg, mctx, lc, h) + gs := newIndexProviderGraphsync(cfg, mctx, lc, h) // Set up data transfer dtDs := namespace.Wrap(ds, datastore.NewKey("/datatransfer/transfers")) @@ -168,7 +165,7 @@ func newIndexerProviderDataTransfer(cfg config.IndexerProviderConfig, mctx helpe return dt, nil } -func newIndexerProviderGraphsync(cfg config.IndexerProviderConfig, mctx helpers.MetricsCtx, lc fx.Lifecycle, h host.Host) graphsync.GraphExchange { +func newIndexProviderGraphsync(cfg config.IndexProviderConfig, mctx helpers.MetricsCtx, lc fx.Lifecycle, h host.Host) graphsync.GraphExchange { graphsyncNetwork := gsnet.NewFromLibp2pHost(h) return graphsyncimpl.New(helpers.LifecycleCtx(mctx, lc), graphsyncNetwork, From bb6235733d8714184a651d2c3132f708b9e5a86d Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Thu, 3 Feb 2022 15:48:05 +0100 Subject: [PATCH 088/385] go mod tidy --- go.sum | 2 -- 1 file changed, 2 deletions(-) diff --git a/go.sum b/go.sum index 88ba59b5bc0..977fa37fcc7 100644 --- a/go.sum +++ b/go.sum @@ -336,8 +336,6 @@ github.com/filecoin-project/go-fil-commcid v0.1.0 h1:3R4ds1A9r6cr8mvZBfMYxTS88Oq github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7LXep5bFEVOVmQWHJvl2mgsGo= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8= -github.com/filecoin-project/go-fil-markets v1.19.1-0.20220202151058-ea0c8f1c8630 h1:h46LVtyElHCjLt7JtIPHjLId+H65izL0ytZ9EC/hA44= -github.com/filecoin-project/go-fil-markets v1.19.1-0.20220202151058-ea0c8f1c8630/go.mod h1:gnZw2JAtaGcAwGA7ASD3cvO7Laz1N06VLP9FVEQfnRg= github.com/filecoin-project/go-fil-markets v1.19.1-0.20220203143446-7ec33d5dc6ee h1:mL4jV1+c5jA9823E4DUfUVSSqPS/jGz75QuIOXVLqvE= github.com/filecoin-project/go-fil-markets v1.19.1-0.20220203143446-7ec33d5dc6ee/go.mod h1:gnZw2JAtaGcAwGA7ASD3cvO7Laz1N06VLP9FVEQfnRg= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= From b6b5046ccee9323abc38542824cb1e57bcee1942 Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Thu, 3 Feb 2022 16:26:04 +0100 Subject: [PATCH 089/385] upgrade go-fil-markets --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d26187b7d5e..2d3e7d232e7 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,7 @@ require ( github.com/filecoin-project/go-data-transfer v1.14.0 github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 - github.com/filecoin-project/go-fil-markets v1.19.1-0.20220203143446-7ec33d5dc6ee + github.com/filecoin-project/go-fil-markets v1.19.1-0.20220203152434-8790cca614d3 github.com/filecoin-project/go-indexer-core v0.2.8 github.com/filecoin-project/go-jsonrpc v0.1.5 github.com/filecoin-project/go-padreader v0.0.1 diff --git a/go.sum b/go.sum index 977fa37fcc7..b2ebceb1c3d 100644 --- a/go.sum +++ b/go.sum @@ -336,8 +336,8 @@ github.com/filecoin-project/go-fil-commcid v0.1.0 h1:3R4ds1A9r6cr8mvZBfMYxTS88Oq github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7LXep5bFEVOVmQWHJvl2mgsGo= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8= -github.com/filecoin-project/go-fil-markets v1.19.1-0.20220203143446-7ec33d5dc6ee h1:mL4jV1+c5jA9823E4DUfUVSSqPS/jGz75QuIOXVLqvE= -github.com/filecoin-project/go-fil-markets v1.19.1-0.20220203143446-7ec33d5dc6ee/go.mod h1:gnZw2JAtaGcAwGA7ASD3cvO7Laz1N06VLP9FVEQfnRg= +github.com/filecoin-project/go-fil-markets v1.19.1-0.20220203152434-8790cca614d3 h1:ak9I3TaeAQof84/DsyJ2BO1rShP77OfyZEiVNltjYAs= +github.com/filecoin-project/go-fil-markets v1.19.1-0.20220203152434-8790cca614d3/go.mod h1:gnZw2JAtaGcAwGA7ASD3cvO7Laz1N06VLP9FVEQfnRg= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= From 7247f8e41fda387cd26533b239d1a9b5b560dcf2 Mon Sep 17 00:00:00 2001 From: Will Scott Date: Thu, 3 Feb 2022 17:24:49 +0100 Subject: [PATCH 090/385] add net protect api methods fix #8015 --- api/api_net.go | 4 ++ api/mocks/mock_full.go | 43 +++++++++++++++ api/proxy_gen.go | 39 ++++++++++++++ api/v0api/v0mocks/mock_full.go | 43 +++++++++++++++ build/openrpc/full.json.gz | Bin 26596 -> 26585 bytes build/openrpc/miner.json.gz | Bin 13091 -> 13088 bytes build/openrpc/worker.json.gz | Bin 3915 -> 3917 bytes documentation/en/api-v0-methods-miner.md | 49 ++++++++++++++++++ documentation/en/api-v0-methods.md | 49 ++++++++++++++++++ documentation/en/api-v1-unstable-methods.md | 49 ++++++++++++++++++ .../en/default-lotus-miner-config.toml | 32 ++++-------- node/impl/net/protect.go | 35 +++++++++++++ 12 files changed, 322 insertions(+), 21 deletions(-) create mode 100644 node/impl/net/protect.go diff --git a/api/api_net.go b/api/api_net.go index 7dddb09ac0a..74581e3acda 100644 --- a/api/api_net.go +++ b/api/api_net.go @@ -51,6 +51,10 @@ type Net interface { NetBlockRemove(ctx context.Context, acl NetBlockList) error //perm:admin NetBlockList(ctx context.Context) (NetBlockList, error) //perm:read + NetProtectAdd(ctx context.Context, acl []peer.ID) error //perm:admin + NetProtectRemove(ctx context.Context, acl []peer.ID) error //perm:admin + NetProtectList(ctx context.Context) ([]peer.ID, error) //perm:read + // ResourceManager API NetStat(ctx context.Context, scope string) (NetStat, error) //perm:read NetLimit(ctx context.Context, scope string) (NetLimit, error) //perm:read diff --git a/api/mocks/mock_full.go b/api/mocks/mock_full.go index e985a794d0c..49c49e22ea3 100644 --- a/api/mocks/mock_full.go +++ b/api/mocks/mock_full.go @@ -1856,6 +1856,49 @@ func (mr *MockFullNodeMockRecorder) NetPeers(arg0 interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetPeers", reflect.TypeOf((*MockFullNode)(nil).NetPeers), arg0) } +// NetProtectAdd mocks base method. +func (m *MockFullNode) NetProtectAdd(arg0 context.Context, arg1 []peer.ID) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NetProtectAdd", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// NetProtectAdd indicates an expected call of NetProtectAdd. +func (mr *MockFullNodeMockRecorder) NetProtectAdd(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetProtectAdd", reflect.TypeOf((*MockFullNode)(nil).NetProtectAdd), arg0, arg1) +} + +// NetProtectList mocks base method. +func (m *MockFullNode) NetProtectList(arg0 context.Context) ([]peer.ID, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NetProtectList", arg0) + ret0, _ := ret[0].([]peer.ID) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// NetProtectList indicates an expected call of NetProtectList. +func (mr *MockFullNodeMockRecorder) NetProtectList(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetProtectList", reflect.TypeOf((*MockFullNode)(nil).NetProtectList), arg0) +} + +// NetProtectRemove mocks base method. +func (m *MockFullNode) NetProtectRemove(arg0 context.Context, arg1 []peer.ID) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NetProtectRemove", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// NetProtectRemove indicates an expected call of NetProtectRemove. +func (mr *MockFullNodeMockRecorder) NetProtectRemove(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetProtectRemove", reflect.TypeOf((*MockFullNode)(nil).NetProtectRemove), arg0, arg1) +} + // NetPubsubScores mocks base method. func (m *MockFullNode) NetPubsubScores(arg0 context.Context) ([]api.PubsubScore, error) { m.ctrl.T.Helper() diff --git a/api/proxy_gen.go b/api/proxy_gen.go index e9bf130a725..a4024ab729a 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -593,6 +593,12 @@ type NetStruct struct { NetPeers func(p0 context.Context) ([]peer.AddrInfo, error) `perm:"read"` + NetProtectAdd func(p0 context.Context, p1 []peer.ID) error `perm:"admin"` + + NetProtectList func(p0 context.Context) ([]peer.ID, error) `perm:"read"` + + NetProtectRemove func(p0 context.Context, p1 []peer.ID) error `perm:"admin"` + NetPubsubScores func(p0 context.Context) ([]PubsubScore, error) `perm:"read"` NetSetLimit func(p0 context.Context, p1 string, p2 NetLimit) error `perm:"admin"` @@ -3672,6 +3678,39 @@ func (s *NetStub) NetPeers(p0 context.Context) ([]peer.AddrInfo, error) { return *new([]peer.AddrInfo), ErrNotSupported } +func (s *NetStruct) NetProtectAdd(p0 context.Context, p1 []peer.ID) error { + if s.Internal.NetProtectAdd == nil { + return ErrNotSupported + } + return s.Internal.NetProtectAdd(p0, p1) +} + +func (s *NetStub) NetProtectAdd(p0 context.Context, p1 []peer.ID) error { + return ErrNotSupported +} + +func (s *NetStruct) NetProtectList(p0 context.Context) ([]peer.ID, error) { + if s.Internal.NetProtectList == nil { + return *new([]peer.ID), ErrNotSupported + } + return s.Internal.NetProtectList(p0) +} + +func (s *NetStub) NetProtectList(p0 context.Context) ([]peer.ID, error) { + return *new([]peer.ID), ErrNotSupported +} + +func (s *NetStruct) NetProtectRemove(p0 context.Context, p1 []peer.ID) error { + if s.Internal.NetProtectRemove == nil { + return ErrNotSupported + } + return s.Internal.NetProtectRemove(p0, p1) +} + +func (s *NetStub) NetProtectRemove(p0 context.Context, p1 []peer.ID) error { + return ErrNotSupported +} + func (s *NetStruct) NetPubsubScores(p0 context.Context) ([]PubsubScore, error) { if s.Internal.NetPubsubScores == nil { return *new([]PubsubScore), ErrNotSupported diff --git a/api/v0api/v0mocks/mock_full.go b/api/v0api/v0mocks/mock_full.go index 26d7959404b..e18c8bfe7ad 100644 --- a/api/v0api/v0mocks/mock_full.go +++ b/api/v0api/v0mocks/mock_full.go @@ -1769,6 +1769,49 @@ func (mr *MockFullNodeMockRecorder) NetPeers(arg0 interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetPeers", reflect.TypeOf((*MockFullNode)(nil).NetPeers), arg0) } +// NetProtectAdd mocks base method. +func (m *MockFullNode) NetProtectAdd(arg0 context.Context, arg1 []peer.ID) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NetProtectAdd", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// NetProtectAdd indicates an expected call of NetProtectAdd. +func (mr *MockFullNodeMockRecorder) NetProtectAdd(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetProtectAdd", reflect.TypeOf((*MockFullNode)(nil).NetProtectAdd), arg0, arg1) +} + +// NetProtectList mocks base method. +func (m *MockFullNode) NetProtectList(arg0 context.Context) ([]peer.ID, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NetProtectList", arg0) + ret0, _ := ret[0].([]peer.ID) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// NetProtectList indicates an expected call of NetProtectList. +func (mr *MockFullNodeMockRecorder) NetProtectList(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetProtectList", reflect.TypeOf((*MockFullNode)(nil).NetProtectList), arg0) +} + +// NetProtectRemove mocks base method. +func (m *MockFullNode) NetProtectRemove(arg0 context.Context, arg1 []peer.ID) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NetProtectRemove", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// NetProtectRemove indicates an expected call of NetProtectRemove. +func (mr *MockFullNodeMockRecorder) NetProtectRemove(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetProtectRemove", reflect.TypeOf((*MockFullNode)(nil).NetProtectRemove), arg0, arg1) +} + // NetPubsubScores mocks base method. func (m *MockFullNode) NetPubsubScores(arg0 context.Context) ([]api.PubsubScore, error) { m.ctrl.T.Helper() diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 7dec77e7cdd932d36240e255426f41fbff01e78e..7ca70d7d9a7bfd719c101badd45b7df84a32d2f5 100644 GIT binary patch delta 24963 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 SJA4HI0RR6pIN}E>M+E?|JEh?O delta 25042 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 CXw;4X diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 111e3892245aaf4e14f3ef40fef994df4cda5e28..28c24c07ba5dda376c6ee34f3d87596b0af164ec 100644 GIT binary patch literal 13088 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 literal 13091 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 diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index d29e027ba491280364ca10c032f2acf6ac9fedc1..97250a33588a13a8b77fb10f5d6d27feb9f798a6 100644 GIT binary patch delta 2619 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 bzP9BkwG$j9Uj9D-0RR7kU5Evh-T(mrc7O(F diff --git a/documentation/en/api-v0-methods-miner.md b/documentation/en/api-v0-methods-miner.md index 4699c8fe805..9da6809be1f 100644 --- a/documentation/en/api-v0-methods-miner.md +++ b/documentation/en/api-v0-methods-miner.md @@ -89,6 +89,9 @@ * [NetLimit](#NetLimit) * [NetPeerInfo](#NetPeerInfo) * [NetPeers](#NetPeers) + * [NetProtectAdd](#NetProtectAdd) + * [NetProtectList](#NetProtectList) + * [NetProtectRemove](#NetProtectRemove) * [NetPubsubScores](#NetPubsubScores) * [NetSetLimit](#NetSetLimit) * [NetStat](#NetStat) @@ -1854,6 +1857,52 @@ Response: ] ``` +### NetProtectAdd + + +Perms: admin + +Inputs: +```json +[ + [ + "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf" + ] +] +``` + +Response: `{}` + +### NetProtectList + + +Perms: read + +Inputs: `null` + +Response: +```json +[ + "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf" +] +``` + +### NetProtectRemove + + +Perms: admin + +Inputs: +```json +[ + [ + "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf" + ] +] +``` + +Response: `{}` + ### NetPubsubScores diff --git a/documentation/en/api-v0-methods.md b/documentation/en/api-v0-methods.md index 883d4d27499..16e86775204 100644 --- a/documentation/en/api-v0-methods.md +++ b/documentation/en/api-v0-methods.md @@ -131,6 +131,9 @@ * [NetLimit](#NetLimit) * [NetPeerInfo](#NetPeerInfo) * [NetPeers](#NetPeers) + * [NetProtectAdd](#NetProtectAdd) + * [NetProtectList](#NetProtectList) + * [NetProtectRemove](#NetProtectRemove) * [NetPubsubScores](#NetPubsubScores) * [NetSetLimit](#NetSetLimit) * [NetStat](#NetStat) @@ -3905,6 +3908,52 @@ Response: ] ``` +### NetProtectAdd + + +Perms: admin + +Inputs: +```json +[ + [ + "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf" + ] +] +``` + +Response: `{}` + +### NetProtectList + + +Perms: read + +Inputs: `null` + +Response: +```json +[ + "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf" +] +``` + +### NetProtectRemove + + +Perms: admin + +Inputs: +```json +[ + [ + "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf" + ] +] +``` + +Response: `{}` + ### NetPubsubScores diff --git a/documentation/en/api-v1-unstable-methods.md b/documentation/en/api-v1-unstable-methods.md index a5fdd999429..0ff7bc8c873 100644 --- a/documentation/en/api-v1-unstable-methods.md +++ b/documentation/en/api-v1-unstable-methods.md @@ -137,6 +137,9 @@ * [NetLimit](#NetLimit) * [NetPeerInfo](#NetPeerInfo) * [NetPeers](#NetPeers) + * [NetProtectAdd](#NetProtectAdd) + * [NetProtectList](#NetProtectList) + * [NetProtectRemove](#NetProtectRemove) * [NetPubsubScores](#NetPubsubScores) * [NetSetLimit](#NetSetLimit) * [NetStat](#NetStat) @@ -4266,6 +4269,52 @@ Response: ] ``` +### NetProtectAdd + + +Perms: admin + +Inputs: +```json +[ + [ + "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf" + ] +] +``` + +Response: `{}` + +### NetProtectList + + +Perms: read + +Inputs: `null` + +Response: +```json +[ + "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf" +] +``` + +### NetProtectRemove + + +Perms: admin + +Inputs: +```json +[ + [ + "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf" + ] +] +``` + +Response: `{}` + ### NetPubsubScores diff --git a/documentation/en/default-lotus-miner-config.toml b/documentation/en/default-lotus-miner-config.toml index 6fad2700c09..c0392cc4a7c 100644 --- a/documentation/en/default-lotus-miner-config.toml +++ b/documentation/en/default-lotus-miner-config.toml @@ -258,38 +258,24 @@ [IndexProvider] - # The maximum number of multihash chunk links that index provider cache can store before - # LRU eviction. If chunks belonging to a single advertisement are larger than the cache can - # hold, the cache is resized to be able to hold all links. The actual disk usage depends on - # LinkedChunkSize and the length of multihashes. For example, for 128-bit long multihashes - # with the default LinkedChunkSize, and LinkCacheSize the cache size can grow to 256MiB. - # - # type int # env var: LOTUS_INDEXPROVIDER_LINKCACHESIZE #LinkCacheSize = 1024 - # The number of multihashes in each chunk of the - # advertised multihash entries linked list. If multihashes are 128-bit, then - # setting LinkedChunkSize = 16384 will result in blocks of 0.25MiB when - # full. - # - # type int # env var: LOTUS_INDEXPROVIDER_LINKEDCHUNKSIZE #LinkedChunkSize = 16384 - # The gossipsub topic name used to publish change to the advertised content. - # # env var: LOTUS_INDEXPROVIDER_PUBSUBTOPIC #PubSubTopic = "/indexer/ingest/mainnet" - # Whether to purge all cached entries on start-up. - # # env var: LOTUS_INDEXPROVIDER_PURGELINKCACHE #PurgeLinkCache = false - # Binding address for the libp2p host contacted by indexer nodes to sync the list of advertised - # multihashes. Note that when port is set to 0 a random port is generated at runtime and may be - # different on every restart. The format of the strings specified must conform to multiaddress; + # env var: LOTUS_INDEXPROVIDER_PUBLISHERKIND + #PublisherKind = "dtsync" + + # Binding address for the libp2p host contacted by indexer nodes to sync the list of advertised + # multihashes. Note that when port is set to 0 a random port is generated at runtime and may be + # different on every restart. The format of the strings specified must conform to multiaddress; # see https://multiformats.io/multiaddr/ # # type: []string @@ -304,13 +290,17 @@ # env var: LOTUS_INDEXPROVIDER_ANNOUNCEADDRESSES #AnnounceAddresses = [] - # The maximum number of simultaneous requests syncing the list of advertised multihashes between + # The maximum number of simultaneous requests syncing the list of advertised multihashes between # the indexers and the index provider. # # type: uint64 # env var: LOTUS_INDEXPROVIDER_MAXSIMULTANEOUSTRANSFERS #MaxSimultaneousTransfers = 20 + [IndexProvider.HttpPublisher] + # env var: LOTUS_INDEXPROVIDER_HTTPPUBLISHER_LISTENMULTIADDR + #ListenMultiaddr = "/ip4/0.0.0.0/tcp/3104/http" + [Sealing] # Upper bound on how many sectors can be waiting for more deals to be packed in it before it begins sealing at any given time. diff --git a/node/impl/net/protect.go b/node/impl/net/protect.go new file mode 100644 index 00000000000..1728985040a --- /dev/null +++ b/node/impl/net/protect.go @@ -0,0 +1,35 @@ +package net + +import ( + "context" + + "github.com/libp2p/go-libp2p-core/peer" +) + +const apiProtectTag = "api" + +func (a *NetAPI) NetProtectAdd(ctx context.Context, peers []peer.ID) error { + for _, p := range peers { + a.Host.ConnManager().Protect(p, apiProtectTag) + } + + return nil +} + +func (a *NetAPI) NetProtectRemove(ctx context.Context, peers []peer.ID) error { + for _, p := range peers { + a.Host.ConnManager().Unprotect(p, apiProtectTag) + } + + return nil +} + +func (a *NetAPI) NetProtectList(ctx context.Context) (result []peer.ID, err error) { + for _, conn := range a.Host.Network().Conns() { + if a.Host.ConnManager().IsProtected(conn.RemotePeer(), apiProtectTag) { + result = append(result, conn.RemotePeer()) + } + } + + return +} From c084130d3eb84a2ecc5acf3ceb63aafec90941f4 Mon Sep 17 00:00:00 2001 From: gammazero Date: Thu, 3 Feb 2022 14:56:21 -0800 Subject: [PATCH 091/385] Lotus chain nodes relay indexer pubsub messages Content providers announce the availability of indexer data using gossip pubsub. The content providers are not connected directly to indexers, so the pubsub messages are relayed to indexers via chain nodes. This PR makes chain nodes relay gossip pubsub messages, on the /indexer/ingest/ topic. --- build/params_shared_funcs.go | 1 + chain/sub/incoming.go | 21 +++++++++++++++++++++ metrics/metrics.go | 13 +++++++++++++ node/builder.go | 2 ++ node/builder_chain.go | 2 ++ node/modules/lp2p/pubsub.go | 1 + node/modules/services.go | 30 ++++++++++++++++++++++++++++++ 7 files changed, 70 insertions(+) diff --git a/build/params_shared_funcs.go b/build/params_shared_funcs.go index f59fee653e9..9d5dfa34777 100644 --- a/build/params_shared_funcs.go +++ b/build/params_shared_funcs.go @@ -13,6 +13,7 @@ import ( func BlocksTopic(netName dtypes.NetworkName) string { return "/fil/blocks/" + string(netName) } func MessagesTopic(netName dtypes.NetworkName) string { return "/fil/msgs/" + string(netName) } +func IngestTopic(netName dtypes.NetworkName) string { return "/indexer/ingest/" + string(netName) } func DhtProtocolName(netName dtypes.NetworkName) protocol.ID { return protocol.ID("/fil/kad/" + string(netName)) } diff --git a/chain/sub/incoming.go b/chain/sub/incoming.go index 2e962a2498c..dd18f25d05b 100644 --- a/chain/sub/incoming.go +++ b/chain/sub/incoming.go @@ -444,3 +444,24 @@ func recordFailure(ctx context.Context, metric *stats.Int64Measure, failureType ) stats.Record(ctx, metric.M(1)) } + +type IndexerMessageValidator struct { + self peer.ID +} + +func NewIndexerMessageValidator(self peer.ID) *IndexerMessageValidator { + return &IndexerMessageValidator{self: self} +} + +func (v *IndexerMessageValidator) Validate(ctx context.Context, pid peer.ID, msg *pubsub.Message) pubsub.ValidationResult { + // This chain-node should not be publishing its own messages. These are + // relayed from miner-nodes or index publishers. If a node appears to be + // local, reject it. + if pid == v.self { + log.Warnf("refusing to relay indexer message from self") + stats.Record(ctx, metrics.IndexerMessageValidationFailure.M(1)) + return pubsub.ValidationReject + } + stats.Record(ctx, metrics.IndexerMessageValidationSuccess.M(1)) + return pubsub.ValidationAccept +} diff --git a/metrics/metrics.go b/metrics/metrics.go index ddd149d8d9f..74549906989 100644 --- a/metrics/metrics.go +++ b/metrics/metrics.go @@ -76,6 +76,8 @@ var ( ChainNodeHeight = stats.Int64("chain/node_height", "Current Height of the node", stats.UnitDimensionless) ChainNodeHeightExpected = stats.Int64("chain/node_height_expected", "Expected Height of the node", stats.UnitDimensionless) ChainNodeWorkerHeight = stats.Int64("chain/node_worker_height", "Current Height of workers on the node", stats.UnitDimensionless) + IndexerMessageValidationFailure = stats.Int64("indexer/failure", "Counter for indexer message validation failures", stats.UnitDimensionless) + IndexerMessageValidationSuccess = stats.Int64("indexer/success", "Counter for indexer message validation successes", stats.UnitDimensionless) MessagePublished = stats.Int64("message/published", "Counter for total locally published messages", stats.UnitDimensionless) MessageReceived = stats.Int64("message/received", "Counter for total received messages", stats.UnitDimensionless) MessageValidationFailure = stats.Int64("message/failure", "Counter for message validation failures", stats.UnitDimensionless) @@ -191,6 +193,15 @@ var ( return view.Distribution(bounds...) }(), } + IndexerMessageValidationFailureView = &view.View{ + Measure: IndexerMessageValidationFailure, + Aggregation: view.Count(), + TagKeys: []tag.Key{FailureType, Local}, + } + IndexerMessageValidationSuccessView = &view.View{ + Measure: IndexerMessageValidationSuccess, + Aggregation: view.Count(), + } MessagePublishedView = &view.View{ Measure: MessagePublished, Aggregation: view.Count(), @@ -490,6 +501,8 @@ var ChainNodeViews = append([]*view.View{ BlockValidationSuccessView, BlockValidationDurationView, BlockDelayView, + IndexerMessageValidationFailureView, + IndexerMessageValidationSuccessView, MessagePublishedView, MessageReceivedView, MessageValidationFailureView, diff --git a/node/builder.go b/node/builder.go index 3f2e5950331..2f1ca182021 100644 --- a/node/builder.go +++ b/node/builder.go @@ -104,6 +104,8 @@ const ( HandleMigrateClientFundsKey HandlePaymentChannelManagerKey + RelayIndexerMessagesKey + // miner GetParamsKey HandleMigrateProviderFundsKey diff --git a/node/builder_chain.go b/node/builder_chain.go index 11283ec3a09..1e568397ea6 100644 --- a/node/builder_chain.go +++ b/node/builder_chain.go @@ -134,6 +134,8 @@ var ChainNode = Options( Override(new(*full.GasPriceCache), full.NewGasPriceCache), + Override(RelayIndexerMessagesKey, modules.RelayIndexerMessages), + // Lite node API ApplyIf(isLiteNode, Override(new(messagepool.Provider), messagepool.NewProviderLite), diff --git a/node/modules/lp2p/pubsub.go b/node/modules/lp2p/pubsub.go index 32b85daf347..8fa005fcdc2 100644 --- a/node/modules/lp2p/pubsub.go +++ b/node/modules/lp2p/pubsub.go @@ -333,6 +333,7 @@ func GossipSub(in GossipIn) (service *pubsub.PubSub, err error) { allowTopics := []string{ build.BlocksTopic(in.Nn), build.MessagesTopic(in.Nn), + build.IngestTopic(in.Nn), } allowTopics = append(allowTopics, drandTopics...) options = append(options, diff --git a/node/modules/services.go b/node/modules/services.go index 17d4a747641..db470aee20c 100644 --- a/node/modules/services.go +++ b/node/modules/services.go @@ -198,6 +198,36 @@ func HandleIncomingMessages(mctx helpers.MetricsCtx, lc fx.Lifecycle, ps *pubsub waitForSync(stmgr, pubsubMsgsSyncEpochs, subscribe) } +func RelayIndexerMessages(lc fx.Lifecycle, ps *pubsub.PubSub, nn dtypes.NetworkName, h host.Host) error { + topicName := build.IngestTopic(nn) + + v := sub.NewIndexerMessageValidator(h.ID()) + + if err := ps.RegisterTopicValidator(topicName, v.Validate); err != nil { + panic(err) + } + + topicHandle, err := ps.Join(topicName) + if err != nil { + return xerrors.Errorf("failed to join pubsub topic %s: %w", topicName, err) + } + cancelFunc, err := topicHandle.Relay() + if err != nil { + return xerrors.Errorf("failed to relay to pubsub messages for topic %s: %w", topicName, err) + } + + // Cancel message relay on shutdown. + lc.Append(fx.Hook{ + OnStop: func(_ context.Context) error { + cancelFunc() + return nil + }, + }) + + log.Infof("relaying messages for pubsub topic %s", topicName) + return nil +} + func NewLocalDiscovery(lc fx.Lifecycle, ds dtypes.MetadataDS) (*discoveryimpl.Local, error) { local, err := discoveryimpl.NewLocal(namespace.Wrap(ds, datastore.NewKey("/deals/local"))) if err != nil { From 4691b2b809e2aca7848eb7b545ebe9bfc9ddd6a5 Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Fri, 4 Feb 2022 12:15:01 +0400 Subject: [PATCH 092/385] changes to the indexer message relay PR --- build/params_shared_funcs.go | 4 +++- node/modules/lp2p/pubsub.go | 2 +- node/modules/services.go | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/build/params_shared_funcs.go b/build/params_shared_funcs.go index 9d5dfa34777..f03a35fecb8 100644 --- a/build/params_shared_funcs.go +++ b/build/params_shared_funcs.go @@ -13,7 +13,9 @@ import ( func BlocksTopic(netName dtypes.NetworkName) string { return "/fil/blocks/" + string(netName) } func MessagesTopic(netName dtypes.NetworkName) string { return "/fil/msgs/" + string(netName) } -func IngestTopic(netName dtypes.NetworkName) string { return "/indexer/ingest/" + string(netName) } +func IndexerIngestTopic(netName dtypes.NetworkName) string { + return "/indexer/ingest/" + string(netName) +} func DhtProtocolName(netName dtypes.NetworkName) protocol.ID { return protocol.ID("/fil/kad/" + string(netName)) } diff --git a/node/modules/lp2p/pubsub.go b/node/modules/lp2p/pubsub.go index 8fa005fcdc2..14f10045085 100644 --- a/node/modules/lp2p/pubsub.go +++ b/node/modules/lp2p/pubsub.go @@ -333,7 +333,7 @@ func GossipSub(in GossipIn) (service *pubsub.PubSub, err error) { allowTopics := []string{ build.BlocksTopic(in.Nn), build.MessagesTopic(in.Nn), - build.IngestTopic(in.Nn), + build.IndexerIngestTopic(in.Nn), } allowTopics = append(allowTopics, drandTopics...) options = append(options, diff --git a/node/modules/services.go b/node/modules/services.go index d3b01ac6bbe..d0095075d6f 100644 --- a/node/modules/services.go +++ b/node/modules/services.go @@ -199,12 +199,12 @@ func HandleIncomingMessages(mctx helpers.MetricsCtx, lc fx.Lifecycle, ps *pubsub } func RelayIndexerMessages(lc fx.Lifecycle, ps *pubsub.PubSub, nn dtypes.NetworkName, h host.Host) error { - topicName := build.IngestTopic(nn) + topicName := build.IndexerIngestTopic(nn) v := sub.NewIndexerMessageValidator(h.ID()) if err := ps.RegisterTopicValidator(topicName, v.Validate); err != nil { - panic(err) + return xerrors.Errorf("failed to register validator for topic %s, err: %w", topicName, err) } topicHandle, err := ps.Join(topicName) From ca46a79144e18c897f59882c747446741ba0d508 Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Fri, 4 Feb 2022 13:04:07 +0400 Subject: [PATCH 093/385] protect full node connection --- markets/idxprov/mesh.go | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/markets/idxprov/mesh.go b/markets/idxprov/mesh.go index d073bbb1e07..3df990e1b2e 100644 --- a/markets/idxprov/mesh.go +++ b/markets/idxprov/mesh.go @@ -4,6 +4,10 @@ import ( "context" "fmt" + "github.com/libp2p/go-libp2p-core/network" + + "github.com/libp2p/go-libp2p-core/peer" + "github.com/filecoin-project/lotus/api/v1api" logging "github.com/ipfs/go-log/v2" @@ -21,16 +25,25 @@ type Libp2pMeshCreator struct { } func (mc Libp2pMeshCreator) Connect(ctx context.Context) error { - addrs, err := mc.fullnodeApi.NetAddrsListen(ctx) + faddrs, err := mc.fullnodeApi.NetAddrsListen(ctx) if err != nil { return err } - if err := mc.idxProvHost.Connect(ctx, addrs); err != nil { + // if we already have a connection to the full node, there's nothing to do here + if mc.idxProvHost.Network().Connectedness(faddrs.ID) == network.Connected { + return nil + } + + // otherwise, connect to the full node, ask it to protect the connection and protect the connection on our end too + if err := mc.idxProvHost.Connect(ctx, faddrs); err != nil { return fmt.Errorf("failed to connect index provider host with the full node: %w", err) } - mc.idxProvHost.ConnManager().Protect(addrs.ID, "markets") - log.Debugw("successfully connected to full node", "fullNodeInfo", addrs.String()) + mc.idxProvHost.ConnManager().Protect(faddrs.ID, "markets") + mc.fullnodeApi.NetProtectAdd(ctx, []peer.ID{mc.idxProvHost.ID()}) + + log.Debugw("successfully connected to full node and asked it protect indexer provider peer conn", "fullNodeInfo", faddrs.String(), + "idxProviderPeerId", mc.idxProvHost.ID()) return nil } From daac7f298862272c3f7ac6ad9fd5d1021c9a882b Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Fri, 4 Feb 2022 13:55:26 +0400 Subject: [PATCH 094/385] fix lint --- markets/idxprov/mesh.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/markets/idxprov/mesh.go b/markets/idxprov/mesh.go index 3df990e1b2e..75f075742dd 100644 --- a/markets/idxprov/mesh.go +++ b/markets/idxprov/mesh.go @@ -40,7 +40,9 @@ func (mc Libp2pMeshCreator) Connect(ctx context.Context) error { return fmt.Errorf("failed to connect index provider host with the full node: %w", err) } mc.idxProvHost.ConnManager().Protect(faddrs.ID, "markets") - mc.fullnodeApi.NetProtectAdd(ctx, []peer.ID{mc.idxProvHost.ID()}) + if err := mc.fullnodeApi.NetProtectAdd(ctx, []peer.ID{mc.idxProvHost.ID()}); err != nil { + return fmt.Errorf("failed to call NetProtectAdd on the full node, err: %w", err) + } log.Debugw("successfully connected to full node and asked it protect indexer provider peer conn", "fullNodeInfo", faddrs.String(), "idxProviderPeerId", mc.idxProvHost.ID()) From eb8296120b6a3ade2d9c92bde345e6ab02802c73 Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Fri, 4 Feb 2022 13:58:47 +0400 Subject: [PATCH 095/385] changes to mesh creation code --- markets/idxprov/mesh.go | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/markets/idxprov/mesh.go b/markets/idxprov/mesh.go index 75f075742dd..5b580c7fda4 100644 --- a/markets/idxprov/mesh.go +++ b/markets/idxprov/mesh.go @@ -4,8 +4,6 @@ import ( "context" "fmt" - "github.com/libp2p/go-libp2p-core/network" - "github.com/libp2p/go-libp2p-core/peer" "github.com/filecoin-project/lotus/api/v1api" @@ -27,19 +25,14 @@ type Libp2pMeshCreator struct { func (mc Libp2pMeshCreator) Connect(ctx context.Context) error { faddrs, err := mc.fullnodeApi.NetAddrsListen(ctx) if err != nil { - return err - } - - // if we already have a connection to the full node, there's nothing to do here - if mc.idxProvHost.Network().Connectedness(faddrs.ID) == network.Connected { - return nil + return fmt.Errorf("failed to fetch full node listen addrs, err: %w", err) } // otherwise, connect to the full node, ask it to protect the connection and protect the connection on our end too if err := mc.idxProvHost.Connect(ctx, faddrs); err != nil { return fmt.Errorf("failed to connect index provider host with the full node: %w", err) } - mc.idxProvHost.ConnManager().Protect(faddrs.ID, "markets") + mc.idxProvHost.ConnManager().Protect(faddrs.ID, "index-provider-gossipsub") if err := mc.fullnodeApi.NetProtectAdd(ctx, []peer.ID{mc.idxProvHost.ID()}); err != nil { return fmt.Errorf("failed to call NetProtectAdd on the full node, err: %w", err) } From 4cddfd1074ba9d78871cff6978518e30653ef314 Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 4 Feb 2022 14:29:50 +0200 Subject: [PATCH 096/385] background cold object reification --- blockstore/splitstore/splitstore.go | 14 ++ blockstore/splitstore/splitstore_reify.go | 181 ++++++++++++++++++++++ 2 files changed, 195 insertions(+) create mode 100644 blockstore/splitstore/splitstore_reify.go diff --git a/blockstore/splitstore/splitstore.go b/blockstore/splitstore/splitstore.go index 6a65e01df36..0d7ad07797e 100644 --- a/blockstore/splitstore/splitstore.go +++ b/blockstore/splitstore/splitstore.go @@ -161,6 +161,12 @@ type SplitStore struct { txnSyncCond sync.Cond txnSync bool + // background cold object reification + reifyMx sync.Mutex + reifyCond sync.Cond + reifyPend map[cid.Cid]struct{} + reifyInProgress map[cid.Cid]struct{} + // registered protectors protectors []func(func(cid.Cid) error) error } @@ -202,6 +208,10 @@ func Open(path string, ds dstore.Datastore, hot, cold bstore.Blockstore, cfg *Co ss.txnSyncCond.L = &ss.txnSyncMx ss.ctx, ss.cancel = context.WithCancel(context.Background()) + ss.reifyCond.L = &ss.reifyMx + ss.reifyPend = make(map[cid.Cid]struct{}) + ss.reifyInProgress = make(map[cid.Cid]struct{}) + if enableDebugLog { ss.debug, err = openDebugLog(path) if err != nil { @@ -645,6 +655,9 @@ func (s *SplitStore) Start(chain ChainAccessor, us stmgr.UpgradeSchedule) error } } + // spawn the reifier + go s.reifyOrchestrator() + // watch the chain chain.SubscribeHeadChanges(s.HeadChange) @@ -676,6 +689,7 @@ func (s *SplitStore) Close() error { } } + s.reifyCond.Broadcast() s.cancel() return multierr.Combine(s.markSetEnv.Close(), s.debug.Close()) } diff --git a/blockstore/splitstore/splitstore_reify.go b/blockstore/splitstore/splitstore_reify.go new file mode 100644 index 00000000000..f60100d8aec --- /dev/null +++ b/blockstore/splitstore/splitstore_reify.go @@ -0,0 +1,181 @@ +package splitstore + +import ( + "runtime" + "sync/atomic" + + "golang.org/x/xerrors" + + blocks "github.com/ipfs/go-block-format" + cid "github.com/ipfs/go-cid" +) + +func (s *SplitStore) reifyColdObject(c cid.Cid) { + if isUnitaryObject(c) { + return + } + + s.reifyMx.Lock() + defer s.reifyMx.Unlock() + + _, ok := s.reifyInProgress[c] + if ok { + return + } + + s.reifyPend[c] = struct{}{} + s.reifyCond.Broadcast() +} + +func (s *SplitStore) reifyOrchestrator() { + workers := runtime.NumCPU() / 4 + if workers < 2 { + workers = 2 + } + + workch := make(chan cid.Cid, workers) + defer close(workch) + + for i := 0; i < workers; i++ { + go s.reifyWorker(workch) + } + + for { + s.reifyMx.Lock() + for len(s.reifyPend) == 0 && atomic.LoadInt32(&s.closing) == 0 { + s.reifyCond.Wait() + } + + if atomic.LoadInt32(&s.closing) != 0 { + s.reifyMx.Unlock() + return + } + + reifyPend := s.reifyPend + s.reifyPend = make(map[cid.Cid]struct{}) + s.reifyMx.Unlock() + + for c := range reifyPend { + select { + case workch <- c: + case <-s.ctx.Done(): + return + } + } + } +} + +func (s *SplitStore) reifyWorker(workch chan cid.Cid) { + for c := range workch { + s.doReify(c) + } +} + +func (s *SplitStore) doReify(c cid.Cid) { + var toreify, totrack, toforget []cid.Cid + + defer func() { + s.reifyMx.Lock() + defer s.reifyMx.Unlock() + + for _, c := range toreify { + delete(s.reifyInProgress, c) + } + for _, c := range totrack { + delete(s.reifyInProgress, c) + } + for _, c := range toforget { + delete(s.reifyInProgress, c) + } + }() + + s.txnLk.RLock() + defer s.txnLk.RUnlock() + + err := s.walkObject(c, newTmpVisitor(), + func(c cid.Cid) error { + if isUnitaryObject(c) { + return errStopWalk + } + + s.reifyMx.Lock() + _, inProgress := s.reifyInProgress[c] + if !inProgress { + s.reifyInProgress[c] = struct{}{} + } + s.reifyMx.Unlock() + + if inProgress { + return errStopWalk + } + + has, err := s.hot.Has(s.ctx, c) + if err != nil { + return xerrors.Errorf("error checking hotstore: %w", err) + } + + if has { + if s.txnMarkSet != nil { + hasMark, err := s.txnMarkSet.Has(c) + if err != nil { + log.Warnf("error checking markset: %s", err) + } else if hasMark { + toforget = append(toforget, c) + return errStopWalk + } + } else { + totrack = append(totrack, c) + return errStopWalk + } + } + + toreify = append(toreify, c) + return nil + }) + + if err != nil { + log.Warnf("error walking cold object for reification (cid: %s): %s", c, err) + return + } + + log.Debugf("reifying %d objects rooted at %s", len(toreify), c) + + batch := make([]blocks.Block, 0, len(toreify)) + for _, c := range toreify { + blk, err := s.cold.Get(s.ctx, c) + if err != nil { + log.Warnf("error retrieving cold object for reification (cid: %s): %s", c, err) + continue + } + + if err := s.checkClosing(); err != nil { + return + } + + batch = append(batch, blk) + } + + if len(batch) > 0 { + err = s.hot.PutMany(s.ctx, batch) + if err != nil { + log.Warnf("error reifying cold object (cid: %s): %s", c, err) + return + } + } + + if s.txnMarkSet != nil { + if len(toreify) > 0 { + s.markLiveRefs(toreify) + } + if len(totrack) > 0 { + s.markLiveRefs(totrack) + } + } else { + if len(toreify) > 0 { + s.trackTxnRefMany(toreify) + } + if len(totrack) > 0 { + s.trackTxnRefMany(totrack) + } + } +} From 268366e4467d179c2b9a2e4350e2b0078612803c Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 4 Feb 2022 16:07:58 +0200 Subject: [PATCH 097/385] cold object reification context option --- blockstore/context.go | 21 +++++++++++++++++++++ blockstore/splitstore/splitstore.go | 21 +++++++++++++++++++-- 2 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 blockstore/context.go diff --git a/blockstore/context.go b/blockstore/context.go new file mode 100644 index 00000000000..61cb93b30f3 --- /dev/null +++ b/blockstore/context.go @@ -0,0 +1,21 @@ +package blockstore + +import ( + "context" +) + +type hotViewKey struct{} + +var hotView = hotViewKey{} + +// WithHotView constructs a new context with an option that provides a hint to the blockstore +// (e.g. the splitstore) that the object (and its ipld references) should be kept hot. +func WithHotView(ctx context.Context) context.Context { + return context.WithValue(ctx, hotView, struct{}{}) +} + +// GetHotView returns true if the hot view option is set in the context +func GetHotView(ctx context.Context) bool { + v := ctx.Value(hotView) + return v != nil +} diff --git a/blockstore/splitstore/splitstore.go b/blockstore/splitstore/splitstore.go index 0d7ad07797e..5c2cf7203f7 100644 --- a/blockstore/splitstore/splitstore.go +++ b/blockstore/splitstore/splitstore.go @@ -274,7 +274,13 @@ func (s *SplitStore) Has(ctx context.Context, cid cid.Cid) (bool, error) { return true, nil } - return s.cold.Has(ctx, cid) + has, err = s.cold.Has(ctx, cid) + if has && bstore.GetHotView(ctx) { + s.reifyColdObject(cid) + } + + return has, err + } func (s *SplitStore) Get(ctx context.Context, cid cid.Cid) (blocks.Block, error) { @@ -318,8 +324,11 @@ func (s *SplitStore) Get(ctx context.Context, cid cid.Cid) (blocks.Block, error) blk, err = s.cold.Get(ctx, cid) if err == nil { - stats.Record(s.ctx, metrics.SplitstoreMiss.M(1)) + if bstore.GetHotView(ctx) { + s.reifyColdObject(cid) + } + stats.Record(s.ctx, metrics.SplitstoreMiss.M(1)) } return blk, err @@ -369,6 +378,10 @@ func (s *SplitStore) GetSize(ctx context.Context, cid cid.Cid) (int, error) { size, err = s.cold.GetSize(ctx, cid) if err == nil { + if bstore.GetHotView(ctx) { + s.reifyColdObject(cid) + } + stats.Record(s.ctx, metrics.SplitstoreMiss.M(1)) } return size, err @@ -546,6 +559,10 @@ func (s *SplitStore) View(ctx context.Context, cid cid.Cid, cb func([]byte) erro err = s.cold.View(ctx, cid, cb) if err == nil { + if bstore.GetHotView(ctx) { + s.reifyColdObject(cid) + } + stats.Record(s.ctx, metrics.SplitstoreMiss.M(1)) } return err From 929a05e8981c1b08b1e3619a2c7764258b933b6c Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 4 Feb 2022 16:16:34 +0200 Subject: [PATCH 098/385] add reification test --- blockstore/splitstore/splitstore_test.go | 130 +++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/blockstore/splitstore/splitstore_test.go b/blockstore/splitstore/splitstore_test.go index 27d58bf1043..6b7e60e6c50 100644 --- a/blockstore/splitstore/splitstore_test.go +++ b/blockstore/splitstore/splitstore_test.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "io/ioutil" + "math/rand" "os" "sync" "sync/atomic" @@ -387,6 +388,135 @@ func TestSplitStoreSuppressCompactionNearUpgrade(t *testing.T) { } } +func testSplitStoreReification(t *testing.T, f func(context.Context, blockstore.Blockstore, cid.Cid) error) { + ds := dssync.MutexWrap(datastore.NewMapDatastore()) + hot := newMockStore() + cold := newMockStore() + + mkRandomBlock := func() blocks.Block { + data := make([]byte, 128) + _, err := rand.Read(data) + if err != nil { + t.Fatal(err) + } + + return blocks.NewBlock(data) + } + + block1 := mkRandomBlock() + block2 := mkRandomBlock() + block3 := mkRandomBlock() + + hdr := mock.MkBlock(nil, 0, 0) + hdr.Messages = block1.Cid() + hdr.ParentMessageReceipts = block2.Cid() + hdr.ParentStateRoot = block3.Cid() + block4, err := hdr.ToStorageBlock() + if err != nil { + t.Fatal(err) + } + + allBlocks := []blocks.Block{block1, block2, block3, block4} + for _, blk := range allBlocks { + err := cold.Put(context.Background(), blk) + if err != nil { + t.Fatal(err) + } + } + + path, err := ioutil.TempDir("", "splitstore.*") + if err != nil { + t.Fatal(err) + } + + t.Cleanup(func() { + _ = os.RemoveAll(path) + }) + + ss, err := Open(path, ds, hot, cold, &Config{MarkSetType: "map"}) + if err != nil { + t.Fatal(err) + } + defer ss.Close() //nolint + + ss.warmupEpoch = 1 + go ss.reifyOrchestrator() + + waitForReification := func() { + for { + ss.reifyMx.Lock() + ready := len(ss.reifyPend) == 0 && len(ss.reifyInProgress) == 0 + ss.reifyMx.Unlock() + + if ready { + return + } + + time.Sleep(time.Millisecond) + } + } + + // first access using the standard view + err = f(context.Background(), ss, block4.Cid()) + if err != nil { + t.Fatal(err) + } + + // nothing should be reified + waitForReification() + for _, blk := range allBlocks { + has, err := hot.Has(context.Background(), blk.Cid()) + if err != nil { + t.Fatal(err) + } + + if has { + t.Fatal("block unexpectedly reified") + } + } + + // now make the hot/reifying view and ensure access reifies + err = f(blockstore.WithHotView(context.Background()), ss, block4.Cid()) + if err != nil { + t.Fatal(err) + } + + // everything should be reified + waitForReification() + for i, blk := range allBlocks { + has, err := hot.Has(context.Background(), blk.Cid()) + if err != nil { + t.Fatal(err) + } + + if !has { + t.Fatalf("block%d was not reified", i+1) + } + } +} + +func TestSplitStoreReification(t *testing.T) { + t.Log("test reification with Has") + testSplitStoreReification(t, func(ctx context.Context, s blockstore.Blockstore, c cid.Cid) error { + _, err := s.Has(ctx, c) + return err + }) + t.Log("test reification with Get") + testSplitStoreReification(t, func(ctx context.Context, s blockstore.Blockstore, c cid.Cid) error { + _, err := s.Get(ctx, c) + return err + }) + t.Log("test reification with GetSize") + testSplitStoreReification(t, func(ctx context.Context, s blockstore.Blockstore, c cid.Cid) error { + _, err := s.GetSize(ctx, c) + return err + }) + t.Log("test reification with View") + testSplitStoreReification(t, func(ctx context.Context, s blockstore.Blockstore, c cid.Cid) error { + return s.View(ctx, c, func(_ []byte) error { return nil }) + }) +} + type mockChain struct { t testing.TB From 73c741f20ce4fff4bd15824dd75e2110bcfa4c8b Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 4 Feb 2022 16:19:28 +0200 Subject: [PATCH 099/385] reify cold objects on block validation/application --- chain/consensus/filcns/compute_state.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/chain/consensus/filcns/compute_state.go b/chain/consensus/filcns/compute_state.go index f7f6284d0a0..34bc439ac19 100644 --- a/chain/consensus/filcns/compute_state.go +++ b/chain/consensus/filcns/compute_state.go @@ -32,6 +32,7 @@ import ( /* inline-gen end */ + "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/builtin" @@ -106,7 +107,7 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, sm *stmgr.StateManager LookbackState: stmgr.LookbackStateGetterForTipset(sm, ts), } - return sm.VMConstructor()(ctx, vmopt) + return sm.VMConstructor()(blockstore.WithHotView(ctx), vmopt) } runCron := func(vmCron *vm.VM, epoch abi.ChainEpoch) error { From 9d92b6eb9213cfd968fda564bc63fb16aa5bad5d Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 4 Feb 2022 16:57:08 +0200 Subject: [PATCH 100/385] correctly wrap hotview in the context for compute_state --- chain/consensus/filcns/compute_state.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/chain/consensus/filcns/compute_state.go b/chain/consensus/filcns/compute_state.go index 34bc439ac19..44b79285420 100644 --- a/chain/consensus/filcns/compute_state.go +++ b/chain/consensus/filcns/compute_state.go @@ -93,6 +93,7 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, sm *stmgr.StateManager partDone() }() + ctx = blockstore.WithHotView(ctx) makeVmWithBaseStateAndEpoch := func(base cid.Cid, e abi.ChainEpoch) (*vm.VM, error) { vmopt := &vm.VMOpts{ StateBase: base, @@ -107,7 +108,7 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, sm *stmgr.StateManager LookbackState: stmgr.LookbackStateGetterForTipset(sm, ts), } - return sm.VMConstructor()(blockstore.WithHotView(ctx), vmopt) + return sm.VMConstructor()(ctx, vmopt) } runCron := func(vmCron *vm.VM, epoch abi.ChainEpoch) error { From 2a669b95fbd898942440330a9dd6bdb0d051e374 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Thu, 16 Dec 2021 22:38:13 -0500 Subject: [PATCH 101/385] :Hook up the FVM --- chain/consensus/filcns/compute_state.go | 9 +- chain/vm/fvm.go | 154 ++++++++++++++++++++++++ chain/vm/vm.go | 2 + chain/vm/vmi.go | 14 +++ extern/filecoin-ffi | 2 +- 5 files changed, 178 insertions(+), 3 deletions(-) create mode 100644 chain/vm/fvm.go create mode 100644 chain/vm/vmi.go diff --git a/chain/consensus/filcns/compute_state.go b/chain/consensus/filcns/compute_state.go index f7f6284d0a0..37e78874db2 100644 --- a/chain/consensus/filcns/compute_state.go +++ b/chain/consensus/filcns/compute_state.go @@ -2,6 +2,7 @@ package filcns import ( "context" + "os" "sync/atomic" "github.com/filecoin-project/lotus/chain/rand" @@ -92,7 +93,7 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, sm *stmgr.StateManager partDone() }() - makeVmWithBaseStateAndEpoch := func(base cid.Cid, e abi.ChainEpoch) (*vm.VM, error) { + makeVmWithBaseStateAndEpoch := func(base cid.Cid, e abi.ChainEpoch) (vm.VMI, error) { vmopt := &vm.VMOpts{ StateBase: base, Epoch: e, @@ -106,10 +107,14 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, sm *stmgr.StateManager LookbackState: stmgr.LookbackStateGetterForTipset(sm, ts), } + if os.Getenv("LOTUS_USE_FVM_DOESNT_WORK_YET") == "1" { + return vm.NewFVM(ctx, vmopt) + } + return sm.VMConstructor()(ctx, vmopt) } - runCron := func(vmCron *vm.VM, epoch abi.ChainEpoch) error { + runCron := func(vmCron vm.VMI, epoch abi.ChainEpoch) error { cronMsg := &types.Message{ To: cron.Address, From: builtin.SystemActorAddr, diff --git a/chain/vm/fvm.go b/chain/vm/fvm.go new file mode 100644 index 00000000000..0630c145bdf --- /dev/null +++ b/chain/vm/fvm.go @@ -0,0 +1,154 @@ +package vm + +import ( + "context" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/crypto" + "github.com/filecoin-project/lotus/chain/actors/aerrors" + "github.com/filecoin-project/specs-actors/v7/actors/runtime" + + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/exitcode" + + "golang.org/x/xerrors" + + "github.com/filecoin-project/lotus/blockstore" + "github.com/filecoin-project/lotus/chain/state" + cbor "github.com/ipfs/go-ipld-cbor" + + ffi "github.com/filecoin-project/filecoin-ffi" + + "github.com/filecoin-project/lotus/chain/types" + "github.com/ipfs/go-cid" +) + +var _ VMI = (*FVM)(nil) + +type Extern interface { + GetRandomnessFromTickets(personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) abi.Randomness + GetRandomnessFromBeacon(personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) abi.Randomness + VerifyConsensusFault(a, b, extra []byte) (address.Address, abi.ChainEpoch, runtime.ConsensusFaultType) +} +type FvmExtern struct { + rand Rand +} + +func (e *FvmExtern) GetRandomnessFromTickets(personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) abi.Randomness { + res, err := e.rand.GetChainRandomness(context.Background(), personalization, randEpoch, entropy) + + if err != nil { + panic(aerrors.Fatalf("could not get ticket randomness: %s", err)) + } + return res +} + +func (e *FvmExtern) GetRandomnessFromBeacon(personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) abi.Randomness { + res, err := e.rand.GetBeaconRandomness(context.Background(), personalization, randEpoch, entropy) + + if err != nil { + panic(aerrors.Fatalf("could not get ticket randomness: %s", err)) + } + return res +} + +type FVM struct { + machineId uint64 + extern FvmExtern +} + +func NewFVM(ctx context.Context, opts *VMOpts) (*FVM, error) { + buf := blockstore.NewBuffered(opts.Bstore) + cst := cbor.NewCborStore(buf) + state, err := state.LoadStateTree(cst, opts.StateBase) + if err != nil { + return nil, err + } + + baseCirc, err := opts.CircSupplyCalc(ctx, opts.Epoch, state) + if err != nil { + return nil, err + } + + id, err := ffi.CreateFVM(0, opts.Epoch, opts.BaseFee, baseCirc, opts.NetworkVersion, opts.StateBase) + if err != nil { + return nil, err + } + + return &FVM{ + extern: FvmExtern{rand: opts.Rand}, + machineId: id, + }, nil +} + +func (vm *FVM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, error) { + msgBytes, err := cmsg.VMMessage().Serialize() + if err != nil { + return nil, xerrors.Errorf("serializing msg: %w", err) + } + + ret, err := ffi.ApplyMessage(vm.machineId, msgBytes) + if err != nil { + return nil, xerrors.Errorf("applying msg: %w", err) + } + + return &ApplyRet{ + MessageReceipt: types.MessageReceipt{ + Return: ret.Return, + ExitCode: exitcode.ExitCode(ret.ExitCode), + GasUsed: ret.GasUsed, + }, + GasCosts: &GasOutputs{ + // TODO: do the other optional fields eventually + BaseFeeBurn: abi.TokenAmount{}, + OverEstimationBurn: abi.TokenAmount{}, + MinerPenalty: ret.MinerPenalty, + MinerTip: ret.MinerTip, + Refund: abi.TokenAmount{}, + GasRefund: 0, + GasBurned: 0, + }, + // TODO: do these eventually, not consensus critical + ActorErr: nil, + ExecutionTrace: types.ExecutionTrace{}, + Duration: 0, + }, nil +} + +func (vm *FVM) ApplyImplicitMessage(ctx context.Context, cmsg *types.Message) (*ApplyRet, error) { + msgBytes, err := cmsg.VMMessage().Serialize() + if err != nil { + return nil, xerrors.Errorf("serializing msg: %w", err) + } + + ret, err := ffi.ApplyMessage(vm.machineId, msgBytes) + if err != nil { + return nil, xerrors.Errorf("applying msg: %w", err) + } + + return &ApplyRet{ + MessageReceipt: types.MessageReceipt{ + Return: ret.Return, + ExitCode: exitcode.ExitCode(ret.ExitCode), + GasUsed: ret.GasUsed, + }, + GasCosts: &GasOutputs{ + // TODO: do the other optional fields eventually + BaseFeeBurn: abi.TokenAmount{}, + OverEstimationBurn: abi.TokenAmount{}, + MinerPenalty: ret.MinerPenalty, + MinerTip: ret.MinerTip, + Refund: abi.TokenAmount{}, + GasRefund: 0, + GasBurned: 0, + }, + // TODO: do these eventually, not consensus critical + ActorErr: nil, + ExecutionTrace: types.ExecutionTrace{}, + Duration: 0, + }, nil +} + +func (vm *FVM) Flush(ctx context.Context) (cid.Cid, error) { + return cid.Undef, nil +} diff --git a/chain/vm/vm.go b/chain/vm/vm.go index 1ab97bc33f8..2ee732d5e20 100644 --- a/chain/vm/vm.go +++ b/chain/vm/vm.go @@ -201,6 +201,8 @@ type ( LookbackStateGetter func(context.Context, abi.ChainEpoch) (*state.StateTree, error) ) +var _ VMI = (*VM)(nil) + type VM struct { cstate *state.StateTree cst *cbor.BasicIpldStore diff --git a/chain/vm/vmi.go b/chain/vm/vmi.go new file mode 100644 index 00000000000..4903354d221 --- /dev/null +++ b/chain/vm/vmi.go @@ -0,0 +1,14 @@ +package vm + +import ( + "context" + + "github.com/filecoin-project/lotus/chain/types" + "github.com/ipfs/go-cid" +) + +type VMI interface { + ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, error) + ApplyImplicitMessage(ctx context.Context, msg *types.Message) (*ApplyRet, error) + Flush(ctx context.Context) (cid.Cid, error) +} diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index e660df5616e..7e1f3a991e4 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit e660df5616e397b2d8ac316f45ddfa7a44637971 +Subproject commit 7e1f3a991e410a71ed9ef33becee8d56d5cb9d26 From fc74a6c8cacae697d9553313f7e17271150d59cb Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 31 Jan 2022 02:31:58 -0800 Subject: [PATCH 102/385] update fvm/ffi bindings --- chain/vm/fvm.go | 50 ++++++++++++++------------------------------- extern/filecoin-ffi | 2 +- go.mod | 4 +--- go.sum | 7 ++----- 4 files changed, 19 insertions(+), 44 deletions(-) diff --git a/chain/vm/fvm.go b/chain/vm/fvm.go index 0630c145bdf..f864966c37d 100644 --- a/chain/vm/fvm.go +++ b/chain/vm/fvm.go @@ -3,11 +3,6 @@ package vm import ( "context" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/crypto" - "github.com/filecoin-project/lotus/chain/actors/aerrors" - "github.com/filecoin-project/specs-actors/v7/actors/runtime" - "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/exitcode" @@ -18,6 +13,7 @@ import ( cbor "github.com/ipfs/go-ipld-cbor" ffi "github.com/filecoin-project/filecoin-ffi" + ffi_cgo "github.com/filecoin-project/filecoin-ffi/cgo" "github.com/filecoin-project/lotus/chain/types" "github.com/ipfs/go-cid" @@ -25,36 +21,18 @@ import ( var _ VMI = (*FVM)(nil) -type Extern interface { - GetRandomnessFromTickets(personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) abi.Randomness - GetRandomnessFromBeacon(personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) abi.Randomness - VerifyConsensusFault(a, b, extra []byte) (address.Address, abi.ChainEpoch, runtime.ConsensusFaultType) -} type FvmExtern struct { - rand Rand -} - -func (e *FvmExtern) GetRandomnessFromTickets(personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) abi.Randomness { - res, err := e.rand.GetChainRandomness(context.Background(), personalization, randEpoch, entropy) - - if err != nil { - panic(aerrors.Fatalf("could not get ticket randomness: %s", err)) - } - return res + Rand + blockstore.Blockstore } -func (e *FvmExtern) GetRandomnessFromBeacon(personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) abi.Randomness { - res, err := e.rand.GetBeaconRandomness(context.Background(), personalization, randEpoch, entropy) - - if err != nil { - panic(aerrors.Fatalf("could not get ticket randomness: %s", err)) - } - return res +func (x *FvmExtern) VerifyConsensusFault(ctx context.Context, h1, h2, extra []byte) (*ffi_cgo.ConsensusFault, error) { + // TODO + panic("unimplemented") } type FVM struct { - machineId uint64 - extern FvmExtern + fvm *ffi.FVM } func NewFVM(ctx context.Context, opts *VMOpts) (*FVM, error) { @@ -70,14 +48,16 @@ func NewFVM(ctx context.Context, opts *VMOpts) (*FVM, error) { return nil, err } - id, err := ffi.CreateFVM(0, opts.Epoch, opts.BaseFee, baseCirc, opts.NetworkVersion, opts.StateBase) + fvm, err := ffi.CreateFVM(0, + &FvmExtern{Rand: opts.Rand, Blockstore: opts.Bstore}, + opts.Epoch, opts.BaseFee, baseCirc, opts.NetworkVersion, opts.StateBase, + ) if err != nil { return nil, err } return &FVM{ - extern: FvmExtern{rand: opts.Rand}, - machineId: id, + fvm: fvm, }, nil } @@ -87,7 +67,7 @@ func (vm *FVM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet return nil, xerrors.Errorf("serializing msg: %w", err) } - ret, err := ffi.ApplyMessage(vm.machineId, msgBytes) + ret, err := vm.fvm.ApplyMessage(msgBytes) if err != nil { return nil, xerrors.Errorf("applying msg: %w", err) } @@ -121,7 +101,7 @@ func (vm *FVM) ApplyImplicitMessage(ctx context.Context, cmsg *types.Message) (* return nil, xerrors.Errorf("serializing msg: %w", err) } - ret, err := ffi.ApplyMessage(vm.machineId, msgBytes) + ret, err := vm.fvm.ApplyMessage(msgBytes) if err != nil { return nil, xerrors.Errorf("applying msg: %w", err) } @@ -150,5 +130,5 @@ func (vm *FVM) ApplyImplicitMessage(ctx context.Context, cmsg *types.Message) (* } func (vm *FVM) Flush(ctx context.Context) (cid.Cid, error) { - return cid.Undef, nil + return vm.fvm.Flush() } diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index 7e1f3a991e4..a7295282a51 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit 7e1f3a991e410a71ed9ef33becee8d56d5cb9d26 +Subproject commit a7295282a51d2b24e1e02e228a5b9f5f7b412bc2 diff --git a/go.mod b/go.mod index 16602b398ec..1c1da6149ea 100644 --- a/go.mod +++ b/go.mod @@ -50,7 +50,7 @@ require ( github.com/filecoin-project/specs-actors/v4 v4.0.1 github.com/filecoin-project/specs-actors/v5 v5.0.4 github.com/filecoin-project/specs-actors/v6 v6.0.1 - github.com/filecoin-project/specs-actors/v7 v7.0.0-rc1 + github.com/filecoin-project/specs-actors/v7 v7.0.0-rc1.0.20220118005651-2470cb39827e github.com/filecoin-project/specs-storage v0.1.1-0.20211228030229-6d460d25a0c9 github.com/filecoin-project/test-vectors/schema v0.0.5 github.com/gbrlsnchs/jwt/v3 v3.0.1 @@ -159,7 +159,6 @@ require ( go.uber.org/fx v1.9.0 go.uber.org/multierr v1.7.0 go.uber.org/zap v1.19.1 - golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b // indirect golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sys v0.0.0-20211209171907-798191bca915 @@ -168,7 +167,6 @@ require ( golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 gopkg.in/cheggaaa/pb.v1 v1.0.28 gotest.tools v2.2.0+incompatible - lukechampine.com/blake3 v1.1.7 // indirect ) replace github.com/filecoin-project/filecoin-ffi => ./extern/filecoin-ffi diff --git a/go.sum b/go.sum index 817c9e1ba35..dd6abce8eab 100644 --- a/go.sum +++ b/go.sum @@ -321,7 +321,6 @@ github.com/filecoin-project/go-data-transfer v1.14.0/go.mod h1:wNJKhaLLYBJDM3VFv github.com/filecoin-project/go-ds-versioning v0.0.0-20211206185234-508abd7c2aff/go.mod h1:C9/l9PnB1+mwPa26BBVpCjG/XQCB0yj/q5CK2J8X1I4= github.com/filecoin-project/go-ds-versioning v0.1.1 h1:JiyBqaQlwC+UM0WhcBtVEeT3XrX59mQhT8U3p7nu86o= github.com/filecoin-project/go-ds-versioning v0.1.1/go.mod h1:C9/l9PnB1+mwPa26BBVpCjG/XQCB0yj/q5CK2J8X1I4= -github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commcid v0.1.0 h1:3R4ds1A9r6cr8mvZBfMYxTS88OqLYEo6roi+GiIeOh8= github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= @@ -378,10 +377,9 @@ github.com/filecoin-project/specs-actors/v5 v5.0.4/go.mod h1:5BAKRAMsOOlD8+qCw4U github.com/filecoin-project/specs-actors/v6 v6.0.0/go.mod h1:V1AYfi5GkHXipx1mnVivoICZh3wtwPxDVuds+fbfQtk= github.com/filecoin-project/specs-actors/v6 v6.0.1 h1:laxvHNsvrq83Y9n+W7znVCePi3oLyRf0Rkl4jFO8Wew= github.com/filecoin-project/specs-actors/v6 v6.0.1/go.mod h1:V1AYfi5GkHXipx1mnVivoICZh3wtwPxDVuds+fbfQtk= -github.com/filecoin-project/specs-actors/v7 v7.0.0-20211117170924-fd07a4c7dff9/go.mod h1:p6LIOFezA1rgRLMewbvdi3Pp6SAu+q9FtJ9CAleSjrE= github.com/filecoin-project/specs-actors/v7 v7.0.0-20211222192039-c83bea50c402/go.mod h1:p6LIOFezA1rgRLMewbvdi3Pp6SAu+q9FtJ9CAleSjrE= -github.com/filecoin-project/specs-actors/v7 v7.0.0-rc1 h1:FuDaXIbcw2hRsFI8SDTmsGGCE+NumpF6aiBoU/2X5W4= -github.com/filecoin-project/specs-actors/v7 v7.0.0-rc1/go.mod h1:TA5FwCna+Yi36POaT7SLKXsgEDvJwc0V/L6ZsO19B9M= +github.com/filecoin-project/specs-actors/v7 v7.0.0-rc1.0.20220118005651-2470cb39827e h1:3P14MvJ5MA0jwEB4WDeROrci4o8KwVVAv2mJ70grbf0= +github.com/filecoin-project/specs-actors/v7 v7.0.0-rc1.0.20220118005651-2470cb39827e/go.mod h1:TA5FwCna+Yi36POaT7SLKXsgEDvJwc0V/L6ZsO19B9M= github.com/filecoin-project/specs-storage v0.1.1-0.20211228030229-6d460d25a0c9 h1:oUYOvF7EvdXS0Zmk9mNkaB6Bu0l+WXBYPzVodKMiLug= github.com/filecoin-project/specs-storage v0.1.1-0.20211228030229-6d460d25a0c9/go.mod h1:Tb88Zq+IBJbvAn3mS89GYj3jdRThBTE/771HCVZdRJU= github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg= @@ -2328,7 +2326,6 @@ golang.org/x/tools v0.0.0-20200711155855-7342f9734a7d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20201112185108-eeaa07dd7696/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= From 04092f3e6b6e10b736d2dda9d5e290d899d75a88 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 1 Feb 2022 20:13:45 -0800 Subject: [PATCH 103/385] update ffi --- extern/filecoin-ffi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index a7295282a51..b71619c2afa 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit a7295282a51d2b24e1e02e228a5b9f5f7b412bc2 +Subproject commit b71619c2afa2487f2f4c5aceb4ba8f1fcb05ba52 From a32b7a32f3f91dadb8d44e7676f2cf40e0114a39 Mon Sep 17 00:00:00 2001 From: vyzo Date: Sat, 5 Feb 2022 20:00:15 +0200 Subject: [PATCH 104/385] directly mark objects in cold object reification --- blockstore/splitstore/splitstore_reify.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blockstore/splitstore/splitstore_reify.go b/blockstore/splitstore/splitstore_reify.go index f60100d8aec..ad51687c178 100644 --- a/blockstore/splitstore/splitstore_reify.go +++ b/blockstore/splitstore/splitstore_reify.go @@ -165,10 +165,10 @@ func (s *SplitStore) doReify(c cid.Cid) { if s.txnMarkSet != nil { if len(toreify) > 0 { - s.markLiveRefs(toreify) + s.txnMarkSet.MarkMany(toreify) } if len(totrack) > 0 { - s.markLiveRefs(totrack) + s.txnMarkSet.MarkMany(totrack) } } else { if len(toreify) > 0 { From 713edd565ccaf9483cbf812ee8585caee2188b2c Mon Sep 17 00:00:00 2001 From: vyzo Date: Sat, 5 Feb 2022 21:30:53 +0200 Subject: [PATCH 105/385] fix lint --- blockstore/splitstore/splitstore_reify.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/blockstore/splitstore/splitstore_reify.go b/blockstore/splitstore/splitstore_reify.go index ad51687c178..3c65bbce807 100644 --- a/blockstore/splitstore/splitstore_reify.go +++ b/blockstore/splitstore/splitstore_reify.go @@ -165,10 +165,14 @@ func (s *SplitStore) doReify(c cid.Cid) { if s.txnMarkSet != nil { if len(toreify) > 0 { - s.txnMarkSet.MarkMany(toreify) + if err := s.txnMarkSet.MarkMany(toreify); err != nil { + log.Warnf("error marking reified objects: %s", err) + } } if len(totrack) > 0 { - s.txnMarkSet.MarkMany(totrack) + if err := s.txnMarkSet.MarkMany(totrack); err != nil { + log.Warnf("error marking tracked objects: %s", err) + } } } else { if len(toreify) > 0 { From 279cdd0760f93961d73e36538f000b66be970616 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 7 Feb 2022 10:33:57 -0800 Subject: [PATCH 106/385] fvm: fix implicit messages and message inclusion gas charging --- chain/vm/fvm.go | 4 ++-- extern/filecoin-ffi | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/chain/vm/fvm.go b/chain/vm/fvm.go index f864966c37d..5b4756dff17 100644 --- a/chain/vm/fvm.go +++ b/chain/vm/fvm.go @@ -67,7 +67,7 @@ func (vm *FVM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet return nil, xerrors.Errorf("serializing msg: %w", err) } - ret, err := vm.fvm.ApplyMessage(msgBytes) + ret, err := vm.fvm.ApplyMessage(msgBytes, uint(cmsg.ChainLength())) if err != nil { return nil, xerrors.Errorf("applying msg: %w", err) } @@ -101,7 +101,7 @@ func (vm *FVM) ApplyImplicitMessage(ctx context.Context, cmsg *types.Message) (* return nil, xerrors.Errorf("serializing msg: %w", err) } - ret, err := vm.fvm.ApplyMessage(msgBytes) + ret, err := vm.fvm.ApplyImplicitMessage(msgBytes) if err != nil { return nil, xerrors.Errorf("applying msg: %w", err) } diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index b71619c2afa..1e18dc4148d 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit b71619c2afa2487f2f4c5aceb4ba8f1fcb05ba52 +Subproject commit 1e18dc4148d5f8aedc91e173b87b632635ad01ee From 1dc6a2fea6ce5726dd6a3954c8e7972e956448f6 Mon Sep 17 00:00:00 2001 From: gammazero Date: Tue, 8 Feb 2022 02:53:25 -0800 Subject: [PATCH 107/385] Add indexer pubsub message authentication and rate limiting --- chain/sub/incoming.go | 195 +++++++++++++++++++++++++++-- chain/sub/ratelimit/queue.go | 89 +++++++++++++ chain/sub/ratelimit/window.go | 70 +++++++++++ chain/sub/ratelimit/window_test.go | 61 +++++++++ node/modules/services.go | 5 +- 5 files changed, 411 insertions(+), 9 deletions(-) create mode 100644 chain/sub/ratelimit/queue.go create mode 100644 chain/sub/ratelimit/window.go create mode 100644 chain/sub/ratelimit/window_test.go diff --git a/chain/sub/incoming.go b/chain/sub/incoming.go index dd18f25d05b..c0ac42a5904 100644 --- a/chain/sub/incoming.go +++ b/chain/sub/incoming.go @@ -2,15 +2,17 @@ package sub import ( "context" - "fmt" + "sync" "time" address "github.com/filecoin-project/go-address" + "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain" "github.com/filecoin-project/lotus/chain/consensus" "github.com/filecoin-project/lotus/chain/messagepool" "github.com/filecoin-project/lotus/chain/store" + "github.com/filecoin-project/lotus/chain/sub/ratelimit" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/metrics" "github.com/filecoin-project/lotus/node/impl/client" @@ -22,6 +24,7 @@ import ( connmgr "github.com/libp2p/go-libp2p-core/connmgr" "github.com/libp2p/go-libp2p-core/peer" pubsub "github.com/libp2p/go-libp2p-pubsub" + "github.com/multiformats/go-varint" "go.opencensus.io/stats" "go.opencensus.io/tag" "golang.org/x/xerrors" @@ -168,12 +171,12 @@ func fetchCids( cidIndex := make(map[cid.Cid]int) for i, c := range cids { if c.Prefix() != msgCidPrefix { - return fmt.Errorf("invalid msg CID: %s", c) + return xerrors.Errorf("invalid msg CID: %s", c) } cidIndex[c] = i } if len(cids) != len(cidIndex) { - return fmt.Errorf("duplicate CIDs in fetchCids input") + return xerrors.Errorf("duplicate CIDs in fetchCids input") } for block := range bserv.GetBlocks(ctx, cids) { @@ -196,7 +199,7 @@ func fetchCids( if len(cidIndex) > 0 { err := ctx.Err() if err == nil { - err = fmt.Errorf("failed to fetch %d messages for unknown reasons", len(cidIndex)) + err = xerrors.Errorf("failed to fetch %d messages for unknown reasons", len(cidIndex)) } return err } @@ -445,23 +448,199 @@ func recordFailure(ctx context.Context, metric *stats.Int64Measure, failureType stats.Record(ctx, metric.M(1)) } +type peerMsgInfo struct { + peerID peer.ID + lastCid cid.Cid + rateLimit *ratelimit.Window + mutex sync.Mutex +} + type IndexerMessageValidator struct { self peer.ID + + peerCache *lru.TwoQueueCache + fullNode api.FullNode } -func NewIndexerMessageValidator(self peer.ID) *IndexerMessageValidator { - return &IndexerMessageValidator{self: self} +func NewIndexerMessageValidator(self peer.ID, fullNode api.FullNode) *IndexerMessageValidator { + peerCache, _ := lru.New2Q(1024) + + return &IndexerMessageValidator{ + self: self, + peerCache: peerCache, + fullNode: fullNode, + } } func (v *IndexerMessageValidator) Validate(ctx context.Context, pid peer.ID, msg *pubsub.Message) pubsub.ValidationResult { // This chain-node should not be publishing its own messages. These are - // relayed from miner-nodes or index publishers. If a node appears to be - // local, reject it. + // relayed from market-nodes. If a node appears to be local, reject it. if pid == v.self { log.Warnf("refusing to relay indexer message from self") stats.Record(ctx, metrics.IndexerMessageValidationFailure.M(1)) return pubsub.ValidationReject } + originPeer := msg.GetFrom() + if originPeer == v.self { + log.Warnf("refusing to relay indexer message originating from self") + stats.Record(ctx, metrics.IndexerMessageValidationFailure.M(1)) + return pubsub.ValidationReject + } + + // Decode CID and originator addresses from message. + minerID, msgCid, err := decodeIndexerMessage(msg.Data) + if err != nil { + log.Errorw("Could not decode pubsub message", "err", err) + return pubsub.ValidationReject + } + + if minerID == "" { + log.Warnw("ignoring messsage missing miner id", "peer", originPeer) + return pubsub.ValidationIgnore + } + + var msgInfo *peerMsgInfo + val, ok := v.peerCache.Get(minerID) + if !ok { + msgInfo = &peerMsgInfo{} + } else { + msgInfo = val.(*peerMsgInfo) + } + + // Lock this peer's message info. + msgInfo.mutex.Lock() + defer msgInfo.mutex.Unlock() + + if !ok || originPeer != msgInfo.peerID { + // Check that the message was signed by an authenticated peer. + err = v.authenticateMessage(ctx, minerID, originPeer) + if err != nil { + log.Warnw("cannot authenticate messsage", "err", err, "peer", originPeer, "minerID", minerID) + stats.Record(ctx, metrics.IndexerMessageValidationFailure.M(1)) + return pubsub.ValidationReject + } + msgInfo.peerID = originPeer + if !ok { + // Add msgInfo to cache only after being authenticated. If two + // messages from the same peer are handled concurrently, there is a + // small chance that one msgInfo could replace the other here when + // the info is first cached. This is OK, so no need to prevent it. + v.peerCache.Add(minerID, msgInfo) + } + } + + // See if message needs to be ignored due to rate limiting. + if v.rateLimitPeer(msgInfo, msgCid) { + return pubsub.ValidationIgnore + } + stats.Record(ctx, metrics.IndexerMessageValidationSuccess.M(1)) return pubsub.ValidationAccept } + +func (v *IndexerMessageValidator) rateLimitPeer(msgInfo *peerMsgInfo, msgCid cid.Cid) bool { + const ( + msgLimit = 5 + msgTimeLimit = 10 * time.Second + repeatTimeLimit = 2 * time.Hour + ) + + timeWindow := msgInfo.rateLimit + + // Check overall message rate. + if timeWindow == nil { + timeWindow = ratelimit.NewWindow(msgLimit, msgTimeLimit) + msgInfo.rateLimit = timeWindow + } else if msgInfo.lastCid == msgCid { + // Check if this is a repeat of the previous message data. + if time.Since(timeWindow.Newest()) < repeatTimeLimit { + log.Warnw("ignoring repeated indexer message", "sender", msgInfo.peerID) + return true + } + } + + err := timeWindow.Add() + if err != nil { + log.Warnw("ignoring indexer message", "sender", msgInfo.peerID, "err", err) + return true + } + + msgInfo.lastCid = msgCid + + return false +} + +func decodeIndexerMessage(data []byte) (string, cid.Cid, error) { + n, msgCid, err := cid.CidFromBytes(data) + if err != nil { + return "", cid.Undef, err + } + if n > len(data) { + return "", cid.Undef, xerrors.New("bad cid length encoding") + } + data = data[n:] + + var minerID string + + if len(data) != 0 { + addrCount, n, err := varint.FromUvarint(data) + if err != nil { + return "", cid.Undef, xerrors.Errorf("cannot read number of multiaddrs: %w", err) + } + if n > len(data) { + return "", cid.Undef, xerrors.New("bad multiaddr count encoding") + } + data = data[n:] + + if addrCount != 0 { + // Read multiaddrs if there is any more data in message data. This allows + // backward-compatability with publishers that do not supply address data. + for i := 0; i < int(addrCount); i++ { + val, n, err := varint.FromUvarint(data) + if err != nil { + return "", cid.Undef, xerrors.Errorf("cannot read multiaddrs length: %w", err) + } + if n > len(data) { + return "", cid.Undef, xerrors.New("bad multiaddr length encoding") + } + data = data[n:] + + if len(data) < int(val) { + return "", cid.Undef, xerrors.New("bad multiaddr encoding") + } + data = data[val:] + } + } + if len(data) != 0 { + minerID = string(data) + } + } + + return minerID, msgCid, nil +} + +func (v *IndexerMessageValidator) authenticateMessage(ctx context.Context, minerID string, peerID peer.ID) error { + // Get miner info from lotus + minerAddress, err := address.NewFromString(minerID) + if err != nil { + return xerrors.Errorf("invalid miner id: %w", err) + } + + ts, err := v.fullNode.ChainHead(ctx) + if err != nil { + return err + } + + minerInfo, err := v.fullNode.StateMinerInfo(ctx, minerAddress, ts.Key()) + if err != nil { + return err + } + + if minerInfo.PeerId == nil { + return xerrors.New("no peer id for miner") + } + if *minerInfo.PeerId != peerID { + return xerrors.New("message not signed by peer in miner info") + } + return nil +} diff --git a/chain/sub/ratelimit/queue.go b/chain/sub/ratelimit/queue.go new file mode 100644 index 00000000000..d5ed001fde4 --- /dev/null +++ b/chain/sub/ratelimit/queue.go @@ -0,0 +1,89 @@ +package ratelimit + +import "errors" + +var ErrRate = errors.New("rate exceeded") + +type queue struct { + buf []int64 + count int + head int + tail int +} + +// cap returns the queue capacity +func (q *queue) cap() int { + return len(q.buf) +} + +// len returns the number of items in the queue +func (q *queue) len() int { + return q.count +} + +// push adds an element to the end of the queue. +func (q *queue) push(elem int64) error { + if q.count == len(q.buf) { + return ErrRate + } + + q.buf[q.tail] = elem + // Calculate new tail position. + q.tail = q.next(q.tail) + q.count++ + return nil +} + +// pop removes and returns the element from the front of the queue. +func (q *queue) pop() int64 { + if q.count <= 0 { + panic("pop from empty queue") + } + ret := q.buf[q.head] + + // Calculate new head position. + q.head = q.next(q.head) + q.count-- + + return ret +} + +// front returns the element at the front of the queue. This is the element +// that would be returned by pop(). This call panics if the queue is empty. +func (q *queue) front() int64 { + if q.count <= 0 { + panic("front() called when empty") + } + return q.buf[q.head] +} + +// back returns the element at the back of the queue. This call panics if the +// queue is empty. +func (q *queue) back() int64 { + if q.count <= 0 { + panic("back() called when empty") + } + return q.buf[q.prev(q.tail)] +} + +// prev returns the previous buffer position wrapping around buffer. +func (q *queue) prev(i int) int { + if i == 0 { + return len(q.buf) - 1 + } + return (i - 1) % len(q.buf) +} + +// next returns the next buffer position wrapping around buffer. +func (q *queue) next(i int) int { + return (i + 1) % len(q.buf) +} + +// truncate pops values that are less than or equal the specified threshold. +func (q *queue) truncate(threshold int64) { + for q.count != 0 && q.buf[q.head] <= threshold { + // pop() without returning a value + q.head = q.next(q.head) + q.count-- + } +} diff --git a/chain/sub/ratelimit/window.go b/chain/sub/ratelimit/window.go new file mode 100644 index 00000000000..f0429d3d383 --- /dev/null +++ b/chain/sub/ratelimit/window.go @@ -0,0 +1,70 @@ +package ratelimit + +import "time" + +// Window is a time windows for counting events within a span of time. The +// windows slides forward in time so that it spans from the most recent event +// to size time in the past. +type Window struct { + q *queue + size int64 +} + +// NewWindow creates a new Window that limits the number of events to maximum +// count of events withing a duration of time. The capacity sets the maximum +// number of events, and size sets the span of time over which the events are +// counted. +func NewWindow(capacity int, size time.Duration) *Window { + return &Window{ + q: &queue{ + buf: make([]int64, capacity), + }, + size: int64(size), + } +} + +// Add attempts to append a new timestamp into the current window. Previously +// added values that are not not within `size` difference from the value being +// added are first removed. Add fails if adding the value would cause the +// window to exceed capacity. +func (w *Window) Add() error { + now := time.Now().UnixNano() + if w.Len() != 0 { + w.q.truncate(now - w.size) + } + return w.q.push(now) +} + +// Cap returns the maximum number of items the window can hold. +func (w *Window) Cap() int { + return w.q.cap() +} + +// Len returns the number of elements currently in the window. +func (w *Window) Len() int { + return w.q.len() +} + +// Span returns the distance from the first to the last item in the window. +func (w *Window) Span() time.Duration { + if w.q.len() < 2 { + return 0 + } + return time.Duration(w.q.back() - w.q.front()) +} + +// Oldest returns the oldest timestamp in the window. +func (w *Window) Oldest() time.Time { + if w.q.len() == 0 { + return time.Time{} + } + return time.Unix(0, w.q.front()) +} + +// Newest returns the newest timestamp in the window. +func (w *Window) Newest() time.Time { + if w.q.len() == 0 { + return time.Time{} + } + return time.Unix(0, w.q.back()) +} diff --git a/chain/sub/ratelimit/window_test.go b/chain/sub/ratelimit/window_test.go new file mode 100644 index 00000000000..f656d6a0b15 --- /dev/null +++ b/chain/sub/ratelimit/window_test.go @@ -0,0 +1,61 @@ +package ratelimit + +import ( + "testing" + "time" +) + +func TestWindow(t *testing.T) { + const ( + maxEvents = 3 + timeLimit = 100 * time.Millisecond + ) + w := NewWindow(maxEvents, timeLimit) + if w.Len() != 0 { + t.Fatal("q.Len() =", w.Len(), "expect 0") + } + if w.Cap() != maxEvents { + t.Fatal("q.Cap() =", w.Cap(), "expect 3") + } + if !w.Newest().IsZero() { + t.Fatal("expected newest to be zero time with empty window") + } + if !w.Oldest().IsZero() { + t.Fatal("expected oldest to be zero time with empty window") + } + if w.Span() != 0 { + t.Fatal("expected span to be zero time with empty window") + } + + var err error + for i := 0; i < maxEvents; i++ { + err = w.Add() + if err != nil { + t.Fatalf("cannot add event %d", i) + } + } + if w.Len() != maxEvents { + t.Fatalf("q.Len() is %d, expected %d", w.Len(), maxEvents) + } + if err = w.Add(); err == nil { + t.Fatalf("add event %d within time limit should have failed", maxEvents+1) + } + + time.Sleep(timeLimit) + if err = w.Add(); err != nil { + t.Fatalf("cannot add event after time limit: %s", err) + } + + prev := w.Newest() + time.Sleep(timeLimit) + err = w.Add() + if err != nil { + t.Fatalf("cannot add event") + } + if w.Newest().Before(prev) { + t.Fatal("newest is before previous value") + } + if w.Oldest().Before(prev) { + t.Fatal("oldest is before previous value") + } +} diff --git a/node/modules/services.go b/node/modules/services.go index d0095075d6f..320a46d943c 100644 --- a/node/modules/services.go +++ b/node/modules/services.go @@ -20,6 +20,7 @@ import ( "github.com/filecoin-project/go-fil-markets/discovery" discoveryimpl "github.com/filecoin-project/go-fil-markets/discovery/impl" + "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain" "github.com/filecoin-project/lotus/chain/beacon" @@ -201,7 +202,9 @@ func HandleIncomingMessages(mctx helpers.MetricsCtx, lc fx.Lifecycle, ps *pubsub func RelayIndexerMessages(lc fx.Lifecycle, ps *pubsub.PubSub, nn dtypes.NetworkName, h host.Host) error { topicName := build.IndexerIngestTopic(nn) - v := sub.NewIndexerMessageValidator(h.ID()) + // TODO: How do this get set? + var fullNode api.FullNode + v := sub.NewIndexerMessageValidator(h.ID(), fullNode) if err := ps.RegisterTopicValidator(topicName, v.Validate); err != nil { return xerrors.Errorf("failed to register validator for topic %s, err: %w", topicName, err) From b2805823ce70fd5d7a194a00bdf975b0ab5ab892 Mon Sep 17 00:00:00 2001 From: gammazero Date: Tue, 8 Feb 2022 04:55:59 -0800 Subject: [PATCH 108/385] Pass to validator the interfaces needed to get miner info --- chain/sub/incoming.go | 20 ++++++++++++-------- node/modules/services.go | 8 +++----- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/chain/sub/incoming.go b/chain/sub/incoming.go index c0ac42a5904..e39d0177fb3 100644 --- a/chain/sub/incoming.go +++ b/chain/sub/incoming.go @@ -6,7 +6,7 @@ import ( "time" address "github.com/filecoin-project/go-address" - "github.com/filecoin-project/lotus/api" + //"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain" "github.com/filecoin-project/lotus/chain/consensus" @@ -16,6 +16,7 @@ import ( "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/metrics" "github.com/filecoin-project/lotus/node/impl/client" + "github.com/filecoin-project/lotus/node/impl/full" lru "github.com/hashicorp/golang-lru" blocks "github.com/ipfs/go-block-format" bserv "github.com/ipfs/go-blockservice" @@ -459,16 +460,18 @@ type IndexerMessageValidator struct { self peer.ID peerCache *lru.TwoQueueCache - fullNode api.FullNode + chainApi full.ChainModuleAPI + stateApi full.StateModuleAPI } -func NewIndexerMessageValidator(self peer.ID, fullNode api.FullNode) *IndexerMessageValidator { +func NewIndexerMessageValidator(self peer.ID, chainApi full.ChainModuleAPI, stateApi full.StateModuleAPI) *IndexerMessageValidator { peerCache, _ := lru.New2Q(1024) return &IndexerMessageValidator{ self: self, peerCache: peerCache, - fullNode: fullNode, + chainApi: chainApi, + stateApi: stateApi, } } @@ -512,7 +515,7 @@ func (v *IndexerMessageValidator) Validate(ctx context.Context, pid peer.ID, msg defer msgInfo.mutex.Unlock() if !ok || originPeer != msgInfo.peerID { - // Check that the message was signed by an authenticated peer. + // Check that the miner ID maps to the peer that sent the message. err = v.authenticateMessage(ctx, minerID, originPeer) if err != nil { log.Warnw("cannot authenticate messsage", "err", err, "peer", originPeer, "minerID", minerID) @@ -626,12 +629,12 @@ func (v *IndexerMessageValidator) authenticateMessage(ctx context.Context, miner return xerrors.Errorf("invalid miner id: %w", err) } - ts, err := v.fullNode.ChainHead(ctx) + ts, err := v.chainApi.ChainHead(ctx) if err != nil { return err } - minerInfo, err := v.fullNode.StateMinerInfo(ctx, minerAddress, ts.Key()) + minerInfo, err := v.stateApi.StateMinerInfo(ctx, minerAddress, ts.Key()) if err != nil { return err } @@ -640,7 +643,8 @@ func (v *IndexerMessageValidator) authenticateMessage(ctx context.Context, miner return xerrors.New("no peer id for miner") } if *minerInfo.PeerId != peerID { - return xerrors.New("message not signed by peer in miner info") + return xerrors.New("miner id does not map to peer that sent message") } + return nil } diff --git a/node/modules/services.go b/node/modules/services.go index 320a46d943c..95a2399d2da 100644 --- a/node/modules/services.go +++ b/node/modules/services.go @@ -20,7 +20,6 @@ import ( "github.com/filecoin-project/go-fil-markets/discovery" discoveryimpl "github.com/filecoin-project/go-fil-markets/discovery/impl" - "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain" "github.com/filecoin-project/lotus/chain/beacon" @@ -36,6 +35,7 @@ import ( "github.com/filecoin-project/lotus/lib/peermgr" marketevents "github.com/filecoin-project/lotus/markets/loggers" "github.com/filecoin-project/lotus/node/hello" + "github.com/filecoin-project/lotus/node/impl/full" "github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/helpers" "github.com/filecoin-project/lotus/node/repo" @@ -199,12 +199,10 @@ func HandleIncomingMessages(mctx helpers.MetricsCtx, lc fx.Lifecycle, ps *pubsub waitForSync(stmgr, pubsubMsgsSyncEpochs, subscribe) } -func RelayIndexerMessages(lc fx.Lifecycle, ps *pubsub.PubSub, nn dtypes.NetworkName, h host.Host) error { +func RelayIndexerMessages(lc fx.Lifecycle, ps *pubsub.PubSub, nn dtypes.NetworkName, h host.Host, chainModule full.ChainModule, stateModule full.StateModule) error { topicName := build.IndexerIngestTopic(nn) - // TODO: How do this get set? - var fullNode api.FullNode - v := sub.NewIndexerMessageValidator(h.ID(), fullNode) + v := sub.NewIndexerMessageValidator(h.ID(), &chainModule, &stateModule) if err := ps.RegisterTopicValidator(topicName, v.Validate); err != nil { return xerrors.Errorf("failed to register validator for topic %s, err: %w", topicName, err) From cc61650f8694ef9e055f9bd06938f149d2bf8950 Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Tue, 8 Feb 2022 13:17:05 +0000 Subject: [PATCH 109/385] Upgrade to latest `index-provider` and set miner ID as extra gossip data Upgrade to the latest `index-provider` which upgrades the go-legs protocol to allow the inclusion of extra gossip data that may be used for gossip validation purposes. In the case of lotus gossip message validators the miner ID is used to verify the sender's peer ID on chain. Relates to: - https://github.com/filecoin-project/lotus/pull/8045 --- go.mod | 2 +- go.sum | 6 ++++-- node/modules/storageminer_idxprov.go | 12 +++++++++--- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 353e5ba7d21..a01ddb8eb1e 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,7 @@ require ( github.com/filecoin-project/go-statemachine v1.0.1 github.com/filecoin-project/go-statestore v0.2.0 github.com/filecoin-project/go-storedcounter v0.1.0 - github.com/filecoin-project/index-provider v0.2.6 + github.com/filecoin-project/index-provider v0.2.7 github.com/filecoin-project/specs-actors v0.9.14 github.com/filecoin-project/specs-actors/v2 v2.3.6 github.com/filecoin-project/specs-actors/v3 v3.1.1 diff --git a/go.sum b/go.sum index c17fbce0d44..45818568329 100644 --- a/go.sum +++ b/go.sum @@ -350,8 +350,9 @@ github.com/filecoin-project/go-indexer-core v0.2.8 h1:h1SRdZKTVcaXlzex3UevHh4OWD github.com/filecoin-project/go-indexer-core v0.2.8/go.mod h1:IagNfTdFuX4057kla43PjRCn3yBuUiZgIxuA0hTUamY= github.com/filecoin-project/go-jsonrpc v0.1.5 h1:ckxqZ09ivBAVf5CSmxxrqqNHC7PJm3GYGtYKiNQ+vGk= github.com/filecoin-project/go-jsonrpc v0.1.5/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4= -github.com/filecoin-project/go-legs v0.2.7 h1:+b1BQv4QKkRNsDUE8Z4sEhLXhfVQ+iGpHhANpYqxJlA= github.com/filecoin-project/go-legs v0.2.7/go.mod h1:NrdELuDbtAH8/xqRMgyOYms67aliQajExInLS6g8zFM= +github.com/filecoin-project/go-legs v0.2.8 h1:l76g9Yi7YzxNHwe60jPmQiezUUF0TMjqB/NP4+f23vU= +github.com/filecoin-project/go-legs v0.2.8/go.mod h1:NrdELuDbtAH8/xqRMgyOYms67aliQajExInLS6g8zFM= github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20/go.mod h1:mPn+LRRd5gEKNAtc+r3ScpW2JRU/pj4NBKdADYWHiak= github.com/filecoin-project/go-padreader v0.0.1 h1:8h2tVy5HpoNbr2gBRr+WD6zV6VD6XHig+ynSGJg8ZOs= github.com/filecoin-project/go-padreader v0.0.1/go.mod h1:VYVPJqwpsfmtoHnAmPx6MUwmrK6HIcDqZJiuZhtmfLQ= @@ -373,8 +374,9 @@ github.com/filecoin-project/go-statestore v0.2.0 h1:cRRO0aPLrxKQCZ2UOQbzFGn4WDNd github.com/filecoin-project/go-statestore v0.2.0/go.mod h1:8sjBYbS35HwPzct7iT4lIXjLlYyPor80aU7t7a/Kspo= github.com/filecoin-project/go-storedcounter v0.1.0 h1:Mui6wSUBC+cQGHbDUBcO7rfh5zQkWJM/CpAZa/uOuus= github.com/filecoin-project/go-storedcounter v0.1.0/go.mod h1:4ceukaXi4vFURIoxYMfKzaRF5Xv/Pinh2oTnoxpv+z8= -github.com/filecoin-project/index-provider v0.2.6 h1:JodDoTiLjDPifRxKSgoyDwD8qzbSZDcyn5IPF0osVAg= github.com/filecoin-project/index-provider v0.2.6/go.mod h1:y87dsIQdcmQS5PWIcifQdRb454ViVxjjFEccMDswIjQ= +github.com/filecoin-project/index-provider v0.2.7 h1:9L2OxdMHT9HttBFCRg/zUVzBiBedPHPpAsSxBYvY9Cg= +github.com/filecoin-project/index-provider v0.2.7/go.mod h1:yLY8V22PYiEvwWaJSXpxwjI4jq6TFaVuBvQHOH/6+wE= github.com/filecoin-project/specs-actors v0.9.13/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= github.com/filecoin-project/specs-actors v0.9.14 h1:68PVstg2UB3ZsMLF+DKFTAs/YKsqhKWynkr0IqmVRQY= github.com/filecoin-project/specs-actors v0.9.14/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= diff --git a/node/modules/storageminer_idxprov.go b/node/modules/storageminer_idxprov.go index 8e59558faf1..dfbc669d350 100644 --- a/node/modules/storageminer_idxprov.go +++ b/node/modules/storageminer_idxprov.go @@ -19,6 +19,7 @@ import ( "github.com/libp2p/go-libp2p-core/peerstore" "go.uber.org/fx" + "github.com/filecoin-project/go-address" datatransfer "github.com/filecoin-project/go-data-transfer" dtimpl "github.com/filecoin-project/go-data-transfer/impl" dtnet "github.com/filecoin-project/go-data-transfer/network" @@ -65,8 +66,8 @@ func IndexProviderHost(cfg config.IndexProviderConfig) func(IdxProv) (idxprov.Ho } } -func IndexProvider(cfg config.IndexProviderConfig) func(params IdxProv, marketHost host.Host, h idxprov.Host) (provider.Interface, error) { - return func(args IdxProv, marketHost host.Host, h idxprov.Host) (provider.Interface, error) { +func IndexProvider(cfg config.IndexProviderConfig) func(params IdxProv, marketHost host.Host, h idxprov.Host, maddr dtypes.MinerAddress) (provider.Interface, error) { + return func(args IdxProv, marketHost host.Host, h idxprov.Host, maddr dtypes.MinerAddress) (provider.Interface, error) { ipds := namespace.Wrap(args.Datastore, datastore.NewKey("/index-provider")) pkey := args.Peerstore.PrivKey(args.PeerID) @@ -84,7 +85,12 @@ func IndexProvider(cfg config.IndexProviderConfig) func(params IdxProv, marketHo maddrs = append(maddrs, a.String()) } - e, err := engine.New(cfg.Ingest, pkey, dt, h, ipds, maddrs) + // Get the miner ID and set as extra gossip data. + // The extra data is required by the lotus-specific index-provider gossip message validators. + ma := address.Address(maddr) + log.Info("Using extra gossip data in index provider engine: %s", ma.String()) + + e, err := engine.New(cfg.Ingest, pkey, dt, h, ipds, maddrs, engine.WithExtraGossipData(ma.Bytes())) if err != nil { return nil, xerrors.Errorf("creating indexer provider engine: %w", err) } From 811bc62d65b5bc8e7d991391d97fb10f0cd040ab Mon Sep 17 00:00:00 2001 From: Nikola Divic Date: Tue, 8 Feb 2022 17:15:45 +0100 Subject: [PATCH 110/385] test: cli test setup & test chain head CLI actions lack unit tests. I decided to use the approach similar to what I found in `send_test.go` using gomock, but I don't rely on custom "service" implementations but mock the whole FullNode API. This first commit validates the test setup by testing the simplest method of the chain category, e.g. `chain head`. This requires a minor refactor of the CLI action code: - The constructor (`GetFullNodeAPI`) checks if there's an injected mock API in the app Metadata and uses that in unit tests. - Actions shouldn't use raw `fmt.*` but instead write to the `app.Writer` so the CLI output is testable --- cli/chain.go | 4 +++- cli/chain_test.go | 54 +++++++++++++++++++++++++++++++++++++++++++++++ cli/util/api.go | 5 +++++ 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 cli/chain_test.go diff --git a/cli/chain.go b/cli/chain.go index 0cbdaa0f703..e782d2ca9a1 100644 --- a/cli/chain.go +++ b/cli/chain.go @@ -67,6 +67,8 @@ var ChainHeadCmd = &cli.Command{ Name: "head", Usage: "Print chain head", Action: func(cctx *cli.Context) error { + afmt := NewAppFmt(cctx.App) + api, closer, err := GetFullNodeAPI(cctx) if err != nil { return err @@ -80,7 +82,7 @@ var ChainHeadCmd = &cli.Command{ } for _, c := range head.Cids() { - fmt.Println(c) + afmt.Println(c) } return nil }, diff --git a/cli/chain_test.go b/cli/chain_test.go new file mode 100644 index 00000000000..c8c491e4da9 --- /dev/null +++ b/cli/chain_test.go @@ -0,0 +1,54 @@ +package cli + +import ( + "bytes" + "context" + "regexp" + "testing" + + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/api/mocks" + "github.com/filecoin-project/lotus/chain/types/mock" + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" + ucli "github.com/urfave/cli/v2" +) + +// newMockAppWithFullAPI returns a gomock-ed CLI app used for unit tests +// see cli/util/api.go:GetFullNodeAPI for mock API injection +func newMockAppWithFullAPI(t *testing.T, cmd *ucli.Command) (*ucli.App, *mocks.MockFullNode, *bytes.Buffer, func()) { + app := ucli.NewApp() + app.Commands = ucli.Commands{cmd} + app.Setup() + + // create and inject the mock API into app Metadata + ctrl := gomock.NewController(t) + mockFullNode := mocks.NewMockFullNode(ctrl) + var fullNode api.FullNode = mockFullNode + app.Metadata["test-full-api"] = fullNode + + // this will only work if the implementation uses the app.Writer, + // if it uses fmt.*, it has to be refactored + buf := &bytes.Buffer{} + app.Writer = buf + + return app, mockFullNode, buf, ctrl.Finish +} + +func TestChainHead(t *testing.T) { + app, mockApi, buf, done := newMockAppWithFullAPI(t, WithCategory("chain", ChainHeadCmd)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + ts := mock.TipSet(mock.MkBlock(nil, 0, 0)) + gomock.InOrder( + mockApi.EXPECT().ChainHead(ctx).Return(ts, nil), + ) + + err := app.Run([]string{"chain", "head"}) + assert.NoError(t, err) + + assert.Regexp(t, regexp.MustCompile(ts.Cids()[0].String()), buf.String()) +} diff --git a/cli/util/api.go b/cli/util/api.go index 4a7247b3232..97e4f2cb89b 100644 --- a/cli/util/api.go +++ b/cli/util/api.go @@ -223,6 +223,11 @@ func GetCommonAPI(ctx *cli.Context) (api.CommonNet, jsonrpc.ClientCloser, error) } func GetFullNodeAPI(ctx *cli.Context) (v0api.FullNode, jsonrpc.ClientCloser, error) { + // use the mocked API in CLI unit tests, see cli/chain_test.go for mock definition + if mock, ok := ctx.App.Metadata["test-full-api"]; ok { + return &v0api.WrapperV1Full{FullNode: mock.(v1api.FullNode)}, func() {}, nil + } + if tn, ok := ctx.App.Metadata["testnode-full"]; ok { return &v0api.WrapperV1Full{FullNode: tn.(v1api.FullNode)}, func() {}, nil } From 78649d45b90576411e9821bc7a86f065e9b79165 Mon Sep 17 00:00:00 2001 From: Nikola Divic Date: Tue, 8 Feb 2022 18:24:45 +0100 Subject: [PATCH 111/385] test: cli chain getblock command Unit test for the cli `chain getblock` command. Tests if output is JSON in the expected format. --- cli/chain.go | 7 ++++--- cli/chain_test.go | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/cli/chain.go b/cli/chain.go index e782d2ca9a1..4d03ac4f7e8 100644 --- a/cli/chain.go +++ b/cli/chain.go @@ -99,6 +99,8 @@ var ChainGetBlock = &cli.Command{ }, }, Action: func(cctx *cli.Context) error { + afmt := NewAppFmt(cctx.App) + api, closer, err := GetFullNodeAPI(cctx) if err != nil { return err @@ -126,7 +128,7 @@ var ChainGetBlock = &cli.Command{ return err } - fmt.Println(string(out)) + afmt.Println(string(out)) return nil } @@ -165,9 +167,8 @@ var ChainGetBlock = &cli.Command{ return err } - fmt.Println(string(out)) + afmt.Println(string(out)) return nil - }, } diff --git a/cli/chain_test.go b/cli/chain_test.go index c8c491e4da9..eb98110f0e3 100644 --- a/cli/chain_test.go +++ b/cli/chain_test.go @@ -3,13 +3,16 @@ package cli import ( "bytes" "context" + "encoding/json" "regexp" "testing" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api/mocks" + types "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types/mock" "github.com/golang/mock/gomock" + cid "github.com/ipfs/go-cid" "github.com/stretchr/testify/assert" ucli "github.com/urfave/cli/v2" ) @@ -52,3 +55,38 @@ func TestChainHead(t *testing.T) { assert.Regexp(t, regexp.MustCompile(ts.Cids()[0].String()), buf.String()) } + +// TestGetBlock checks if "lotus chain getblock" returns the block information in the expected format +func TestGetBlock(t *testing.T) { + app, mockApi, buf, done := newMockAppWithFullAPI(t, WithCategory("chain", ChainGetBlock)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + block := mock.MkBlock(nil, 0, 0) + blockMsgs := api.BlockMessages{} + + gomock.InOrder( + mockApi.EXPECT().ChainGetBlock(ctx, block.Cid()).Return(block, nil), + mockApi.EXPECT().ChainGetBlockMessages(ctx, block.Cid()).Return(&blockMsgs, nil), + mockApi.EXPECT().ChainGetParentMessages(ctx, block.Cid()).Return([]api.Message{}, nil), + mockApi.EXPECT().ChainGetParentReceipts(ctx, block.Cid()).Return([]*types.MessageReceipt{}, nil), + ) + + err := app.Run([]string{"chain", "getblock", block.Cid().String()}) + assert.NoError(t, err) + + out := struct { + types.BlockHeader + BlsMessages []*types.Message + SecpkMessages []*types.SignedMessage + ParentReceipts []*types.MessageReceipt + ParentMessages []cid.Cid + }{} + + err = json.Unmarshal(buf.Bytes(), &out) + assert.NoError(t, err) + + assert.True(t, block.Cid().Equals(out.Cid())) +} From 03bc45a26a867a8e17ac9dd3d5c51571754d78f7 Mon Sep 17 00:00:00 2001 From: zenground0 Date: Tue, 8 Feb 2022 12:47:23 -0500 Subject: [PATCH 112/385] Update ci config to match auto gen --- .circleci/config.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 53611d56515..5672130eb3f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -850,6 +850,11 @@ workflows: suite: itest-get_messages_in_ts target: "./itests/get_messages_in_ts_test.go" + - test: + name: test-itest-mempool + suite: itest-mempool + target: "./itests/mempool_test.go" + - test: name: test-itest-multisig suite: itest-multisig From 32b3618c7476b189bad02c8d263898d0e2beb5b7 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 8 Feb 2022 13:20:03 -0800 Subject: [PATCH 113/385] fvm: feed in correct "base" circulating supply --- chain/consensus/filcns/compute_state.go | 11 +++++++++++ chain/vm/fvm.go | 16 +--------------- chain/vm/vm.go | 2 ++ 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/chain/consensus/filcns/compute_state.go b/chain/consensus/filcns/compute_state.go index 37e78874db2..82763c05240 100644 --- a/chain/consensus/filcns/compute_state.go +++ b/chain/consensus/filcns/compute_state.go @@ -94,6 +94,16 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, sm *stmgr.StateManager }() makeVmWithBaseStateAndEpoch := func(base cid.Cid, e abi.ChainEpoch) (vm.VMI, error) { + st, err := sm.StateTree(base) + if err != nil { + return nil, err + } + supply, err := sm.GetVMCirculatingSupplyDetailed(ctx, e, st) + if err != nil { + return nil, err + } + circulating := big.Add(supply.FilMined, supply.FilVested) + vmopt := &vm.VMOpts{ StateBase: base, Epoch: e, @@ -102,6 +112,7 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, sm *stmgr.StateManager Actors: NewActorRegistry(), Syscalls: sm.Syscalls, CircSupplyCalc: sm.GetVMCirculatingSupply, + BaseCircSupply: circulating, NetworkVersion: sm.GetNetworkVersion(ctx, e), BaseFee: baseFee, LookbackState: stmgr.LookbackStateGetterForTipset(sm, ts), diff --git a/chain/vm/fvm.go b/chain/vm/fvm.go index 5b4756dff17..1049a8ddc22 100644 --- a/chain/vm/fvm.go +++ b/chain/vm/fvm.go @@ -9,8 +9,6 @@ import ( "golang.org/x/xerrors" "github.com/filecoin-project/lotus/blockstore" - "github.com/filecoin-project/lotus/chain/state" - cbor "github.com/ipfs/go-ipld-cbor" ffi "github.com/filecoin-project/filecoin-ffi" ffi_cgo "github.com/filecoin-project/filecoin-ffi/cgo" @@ -36,21 +34,9 @@ type FVM struct { } func NewFVM(ctx context.Context, opts *VMOpts) (*FVM, error) { - buf := blockstore.NewBuffered(opts.Bstore) - cst := cbor.NewCborStore(buf) - state, err := state.LoadStateTree(cst, opts.StateBase) - if err != nil { - return nil, err - } - - baseCirc, err := opts.CircSupplyCalc(ctx, opts.Epoch, state) - if err != nil { - return nil, err - } - fvm, err := ffi.CreateFVM(0, &FvmExtern{Rand: opts.Rand, Blockstore: opts.Bstore}, - opts.Epoch, opts.BaseFee, baseCirc, opts.NetworkVersion, opts.StateBase, + opts.Epoch, opts.BaseFee, opts.BaseCircSupply, opts.NetworkVersion, opts.StateBase, ) if err != nil { return nil, err diff --git a/chain/vm/vm.go b/chain/vm/vm.go index 2ee732d5e20..831b5825466 100644 --- a/chain/vm/vm.go +++ b/chain/vm/vm.go @@ -227,6 +227,8 @@ type VMOpts struct { Actors *ActorRegistry Syscalls SyscallBuilder CircSupplyCalc CircSupplyCalculator + // Amount of FIL vested & mined. + BaseCircSupply abi.TokenAmount NetworkVersion network.Version BaseFee abi.TokenAmount LookbackState LookbackStateGetter From e8d771fcac1ac3394b461ce24b99cd94dc1b79cf Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 8 Feb 2022 15:26:20 -0800 Subject: [PATCH 114/385] pass only fil-vested into FVM --- chain/consensus/filcns/compute_state.go | 3 +-- chain/vm/fvm.go | 2 +- chain/vm/vm.go | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/chain/consensus/filcns/compute_state.go b/chain/consensus/filcns/compute_state.go index 82763c05240..ceebf8b357d 100644 --- a/chain/consensus/filcns/compute_state.go +++ b/chain/consensus/filcns/compute_state.go @@ -102,7 +102,6 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, sm *stmgr.StateManager if err != nil { return nil, err } - circulating := big.Add(supply.FilMined, supply.FilVested) vmopt := &vm.VMOpts{ StateBase: base, @@ -112,7 +111,7 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, sm *stmgr.StateManager Actors: NewActorRegistry(), Syscalls: sm.Syscalls, CircSupplyCalc: sm.GetVMCirculatingSupply, - BaseCircSupply: circulating, + FilVested: supply.FilVested, NetworkVersion: sm.GetNetworkVersion(ctx, e), BaseFee: baseFee, LookbackState: stmgr.LookbackStateGetterForTipset(sm, ts), diff --git a/chain/vm/fvm.go b/chain/vm/fvm.go index 1049a8ddc22..1e394a20258 100644 --- a/chain/vm/fvm.go +++ b/chain/vm/fvm.go @@ -36,7 +36,7 @@ type FVM struct { func NewFVM(ctx context.Context, opts *VMOpts) (*FVM, error) { fvm, err := ffi.CreateFVM(0, &FvmExtern{Rand: opts.Rand, Blockstore: opts.Bstore}, - opts.Epoch, opts.BaseFee, opts.BaseCircSupply, opts.NetworkVersion, opts.StateBase, + opts.Epoch, opts.BaseFee, opts.FilVested, opts.NetworkVersion, opts.StateBase, ) if err != nil { return nil, err diff --git a/chain/vm/vm.go b/chain/vm/vm.go index 831b5825466..3e2b76fe61c 100644 --- a/chain/vm/vm.go +++ b/chain/vm/vm.go @@ -227,8 +227,8 @@ type VMOpts struct { Actors *ActorRegistry Syscalls SyscallBuilder CircSupplyCalc CircSupplyCalculator - // Amount of FIL vested & mined. - BaseCircSupply abi.TokenAmount + // Amount of FIL vested from genesis actors. + FilVested abi.TokenAmount NetworkVersion network.Version BaseFee abi.TokenAmount LookbackState LookbackStateGetter From e8bdf8171bbed0cb24ee38c7bfc92120854b55ad Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 8 Feb 2022 20:54:53 -0800 Subject: [PATCH 115/385] chore: cleanup fil vested calculation 1. Move lock, loading, etc into GetFilVested. 2. Call it directly when creating the FVM. 3. Detach GetFilLocked from state manager. Really, this just makes it a bit easier to reason about this code. --- chain/consensus/filcns/compute_state.go | 8 +--- chain/stmgr/supply.go | 57 ++++++++++++++----------- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/chain/consensus/filcns/compute_state.go b/chain/consensus/filcns/compute_state.go index ceebf8b357d..28bdc0eb39a 100644 --- a/chain/consensus/filcns/compute_state.go +++ b/chain/consensus/filcns/compute_state.go @@ -94,11 +94,7 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, sm *stmgr.StateManager }() makeVmWithBaseStateAndEpoch := func(base cid.Cid, e abi.ChainEpoch) (vm.VMI, error) { - st, err := sm.StateTree(base) - if err != nil { - return nil, err - } - supply, err := sm.GetVMCirculatingSupplyDetailed(ctx, e, st) + filVested, err := sm.GetFilVested(ctx, e) if err != nil { return nil, err } @@ -111,7 +107,7 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, sm *stmgr.StateManager Actors: NewActorRegistry(), Syscalls: sm.Syscalls, CircSupplyCalc: sm.GetVMCirculatingSupply, - FilVested: supply.FilVested, + FilVested: filVested, NetworkVersion: sm.GetNetworkVersion(ctx, e), BaseFee: baseFee, LookbackState: stmgr.LookbackStateGetterForTipset(sm, ts), diff --git a/chain/stmgr/supply.go b/chain/stmgr/supply.go index 0744c02aa02..7e239d2dba3 100644 --- a/chain/stmgr/supply.go +++ b/chain/stmgr/supply.go @@ -196,8 +196,32 @@ func (sm *StateManager) setupPostCalicoVesting(ctx context.Context) error { // GetVestedFunds returns all funds that have "left" actors that are in the genesis state: // - For Multisigs, it counts the actual amounts that have vested at the given epoch // - For Accounts, it counts max(currentBalance - genesisBalance, 0). -func (sm *StateManager) GetFilVested(ctx context.Context, height abi.ChainEpoch, st *state.StateTree) (abi.TokenAmount, error) { +func (sm *StateManager) GetFilVested(ctx context.Context, height abi.ChainEpoch) (abi.TokenAmount, error) { vf := big.Zero() + + sm.genesisMsigLk.Lock() + defer sm.genesisMsigLk.Unlock() + + // TODO: combine all this? + if sm.preIgnitionVesting == nil || sm.genesisPledge.IsZero() || sm.genesisMarketFunds.IsZero() { + err := sm.setupGenesisVestingSchedule(ctx) + if err != nil { + return vf, xerrors.Errorf("failed to setup pre-ignition vesting schedule: %w", err) + } + } + if sm.postIgnitionVesting == nil { + err := sm.setupPostIgnitionVesting(ctx) + if err != nil { + return vf, xerrors.Errorf("failed to setup post-ignition vesting schedule: %w", err) + } + } + if sm.postCalicoVesting == nil { + err := sm.setupPostCalicoVesting(ctx) + if err != nil { + return vf, xerrors.Errorf("failed to setup post-calico vesting schedule: %w", err) + } + } + if height <= build.UpgradeIgnitionHeight { for _, v := range sm.preIgnitionVesting { au := big.Sub(v.InitialBalance, v.AmountLocked(height)) @@ -282,7 +306,7 @@ func getFilPowerLocked(ctx context.Context, st *state.StateTree) (abi.TokenAmoun return pst.TotalLocked() } -func (sm *StateManager) GetFilLocked(ctx context.Context, st *state.StateTree) (abi.TokenAmount, error) { +func GetFilLocked(ctx context.Context, st *state.StateTree) (abi.TokenAmount, error) { filMarketLocked, err := getFilMarketLocked(ctx, st) if err != nil { @@ -315,29 +339,12 @@ func (sm *StateManager) GetVMCirculatingSupply(ctx context.Context, height abi.C return cs.FilCirculating, err } -func (sm *StateManager) GetVMCirculatingSupplyDetailed(ctx context.Context, height abi.ChainEpoch, st *state.StateTree) (api.CirculatingSupply, error) { - sm.genesisMsigLk.Lock() - defer sm.genesisMsigLk.Unlock() - if sm.preIgnitionVesting == nil || sm.genesisPledge.IsZero() || sm.genesisMarketFunds.IsZero() { - err := sm.setupGenesisVestingSchedule(ctx) - if err != nil { - return api.CirculatingSupply{}, xerrors.Errorf("failed to setup pre-ignition vesting schedule: %w", err) - } - } - if sm.postIgnitionVesting == nil { - err := sm.setupPostIgnitionVesting(ctx) - if err != nil { - return api.CirculatingSupply{}, xerrors.Errorf("failed to setup post-ignition vesting schedule: %w", err) - } - } - if sm.postCalicoVesting == nil { - err := sm.setupPostCalicoVesting(ctx) - if err != nil { - return api.CirculatingSupply{}, xerrors.Errorf("failed to setup post-calico vesting schedule: %w", err) - } - } +func (sm *StateManager) loadGenesisMsigs(ctx context.Context) error { + return nil +} - filVested, err := sm.GetFilVested(ctx, height, st) +func (sm *StateManager) GetVMCirculatingSupplyDetailed(ctx context.Context, height abi.ChainEpoch, st *state.StateTree) (api.CirculatingSupply, error) { + filVested, err := sm.GetFilVested(ctx, height) if err != nil { return api.CirculatingSupply{}, xerrors.Errorf("failed to calculate filVested: %w", err) } @@ -360,7 +367,7 @@ func (sm *StateManager) GetVMCirculatingSupplyDetailed(ctx context.Context, heig return api.CirculatingSupply{}, xerrors.Errorf("failed to calculate filBurnt: %w", err) } - filLocked, err := sm.GetFilLocked(ctx, st) + filLocked, err := GetFilLocked(ctx, st) if err != nil { return api.CirculatingSupply{}, xerrors.Errorf("failed to calculate filLocked: %w", err) } From 743862857efb2516038a2fc1bb3b554b5317cec6 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 8 Feb 2022 20:57:20 -0800 Subject: [PATCH 116/385] ffi: update FFI for fvm changes --- extern/filecoin-ffi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index 1e18dc4148d..73f84f3d3c9 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit 1e18dc4148d5f8aedc91e173b87b632635ad01ee +Subproject commit 73f84f3d3c96c260ebea01ccad6a9754a51f3f99 From 1cd590ace93d627fee4d8d8d92ae130dd125f45e Mon Sep 17 00:00:00 2001 From: Nikola Divic Date: Wed, 9 Feb 2022 15:29:10 +0100 Subject: [PATCH 117/385] test: chain read-obj Simple test that checks if this CLI method prints the IPLD node referenced by the given CID encoded in hexadecimal. --- cli/chain.go | 4 +++- cli/chain_test.go | 27 ++++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/cli/chain.go b/cli/chain.go index 4d03ac4f7e8..43d5ffb1f72 100644 --- a/cli/chain.go +++ b/cli/chain.go @@ -185,6 +185,8 @@ var ChainReadObjCmd = &cli.Command{ Usage: "Read the raw bytes of an object", ArgsUsage: "[objectCid]", Action: func(cctx *cli.Context) error { + afmt := NewAppFmt(cctx.App) + api, closer, err := GetFullNodeAPI(cctx) if err != nil { return err @@ -202,7 +204,7 @@ var ChainReadObjCmd = &cli.Command{ return err } - fmt.Printf("%x\n", obj) + afmt.Printf("%x\n", obj) return nil }, } diff --git a/cli/chain_test.go b/cli/chain_test.go index eb98110f0e3..4a961d0229f 100644 --- a/cli/chain_test.go +++ b/cli/chain_test.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "encoding/json" + "fmt" "regexp" "testing" @@ -56,7 +57,7 @@ func TestChainHead(t *testing.T) { assert.Regexp(t, regexp.MustCompile(ts.Cids()[0].String()), buf.String()) } -// TestGetBlock checks if "lotus chain getblock" returns the block information in the expected format +// TestGetBlock checks if "chain getblock" returns the block information in the expected format func TestGetBlock(t *testing.T) { app, mockApi, buf, done := newMockAppWithFullAPI(t, WithCategory("chain", ChainGetBlock)) defer done() @@ -77,6 +78,7 @@ func TestGetBlock(t *testing.T) { err := app.Run([]string{"chain", "getblock", block.Cid().String()}) assert.NoError(t, err) + // expected output format out := struct { types.BlockHeader BlsMessages []*types.Message @@ -90,3 +92,26 @@ func TestGetBlock(t *testing.T) { assert.True(t, block.Cid().Equals(out.Cid())) } + +// TestChainReadObj checks if "chain read-obj" prints the referenced IPLD node as hex, if exists +func TestReadOjb(t *testing.T) { + app, mockApi, buf, done := newMockAppWithFullAPI(t, WithCategory("chain", ChainReadObjCmd)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + block := mock.MkBlock(nil, 0, 0) + obj := new(bytes.Buffer) + err := block.MarshalCBOR(obj) + assert.NoError(t, err) + + gomock.InOrder( + mockApi.EXPECT().ChainReadObj(ctx, block.Cid()).Return(obj.Bytes(), nil), + ) + + err = app.Run([]string{"chain", "read-obj", block.Cid().String()}) + assert.NoError(t, err) + + assert.Equal(t, buf.String(), fmt.Sprintf("%x\n", obj.Bytes())) +} From c0f47e5eed5e6e83aa289d0455e075ef9d8f3d17 Mon Sep 17 00:00:00 2001 From: Nikola Divic Date: Wed, 9 Feb 2022 15:56:13 +0100 Subject: [PATCH 118/385] test: chain delete-obj cli command Contains two subtests, that check if the --really-do-it flag (force) is respected, since removing wrong objects may lead to sync issues. --- cli/chain.go | 4 +++- cli/chain_test.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/cli/chain.go b/cli/chain.go index 43d5ffb1f72..26524badb80 100644 --- a/cli/chain.go +++ b/cli/chain.go @@ -220,6 +220,8 @@ var ChainDeleteObjCmd = &cli.Command{ }, }, Action: func(cctx *cli.Context) error { + afmt := NewAppFmt(cctx.App) + api, closer, err := GetFullNodeAPI(cctx) if err != nil { return err @@ -241,7 +243,7 @@ var ChainDeleteObjCmd = &cli.Command{ return err } - fmt.Printf("Obj %s deleted\n", c.String()) + afmt.Printf("Obj %s deleted\n", c.String()) return nil }, } diff --git a/cli/chain_test.go b/cli/chain_test.go index 4a961d0229f..b20ecbf31ae 100644 --- a/cli/chain_test.go +++ b/cli/chain_test.go @@ -115,3 +115,36 @@ func TestReadOjb(t *testing.T) { assert.Equal(t, buf.String(), fmt.Sprintf("%x\n", obj.Bytes())) } + +// TestChainDeleteObj checks if "chain delete-obj" deletes an object from the chain blockstore, respecting the --really-do-it flag +func TestChainDeleteObj(t *testing.T) { + cmd := WithCategory("chain", ChainDeleteObjCmd) + block := mock.MkBlock(nil, 0, 0) + + // given no force flag, it should return an error and no API calls should be made + t.Run("no-really-do-it", func(t *testing.T) { + app, _, _, done := newMockAppWithFullAPI(t, cmd) + defer done() + + err := app.Run([]string{"chain", "delete-obj", block.Cid().String()}) + assert.Error(t, err) + }) + + // given a force flag, API delete should be called + t.Run("really-do-it", func(t *testing.T) { + app, mockApi, buf, done := newMockAppWithFullAPI(t, cmd) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + gomock.InOrder( + mockApi.EXPECT().ChainDeleteObj(ctx, block.Cid()).Return(nil), + ) + + err := app.Run([]string{"chain", "delete-obj", "--really-do-it=true", block.Cid().String()}) + assert.NoError(t, err) + + assert.Contains(t, buf.String(), block.Cid().String()) + }) +} From a923d7c884d155d7fb83811b320878205b1592fa Mon Sep 17 00:00:00 2001 From: Nikola Divic Date: Wed, 9 Feb 2022 16:22:52 +0100 Subject: [PATCH 119/385] test: chain stat-obj cli command Test expected output with respect to the --base flag --- cli/chain.go | 5 +++-- cli/chain_test.go | 53 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/cli/chain.go b/cli/chain.go index 26524badb80..10fa9900f52 100644 --- a/cli/chain.go +++ b/cli/chain.go @@ -264,6 +264,7 @@ var ChainStatObjCmd = &cli.Command{ }, }, Action: func(cctx *cli.Context) error { + afmt := NewAppFmt(cctx.App) api, closer, err := GetFullNodeAPI(cctx) if err != nil { return err @@ -289,8 +290,8 @@ var ChainStatObjCmd = &cli.Command{ return err } - fmt.Printf("Links: %d\n", stats.Links) - fmt.Printf("Size: %s (%d)\n", types.SizeStr(types.NewInt(stats.Size)), stats.Size) + afmt.Printf("Links: %d\n", stats.Links) + afmt.Printf("Size: %s (%d)\n", types.SizeStr(types.NewInt(stats.Size)), stats.Size) return nil }, } diff --git a/cli/chain_test.go b/cli/chain_test.go index b20ecbf31ae..fd43644d1ea 100644 --- a/cli/chain_test.go +++ b/cli/chain_test.go @@ -6,6 +6,7 @@ import ( "encoding/json" "fmt" "regexp" + "strings" "testing" "github.com/filecoin-project/lotus/api" @@ -130,7 +131,7 @@ func TestChainDeleteObj(t *testing.T) { assert.Error(t, err) }) - // given a force flag, API delete should be called + // given a force flag, it calls API delete t.Run("really-do-it", func(t *testing.T) { app, mockApi, buf, done := newMockAppWithFullAPI(t, cmd) defer done() @@ -148,3 +149,53 @@ func TestChainDeleteObj(t *testing.T) { assert.Contains(t, buf.String(), block.Cid().String()) }) } + +func TestChainStatObj(t *testing.T) { + cmd := WithCategory("chain", ChainStatObjCmd) + block := mock.MkBlock(nil, 0, 0) + stat := api.ObjStat{Size: 123, Links: 321} + + checkOutput := func(buf *bytes.Buffer) { + out := buf.String() + outSplit := strings.Split(out, "\n") + + assert.Contains(t, outSplit[0], fmt.Sprintf("%d", stat.Links)) + assert.Contains(t, outSplit[1], fmt.Sprintf("%d", stat.Size)) + } + + // given no --base flag, it calls ChainStatObj with base=cid.Undef + t.Run("no-base", func(t *testing.T) { + app, mockApi, buf, done := newMockAppWithFullAPI(t, cmd) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + gomock.InOrder( + mockApi.EXPECT().ChainStatObj(ctx, block.Cid(), cid.Undef).Return(stat, nil), + ) + + err := app.Run([]string{"chain", "stat-obj", block.Cid().String()}) + assert.NoError(t, err) + + checkOutput(buf) + }) + + // given a --base flag, it calls ChainStatObj with that base + t.Run("base", func(t *testing.T) { + app, mockApi, buf, done := newMockAppWithFullAPI(t, cmd) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + gomock.InOrder( + mockApi.EXPECT().ChainStatObj(ctx, block.Cid(), block.Cid()).Return(stat, nil), + ) + + err := app.Run([]string{"chain", "stat-obj", fmt.Sprintf("-base=%s", block.Cid().String()), block.Cid().String()}) + assert.NoError(t, err) + + checkOutput(buf) + }) +} From e797ec138d32b5840af6c52deb0e1d4c323b3b2b Mon Sep 17 00:00:00 2001 From: Nikola Divic Date: Wed, 9 Feb 2022 17:29:29 +0100 Subject: [PATCH 120/385] test: chain getmessage cli command I also added some helper functions for mocking in the types/mock pkg --- chain/types/mock/chain.go | 38 +++++++++++++++++++++++++++++--------- cli/chain.go | 4 +++- cli/chain_test.go | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 10 deletions(-) diff --git a/chain/types/mock/chain.go b/chain/types/mock/chain.go index e4bb2fcee0c..c69f7f56fad 100644 --- a/chain/types/mock/chain.go +++ b/chain/types/mock/chain.go @@ -2,6 +2,7 @@ package mock import ( "context" + "crypto/rand" "fmt" "github.com/filecoin-project/go-address" @@ -24,15 +25,7 @@ func Address(i uint64) address.Address { } func MkMessage(from, to address.Address, nonce uint64, w *wallet.LocalWallet) *types.SignedMessage { - msg := &types.Message{ - To: to, - From: from, - Value: types.NewInt(1), - Nonce: nonce, - GasLimit: 1000000, - GasFeeCap: types.NewInt(100), - GasPremium: types.NewInt(1), - } + msg := UnsignedMessage(from, to, nonce) sig, err := w.WalletSign(context.TODO(), from, msg.Cid().Bytes(), api.MsgMeta{}) if err != nil { @@ -96,3 +89,30 @@ func TipSet(blks ...*types.BlockHeader) *types.TipSet { } return ts } + +func RandomActorAddress() (*address.Address, error) { + bytes := make([]byte, 32) + _, err := rand.Read(bytes) + if err != nil { + return nil, err + } + + addr, err := address.NewActorAddress(bytes) + if err != nil { + return nil, err + } + + return &addr, nil +} + +func UnsignedMessage(from, to address.Address, nonce uint64) *types.Message { + return &types.Message{ + To: to, + From: from, + Value: types.NewInt(1), + Nonce: nonce, + GasLimit: 1000000, + GasFeeCap: types.NewInt(100), + GasPremium: types.NewInt(1), + } +} diff --git a/cli/chain.go b/cli/chain.go index 10fa9900f52..d3259c6c81e 100644 --- a/cli/chain.go +++ b/cli/chain.go @@ -301,6 +301,8 @@ var ChainGetMsgCmd = &cli.Command{ Usage: "Get and print a message by its cid", ArgsUsage: "[messageCid]", Action: func(cctx *cli.Context) error { + afmt := NewAppFmt(cctx.App) + if !cctx.Args().Present() { return fmt.Errorf("must pass a cid of a message to get") } @@ -339,7 +341,7 @@ var ChainGetMsgCmd = &cli.Command{ return err } - fmt.Println(string(enc)) + afmt.Println(string(enc)) return nil }, } diff --git a/cli/chain_test.go b/cli/chain_test.go index fd43644d1ea..064393f3a8a 100644 --- a/cli/chain_test.go +++ b/cli/chain_test.go @@ -150,6 +150,7 @@ func TestChainDeleteObj(t *testing.T) { }) } +// TestChainStatObj checks if "chain delete-obj" prints size and IPLD link counts for object, respecting the --base flag func TestChainStatObj(t *testing.T) { cmd := WithCategory("chain", ChainStatObjCmd) block := mock.MkBlock(nil, 0, 0) @@ -199,3 +200,37 @@ func TestChainStatObj(t *testing.T) { checkOutput(buf) }) } + +// TestChainGetMsg checks if "chain getmessage" properly decodes and serializes as JSON a Message fetched from the IPLD store +func TestChainGetMsg(t *testing.T) { + app, mockApi, buf, done := newMockAppWithFullAPI(t, WithCategory("chain", ChainGetMsgCmd)) + defer done() + + from, err := mock.RandomActorAddress() + assert.NoError(t, err) + + to, err := mock.RandomActorAddress() + assert.NoError(t, err) + + msg := mock.UnsignedMessage(*from, *to, 0) + + obj := new(bytes.Buffer) + err = msg.MarshalCBOR(obj) + assert.NoError(t, err) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + gomock.InOrder( + mockApi.EXPECT().ChainReadObj(ctx, msg.Cid()).Return(obj.Bytes(), nil), + ) + + err = app.Run([]string{"chain", "getmessage", msg.Cid().String()}) + assert.NoError(t, err) + + var out types.Message + err = json.Unmarshal(buf.Bytes(), &out) + assert.NoError(t, err) + + assert.Equal(t, *msg, out) +} From a62e0270025a17facc64ce416c5901e0a298ab9c Mon Sep 17 00:00:00 2001 From: gammazero Date: Wed, 9 Feb 2022 10:29:49 -0800 Subject: [PATCH 121/385] review changes --- chain/sub/incoming.go | 5 ++--- chain/sub/ratelimit/queue.go | 4 ++-- chain/sub/ratelimit/window_test.go | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/chain/sub/incoming.go b/chain/sub/incoming.go index e39d0177fb3..222ad3dea29 100644 --- a/chain/sub/incoming.go +++ b/chain/sub/incoming.go @@ -6,7 +6,6 @@ import ( "time" address "github.com/filecoin-project/go-address" - //"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain" "github.com/filecoin-project/lotus/chain/consensus" @@ -465,7 +464,7 @@ type IndexerMessageValidator struct { } func NewIndexerMessageValidator(self peer.ID, chainApi full.ChainModuleAPI, stateApi full.StateModuleAPI) *IndexerMessageValidator { - peerCache, _ := lru.New2Q(1024) + peerCache, _ := lru.New2Q(8192) return &IndexerMessageValidator{ self: self, @@ -498,7 +497,7 @@ func (v *IndexerMessageValidator) Validate(ctx context.Context, pid peer.ID, msg } if minerID == "" { - log.Warnw("ignoring messsage missing miner id", "peer", originPeer) + log.Debugw("ignoring messsage missing miner id", "peer", originPeer) return pubsub.ValidationIgnore } diff --git a/chain/sub/ratelimit/queue.go b/chain/sub/ratelimit/queue.go index d5ed001fde4..49f9bef6682 100644 --- a/chain/sub/ratelimit/queue.go +++ b/chain/sub/ratelimit/queue.go @@ -2,7 +2,7 @@ package ratelimit import "errors" -var ErrRate = errors.New("rate exceeded") +var ErrRateLimitExceeded = errors.New("rate limit exceeded") type queue struct { buf []int64 @@ -24,7 +24,7 @@ func (q *queue) len() int { // push adds an element to the end of the queue. func (q *queue) push(elem int64) error { if q.count == len(q.buf) { - return ErrRate + return ErrRateLimitExceeded } q.buf[q.tail] = elem diff --git a/chain/sub/ratelimit/window_test.go b/chain/sub/ratelimit/window_test.go index f656d6a0b15..c86b65ef75b 100644 --- a/chain/sub/ratelimit/window_test.go +++ b/chain/sub/ratelimit/window_test.go @@ -37,8 +37,8 @@ func TestWindow(t *testing.T) { if w.Len() != maxEvents { t.Fatalf("q.Len() is %d, expected %d", w.Len(), maxEvents) } - if err = w.Add(); err == nil { - t.Fatalf("add event %d within time limit should have failed", maxEvents+1) + if err = w.Add(); err != ErrRateLimitExceeded { + t.Fatalf("add event %d within time limit should have failed with err: %s", maxEvents+1, ErrRateLimitExceeded) } time.Sleep(timeLimit) From 7d2810abbcc312ef970e56f3cb1363c80c12a586 Mon Sep 17 00:00:00 2001 From: Nikola Divic Date: Wed, 9 Feb 2022 19:54:45 +0100 Subject: [PATCH 122/385] test: don't parse err messages in messagepool_test Per @vyzo's feedback, we shouldn't parse err messages but figure out a way to do this smarter. I updated the code just check for error existence and @brdji should figure out what to do next. --- chain/messagepool/messagepool_test.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/chain/messagepool/messagepool_test.go b/chain/messagepool/messagepool_test.go index 86c3a49d147..d7f075aabc7 100644 --- a/chain/messagepool/messagepool_test.go +++ b/chain/messagepool/messagepool_test.go @@ -901,7 +901,8 @@ func TestMessageSignatureInvalid(t *testing.T) { } err = mp.Add(context.TODO(), sm) assert.Error(t, err) - assert.Contains(t, err.Error(), "invalid signature length") + // assert.Contains(t, err.Error(), "invalid signature length") + assert.Error(t, err) } } @@ -931,7 +932,8 @@ func TestAddMessageTwice(t *testing.T) { // try to add it twice err = mp.Add(context.TODO(), sm) - assert.Contains(t, err.Error(), "with nonce 0 already in mpool") + // assert.Contains(t, err.Error(), "with nonce 0 already in mpool") + assert.Error(t, err) } } @@ -961,7 +963,8 @@ func TestAddMessageTwiceNonceGap(t *testing.T) { // then try to add message again err = mp.Add(context.TODO(), sm) - assert.Contains(t, err.Error(), "unfulfilled nonce gap") + // assert.Contains(t, err.Error(), "unfulfilled nonce gap") + assert.Error(t, err) } } @@ -993,7 +996,8 @@ func TestAddMessageTwiceCidDiff(t *testing.T) { //stm: @CHAIN_MEMPOOL_PUSH_001 // then try to add message again err = mp.Add(context.TODO(), sm2) - assert.Contains(t, err.Error(), "replace by fee has too low GasPremium") + // assert.Contains(t, err.Error(), "replace by fee has too low GasPremium") + assert.Error(t, err) } } From 3ff209d95d76def5fc648b8d08ab4366c925bb46 Mon Sep 17 00:00:00 2001 From: gammazero Date: Wed, 9 Feb 2022 11:06:56 -0800 Subject: [PATCH 123/385] Add replay rejection --- chain/sub/incoming.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/chain/sub/incoming.go b/chain/sub/incoming.go index 222ad3dea29..f8578bee80c 100644 --- a/chain/sub/incoming.go +++ b/chain/sub/incoming.go @@ -1,6 +1,7 @@ package sub import ( + "bytes" "context" "sync" "time" @@ -451,6 +452,7 @@ func recordFailure(ctx context.Context, metric *stats.Int64Measure, failureType type peerMsgInfo struct { peerID peer.ID lastCid cid.Cid + lastSeqno []byte rateLimit *ratelimit.Window mutex sync.Mutex } @@ -513,6 +515,17 @@ func (v *IndexerMessageValidator) Validate(ctx context.Context, pid peer.ID, msg msgInfo.mutex.Lock() defer msgInfo.mutex.Unlock() + if ok { + // Reject replayed messages. + seqno := msg.Message.GetSeqno() + if bytes.Equal(msgInfo.lastSeqno, seqno) { + log.Warnf("rejecting replayed indexer message") + stats.Record(ctx, metrics.IndexerMessageValidationFailure.M(1)) + return pubsub.ValidationReject + } + msgInfo.lastSeqno = seqno + } + if !ok || originPeer != msgInfo.peerID { // Check that the miner ID maps to the peer that sent the message. err = v.authenticateMessage(ctx, minerID, originPeer) From ae49729afb5699a85fba7707dc798e0d9822ecb5 Mon Sep 17 00:00:00 2001 From: Nikola Divic Date: Wed, 9 Feb 2022 20:46:51 +0100 Subject: [PATCH 124/385] test: chain sethead cli command Also moved the mock definition to a separate file (mocks_test.go) because it's gonna be used in other test files, and it didn't make sense for it to stay inside chain_test.go. --- cli/chain_test.go | 100 ++++++++++++++++++++++++++++++++-------------- cli/mocks_test.go | 32 +++++++++++++++ cli/util/api.go | 2 +- 3 files changed, 102 insertions(+), 32 deletions(-) create mode 100644 cli/mocks_test.go diff --git a/cli/chain_test.go b/cli/chain_test.go index 064393f3a8a..7607ea08d3a 100644 --- a/cli/chain_test.go +++ b/cli/chain_test.go @@ -9,39 +9,17 @@ import ( "strings" "testing" + "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/lotus/api" - "github.com/filecoin-project/lotus/api/mocks" types "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types/mock" "github.com/golang/mock/gomock" cid "github.com/ipfs/go-cid" "github.com/stretchr/testify/assert" - ucli "github.com/urfave/cli/v2" ) -// newMockAppWithFullAPI returns a gomock-ed CLI app used for unit tests -// see cli/util/api.go:GetFullNodeAPI for mock API injection -func newMockAppWithFullAPI(t *testing.T, cmd *ucli.Command) (*ucli.App, *mocks.MockFullNode, *bytes.Buffer, func()) { - app := ucli.NewApp() - app.Commands = ucli.Commands{cmd} - app.Setup() - - // create and inject the mock API into app Metadata - ctrl := gomock.NewController(t) - mockFullNode := mocks.NewMockFullNode(ctrl) - var fullNode api.FullNode = mockFullNode - app.Metadata["test-full-api"] = fullNode - - // this will only work if the implementation uses the app.Writer, - // if it uses fmt.*, it has to be refactored - buf := &bytes.Buffer{} - app.Writer = buf - - return app, mockFullNode, buf, ctrl.Finish -} - func TestChainHead(t *testing.T) { - app, mockApi, buf, done := newMockAppWithFullAPI(t, WithCategory("chain", ChainHeadCmd)) + app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("chain", ChainHeadCmd)) defer done() ctx, cancel := context.WithCancel(context.Background()) @@ -60,7 +38,7 @@ func TestChainHead(t *testing.T) { // TestGetBlock checks if "chain getblock" returns the block information in the expected format func TestGetBlock(t *testing.T) { - app, mockApi, buf, done := newMockAppWithFullAPI(t, WithCategory("chain", ChainGetBlock)) + app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("chain", ChainGetBlock)) defer done() ctx, cancel := context.WithCancel(context.Background()) @@ -96,7 +74,7 @@ func TestGetBlock(t *testing.T) { // TestChainReadObj checks if "chain read-obj" prints the referenced IPLD node as hex, if exists func TestReadOjb(t *testing.T) { - app, mockApi, buf, done := newMockAppWithFullAPI(t, WithCategory("chain", ChainReadObjCmd)) + app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("chain", ChainReadObjCmd)) defer done() ctx, cancel := context.WithCancel(context.Background()) @@ -124,7 +102,7 @@ func TestChainDeleteObj(t *testing.T) { // given no force flag, it should return an error and no API calls should be made t.Run("no-really-do-it", func(t *testing.T) { - app, _, _, done := newMockAppWithFullAPI(t, cmd) + app, _, _, done := NewMockAppWithFullAPI(t, cmd) defer done() err := app.Run([]string{"chain", "delete-obj", block.Cid().String()}) @@ -133,7 +111,7 @@ func TestChainDeleteObj(t *testing.T) { // given a force flag, it calls API delete t.Run("really-do-it", func(t *testing.T) { - app, mockApi, buf, done := newMockAppWithFullAPI(t, cmd) + app, mockApi, buf, done := NewMockAppWithFullAPI(t, cmd) defer done() ctx, cancel := context.WithCancel(context.Background()) @@ -166,7 +144,7 @@ func TestChainStatObj(t *testing.T) { // given no --base flag, it calls ChainStatObj with base=cid.Undef t.Run("no-base", func(t *testing.T) { - app, mockApi, buf, done := newMockAppWithFullAPI(t, cmd) + app, mockApi, buf, done := NewMockAppWithFullAPI(t, cmd) defer done() ctx, cancel := context.WithCancel(context.Background()) @@ -184,7 +162,7 @@ func TestChainStatObj(t *testing.T) { // given a --base flag, it calls ChainStatObj with that base t.Run("base", func(t *testing.T) { - app, mockApi, buf, done := newMockAppWithFullAPI(t, cmd) + app, mockApi, buf, done := NewMockAppWithFullAPI(t, cmd) defer done() ctx, cancel := context.WithCancel(context.Background()) @@ -203,7 +181,7 @@ func TestChainStatObj(t *testing.T) { // TestChainGetMsg checks if "chain getmessage" properly decodes and serializes as JSON a Message fetched from the IPLD store func TestChainGetMsg(t *testing.T) { - app, mockApi, buf, done := newMockAppWithFullAPI(t, WithCategory("chain", ChainGetMsgCmd)) + app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("chain", ChainGetMsgCmd)) defer done() from, err := mock.RandomActorAddress() @@ -234,3 +212,63 @@ func TestChainGetMsg(t *testing.T) { assert.Equal(t, *msg, out) } + +func TestSetHead(t *testing.T) { + cmd := WithCategory("chain", ChainSetHeadCmd) + genesis := mock.TipSet(mock.MkBlock(nil, 0, 0)) + ts := mock.TipSet(mock.MkBlock(genesis, 1, 0)) + epoch := abi.ChainEpoch(uint64(0)) + + // given the -genesis flag, resets head to genesis ignoring the provided ts positional argument + t.Run("genesis", func(t *testing.T) { + app, mockApi, _, done := NewMockAppWithFullAPI(t, cmd) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + gomock.InOrder( + mockApi.EXPECT().ChainGetGenesis(ctx).Return(genesis, nil), + mockApi.EXPECT().ChainSetHead(ctx, genesis.Key()).Return(nil), + ) + + err := app.Run([]string{"chain", "sethead", "-genesis=true", ts.Key().String()}) + assert.NoError(t, err) + }) + + // given the -epoch flag, resets head to given epoch, ignoring the provided ts positional argument + t.Run("epoch", func(t *testing.T) { + app, mockApi, _, done := NewMockAppWithFullAPI(t, cmd) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + gomock.InOrder( + mockApi.EXPECT().ChainGetTipSetByHeight(ctx, epoch, types.EmptyTSK).Return(genesis, nil), + mockApi.EXPECT().ChainSetHead(ctx, genesis.Key()).Return(nil), + ) + + err := app.Run([]string{"chain", "sethead", fmt.Sprintf("-epoch=%s", epoch), ts.Key().String()}) + assert.NoError(t, err) + }) + + // given no flag, resets the head to given tipset key + t.Run("default", func(t *testing.T) { + app, mockApi, _, done := NewMockAppWithFullAPI(t, cmd) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + gomock.InOrder( + mockApi.EXPECT().ChainGetBlock(ctx, ts.Key().Cids()[0]).Return(ts.Blocks()[0], nil), + mockApi.EXPECT().ChainSetHead(ctx, ts.Key()).Return(nil), + ) + + // ts.Key should be passed as an array of arguments (CIDs) + // since we have only one CID in the key, this is ok + err := app.Run([]string{"chain", "sethead", ts.Key().Cids()[0].String()}) + assert.NoError(t, err) + }) +} diff --git a/cli/mocks_test.go b/cli/mocks_test.go new file mode 100644 index 00000000000..c9cccac080e --- /dev/null +++ b/cli/mocks_test.go @@ -0,0 +1,32 @@ +package cli + +import ( + "bytes" + "testing" + + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/api/mocks" + "github.com/golang/mock/gomock" + ucli "github.com/urfave/cli/v2" +) + +// newMockAppWithFullAPI returns a gomock-ed CLI app used for unit tests +// see cli/util/api.go:GetFullNodeAPI for mock API injection +func NewMockAppWithFullAPI(t *testing.T, cmd *ucli.Command) (*ucli.App, *mocks.MockFullNode, *bytes.Buffer, func()) { + app := ucli.NewApp() + app.Commands = ucli.Commands{cmd} + app.Setup() + + // create and inject the mock API into app Metadata + ctrl := gomock.NewController(t) + mockFullNode := mocks.NewMockFullNode(ctrl) + var fullNode api.FullNode = mockFullNode + app.Metadata["test-full-api"] = fullNode + + // this will only work if the implementation uses the app.Writer, + // if it uses fmt.*, it has to be refactored + buf := &bytes.Buffer{} + app.Writer = buf + + return app, mockFullNode, buf, ctrl.Finish +} diff --git a/cli/util/api.go b/cli/util/api.go index 97e4f2cb89b..d87817bb39f 100644 --- a/cli/util/api.go +++ b/cli/util/api.go @@ -223,7 +223,7 @@ func GetCommonAPI(ctx *cli.Context) (api.CommonNet, jsonrpc.ClientCloser, error) } func GetFullNodeAPI(ctx *cli.Context) (v0api.FullNode, jsonrpc.ClientCloser, error) { - // use the mocked API in CLI unit tests, see cli/chain_test.go for mock definition + // use the mocked API in CLI unit tests, see cli/mocks_test.go for mock definition if mock, ok := ctx.App.Metadata["test-full-api"]; ok { return &v0api.WrapperV1Full{FullNode: mock.(v1api.FullNode)}, func() {}, nil } From 0d6eb7fefcbc59d2d3c8b69c3721b5f412494615 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 9 Feb 2022 14:13:58 -0800 Subject: [PATCH 125/385] ffi: update for fixed FVM lifetime management --- extern/filecoin-ffi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index 73f84f3d3c9..f029f279a84 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit 73f84f3d3c96c260ebea01ccad6a9754a51f3f99 +Subproject commit f029f279a84dfc187d13f275edc7545ee2299cf5 From 4e37131602c30e2734d4c7a20a1908cc311499be Mon Sep 17 00:00:00 2001 From: Nikola Divic Date: Wed, 9 Feb 2022 23:47:40 +0100 Subject: [PATCH 126/385] test: chain inspect-usage cli command --- cli/chain.go | 19 ++++++++-------- cli/chain_test.go | 57 ++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 62 insertions(+), 14 deletions(-) diff --git a/cli/chain.go b/cli/chain.go index d3259c6c81e..03dc309e052 100644 --- a/cli/chain.go +++ b/cli/chain.go @@ -416,6 +416,7 @@ var ChainInspectUsage = &cli.Command{ }, }, Action: func(cctx *cli.Context) error { + afmt := NewAppFmt(cctx.App) api, closer, err := GetFullNodeAPI(cctx) if err != nil { return err @@ -517,23 +518,23 @@ var ChainInspectUsage = &cli.Command{ numRes := cctx.Int("num-results") - fmt.Printf("Total Gas Limit: %d\n", sum) - fmt.Printf("By Sender:\n") + afmt.Printf("Total Gas Limit: %d\n", sum) + afmt.Printf("By Sender:\n") for i := 0; i < numRes && i < len(senderVals); i++ { sv := senderVals[i] - fmt.Printf("%s\t%0.2f%%\t(total: %d, count: %d)\n", sv.Key, (100*float64(sv.Gas))/float64(sum), sv.Gas, bySenderC[sv.Key]) + afmt.Printf("%s\t%0.2f%%\t(total: %d, count: %d)\n", sv.Key, (100*float64(sv.Gas))/float64(sum), sv.Gas, bySenderC[sv.Key]) } - fmt.Println() - fmt.Printf("By Receiver:\n") + afmt.Println() + afmt.Printf("By Receiver:\n") for i := 0; i < numRes && i < len(destVals); i++ { sv := destVals[i] - fmt.Printf("%s\t%0.2f%%\t(total: %d, count: %d)\n", sv.Key, (100*float64(sv.Gas))/float64(sum), sv.Gas, byDestC[sv.Key]) + afmt.Printf("%s\t%0.2f%%\t(total: %d, count: %d)\n", sv.Key, (100*float64(sv.Gas))/float64(sum), sv.Gas, byDestC[sv.Key]) } - fmt.Println() - fmt.Printf("By Method:\n") + afmt.Println() + afmt.Printf("By Method:\n") for i := 0; i < numRes && i < len(methodVals); i++ { sv := methodVals[i] - fmt.Printf("%s\t%0.2f%%\t(total: %d, count: %d)\n", sv.Key, (100*float64(sv.Gas))/float64(sum), sv.Gas, byMethodC[sv.Key]) + afmt.Printf("%s\t%0.2f%%\t(total: %d, count: %d)\n", sv.Key, (100*float64(sv.Gas))/float64(sum), sv.Gas, byMethodC[sv.Key]) } return nil diff --git a/cli/chain_test.go b/cli/chain_test.go index 7607ea08d3a..105d9d550b2 100644 --- a/cli/chain_test.go +++ b/cli/chain_test.go @@ -10,9 +10,11 @@ import ( "testing" "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/lotus/api" types "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types/mock" + "github.com/filecoin-project/specs-actors/v7/actors/builtin" "github.com/golang/mock/gomock" cid "github.com/ipfs/go-cid" "github.com/stretchr/testify/assert" @@ -36,7 +38,6 @@ func TestChainHead(t *testing.T) { assert.Regexp(t, regexp.MustCompile(ts.Cids()[0].String()), buf.String()) } -// TestGetBlock checks if "chain getblock" returns the block information in the expected format func TestGetBlock(t *testing.T) { app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("chain", ChainGetBlock)) defer done() @@ -72,7 +73,6 @@ func TestGetBlock(t *testing.T) { assert.True(t, block.Cid().Equals(out.Cid())) } -// TestChainReadObj checks if "chain read-obj" prints the referenced IPLD node as hex, if exists func TestReadOjb(t *testing.T) { app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("chain", ChainReadObjCmd)) defer done() @@ -95,7 +95,6 @@ func TestReadOjb(t *testing.T) { assert.Equal(t, buf.String(), fmt.Sprintf("%x\n", obj.Bytes())) } -// TestChainDeleteObj checks if "chain delete-obj" deletes an object from the chain blockstore, respecting the --really-do-it flag func TestChainDeleteObj(t *testing.T) { cmd := WithCategory("chain", ChainDeleteObjCmd) block := mock.MkBlock(nil, 0, 0) @@ -128,7 +127,6 @@ func TestChainDeleteObj(t *testing.T) { }) } -// TestChainStatObj checks if "chain delete-obj" prints size and IPLD link counts for object, respecting the --base flag func TestChainStatObj(t *testing.T) { cmd := WithCategory("chain", ChainStatObjCmd) block := mock.MkBlock(nil, 0, 0) @@ -179,7 +177,6 @@ func TestChainStatObj(t *testing.T) { }) } -// TestChainGetMsg checks if "chain getmessage" properly decodes and serializes as JSON a Message fetched from the IPLD store func TestChainGetMsg(t *testing.T) { app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("chain", ChainGetMsgCmd)) defer done() @@ -272,3 +269,53 @@ func TestSetHead(t *testing.T) { assert.NoError(t, err) }) } + +func TestInspectUsage(t *testing.T) { + cmd := WithCategory("chain", ChainInspectUsage) + ts := mock.TipSet(mock.MkBlock(nil, 0, 0)) + + from, err := mock.RandomActorAddress() + assert.NoError(t, err) + + to, err := mock.RandomActorAddress() + assert.NoError(t, err) + + msg := mock.UnsignedMessage(*from, *to, 0) + msgs := []api.Message{{Cid: msg.Cid(), Message: msg}} + + actor := &types.Actor{ + Code: builtin.StorageMarketActorCodeID, + Nonce: 0, + Balance: big.NewInt(1000000000), + } + + t.Run("default", func(t *testing.T) { + app, mockApi, buf, done := NewMockAppWithFullAPI(t, cmd) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + gomock.InOrder( + mockApi.EXPECT().ChainHead(ctx).Return(ts, nil), + mockApi.EXPECT().ChainGetParentMessages(ctx, ts.Blocks()[0].Cid()).Return(msgs, nil), + mockApi.EXPECT().ChainGetTipSet(ctx, ts.Parents()).Return(nil, nil), + mockApi.EXPECT().StateGetActor(ctx, *to, ts.Key()).Return(actor, nil), + ) + + err := app.Run([]string{"chain", "inspect-usage"}) + assert.NoError(t, err) + + out := buf.String() + + fmt.Println("🔥: ", out) + + // output is plaintext, had to do string matching + assert.Contains(t, out, "By Sender") + assert.Contains(t, out, from.String()) + assert.Contains(t, out, "By Receiver") + assert.Contains(t, out, to.String()) + assert.Contains(t, out, "By Method") + assert.Contains(t, out, "Send") + }) +} From b3f7db7a15dbf1219b0cd419f45eec2bc963ffd3 Mon Sep 17 00:00:00 2001 From: Nikola Divic Date: Thu, 10 Feb 2022 00:36:38 +0100 Subject: [PATCH 127/385] test: chain list (love) cli command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some "funky" string matching in this one, but I think that's ok. Chain is love. ❤️ --- cli/chain.go | 15 +++++++------- cli/chain_test.go | 53 ++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 56 insertions(+), 12 deletions(-) diff --git a/cli/chain.go b/cli/chain.go index 03dc309e052..cc024dbd352 100644 --- a/cli/chain.go +++ b/cli/chain.go @@ -559,6 +559,7 @@ var ChainListCmd = &cli.Command{ }, }, Action: func(cctx *cli.Context) error { + afmt := NewAppFmt(cctx.App) api, closer, err := GetFullNodeAPI(cctx) if err != nil { return err @@ -606,7 +607,7 @@ var ChainListCmd = &cli.Command{ tss = otss for i, ts := range tss { pbf := ts.Blocks()[0].ParentBaseFee - fmt.Printf("%d: %d blocks (baseFee: %s -> maxFee: %s)\n", ts.Height(), len(ts.Blocks()), ts.Blocks()[0].ParentBaseFee, types.FIL(types.BigMul(pbf, types.NewInt(uint64(build.BlockGasLimit))))) + afmt.Printf("%d: %d blocks (baseFee: %s -> maxFee: %s)\n", ts.Height(), len(ts.Blocks()), ts.Blocks()[0].ParentBaseFee, types.FIL(types.BigMul(pbf, types.NewInt(uint64(build.BlockGasLimit))))) for _, b := range ts.Blocks() { msgs, err := api.ChainGetBlockMessages(ctx, b.Cid()) @@ -632,7 +633,7 @@ var ChainListCmd = &cli.Command{ avgpremium = big.Div(psum, big.NewInt(int64(lenmsgs))) } - fmt.Printf("\t%s: \t%d msgs, gasLimit: %d / %d (%0.2f%%), avgPremium: %s\n", b.Miner, len(msgs.BlsMessages)+len(msgs.SecpkMessages), limitSum, build.BlockGasLimit, 100*float64(limitSum)/float64(build.BlockGasLimit), avgpremium) + afmt.Printf("\t%s: \t%d msgs, gasLimit: %d / %d (%0.2f%%), avgPremium: %s\n", b.Miner, len(msgs.BlsMessages)+len(msgs.SecpkMessages), limitSum, build.BlockGasLimit, 100*float64(limitSum)/float64(build.BlockGasLimit), avgpremium) } if i < len(tss)-1 { msgs, err := api.ChainGetParentMessages(ctx, tss[i+1].Blocks()[0].Cid()) @@ -657,13 +658,13 @@ var ChainListCmd = &cli.Command{ gasEfficiency := 100 * float64(gasUsed) / float64(limitSum) gasCapacity := 100 * float64(limitSum) / float64(build.BlockGasLimit) - fmt.Printf("\ttipset: \t%d msgs, %d (%0.2f%%) / %d (%0.2f%%)\n", len(msgs), gasUsed, gasEfficiency, limitSum, gasCapacity) + afmt.Printf("\ttipset: \t%d msgs, %d (%0.2f%%) / %d (%0.2f%%)\n", len(msgs), gasUsed, gasEfficiency, limitSum, gasCapacity) } - fmt.Println() + afmt.Println() } } else { for i := len(tss) - 1; i >= 0; i-- { - printTipSet(cctx.String("format"), tss[i]) + printTipSet(cctx.String("format"), tss[i], afmt) } } return nil @@ -889,7 +890,7 @@ func handleHamtAddress(ctx context.Context, api v0api.FullNode, r cid.Cid) error }) } -func printTipSet(format string, ts *types.TipSet) { +func printTipSet(format string, ts *types.TipSet, afmt *AppFmt) { format = strings.ReplaceAll(format, "", fmt.Sprint(ts.Height())) format = strings.ReplaceAll(format, "(&)2pE5Pct$!r{Dp!zEQ<;jmW|!$GwL95aZH@-D z@poh!rOzze8>Dt7ya!n|BRs+6*sBI4cL1efv8^DjgRYwr)zPu+bkozy=vGGWR7SS~ z@_cYK%qp!R#K8wl%=!W{gi;(M;K|4wOSYf(G5N-A#P#DHT$k}Jg=i`{my$hHaWTba zW`CztvNx@UV=TkT z6(A=2ruAsm()pvTk~@N2KO%Z=8+R3p?!;lpb90iCl{ZyT&_2{0^(+NlMKec6u$AIk zQbY@Nkl#v0U5mD1g_z8&fo`wQSj54Uk$9YqN{r0JB z0ELG{wcL2oebc#qOZa#u01i9a5|i*pQfh?rwl@Y&BqzdKu;-edAFfo{(NR`LV~#~o zLT0k>3mr(F^elaD&YBg7&H4xC-UxOOxw${?qAb~7a8BEX+_fjO`x$b#r^0ufm46s3 zCcJtj^zi$<8nB+gxea!Br^v7r(-1aNL`^hT<|N>R-y37gecMa(HlxJ;)M zuOOT7+8p<`QZsgE=H838t;Tv*j+#fVlz9_Bk> z>L4Q~kDE)R&8V`m_Qr%1zF9%K(0>Y8G@&718XI);Gr!nwx+WLgHFE@0{m7c((9mJE zH=LavQ@3X(KggNM_cM(45c_;E?&aqcULqz?enHTpwK5B%aMU7wykFuI@p-X;jCRwI zpiE%Clg#&ha?%vati&RzR$ix&isP?lvdTJ|q-b?XU6EC+*T=O@TSN8I)_-aj>}y5# z`C#17Ph|5_IxCB6_PvTPJ(feNu<2vXa`t@jH1Z0YJrD06-h-aZ?QJuEUy=xYA)EC< zerC|Mv#GmZ_dslW%l>L=+bYg%4;{Gx6zfu6TceXC}mrP@op)yELU7NZkq^Dn~g=hvB3jx z>VnIQlLqStwUxAX&kLiB)D1xl|FWmmA~?g(vyaQxYiu5V{v4d`3K<)GnP*Cb;0w;q z3i>FuyNZozYX@ls7)#I9ioa2@PS9*@PA0H-FdC1B2ZQc-axk9F;D5nnhGzO~td9^v zk=oHk@u0fy#kgokBYoVRLj7RWotg)OAsik|4Sjq7XZmo~HF_g7G~T6_jN->tZ$lAao;rmF1@6Z=xAqiVms&(x%S#IB7brr^5mQL2`w)c8y6eU z(vEvaj0`9GXfhad*el`b>U9T4gK>W}81si$4{)U&cYEXUV4`=&M@_;~U8GsPDE z>fIEn^EMaIfq#~TEbK0|<8JcN$BWOr;XCM}L=R6Lt()k0+#ioedc5!8S%cksFrPYF zFM&ZXt%;twfk)gQ&l{2 zh3PY*k`$)Th)Q$9v?OgdElkVP=5~Z>rBz4@(`Q5_DNLUYm9#MJ)expBX}(*_v_|*k zh3TlPkGj31zC`8Lz$5HUmq^oouh;GMhJ&M?o`H<6E1`2B$7htnCsGMSB2q_#L2oeB zCxd~Wq<;>*t4{`_;izGJM&qOIWNW`|+)%s*wORhFTrmAvv7i5|gtj|rRN$L8$ zWEv5%GepJR$VvIy)d%C@(I_GOy=M(deqADBciDGZxbCj+v}wA#zSFko?)pv&$zArH zl#{#cJ1rr1*LT{~++E*k+j3WZMGg8lAY zuWg9wzJ{2_jMrA8?hDnn61A16twjAUC4cIgxL$StR+K*X*=rjW&_)Fm2+}qxV4tD_ zo|q(kPvF!F)4;u4)=${$#QO;!`OlB5wa8r6JK72Vn}=%U7g;ECU7!b3CHX!;TzYql zkLb7bhkhb(V>KU=>BBOFVz0~02u}u9nU9ZNOZ7WrVkyl^Wdi-2<`RunYXC;ls7@6N z5r*@bLwwE9WrBqimm|ip5<-k{yJC^X7{izUhD!vc&&rHdrEo{JCvo{xf`+*G+GXk9 beXW%-9&1lew@?2+00960-F=Qb@@@hE=Rn+} delta 12757 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 bzShbZkF}?#+o%5@00960#&=jp@@@hEv0L5E diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index d6c6806caadfecc60a2bad43c9b8e54d73222d61..ef2c8c6bd65726074614b84a1e857f384e38abfa 100644 GIT binary patch delta 3825 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 delta 3825 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 diff --git a/build/version.go b/build/version.go index 5745c0e8dc8..c80c1df4086 100644 --- a/build/version.go +++ b/build/version.go @@ -37,7 +37,7 @@ func BuildTypeString() string { } // BuildVersion is the local build version -const BuildVersion = "1.15.0-dev" +const BuildVersion = "1.15.1-dev" func UserVersion() string { if os.Getenv("LOTUS_VERSION_IGNORE_COMMIT") == "1" { diff --git a/documentation/en/cli-lotus-miner.md b/documentation/en/cli-lotus-miner.md index 6543beab738..0cf5b35e7c2 100644 --- a/documentation/en/cli-lotus-miner.md +++ b/documentation/en/cli-lotus-miner.md @@ -7,7 +7,7 @@ USAGE: lotus-miner [global options] command [command options] [arguments...] VERSION: - 1.15.0-dev + 1.15.1-dev COMMANDS: init Initialize a lotus miner repo diff --git a/documentation/en/cli-lotus-worker.md b/documentation/en/cli-lotus-worker.md index 5969323c2fe..c74d8e8dad1 100644 --- a/documentation/en/cli-lotus-worker.md +++ b/documentation/en/cli-lotus-worker.md @@ -7,7 +7,7 @@ USAGE: lotus-worker [global options] command [command options] [arguments...] VERSION: - 1.15.0-dev + 1.15.1-dev COMMANDS: run Start lotus worker diff --git a/documentation/en/cli-lotus.md b/documentation/en/cli-lotus.md index 54c0d36dfe6..e7ebf8af69e 100644 --- a/documentation/en/cli-lotus.md +++ b/documentation/en/cli-lotus.md @@ -7,7 +7,7 @@ USAGE: lotus [global options] command [command options] [arguments...] VERSION: - 1.15.0-dev + 1.15.1-dev COMMANDS: daemon Start a lotus daemon process From 7e7844f169e5924a6c0616a5d1e20ded31a67dee Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Fri, 11 Feb 2022 12:15:21 +0000 Subject: [PATCH 145/385] Fix log message formatting when instantiating index provider --- node/modules/storageminer_idxprov.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/modules/storageminer_idxprov.go b/node/modules/storageminer_idxprov.go index dfbc669d350..b8333441b1e 100644 --- a/node/modules/storageminer_idxprov.go +++ b/node/modules/storageminer_idxprov.go @@ -88,7 +88,7 @@ func IndexProvider(cfg config.IndexProviderConfig) func(params IdxProv, marketHo // Get the miner ID and set as extra gossip data. // The extra data is required by the lotus-specific index-provider gossip message validators. ma := address.Address(maddr) - log.Info("Using extra gossip data in index provider engine: %s", ma.String()) + log.Infof("Using extra gossip data in index provider engine: %s", ma.String()) e, err := engine.New(cfg.Ingest, pkey, dt, h, ipds, maddrs, engine.WithExtraGossipData(ma.Bytes())) if err != nil { From 34bfd13548f84ed90900518ac12792dd048f44c2 Mon Sep 17 00:00:00 2001 From: Nikola Divic Date: Fri, 11 Feb 2022 15:06:06 +0100 Subject: [PATCH 146/385] doc: add stm annotations to the syncer tests Add annotations for the test crawler for the lotus.systemtestmatrix.com dashboard. --- chain/sync_manager_test.go | 6 ++++-- chain/sync_test.go | 5 +++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/chain/sync_manager_test.go b/chain/sync_manager_test.go index bb0bbe1f51f..d91ab1788b3 100644 --- a/chain/sync_manager_test.go +++ b/chain/sync_manager_test.go @@ -249,7 +249,8 @@ func TestSyncManagerBucketSet(t *testing.T) { bucketSet := syncBucketSet{buckets: []*syncTargetBucket{bucket1}} fmt.Println("bucketSet: ", bucketSet.String()) - // inserting a tipset from an existing chain, should add to an existing bucket + // inserting a tipset (potential sync target) from an existing chain, should add to an existing bucket + //stm: @CHAIN_SYNCER_ADD_SYNC_TARGET_001 ts3 := mock.TipSet(mock.MkBlock(ts2, 2, 0)) bucketSet.Insert(ts3) require.Equal(t, 1, len(bucketSet.buckets)) @@ -264,7 +265,8 @@ func TestSyncManagerBucketSet(t *testing.T) { require.Equal(t, 1, len(bucketSet.buckets[1].tips)) fmt.Println("bucketSet: ", bucketSet.String()) - // Pop removes the best bucket, e.g. bucket1 + // Pop removes the best bucket (best sync target), e.g. bucket1 + //stm: @CHAIN_SYNCER_SELECT_SYNC_TARGET_001 popped := bucketSet.Pop() require.Equal(t, popped, bucket1) require.Equal(t, 1, len(bucketSet.buckets)) diff --git a/chain/sync_test.go b/chain/sync_test.go index 2bc49dbec9c..96ed1440e92 100644 --- a/chain/sync_test.go +++ b/chain/sync_test.go @@ -1108,6 +1108,7 @@ func TestIncomingBlocks(t *testing.T) { require.NoError(t, tu.mn.LinkAll()) clientNode := tu.nds[client] + //stm: @CHAIN_SYNCER_INCOMING_BLOCKS_001 incoming, err := clientNode.SyncIncomingBlocks(tu.ctx) require.NoError(tu.t, err) @@ -1151,6 +1152,7 @@ func TestSyncManualBadTS(t *testing.T) { require.True(tu.t, !sourceHead.Equals(clientHead), "source and client should be out of sync in test setup") + //stm: @CHAIN_SYNCER_MARK_BAD_001 err = tu.nds[client].SyncMarkBad(tu.ctx, sourceHead.Cids()[0]) require.NoError(tu.t, err) @@ -1158,6 +1160,7 @@ func TestSyncManualBadTS(t *testing.T) { err = tu.nds[client].SyncMarkBad(tu.ctx, sourceHeadParent) require.NoError(tu.t, err) + //stm: @CHAIN_SYNCER_CHECK_BAD_001 reason, err := tu.nds[client].SyncCheckBad(tu.ctx, sourceHead.Cids()[0]) require.NoError(tu.t, err) require.NotEqual(tu.t, "", reason, "block is not bad after manually marking") @@ -1179,6 +1182,7 @@ func TestSyncManualBadTS(t *testing.T) { // Assertion 2: // - after unmarking blocks as bad and reconnecting, source & client should be in sync + //stm: @CHAIN_SYNCER_UNMARK_BAD_001 err = tu.nds[client].SyncUnmarkBad(tu.ctx, sourceHead.Cids()[0]) require.NoError(tu.t, err) @@ -1223,6 +1227,7 @@ func TestSyncState(t *testing.T) { activeSyncs := []api.ActiveSync{} for len(activeSyncs) == 0 { + //stm: @CHAIN_SYNCER_STATE_001 state, err = clientNode.SyncState(tu.ctx) require.NoError(tu.t, err) activeSyncs = state.ActiveSyncs From 8a2d27309d3568624360bd085ced3ed294a48616 Mon Sep 17 00:00:00 2001 From: TheMenko Date: Fri, 11 Feb 2022 16:30:28 +0100 Subject: [PATCH 147/385] adding cli wallet tests --- cli/wallet_test.go | 288 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 288 insertions(+) create mode 100644 cli/wallet_test.go diff --git a/cli/wallet_test.go b/cli/wallet_test.go new file mode 100644 index 00000000000..f6861b37f8c --- /dev/null +++ b/cli/wallet_test.go @@ -0,0 +1,288 @@ +package cli + +import ( + "context" + "testing" + + "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/crypto" + "github.com/filecoin-project/lotus/api" + apitypes "github.com/filecoin-project/lotus/api/types" + types "github.com/filecoin-project/lotus/chain/types" + "github.com/golang/mock/gomock" + "github.com/ipfs/go-cid" + "github.com/stretchr/testify/assert" +) + +func TestWalletNew(t *testing.T) { + app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletNew)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + keyType := types.KeyType("secp256k1") + address := address.Address{} + + mockApi.EXPECT().WalletNew(ctx, keyType).Return(address, nil) + + err := app.Run([]string{"wallet", "new"}) + assert.NoError(t, err) +} + +func TestWalletList(t *testing.T) { + + addr, err := address.NewIDAddress(1234) + addresses := []address.Address{addr} + assert.NoError(t, err) + + cid := cid.Cid{} + key := types.NewTipSetKey(cid) + + actor := types.Actor{ + Code: cid, + Head: cid, + Nonce: 0, + Balance: big.NewInt(100), + } + + t.Run("wallet-list-addr-only", func(t *testing.T) { + + app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletList)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + gomock.InOrder( + mockApi.EXPECT().WalletList(ctx).Return(addresses, nil), + mockApi.EXPECT().WalletDefaultAddress(ctx).Return(addr, nil), + mockApi.EXPECT().StateGetActor(ctx, addr, key).Return(&actor, nil), + ) + + err := app.Run([]string{"wallet", "list", "addr-only"}) + assert.NoError(t, err) + }) + t.Run("wallet-list-id", func(t *testing.T) { + + app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletList)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + gomock.InOrder( + mockApi.EXPECT().WalletList(ctx).Return(addresses, nil), + mockApi.EXPECT().WalletDefaultAddress(ctx).Return(addr, nil), + mockApi.EXPECT().StateGetActor(ctx, addr, key).Return(&actor, nil), + mockApi.EXPECT().StateLookupID(ctx, addr, key).Return(addr, nil), + ) + + err := app.Run([]string{"wallet", "list", "--id"}) + assert.NoError(t, err) + }) + t.Run("wallet-list-market", func(t *testing.T) { + + app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletList)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + balance := api.MarketBalance{ + Escrow: big.NewInt(1234), + Locked: big.NewInt(123), + } + + gomock.InOrder( + mockApi.EXPECT().WalletList(ctx).Return(addresses, nil), + mockApi.EXPECT().WalletDefaultAddress(ctx).Return(addr, nil), + mockApi.EXPECT().StateGetActor(ctx, addr, key).Return(&actor, nil), + mockApi.EXPECT().StateMarketBalance(ctx, addr, key).Return(balance, nil), + ) + + err := app.Run([]string{"wallet", "list", "--market"}) + assert.NoError(t, err) + }) +} + +func TestWalletBalance(t *testing.T) { + app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletBalance)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + addr, err := address.NewIDAddress(1234) + assert.NoError(t, err) + + balance := big.NewInt(1234) + + mockApi.EXPECT().WalletBalance(ctx, addr).Return(balance, nil) + + err = app.Run([]string{"wallet", "balance", "f01234"}) + assert.NoError(t, err) +} + +func TestWalletGetDefault(t *testing.T) { + app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletGetDefault)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + addr := address.Address{} + + mockApi.EXPECT().WalletDefaultAddress(ctx).Return(addr, nil) + + err := app.Run([]string{"wallet", "default"}) + assert.NoError(t, err) +} + +func TestWalletSetDefault(t *testing.T) { + app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletSetDefault)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + addr, err := address.NewIDAddress(1234) + assert.NoError(t, err) + + mockApi.EXPECT().WalletSetDefault(ctx, addr).Return(nil) + + err = app.Run([]string{"wallet", "set-default", "f01234"}) + assert.NoError(t, err) +} + +func TestWalletExport(t *testing.T) { + app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletExport)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + addr, err := address.NewIDAddress(1234) + assert.NoError(t, err) + + keyInfo := types.KeyInfo{} + + mockApi.EXPECT().WalletExport(ctx, addr).Return(&keyInfo, nil) + + err = app.Run([]string{"wallet", "export", "f01234"}) + assert.NoError(t, err) +} + +func TestWalletSign(t *testing.T) { + app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletSign)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + addr, err := address.NewIDAddress(1234) + assert.NoError(t, err) + + msg := []byte{1} + signature := crypto.Signature{} + + mockApi.EXPECT().WalletSign(ctx, addr, msg).Return(&signature, nil) + + err = app.Run([]string{"wallet", "sign", "f01234", "01"}) + assert.NoError(t, err) +} + +func TestWalletVerify(t *testing.T) { + app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletVerify)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + addr, err := address.NewIDAddress(1234) + assert.NoError(t, err) + + msg := []byte{1} + signature := crypto.Signature{ + Type: crypto.SigTypeSecp256k1, + Data: []byte{}, + } + + mockApi.EXPECT().WalletVerify(ctx, addr, msg, &signature).Return(true, nil) + + err = app.Run([]string{"wallet", "verify", "f01234", "01", "01"}) + assert.NoError(t, err) +} + +func TestWalletDelete(t *testing.T) { + app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletDelete)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + addr, err := address.NewIDAddress(1234) + assert.NoError(t, err) + + mockApi.EXPECT().WalletDelete(ctx, addr).Return(nil) + + err = app.Run([]string{"wallet", "delete", "f01234"}) + assert.NoError(t, err) +} + +func TestWalletMarketWithdraw(t *testing.T) { + app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletMarket)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + addr, err := address.NewIDAddress(1234) + assert.NoError(t, err) + + balance := api.MarketBalance{ + Escrow: big.NewInt(100), + Locked: big.NewInt(10), + } + + cid := cid.Cid{} + msgLookup := api.MsgLookup{} + + var networkVers apitypes.NetworkVersion + + gomock.InOrder( + mockApi.EXPECT().StateMarketBalance(ctx, addr, types.TipSetKey{}).Return(balance, nil), + // mock reserve to 10 + mockApi.EXPECT().MarketGetReserved(ctx, addr).Return(big.NewInt(10), nil), + // available should be 80.. escrow - locked - reserve + mockApi.EXPECT().MarketWithdraw(ctx, addr, addr, big.NewInt(80)).Return(cid, nil), + mockApi.EXPECT().StateWaitMsg(ctx, cid, uint64(5), abi.ChainEpoch(int64(-1)), true).Return(&msgLookup, nil), + mockApi.EXPECT().StateNetworkVersion(ctx, types.TipSetKey{}).Return(networkVers, nil), + ) + + err = app.Run([]string{"wallet", "market", "withdraw", "--wallet", addr.String()}) + assert.NoError(t, err) +} + +func TestWalletMarketAdd(t *testing.T) { + app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletMarket)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + toAddr := address.Address{} + defaultAddr := address.Address{} + + cid := cid.Cid{} + + gomock.InOrder( + mockApi.EXPECT().WalletDefaultAddress(ctx).Return(defaultAddr, nil), + mockApi.EXPECT().MarketAddBalance(ctx, defaultAddr, toAddr, big.NewInt(80)).Return(cid, nil), + ) + + err := app.Run([]string{"wallet", "market", "add", "0.000000000000000080", "--address", toAddr.String()}) + assert.NoError(t, err) +} From ec0607900da136a481f64f72aabd4c2f5d17beee Mon Sep 17 00:00:00 2001 From: Nikola Divic Date: Fri, 11 Feb 2022 17:45:19 +0100 Subject: [PATCH 148/385] test: sync state cli command --- cli/sync.go | 22 ++++++++++--------- cli/sync_test.go | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 10 deletions(-) create mode 100644 cli/sync_test.go diff --git a/cli/sync.go b/cli/sync.go index c7b010111c3..a486046bb88 100644 --- a/cli/sync.go +++ b/cli/sync.go @@ -33,6 +33,8 @@ var SyncStatusCmd = &cli.Command{ Name: "status", Usage: "check sync status", Action: func(cctx *cli.Context) error { + afmt := NewAppFmt(cctx.App) + apic, closer, err := GetFullNodeAPI(cctx) if err != nil { return err @@ -45,9 +47,9 @@ var SyncStatusCmd = &cli.Command{ return err } - fmt.Println("sync status:") + afmt.Println("sync status:") for _, ss := range state.ActiveSyncs { - fmt.Printf("worker %d:\n", ss.WorkerID) + afmt.Printf("worker %d:\n", ss.WorkerID) var base, target []cid.Cid var heightDiff int64 var theight abi.ChainEpoch @@ -62,20 +64,20 @@ var SyncStatusCmd = &cli.Command{ } else { heightDiff = 0 } - fmt.Printf("\tBase:\t%s\n", base) - fmt.Printf("\tTarget:\t%s (%d)\n", target, theight) - fmt.Printf("\tHeight diff:\t%d\n", heightDiff) - fmt.Printf("\tStage: %s\n", ss.Stage) - fmt.Printf("\tHeight: %d\n", ss.Height) + afmt.Printf("\tBase:\t%s\n", base) + afmt.Printf("\tTarget:\t%s (%d)\n", target, theight) + afmt.Printf("\tHeight diff:\t%d\n", heightDiff) + afmt.Printf("\tStage: %s\n", ss.Stage) + afmt.Printf("\tHeight: %d\n", ss.Height) if ss.End.IsZero() { if !ss.Start.IsZero() { - fmt.Printf("\tElapsed: %s\n", time.Since(ss.Start)) + afmt.Printf("\tElapsed: %s\n", time.Since(ss.Start)) } } else { - fmt.Printf("\tElapsed: %s\n", ss.End.Sub(ss.Start)) + afmt.Printf("\tElapsed: %s\n", ss.End.Sub(ss.Start)) } if ss.Stage == api.StageSyncErrored { - fmt.Printf("\tError: %s\n", ss.Message) + afmt.Printf("\tError: %s\n", ss.Message) } } return nil diff --git a/cli/sync_test.go b/cli/sync_test.go new file mode 100644 index 00000000000..5c5961782ea --- /dev/null +++ b/cli/sync_test.go @@ -0,0 +1,56 @@ +package cli + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/types/mock" + "github.com/stretchr/testify/assert" +) + +func TestSyncStatus(t *testing.T) { + app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("sync", SyncStatusCmd)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + ts1 := mock.TipSet(mock.MkBlock(nil, 0, 0)) + ts2 := mock.TipSet(mock.MkBlock(ts1, 0, 0)) + + start := time.Now() + end := start.Add(time.Minute) + + state := &api.SyncState{ + ActiveSyncs: []api.ActiveSync{{ + WorkerID: 1, + Base: ts1, + Target: ts2, + Stage: api.StageMessages, + Height: abi.ChainEpoch(0), + Start: start, + End: end, + Message: "whatever", + }}, + VMApplied: 0, + } + + mockApi.EXPECT().SyncState(ctx).Return(state, nil) + + err := app.Run([]string{"sync", "status"}) + assert.NoError(t, err) + + out := buf.String() + + // output is plaintext, had to do string matching + assert.Contains(t, out, fmt.Sprintf("Base:\t[%s]", ts1.Blocks()[0].Cid().String())) + assert.Contains(t, out, fmt.Sprintf("Target:\t[%s]", ts2.Blocks()[0].Cid().String())) + assert.Contains(t, out, "Height diff:\t1") + assert.Contains(t, out, "Stage: message sync") + assert.Contains(t, out, "Height: 0") + assert.Contains(t, out, "Elapsed: 1m0s") +} From 7fc2f9dc296083a02942b312349bb70a2964ced1 Mon Sep 17 00:00:00 2001 From: Nikola Divic Date: Fri, 11 Feb 2022 17:54:53 +0100 Subject: [PATCH 149/385] test: sync mark-bad cli command --- cli/sync_test.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/cli/sync_test.go b/cli/sync_test.go index 5c5961782ea..50be068f006 100644 --- a/cli/sync_test.go +++ b/cli/sync_test.go @@ -54,3 +54,18 @@ func TestSyncStatus(t *testing.T) { assert.Contains(t, out, "Height: 0") assert.Contains(t, out, "Elapsed: 1m0s") } + +func TestSyncMarkBad(t *testing.T) { + app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("sync", SyncMarkBadCmd)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + blk := mock.MkBlock(nil, 0, 0) + + mockApi.EXPECT().SyncMarkBad(ctx, blk.Cid()).Return(nil) + + err := app.Run([]string{"sync", "mark-bad", blk.Cid().String()}) + assert.NoError(t, err) +} From 0f79a0024c6f5f83dca4d1c7fa1e845a27c7d495 Mon Sep 17 00:00:00 2001 From: Nikola Divic Date: Fri, 11 Feb 2022 18:00:01 +0100 Subject: [PATCH 150/385] test: sync unmark-bad cli command --- cli/sync_test.go | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/cli/sync_test.go b/cli/sync_test.go index 50be068f006..7612d5da97c 100644 --- a/cli/sync_test.go +++ b/cli/sync_test.go @@ -69,3 +69,33 @@ func TestSyncMarkBad(t *testing.T) { err := app.Run([]string{"sync", "mark-bad", blk.Cid().String()}) assert.NoError(t, err) } + +func TestSyncUnmarkBad(t *testing.T) { + t.Run("one-block", func(t *testing.T) { + app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("sync", SyncUnmarkBadCmd)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + blk := mock.MkBlock(nil, 0, 0) + + mockApi.EXPECT().SyncUnmarkBad(ctx, blk.Cid()).Return(nil) + + err := app.Run([]string{"sync", "unmark-bad", blk.Cid().String()}) + assert.NoError(t, err) + }) + + t.Run("all", func(t *testing.T) { + app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("sync", SyncUnmarkBadCmd)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + mockApi.EXPECT().SyncUnmarkAllBad(ctx).Return(nil) + + err := app.Run([]string{"sync", "unmark-bad", "-all"}) + assert.NoError(t, err) + }) +} From 05c8635749e53eb5591dce54cf895f9c2a4bcf51 Mon Sep 17 00:00:00 2001 From: Nikola Divic Date: Fri, 11 Feb 2022 18:08:36 +0100 Subject: [PATCH 151/385] test: sync check-bad cli command --- cli/sync.go | 6 ++++-- cli/sync_test.go | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/cli/sync.go b/cli/sync.go index a486046bb88..0c498437942 100644 --- a/cli/sync.go +++ b/cli/sync.go @@ -170,6 +170,8 @@ var SyncCheckBadCmd = &cli.Command{ Usage: "check if the given block was marked bad, and for what reason", ArgsUsage: "[blockCid]", Action: func(cctx *cli.Context) error { + afmt := NewAppFmt(cctx.App) + napi, closer, err := GetFullNodeAPI(cctx) if err != nil { return err @@ -192,11 +194,11 @@ var SyncCheckBadCmd = &cli.Command{ } if reason == "" { - fmt.Println("block was not marked as bad") + afmt.Println("block was not marked as bad") return nil } - fmt.Println(reason) + afmt.Println(reason) return nil }, } diff --git a/cli/sync_test.go b/cli/sync_test.go index 7612d5da97c..85b05fa5c57 100644 --- a/cli/sync_test.go +++ b/cli/sync_test.go @@ -99,3 +99,40 @@ func TestSyncUnmarkBad(t *testing.T) { assert.NoError(t, err) }) } + +func TestSyncCheckBad(t *testing.T) { + t.Run("not-bad", func(t *testing.T) { + app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("sync", SyncCheckBadCmd)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + blk := mock.MkBlock(nil, 0, 0) + + mockApi.EXPECT().SyncCheckBad(ctx, blk.Cid()).Return("", nil) + + err := app.Run([]string{"sync", "check-bad", blk.Cid().String()}) + assert.NoError(t, err) + + assert.Contains(t, buf.String(), "block was not marked as bad") + }) + + t.Run("bad", func(t *testing.T) { + app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("sync", SyncCheckBadCmd)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + blk := mock.MkBlock(nil, 0, 0) + reason := "whatever" + + mockApi.EXPECT().SyncCheckBad(ctx, blk.Cid()).Return(reason, nil) + + err := app.Run([]string{"sync", "check-bad", blk.Cid().String()}) + assert.NoError(t, err) + + assert.Contains(t, buf.String(), reason) + }) +} From 94374aa93d4ef3fb6174e6d6422352599dccc894 Mon Sep 17 00:00:00 2001 From: Nikola Divic Date: Fri, 11 Feb 2022 18:30:07 +0100 Subject: [PATCH 152/385] test: sync checkpoint cli command --- cli/sync_test.go | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/cli/sync_test.go b/cli/sync_test.go index 85b05fa5c57..174279d0820 100644 --- a/cli/sync_test.go +++ b/cli/sync_test.go @@ -8,7 +8,9 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types/mock" + "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" ) @@ -136,3 +138,44 @@ func TestSyncCheckBad(t *testing.T) { assert.Contains(t, buf.String(), reason) }) } + +func TestSyncCheckpoint(t *testing.T) { + t.Run("tipset", func(t *testing.T) { + app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("sync", SyncCheckpointCmd)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + blk := mock.MkBlock(nil, 0, 0) + ts := mock.TipSet(blk) + + gomock.InOrder( + mockApi.EXPECT().ChainGetBlock(ctx, blk.Cid()).Return(blk, nil), + mockApi.EXPECT().SyncCheckpoint(ctx, ts.Key()).Return(nil), + ) + + err := app.Run([]string{"sync", "checkpoint", blk.Cid().String()}) + assert.NoError(t, err) + }) + + t.Run("epoch", func(t *testing.T) { + app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("sync", SyncCheckpointCmd)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + epoch := abi.ChainEpoch(0) + blk := mock.MkBlock(nil, 0, 0) + ts := mock.TipSet(blk) + + gomock.InOrder( + mockApi.EXPECT().ChainGetTipSetByHeight(ctx, epoch, types.EmptyTSK).Return(ts, nil), + mockApi.EXPECT().SyncCheckpoint(ctx, ts.Key()).Return(nil), + ) + + err := app.Run([]string{"sync", "checkpoint", fmt.Sprintf("-epoch=%d", epoch)}) + assert.NoError(t, err) + }) +} From e89f7d90238748bdec8dfe1a15e1f54bd6d2eb98 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 11 Feb 2022 10:09:40 -0800 Subject: [PATCH 153/385] feat: shed: add a state-tree diff command to lotus shed This makes it easier to debug state mismatches by providing a nice way to figure out which actors differ between two state-trees and how (balance, nonce, state, etc.). It doesn't provide a way to actually _diff_ those state-trees, but one can use `lotus chain get` to figure that out (although it would be _nice_ to provide something a bit smarter). --- cmd/lotus-shed/diff.go | 104 +++++++++++++++++++++++++++++++++++++++++ cmd/lotus-shed/main.go | 1 + 2 files changed, 105 insertions(+) create mode 100644 cmd/lotus-shed/diff.go diff --git a/cmd/lotus-shed/diff.go b/cmd/lotus-shed/diff.go new file mode 100644 index 00000000000..bcaa041227e --- /dev/null +++ b/cmd/lotus-shed/diff.go @@ -0,0 +1,104 @@ +package main + +import ( + "fmt" + + "github.com/urfave/cli/v2" + "golang.org/x/xerrors" + + "github.com/ipfs/go-cid" + + "github.com/filecoin-project/lotus/chain/types" + lcli "github.com/filecoin-project/lotus/cli" +) + +var diffCmd = &cli.Command{ + Name: "diff", + Usage: "diff state objects", + Subcommands: []*cli.Command{diffStateTrees}, +} + +var diffStateTrees = &cli.Command{ + Name: "state-trees", + Usage: "diff two state-trees", + ArgsUsage: " ", + Action: func(cctx *cli.Context) error { + api, closer, err := lcli.GetFullNodeAPI(cctx) + if err != nil { + return err + } + + defer closer() + ctx := lcli.ReqContext(cctx) + + if cctx.NArg() != 2 { + return xerrors.Errorf("expected two state-tree roots") + } + + argA := cctx.Args().Get(1) + rootA, err := cid.Parse(argA) + if err != nil { + return xerrors.Errorf("first state-tree root (%q) is not a CID: %w", argA, err) + } + argB := cctx.Args().Get(1) + rootB, err := cid.Parse(argB) + if err != nil { + return xerrors.Errorf("second state-tree root (%q) is not a CID: %w", argB, err) + } + + if rootA == rootB { + fmt.Println("state trees do not differ") + return nil + } + + changedB, err := api.StateChangedActors(ctx, rootA, rootB) + if err != nil { + return err + } + changedA, err := api.StateChangedActors(ctx, rootB, rootA) + if err != nil { + return err + } + + diff := func(stateA, stateB types.Actor) { + if stateB.Code != stateA.Code { + fmt.Printf(" code: %s != %s\n", stateA.Code, stateB.Code) + } + if stateB.Head != stateA.Head { + fmt.Printf(" state: %s != %s\n", stateA.Head, stateB.Head) + } + if stateB.Nonce != stateA.Nonce { + fmt.Printf(" nonce: %d != %d\n", stateA.Nonce, stateB.Nonce) + } + if !stateB.Balance.Equals(stateA.Balance) { + fmt.Printf(" balance: %s != %s\n", stateA.Balance, stateB.Balance) + } + } + + fmt.Printf("state differences between %s (first) and %s (second):\n\n", rootA, rootB) + for addr, stateA := range changedA { + fmt.Println(addr) + stateB, ok := changedB[addr] + if ok { + diff(stateA, stateB) + continue + } else { + fmt.Printf(" actor does not exist in second state-tree (%s)\n", rootB) + } + fmt.Println() + delete(changedB, addr) + } + for addr, stateB := range changedB { + fmt.Println(addr) + stateA, ok := changedA[addr] + if ok { + diff(stateA, stateB) + continue + } else { + fmt.Printf(" actor does not exist in first state-tree (%s)\n", rootA) + } + fmt.Println() + } + return nil + }, +} diff --git a/cmd/lotus-shed/main.go b/cmd/lotus-shed/main.go index 9bcea72240e..45fd24e18a6 100644 --- a/cmd/lotus-shed/main.go +++ b/cmd/lotus-shed/main.go @@ -68,6 +68,7 @@ func main() { sendCsvCmd, terminationsCmd, migrationsCmd, + diffCmd, } app := &cli.App{ From b47cde70fafc073d595fe490535d44cb05dbe8dd Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Fri, 11 Feb 2022 18:30:29 +0000 Subject: [PATCH 154/385] Decode gossip extra data as []bytes The type of extra data in go-legs gossip is bytes. But when it is parsed as miner ID, it is cast to string then parsed. Instead, it should be decoded from bytes. --- chain/sub/incoming.go | 19 +++++----- chain/sub/incoming_test.go | 71 +++++++++++++++++++++++++++++++++++++- 2 files changed, 80 insertions(+), 10 deletions(-) diff --git a/chain/sub/incoming.go b/chain/sub/incoming.go index be2c75641ee..2a86286348f 100644 --- a/chain/sub/incoming.go +++ b/chain/sub/incoming.go @@ -503,7 +503,14 @@ func (v *IndexerMessageValidator) Validate(ctx context.Context, pid peer.ID, msg return pubsub.ValidationIgnore } - minerID := string(idxrMsg.ExtraData) + // Get miner info from lotus + minerAddr, err := address.NewFromBytes(idxrMsg.ExtraData) + if err != nil { + log.Warnw("cannot parse extra data as miner address", "err", err, "extraData", idxrMsg.ExtraData) + return pubsub.ValidationReject + } + + minerID := minerAddr.String() msgCid := idxrMsg.Cid var msgInfo *peerMsgInfo @@ -530,7 +537,7 @@ func (v *IndexerMessageValidator) Validate(ctx context.Context, pid peer.ID, msg if !ok || originPeer != msgInfo.peerID { // Check that the miner ID maps to the peer that sent the message. - err = v.authenticateMessage(ctx, minerID, originPeer) + err = v.authenticateMessage(ctx, minerAddr, originPeer) if err != nil { log.Warnw("cannot authenticate messsage", "err", err, "peer", originPeer, "minerID", minerID) stats.Record(ctx, metrics.IndexerMessageValidationFailure.M(1)) @@ -587,13 +594,7 @@ func (v *IndexerMessageValidator) rateLimitPeer(msgInfo *peerMsgInfo, msgCid cid return false } -func (v *IndexerMessageValidator) authenticateMessage(ctx context.Context, minerID string, peerID peer.ID) error { - // Get miner info from lotus - minerAddress, err := address.NewFromString(minerID) - if err != nil { - return xerrors.Errorf("invalid miner id: %w", err) - } - +func (v *IndexerMessageValidator) authenticateMessage(ctx context.Context, minerAddress address.Address, peerID peer.ID) error { ts, err := v.chainApi.ChainHead(ctx) if err != nil { return err diff --git a/chain/sub/incoming_test.go b/chain/sub/incoming_test.go index 1a3ab2785ec..f90dcb373df 100644 --- a/chain/sub/incoming_test.go +++ b/chain/sub/incoming_test.go @@ -2,13 +2,20 @@ package sub import ( + "bytes" "context" "testing" - address "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-legs/dtsync" + "github.com/filecoin-project/lotus/api/mocks" "github.com/filecoin-project/lotus/chain/types" + "github.com/golang/mock/gomock" blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" + "github.com/libp2p/go-libp2p-core/peer" + pubsub "github.com/libp2p/go-libp2p-pubsub" + pb "github.com/libp2p/go-libp2p-pubsub/pb" ) type getter struct { @@ -63,3 +70,65 @@ func TestFetchCidsWithDedup(t *testing.T) { t.Fatalf("there is a nil message: first %p, last %p", res[0], res[len(res)-1]) } } + +func TestIndexerMessageValidator_Validate(t *testing.T) { + validCid, err := cid.Decode("QmbpDgg5kRLDgMxS8vPKNFXEcA6D5MC4CkuUdSWDVtHPGK") + if err != nil { + t.Fatal(err) + } + tests := []struct { + name string + selfPID string + senderPID string + extraData []byte + wantValidation pubsub.ValidationResult + }{ + { + name: "invalid extra data is rejected", + selfPID: "12D3KooWQiCbqEStCkdqUvr69gQsrp9urYJZUCkzsQXia7mbqbFW", + senderPID: "12D3KooWE8yt84RVwW3sFcd6WMjbUdWrZer2YtT4dmtj3dHdahSZ", + extraData: []byte("f0127896"), // note, casting encoded address to byte is invalid. + wantValidation: pubsub.ValidationReject, + }, + { + name: "same sender and receiver is ignored", + selfPID: "12D3KooWQiCbqEStCkdqUvr69gQsrp9urYJZUCkzsQXia7mbqbFW", + senderPID: "12D3KooWQiCbqEStCkdqUvr69gQsrp9urYJZUCkzsQXia7mbqbFW", + wantValidation: pubsub.ValidationIgnore, + }, + } + for _, tc := range tests { + tc := tc + t.Run(tc.name, func(t *testing.T) { + mc := gomock.NewController(t) + node := mocks.NewMockFullNode(mc) + subject := NewIndexerMessageValidator(peer.ID(tc.selfPID), node, node) + message := dtsync.Message{ + Cid: validCid, + Addrs: nil, + ExtraData: tc.extraData, + } + buf := bytes.NewBuffer(nil) + if err := message.MarshalCBOR(buf); err != nil { + t.Fatal(err) + } + + topic := "topic" + pbm := &pb.Message{ + Data: buf.Bytes(), + Topic: &topic, + From: nil, + Seqno: nil, + } + validate := subject.Validate(context.Background(), peer.ID(tc.senderPID), &pubsub.Message{ + Message: pbm, + ReceivedFrom: peer.ID(tc.senderPID), + ValidatorData: nil, + }) + + if validate != tc.wantValidation { + t.Fatalf("expected %v but got %v", tc.wantValidation, validate) + } + }) + } +} From 230b8554f6a319f25c8c9cf6855718c2fae24d13 Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Fri, 11 Feb 2022 19:36:36 +0000 Subject: [PATCH 155/385] Override `testnetnet` to `mainnet` in indexer ingest topic Override `testnetnet` to `mainnet` when constructing indexer ingestion topic. --- build/params_shared_funcs.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/build/params_shared_funcs.go b/build/params_shared_funcs.go index f03a35fecb8..7dd2dc8da3d 100644 --- a/build/params_shared_funcs.go +++ b/build/params_shared_funcs.go @@ -14,7 +14,15 @@ import ( func BlocksTopic(netName dtypes.NetworkName) string { return "/fil/blocks/" + string(netName) } func MessagesTopic(netName dtypes.NetworkName) string { return "/fil/msgs/" + string(netName) } func IndexerIngestTopic(netName dtypes.NetworkName) string { - return "/indexer/ingest/" + string(netName) + + nn := string(netName) + // The network name testnetnet is here for historical reasons. + // Going forward we aim to use the name `mainnet` where possible. + if nn == "testnetnet" { + nn = "mainnet" + } + + return "/indexer/ingest/" + nn } func DhtProtocolName(netName dtypes.NetworkName) protocol.ID { return protocol.ID("/fil/kad/" + string(netName)) From 59351c8cb802b8941741bbfbbdd5255a84742220 Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Fri, 11 Feb 2022 15:51:49 +0000 Subject: [PATCH 156/385] Add `lotus net` CLI command to add/remove/list protected peers Add CLI commands under `lotus net` to add/ remove/list protected peers. --- cli/net.go | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/cli/net.go b/cli/net.go index 524b0d753e5..0ff15e38a22 100644 --- a/cli/net.go +++ b/cli/net.go @@ -38,6 +38,9 @@ var NetCmd = &cli.Command{ NetBlockCmd, NetStatCmd, NetLimitCmd, + NetProtectAdd, + NetProtectRemove, + NetProtectList, }, } @@ -708,3 +711,108 @@ var NetLimitCmd = &cli.Command{ return enc.Encode(result) }, } + +var NetProtectAdd = &cli.Command{ + Name: "protect", + Usage: "Add one or more peer IDs to the list of protected peer connections", + ArgsUsage: " [...]", + Action: func(cctx *cli.Context) error { + api, closer, err := GetAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := ReqContext(cctx) + + pids, err := decodePeerIDsFromArgs(cctx) + if err != nil { + return err + } + + err = api.NetProtectAdd(ctx, pids) + if err != nil { + return err + } + + fmt.Println("added to protected peers:") + for _, pid := range pids { + fmt.Printf(" %s\n", pid) + } + return nil + }, +} + +var NetProtectRemove = &cli.Command{ + Name: "unprotect", + Usage: "Remove one or more peer IDs from the list of protected peer connections.", + ArgsUsage: " [...]", + Action: func(cctx *cli.Context) error { + api, closer, err := GetAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := ReqContext(cctx) + + pids, err := decodePeerIDsFromArgs(cctx) + if err != nil { + return err + } + + err = api.NetProtectRemove(ctx, pids) + if err != nil { + return err + } + + fmt.Printf("removed from protected peers:") + for _, pid := range pids { + fmt.Printf(" %s\n", pid) + } + return nil + }, +} + +// decodePeerIDsFromArgs decodes all the arguments present in cli.Context.Args as peer.ID. +// +// This function requires at least one argument to be present, and arguments must not be empty +// string. Otherwise, an error is returned. +func decodePeerIDsFromArgs(cctx *cli.Context) ([]peer.ID, error) { + pidArgs := cctx.Args().Slice() + if len(pidArgs) == 0 { + return nil, xerrors.Errorf("must specify at least one peer ID as an argument") + } + var pids []peer.ID + for _, pidStr := range pidArgs { + if pidStr == "" { + return nil, xerrors.Errorf("peer ID must not be empty") + } + pid, err := peer.Decode(pidStr) + if err != nil { + return nil, err + } + pids = append(pids, pid) + } + return pids, nil +} + +var NetProtectList = &cli.Command{ + Name: "list-protected", + Usage: "List the peer IDs with protected connection.", + Action: func(cctx *cli.Context) error { + api, closer, err := GetAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := ReqContext(cctx) + pids, err := api.NetProtectList(ctx) + if err != nil { + return err + } + + for _, pid := range pids { + fmt.Printf("%s\n", pid) + } + return nil + }, +} From 1bf7e6a408914ed213f3c8e5d9a68abefa1bc77c Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Fri, 11 Feb 2022 20:02:56 +0000 Subject: [PATCH 157/385] Fix `gen-check` --- documentation/en/cli-lotus-miner.md | 66 +++++++++++++++++++++++------ documentation/en/cli-lotus.md | 66 +++++++++++++++++++++++------ 2 files changed, 108 insertions(+), 24 deletions(-) diff --git a/documentation/en/cli-lotus-miner.md b/documentation/en/cli-lotus-miner.md index e73621762e1..81cce261801 100644 --- a/documentation/en/cli-lotus-miner.md +++ b/documentation/en/cli-lotus-miner.md @@ -1214,18 +1214,21 @@ USAGE: lotus-miner net command [command options] [arguments...] COMMANDS: - peers Print peers - connect Connect to a peer - listen List listen addresses - id Get node identity - findpeer Find the addresses of a given peerID - scores Print peers' pubsub scores - reachability Print information about reachability from the internet - bandwidth Print bandwidth usage information - block Manage network connection gating rules - stat Report resource usage for a scope - limit Get or set resource limits for a scope - help, h Shows a list of commands or help for one command + peers Print peers + connect Connect to a peer + listen List listen addresses + id Get node identity + findpeer Find the addresses of a given peerID + scores Print peers' pubsub scores + reachability Print information about reachability from the internet + bandwidth Print bandwidth usage information + block Manage network connection gating rules + stat Report resource usage for a scope + limit Get or set resource limits for a scope + protect Add one or more peer IDs to the list of protected peer connections + unprotect Remove one or more peer IDs from the list of protected peer connections. + list-protected List the peer IDs with protected connection. + help, h Shows a list of commands or help for one command OPTIONS: --help, -h show help (default: false) @@ -1539,6 +1542,45 @@ OPTIONS: ``` +### lotus-miner net protect +``` +NAME: + lotus-miner net protect - Add one or more peer IDs to the list of protected peer connections + +USAGE: + lotus-miner net protect [command options] [...] + +OPTIONS: + --help, -h show help (default: false) + +``` + +### lotus-miner net unprotect +``` +NAME: + lotus-miner net unprotect - Remove one or more peer IDs from the list of protected peer connections. + +USAGE: + lotus-miner net unprotect [command options] [...] + +OPTIONS: + --help, -h show help (default: false) + +``` + +### lotus-miner net list-protected +``` +NAME: + lotus-miner net list-protected - List the peer IDs with protected connection. + +USAGE: + lotus-miner net list-protected [command options] [arguments...] + +OPTIONS: + --help, -h show help (default: false) + +``` + ## lotus-miner pieces ``` NAME: diff --git a/documentation/en/cli-lotus.md b/documentation/en/cli-lotus.md index 3dd7043bddc..315f2f055e6 100644 --- a/documentation/en/cli-lotus.md +++ b/documentation/en/cli-lotus.md @@ -2584,18 +2584,21 @@ USAGE: lotus net command [command options] [arguments...] COMMANDS: - peers Print peers - connect Connect to a peer - listen List listen addresses - id Get node identity - findpeer Find the addresses of a given peerID - scores Print peers' pubsub scores - reachability Print information about reachability from the internet - bandwidth Print bandwidth usage information - block Manage network connection gating rules - stat Report resource usage for a scope - limit Get or set resource limits for a scope - help, h Shows a list of commands or help for one command + peers Print peers + connect Connect to a peer + listen List listen addresses + id Get node identity + findpeer Find the addresses of a given peerID + scores Print peers' pubsub scores + reachability Print information about reachability from the internet + bandwidth Print bandwidth usage information + block Manage network connection gating rules + stat Report resource usage for a scope + limit Get or set resource limits for a scope + protect Add one or more peer IDs to the list of protected peer connections + unprotect Remove one or more peer IDs from the list of protected peer connections. + list-protected List the peer IDs with protected connection. + help, h Shows a list of commands or help for one command OPTIONS: --help, -h show help (default: false) @@ -2909,6 +2912,45 @@ OPTIONS: ``` +### lotus net protect +``` +NAME: + lotus net protect - Add one or more peer IDs to the list of protected peer connections + +USAGE: + lotus net protect [command options] [...] + +OPTIONS: + --help, -h show help (default: false) + +``` + +### lotus net unprotect +``` +NAME: + lotus net unprotect - Remove one or more peer IDs from the list of protected peer connections. + +USAGE: + lotus net unprotect [command options] [...] + +OPTIONS: + --help, -h show help (default: false) + +``` + +### lotus net list-protected +``` +NAME: + lotus net list-protected - List the peer IDs with protected connection. + +USAGE: + lotus net list-protected [command options] [arguments...] + +OPTIONS: + --help, -h show help (default: false) + +``` + ## lotus sync ``` NAME: From baee4a157638c2f6ae804392e76297aae3a5d767 Mon Sep 17 00:00:00 2001 From: Nikola Divic Date: Fri, 11 Feb 2022 21:56:28 +0100 Subject: [PATCH 158/385] test: (kinda) fix flaky test deals_retry_deal_no_funds_test.go:TestDealsRetryLackOfFunds seems to be flaky, sometimes it passes and sometimes it doesn't. The first suspect for me was time.Sleep(), which I replaced with waiting until a deal state where you can restart is reached. --- itests/deals_retry_deal_no_funds_test.go | 3 +-- itests/kit/deals.go | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/itests/deals_retry_deal_no_funds_test.go b/itests/deals_retry_deal_no_funds_test.go index a14a0d08536..ce8cd9729ea 100644 --- a/itests/deals_retry_deal_no_funds_test.go +++ b/itests/deals_retry_deal_no_funds_test.go @@ -95,12 +95,11 @@ func TestDealsRetryLackOfFunds(t *testing.T) { dp.FastRetrieval = true dp.EpochPrice = abi.NewTokenAmount(62500000) // minimum asking price. deal := dh.StartDeal(ctx, dp) + dh.WaitUntilDataTransfer(ctx, deal) propcid := *deal go func() { - time.Sleep(3 * time.Second) - kit.SendFunds(ctx, t, minerFullNode, publishStorageDealKey.Address, types.FromFil(1)) err := miner.MarketRetryPublishDeal(ctx, propcid) diff --git a/itests/kit/deals.go b/itests/kit/deals.go index f8de14d624a..108c38c2d97 100644 --- a/itests/kit/deals.go +++ b/itests/kit/deals.go @@ -134,6 +134,29 @@ func (dh *DealHarness) StartDeal(ctx context.Context, dealParams api.StartDealPa return dealProposalCid } +func (dh *DealHarness) WaitUntilDataTransfer(ctx context.Context, deal *cid.Cid) { +loop: + for { + di, err := dh.client.ClientGetDealInfo(ctx, *deal) + if err != nil { + dh.t.Fatal("can't fetch deal info") + } + + switch di.State { + case storagemarket.StorageDealProposalRejected: + dh.t.Fatal("deal rejected") + case storagemarket.StorageDealFailing: + dh.t.Fatal("deal failed") + case storagemarket.StorageDealError: + dh.t.Fatal("deal errored") + case storagemarket.StorageDealStartDataTransfer: + break loop + } + + time.Sleep(time.Millisecond * 100) + } +} + // WaitDealSealed waits until the deal is sealed. func (dh *DealHarness) WaitDealSealed(ctx context.Context, deal *cid.Cid, noseal, noSealStart bool, cb func()) { loop: From d50a26f4ae015dd6753f921c6342842179e4d038 Mon Sep 17 00:00:00 2001 From: Nikola Divic Date: Sat, 12 Feb 2022 17:10:00 +0100 Subject: [PATCH 159/385] Revert "test: (kinda) fix flaky test" This reverts commit baee4a157638c2f6ae804392e76297aae3a5d767. --- itests/deals_retry_deal_no_funds_test.go | 3 ++- itests/kit/deals.go | 23 ----------------------- 2 files changed, 2 insertions(+), 24 deletions(-) diff --git a/itests/deals_retry_deal_no_funds_test.go b/itests/deals_retry_deal_no_funds_test.go index ce8cd9729ea..a14a0d08536 100644 --- a/itests/deals_retry_deal_no_funds_test.go +++ b/itests/deals_retry_deal_no_funds_test.go @@ -95,11 +95,12 @@ func TestDealsRetryLackOfFunds(t *testing.T) { dp.FastRetrieval = true dp.EpochPrice = abi.NewTokenAmount(62500000) // minimum asking price. deal := dh.StartDeal(ctx, dp) - dh.WaitUntilDataTransfer(ctx, deal) propcid := *deal go func() { + time.Sleep(3 * time.Second) + kit.SendFunds(ctx, t, minerFullNode, publishStorageDealKey.Address, types.FromFil(1)) err := miner.MarketRetryPublishDeal(ctx, propcid) diff --git a/itests/kit/deals.go b/itests/kit/deals.go index 108c38c2d97..f8de14d624a 100644 --- a/itests/kit/deals.go +++ b/itests/kit/deals.go @@ -134,29 +134,6 @@ func (dh *DealHarness) StartDeal(ctx context.Context, dealParams api.StartDealPa return dealProposalCid } -func (dh *DealHarness) WaitUntilDataTransfer(ctx context.Context, deal *cid.Cid) { -loop: - for { - di, err := dh.client.ClientGetDealInfo(ctx, *deal) - if err != nil { - dh.t.Fatal("can't fetch deal info") - } - - switch di.State { - case storagemarket.StorageDealProposalRejected: - dh.t.Fatal("deal rejected") - case storagemarket.StorageDealFailing: - dh.t.Fatal("deal failed") - case storagemarket.StorageDealError: - dh.t.Fatal("deal errored") - case storagemarket.StorageDealStartDataTransfer: - break loop - } - - time.Sleep(time.Millisecond * 100) - } -} - // WaitDealSealed waits until the deal is sealed. func (dh *DealHarness) WaitDealSealed(ctx context.Context, deal *cid.Cid, noseal, noSealStart bool, cb func()) { loop: From aca2a0fd1b8fafb594a3e9375d1d7231aca3f15d Mon Sep 17 00:00:00 2001 From: Nikola Divic Date: Sat, 12 Feb 2022 17:48:45 +0100 Subject: [PATCH 160/385] test: fix flake in TestMemPoolBatchPushUntrusted integration test The flake was caused by improper waiting for certain chain operations to finish: - We didn't wait for messages to be registered as pushed - We improperly waited for a fixed time (10 seconds) for messages to be mined, which in the best case would wait longer than necessary and in the worst case would cause the test to break. What I did: - fixed by waiting in a loop for "just enough time". This fixed the flake and made the test run faster, on average, because we don't have unnecessary waiting. - I added a "circuit-breaker" where the wait loop will timeout after 10 seconds. --- itests/mempool_test.go | 66 ++++++++++++++++++++++++++++++------------ 1 file changed, 48 insertions(+), 18 deletions(-) diff --git a/itests/mempool_test.go b/itests/mempool_test.go index f5fb408e0aa..51e0afafd2a 100644 --- a/itests/mempool_test.go +++ b/itests/mempool_test.go @@ -3,6 +3,7 @@ package itests import ( "context" + "fmt" "testing" "time" @@ -380,7 +381,7 @@ func TestMemPoolBatchPushUntrusted(t *testing.T) { ctx := context.Background() const blockTime = 100 * time.Millisecond firstNode, _, _, ens := kit.EnsembleTwoOne(t, kit.MockProofs()) - ens.InterconnectAll().BeginMining(blockTime) + ens.InterconnectAll() kit.QuietMiningLogs() sender := firstNode.DefaultKey.Address @@ -416,18 +417,33 @@ func TestMemPoolBatchPushUntrusted(t *testing.T) { _, err = firstNode.MpoolBatchPushUntrusted(ctx, sms) require.NoError(t, err) - // check pending messages for address - msgStatuses, err := firstNode.MpoolCheckPendingMessages(ctx, sender) - require.NoError(t, err) - require.Equal(t, totalMessages, len(msgStatuses)) - for _, msgStatusList := range msgStatuses { - for _, status := range msgStatusList { - require.True(t, status.OK) + // check pending messages for address, wait until they are all pushed + timeout := time.After(time.Second * 10) + for { + msgStatuses, err := firstNode.MpoolCheckPendingMessages(ctx, sender) + require.NoError(t, err) + + if len(msgStatuses) == totalMessages { + for _, msgStatusList := range msgStatuses { + for _, status := range msgStatusList { + require.True(t, status.OK) + } + } + break + } + + select { + case <-timeout: + t.Fatal("waiting for batch push timed out") + default: + fmt.Printf("waiting for %d more messages to be pushed\n", len(msgStatuses)-totalMessages) + time.Sleep(time.Millisecond * 100) } } // verify messages should be the ones included in the next block selected, _ := firstNode.MpoolSelect(ctx, types.EmptyTSK, 0) + for _, msg := range sms { found := false for _, selectedMsg := range selected { @@ -439,17 +455,31 @@ func TestMemPoolBatchPushUntrusted(t *testing.T) { require.True(t, found) } - time.Sleep(10 * blockTime) + ens.BeginMining(blockTime) - // pool pending list should be empty - pending, err := firstNode.MpoolPending(context.TODO(), types.EmptyTSK) - require.NoError(t, err) - require.Equal(t, 0, len(pending)) - - // all messages should be added to the chain - for _, lookMsg := range sms { - msgLookup, err := firstNode.StateWaitMsg(ctx, lookMsg.Cid(), 3, api.LookbackNoLimit, true) + // wait until pending messages are mined + timeout = time.After(time.Second * 10) + for { + // pool pending list should be empty + pending, err := firstNode.MpoolPending(context.TODO(), types.EmptyTSK) require.NoError(t, err) - require.NotNil(t, msgLookup) + + if len(pending) == 0 { + // all messages should be added to the chain + for _, lookMsg := range sms { + msgLookup, err := firstNode.StateWaitMsg(ctx, lookMsg.Cid(), 3, api.LookbackNoLimit, true) + require.NoError(t, err) + require.NotNil(t, msgLookup) + } + break + } + + select { + case <-timeout: + t.Fatal("waiting for pending messages to be mined timed out") + default: + fmt.Printf("waiting for %d more messages to be mined\n", len(pending)) + time.Sleep(time.Millisecond * 100) + } } } From 34387326d16b14c03c7ad97ce74cc988f3a5dfc8 Mon Sep 17 00:00:00 2001 From: Nikola Divic Date: Sat, 12 Feb 2022 19:52:51 +0100 Subject: [PATCH 161/385] test: fix flaky message pool integration tests Using the same pattern described in my previous commit. I also added the CircuitBreaker to the itests kit as it may be useful for other integration tests when debugging flakyness caused by timeouts. --- itests/kit/circuit.go | 34 ++++++ itests/mempool_test.go | 246 +++++++++++++++++++++++------------------ 2 files changed, 175 insertions(+), 105 deletions(-) create mode 100644 itests/kit/circuit.go diff --git a/itests/kit/circuit.go b/itests/kit/circuit.go new file mode 100644 index 00000000000..d2857010e31 --- /dev/null +++ b/itests/kit/circuit.go @@ -0,0 +1,34 @@ +package kit + +import ( + "fmt" + "testing" + "time" +) + +/* +CircuitBreaker implements a simple time-based circuit breaker used for waiting for async operations to finish. + +This is how it works: + - It runs the `cb` function until it returns true, + - waiting for `throttle` duration between each iteration, + - or at most `timeout` duration until it breaks test execution. + +You can use it if t.Deadline() is not "granular" enough, and you want to know which specific piece of code timed out, +or you need to set different deadlines in the same test. +*/ +func CircuitBreaker(t *testing.T, label string, throttle, timeout time.Duration, cb func() bool) { + tmo := time.After(timeout) + for { + if cb() { + break + } + select { + case <-tmo: + t.Fatal("timeout: ", label) + default: + fmt.Printf("waiting: %s\n", label) + time.Sleep(throttle) + } + } +} diff --git a/itests/mempool_test.go b/itests/mempool_test.go index 51e0afafd2a..a1c2a330e50 100644 --- a/itests/mempool_test.go +++ b/itests/mempool_test.go @@ -3,7 +3,6 @@ package itests import ( "context" - "fmt" "testing" "time" @@ -14,6 +13,9 @@ import ( "github.com/stretchr/testify/require" ) +const mPoolThrottle = time.Millisecond * 100 +const mPoolTimeout = time.Second * 10 + func TestMemPoolPushSingleNode(t *testing.T) { //stm: @CHAIN_MEMPOOL_CREATE_MSG_CHAINS_001, @CHAIN_MEMPOOL_SELECT_001 //stm: @CHAIN_MEMPOOL_PENDING_001, @CHAIN_STATE_WAIT_MSG_001, @CHAIN_MEMPOOL_CAP_GAS_FEE_001 @@ -21,7 +23,7 @@ func TestMemPoolPushSingleNode(t *testing.T) { ctx := context.Background() const blockTime = 100 * time.Millisecond firstNode, _, _, ens := kit.EnsembleTwoOne(t, kit.MockProofs()) - ens.InterconnectAll().BeginMining(blockTime) + ens.InterconnectAll() kit.QuietMiningLogs() sender := firstNode.DefaultKey.Address @@ -53,13 +55,18 @@ func TestMemPoolPushSingleNode(t *testing.T) { } // check pending messages for address - msgStatuses, _ := firstNode.MpoolCheckPendingMessages(ctx, sender) - require.Equal(t, totalMessages, len(msgStatuses)) - for _, msgStatusList := range msgStatuses { - for _, status := range msgStatusList { - require.True(t, status.OK) + kit.CircuitBreaker(t, "push messages", mPoolThrottle, mPoolTimeout, func() bool { + msgStatuses, _ := firstNode.MpoolCheckPendingMessages(ctx, sender) + if len(msgStatuses) == totalMessages { + for _, msgStatusList := range msgStatuses { + for _, status := range msgStatusList { + require.True(t, status.OK) + } + } + return true } - } + return false + }) // verify messages should be the ones included in the next block selected, _ := firstNode.MpoolSelect(ctx, types.EmptyTSK, 0) @@ -74,19 +81,24 @@ func TestMemPoolPushSingleNode(t *testing.T) { require.True(t, found) } - time.Sleep(10 * blockTime) - - // pool pending list should be empty - pending, err := firstNode.MpoolPending(context.TODO(), types.EmptyTSK) - require.NoError(t, err) - require.Equal(t, 0, len(pending)) + ens.BeginMining(blockTime) - // all messages should be added to the chain - for _, lookMsg := range sms { - msgLookup, err := firstNode.StateWaitMsg(ctx, lookMsg.Cid(), 3, api.LookbackNoLimit, true) + kit.CircuitBreaker(t, "mine messages", mPoolThrottle, mPoolTimeout, func() bool { + // pool pending list should be empty + pending, err := firstNode.MpoolPending(context.TODO(), types.EmptyTSK) require.NoError(t, err) - require.NotNil(t, msgLookup) - } + + if len(pending) == 0 { + // all messages should be added to the chain + for _, lookMsg := range sms { + msgLookup, err := firstNode.StateWaitMsg(ctx, lookMsg.Cid(), 3, api.LookbackNoLimit, true) + require.NoError(t, err) + require.NotNil(t, msgLookup) + } + return true + } + return false + }) } func TestMemPoolPushTwoNodes(t *testing.T) { @@ -96,7 +108,7 @@ func TestMemPoolPushTwoNodes(t *testing.T) { ctx := context.Background() const blockTime = 100 * time.Millisecond firstNode, secondNode, _, ens := kit.EnsembleTwoOne(t, kit.MockProofs()) - ens.InterconnectAll().BeginMining(blockTime) + ens.InterconnectAll() kit.QuietMiningLogs() sender := firstNode.DefaultKey.Address @@ -141,26 +153,30 @@ func TestMemPoolPushTwoNodes(t *testing.T) { sms = append(sms, sm2) } - time.Sleep(10 * blockTime) - - pending1, err := firstNode.MpoolPending(context.TODO(), types.EmptyTSK) - require.NoError(t, err) - require.Equal(t, 0, len(pending1)) - - pending2, err := secondNode.MpoolPending(context.TODO(), types.EmptyTSK) - require.NoError(t, err) - require.Equal(t, 0, len(pending2)) + ens.BeginMining(blockTime) - // Check messages on both nodes - for _, lookMsg := range sms { - msgLookup1, err := firstNode.StateWaitMsg(ctx, lookMsg.Cid(), 3, api.LookbackNoLimit, true) + kit.CircuitBreaker(t, "push & mine messages", mPoolThrottle, mPoolTimeout, func() bool { + pending1, err := firstNode.MpoolPending(context.TODO(), types.EmptyTSK) require.NoError(t, err) - require.NotNil(t, msgLookup1) - msgLookup2, err := secondNode.StateWaitMsg(ctx, lookMsg.Cid(), 3, api.LookbackNoLimit, true) + pending2, err := secondNode.MpoolPending(context.TODO(), types.EmptyTSK) require.NoError(t, err) - require.NotNil(t, msgLookup2) - } + + if len(pending1) == 0 && len(pending2) == 0 { + // Check messages on both nodes + for _, lookMsg := range sms { + msgLookup1, err := firstNode.StateWaitMsg(ctx, lookMsg.Cid(), 3, api.LookbackNoLimit, true) + require.NoError(t, err) + require.NotNil(t, msgLookup1) + + msgLookup2, err := secondNode.StateWaitMsg(ctx, lookMsg.Cid(), 3, api.LookbackNoLimit, true) + require.NoError(t, err) + require.NotNil(t, msgLookup2) + } + return true + } + return false + }) } func TestMemPoolClearPending(t *testing.T) { @@ -169,7 +185,7 @@ func TestMemPoolClearPending(t *testing.T) { ctx := context.Background() const blockTime = 100 * time.Millisecond firstNode, _, _, ens := kit.EnsembleTwoOne(t, kit.MockProofs()) - ens.InterconnectAll().BeginMining(blockTime) + ens.InterconnectAll() kit.QuietMiningLogs() sender := firstNode.DefaultKey.Address @@ -192,17 +208,30 @@ func TestMemPoolClearPending(t *testing.T) { _, err = firstNode.MpoolPushMessage(ctx, msg, nil) require.NoError(t, err) + // message should be in the mempool + kit.CircuitBreaker(t, "push message", mPoolThrottle, mPoolTimeout, func() bool { + pending, err := firstNode.MpoolPending(context.TODO(), types.EmptyTSK) + require.NoError(t, err) + + return len(pending) == 1 + }) + err = firstNode.MpoolClear(ctx, true) require.NoError(t, err) // pool should be empty now - pending, err := firstNode.MpoolPending(context.TODO(), types.EmptyTSK) - require.NoError(t, err) - require.Equal(t, 0, len(pending)) + kit.CircuitBreaker(t, "clear mempool", mPoolThrottle, mPoolTimeout, func() bool { + pending, err := firstNode.MpoolPending(context.TODO(), types.EmptyTSK) + require.NoError(t, err) + + return len(pending) == 0 + }) - time.Sleep(2 * blockTime) + // mine a couple of blocks + ens.BeginMining(blockTime) + time.Sleep(5 * blockTime) - // waiting for the message should produce nothing + // make sure that the cleared message wasn't picked up and mined _, err = firstNode.StateWaitMsg(ctx, msg.Cid(), 3, api.LookbackNoLimit, true) require.Error(t, err) } @@ -215,7 +244,7 @@ func TestMemPoolBatchPush(t *testing.T) { ctx := context.Background() const blockTime = 100 * time.Millisecond firstNode, _, _, ens := kit.EnsembleTwoOne(t, kit.MockProofs()) - ens.InterconnectAll().BeginMining(blockTime) + ens.InterconnectAll() kit.QuietMiningLogs() sender := firstNode.DefaultKey.Address @@ -252,14 +281,20 @@ func TestMemPoolBatchPush(t *testing.T) { require.NoError(t, err) // check pending messages for address - msgStatuses, err := firstNode.MpoolCheckPendingMessages(ctx, sender) - require.NoError(t, err) - require.Equal(t, totalMessages, len(msgStatuses)) - for _, msgStatusList := range msgStatuses { - for _, status := range msgStatusList { - require.True(t, status.OK) + kit.CircuitBreaker(t, "batch push", mPoolThrottle, mPoolTimeout, func() bool { + msgStatuses, err := firstNode.MpoolCheckPendingMessages(ctx, sender) + require.NoError(t, err) + + if len(msgStatuses) == totalMessages { + for _, msgStatusList := range msgStatuses { + for _, status := range msgStatusList { + require.True(t, status.OK) + } + } + return true } - } + return false + }) // verify messages should be the ones included in the next block selected, _ := firstNode.MpoolSelect(ctx, types.EmptyTSK, 0) @@ -275,19 +310,24 @@ func TestMemPoolBatchPush(t *testing.T) { require.True(t, found) } - time.Sleep(10 * blockTime) - - // pool pending list should be empty - pending, err := firstNode.MpoolPending(context.TODO(), types.EmptyTSK) - require.NoError(t, err) - require.Equal(t, 0, len(pending)) + ens.BeginMining(blockTime) - // all messages should be added to the chain - for _, lookMsg := range sms { - msgLookup, err := firstNode.StateWaitMsg(ctx, lookMsg.Cid(), 3, api.LookbackNoLimit, true) + kit.CircuitBreaker(t, "mine messages", mPoolThrottle, mPoolTimeout, func() bool { + // pool pending list should be empty + pending, err := firstNode.MpoolPending(context.TODO(), types.EmptyTSK) require.NoError(t, err) - require.NotNil(t, msgLookup) - } + + if len(pending) == 0 { + // all messages should be added to the chain + for _, lookMsg := range sms { + msgLookup, err := firstNode.StateWaitMsg(ctx, lookMsg.Cid(), 3, api.LookbackNoLimit, true) + require.NoError(t, err) + require.NotNil(t, msgLookup) + } + return true + } + return false + }) } func TestMemPoolPushSingleNodeUntrusted(t *testing.T) { @@ -298,7 +338,7 @@ func TestMemPoolPushSingleNodeUntrusted(t *testing.T) { ctx := context.Background() const blockTime = 100 * time.Millisecond firstNode, _, _, ens := kit.EnsembleTwoOne(t, kit.MockProofs()) - ens.InterconnectAll().BeginMining(blockTime) + ens.InterconnectAll() kit.QuietMiningLogs() sender := firstNode.DefaultKey.Address @@ -336,14 +376,20 @@ func TestMemPoolPushSingleNodeUntrusted(t *testing.T) { sms = append(sms, signedMessage) } - // check pending messages for address - msgStatuses, _ := firstNode.MpoolCheckPendingMessages(ctx, sender) - require.Equal(t, totalMessages, len(msgStatuses)) - for _, msgStatusList := range msgStatuses { - for _, status := range msgStatusList { - require.True(t, status.OK) + kit.CircuitBreaker(t, "push untrusted messages", mPoolThrottle, mPoolTimeout, func() bool { + // check pending messages for address + msgStatuses, _ := firstNode.MpoolCheckPendingMessages(ctx, sender) + + if len(msgStatuses) == totalMessages { + for _, msgStatusList := range msgStatuses { + for _, status := range msgStatusList { + require.True(t, status.OK) + } + } + return true } - } + return false + }) // verify messages should be the ones included in the next block selected, _ := firstNode.MpoolSelect(ctx, types.EmptyTSK, 0) @@ -358,19 +404,25 @@ func TestMemPoolPushSingleNodeUntrusted(t *testing.T) { require.True(t, found) } - time.Sleep(10 * blockTime) - - // pool pending list should be empty - pending, err := firstNode.MpoolPending(context.TODO(), types.EmptyTSK) - require.NoError(t, err) - require.Equal(t, 0, len(pending)) + ens.BeginMining(blockTime) - // all messages should be added to the chain - for _, lookMsg := range sms { - msgLookup, err := firstNode.StateWaitMsg(ctx, lookMsg.Cid(), 3, api.LookbackNoLimit, true) + kit.CircuitBreaker(t, "mine untrusted messages", mPoolThrottle, mPoolTimeout, func() bool { + // pool pending list should be empty + pending, err := firstNode.MpoolPending(context.TODO(), types.EmptyTSK) require.NoError(t, err) - require.NotNil(t, msgLookup) - } + + if len(pending) == 0 { + // all messages should be added to the chain + for _, lookMsg := range sms { + msgLookup, err := firstNode.StateWaitMsg(ctx, lookMsg.Cid(), 3, api.LookbackNoLimit, true) + require.NoError(t, err) + require.NotNil(t, msgLookup) + } + return true + } + return false + }) + } func TestMemPoolBatchPushUntrusted(t *testing.T) { @@ -418,8 +470,7 @@ func TestMemPoolBatchPushUntrusted(t *testing.T) { require.NoError(t, err) // check pending messages for address, wait until they are all pushed - timeout := time.After(time.Second * 10) - for { + kit.CircuitBreaker(t, "push untrusted messages", mPoolThrottle, mPoolTimeout, func() bool { msgStatuses, err := firstNode.MpoolCheckPendingMessages(ctx, sender) require.NoError(t, err) @@ -429,17 +480,10 @@ func TestMemPoolBatchPushUntrusted(t *testing.T) { require.True(t, status.OK) } } - break + return true } - - select { - case <-timeout: - t.Fatal("waiting for batch push timed out") - default: - fmt.Printf("waiting for %d more messages to be pushed\n", len(msgStatuses)-totalMessages) - time.Sleep(time.Millisecond * 100) - } - } + return false + }) // verify messages should be the ones included in the next block selected, _ := firstNode.MpoolSelect(ctx, types.EmptyTSK, 0) @@ -457,10 +501,8 @@ func TestMemPoolBatchPushUntrusted(t *testing.T) { ens.BeginMining(blockTime) - // wait until pending messages are mined - timeout = time.After(time.Second * 10) - for { - // pool pending list should be empty + // wait until pending messages are mined, pool pending list should be empty + kit.CircuitBreaker(t, "mine untrusted messages", mPoolThrottle, mPoolTimeout, func() bool { pending, err := firstNode.MpoolPending(context.TODO(), types.EmptyTSK) require.NoError(t, err) @@ -471,15 +513,9 @@ func TestMemPoolBatchPushUntrusted(t *testing.T) { require.NoError(t, err) require.NotNil(t, msgLookup) } - break + return true } + return false + }) - select { - case <-timeout: - t.Fatal("waiting for pending messages to be mined timed out") - default: - fmt.Printf("waiting for %d more messages to be mined\n", len(pending)) - time.Sleep(time.Millisecond * 100) - } - } } From e6c8c9a6ab8a8ad148a9edec3995bc1b405652b3 Mon Sep 17 00:00:00 2001 From: Nikola Divic Date: Sun, 13 Feb 2022 17:14:27 +0100 Subject: [PATCH 162/385] doc: add stm annotation to cli chain tests --- cli/chain_test.go | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/cli/chain_test.go b/cli/chain_test.go index f3da80197a7..841cfb689f7 100644 --- a/cli/chain_test.go +++ b/cli/chain_test.go @@ -32,6 +32,7 @@ func TestChainHead(t *testing.T) { mockApi.EXPECT().ChainHead(ctx).Return(ts, nil), ) + //stm: @CLI_CHAIN_HEAD_001 err := app.Run([]string{"chain", "head"}) assert.NoError(t, err) @@ -55,6 +56,7 @@ func TestGetBlock(t *testing.T) { mockApi.EXPECT().ChainGetParentReceipts(ctx, block.Cid()).Return([]*types.MessageReceipt{}, nil), ) + //stm: @CLI_CHAIN_GET_BLOCK_001 err := app.Run([]string{"chain", "getblock", block.Cid().String()}) assert.NoError(t, err) @@ -89,6 +91,7 @@ func TestReadOjb(t *testing.T) { mockApi.EXPECT().ChainReadObj(ctx, block.Cid()).Return(obj.Bytes(), nil), ) + //stm: @CLI_CHAIN_READ_OBJECT_001 err = app.Run([]string{"chain", "read-obj", block.Cid().String()}) assert.NoError(t, err) @@ -104,6 +107,7 @@ func TestChainDeleteObj(t *testing.T) { app, _, _, done := NewMockAppWithFullAPI(t, cmd) defer done() + //stm: @CLI_CHAIN_DELETE_OBJECT_002 err := app.Run([]string{"chain", "delete-obj", block.Cid().String()}) assert.Error(t, err) }) @@ -120,6 +124,7 @@ func TestChainDeleteObj(t *testing.T) { mockApi.EXPECT().ChainDeleteObj(ctx, block.Cid()).Return(nil), ) + //stm: @CLI_CHAIN_DELETE_OBJECT_001 err := app.Run([]string{"chain", "delete-obj", "--really-do-it=true", block.Cid().String()}) assert.NoError(t, err) @@ -152,6 +157,7 @@ func TestChainStatObj(t *testing.T) { mockApi.EXPECT().ChainStatObj(ctx, block.Cid(), cid.Undef).Return(stat, nil), ) + //stm: @CLI_CHAIN_STAT_OBJECT_001 err := app.Run([]string{"chain", "stat-obj", block.Cid().String()}) assert.NoError(t, err) @@ -170,6 +176,7 @@ func TestChainStatObj(t *testing.T) { mockApi.EXPECT().ChainStatObj(ctx, block.Cid(), block.Cid()).Return(stat, nil), ) + //stm: @CLI_CHAIN_STAT_OBJECT_002 err := app.Run([]string{"chain", "stat-obj", fmt.Sprintf("-base=%s", block.Cid().String()), block.Cid().String()}) assert.NoError(t, err) @@ -200,6 +207,7 @@ func TestChainGetMsg(t *testing.T) { mockApi.EXPECT().ChainReadObj(ctx, msg.Cid()).Return(obj.Bytes(), nil), ) + //stm: @CLI_CHAIN_GET_MESSAGE_001 err = app.Run([]string{"chain", "getmessage", msg.Cid().String()}) assert.NoError(t, err) @@ -229,6 +237,7 @@ func TestSetHead(t *testing.T) { mockApi.EXPECT().ChainSetHead(ctx, genesis.Key()).Return(nil), ) + //stm: @CLI_CHAIN_SET_HEAD_003 err := app.Run([]string{"chain", "sethead", "-genesis=true", ts.Key().String()}) assert.NoError(t, err) }) @@ -246,6 +255,7 @@ func TestSetHead(t *testing.T) { mockApi.EXPECT().ChainSetHead(ctx, genesis.Key()).Return(nil), ) + //stm: @CLI_CHAIN_SET_HEAD_002 err := app.Run([]string{"chain", "sethead", fmt.Sprintf("-epoch=%s", epoch), ts.Key().String()}) assert.NoError(t, err) }) @@ -263,8 +273,7 @@ func TestSetHead(t *testing.T) { mockApi.EXPECT().ChainSetHead(ctx, ts.Key()).Return(nil), ) - // ts.Key should be passed as an array of arguments (CIDs) - // since we have only one CID in the key, this is ok + //stm: @CLI_CHAIN_SET_HEAD_001 err := app.Run([]string{"chain", "sethead", ts.Key().Cids()[0].String()}) assert.NoError(t, err) }) @@ -303,6 +312,7 @@ func TestInspectUsage(t *testing.T) { mockApi.EXPECT().StateGetActor(ctx, *to, ts.Key()).Return(actor, nil), ) + //stm: @CLI_CHAIN_INSPECT_USAGE_001 err := app.Run([]string{"chain", "inspect-usage"}) assert.NoError(t, err) @@ -352,6 +362,7 @@ func TestChainList(t *testing.T) { mockApi.EXPECT().ChainGetBlockMessages(ctx, head.Blocks()[0].Cid()).Return(blockMsgs, nil), ) + //stm: CLI_CHAIN_LIST_001 err := app.Run([]string{"chain", "love", "--gas-stats=true"}) // chain is love ❤️ assert.NoError(t, err) @@ -382,6 +393,7 @@ func TestChainGet(t *testing.T) { mockApi.EXPECT().ChainGetNode(ctx, path).Return(&api.IpldObject{Cid: blk.Cid(), Obj: blk}, nil), ) + //stm: @CLI_CHAIN_GET_001 err := app.Run([]string{"chain", "get", path}) assert.NoError(t, err) @@ -407,6 +419,7 @@ func TestChainGet(t *testing.T) { mockApi.EXPECT().ChainGetNode(ctx, p2).Return(&api.IpldObject{Cid: blk.Cid(), Obj: blk}, nil), ) + //stm: @CLI_CHAIN_GET_002 err := app.Run([]string{"chain", "get", p1}) assert.NoError(t, err) @@ -430,6 +443,7 @@ func TestChainGet(t *testing.T) { mockApi.EXPECT().ChainGetNode(ctx, path).Return(&api.IpldObject{Cid: blk.Cid(), Obj: blk}, nil), ) + //stm: @CLI_CHAIN_GET_004 err := app.Run([]string{"chain", "get", "-as-type=foo", path}) assert.Error(t, err) }) @@ -465,6 +479,7 @@ func TestChainBisect(t *testing.T) { mockApi.EXPECT().ChainGetNode(ctx, path).Return(&api.IpldObject{Cid: blk2.Cid(), Obj: blk2}, nil), ) + //stm: @CLI_CHAIN_BISECT_001 err := app.Run([]string{"chain", "bisect", fmt.Sprintf("%d", minHeight), fmt.Sprintf("%d", maxHeight), subpath, shell}) assert.NoError(t, err) @@ -497,6 +512,7 @@ func TestChainExport(t *testing.T) { mockApi.EXPECT().ChainExport(ctx, abi.ChainEpoch(0), false, ts.Key()).Return(export, nil), ) + //stm: @CLI_CHAIN_EXPORT_001 err := app.Run([]string{"chain", "export", "whatever.car"}) assert.NoError(t, err) @@ -522,6 +538,7 @@ func TestChainGasPrice(t *testing.T) { calls++ }) + //stm: @CLI_CHAIN_GAS_PRICE_001 err := app.Run([]string{"chain", "gas-price"}) assert.NoError(t, err) From 93d9bfb682e0ef3a8bce5c769d7c9df75894ae82 Mon Sep 17 00:00:00 2001 From: Nikola Divic Date: Sun, 13 Feb 2022 18:39:37 +0100 Subject: [PATCH 163/385] doc: stm test annotations for cli/sync category --- cli/sync_test.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cli/sync_test.go b/cli/sync_test.go index 174279d0820..90f20a029e0 100644 --- a/cli/sync_test.go +++ b/cli/sync_test.go @@ -43,6 +43,7 @@ func TestSyncStatus(t *testing.T) { mockApi.EXPECT().SyncState(ctx).Return(state, nil) + //stm: @CLI_SYNC_STATUS_001 err := app.Run([]string{"sync", "status"}) assert.NoError(t, err) @@ -68,6 +69,7 @@ func TestSyncMarkBad(t *testing.T) { mockApi.EXPECT().SyncMarkBad(ctx, blk.Cid()).Return(nil) + //stm: @CLI_SYNC_MARK_BAD_001 err := app.Run([]string{"sync", "mark-bad", blk.Cid().String()}) assert.NoError(t, err) } @@ -84,6 +86,7 @@ func TestSyncUnmarkBad(t *testing.T) { mockApi.EXPECT().SyncUnmarkBad(ctx, blk.Cid()).Return(nil) + //stm: @CLI_SYNC_UNMARK_BAD_001 err := app.Run([]string{"sync", "unmark-bad", blk.Cid().String()}) assert.NoError(t, err) }) @@ -97,6 +100,7 @@ func TestSyncUnmarkBad(t *testing.T) { mockApi.EXPECT().SyncUnmarkAllBad(ctx).Return(nil) + //stm: @CLI_SYNC_UNMARK_BAD_002 err := app.Run([]string{"sync", "unmark-bad", "-all"}) assert.NoError(t, err) }) @@ -114,6 +118,7 @@ func TestSyncCheckBad(t *testing.T) { mockApi.EXPECT().SyncCheckBad(ctx, blk.Cid()).Return("", nil) + //stm: @CLI_SYNC_CHECK_BAD_002 err := app.Run([]string{"sync", "check-bad", blk.Cid().String()}) assert.NoError(t, err) @@ -132,6 +137,7 @@ func TestSyncCheckBad(t *testing.T) { mockApi.EXPECT().SyncCheckBad(ctx, blk.Cid()).Return(reason, nil) + //stm: @CLI_SYNC_CHECK_BAD_001 err := app.Run([]string{"sync", "check-bad", blk.Cid().String()}) assert.NoError(t, err) @@ -155,6 +161,7 @@ func TestSyncCheckpoint(t *testing.T) { mockApi.EXPECT().SyncCheckpoint(ctx, ts.Key()).Return(nil), ) + //stm: @CLI_SYNC_CHECKPOINT_001 err := app.Run([]string{"sync", "checkpoint", blk.Cid().String()}) assert.NoError(t, err) }) @@ -175,6 +182,7 @@ func TestSyncCheckpoint(t *testing.T) { mockApi.EXPECT().SyncCheckpoint(ctx, ts.Key()).Return(nil), ) + //stm: @CLI_SYNC_CHECKPOINT_002 err := app.Run([]string{"sync", "checkpoint", fmt.Sprintf("-epoch=%d", epoch)}) assert.NoError(t, err) }) From b576785aac0e1cbcde8a0f59eb0cfc196e9c03dc Mon Sep 17 00:00:00 2001 From: vyzo Date: Mon, 14 Feb 2022 16:03:17 +0200 Subject: [PATCH 164/385] rename GetHotView to IsHotView --- blockstore/context.go | 4 ++-- blockstore/splitstore/splitstore.go | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/blockstore/context.go b/blockstore/context.go index 61cb93b30f3..ebb6fafe337 100644 --- a/blockstore/context.go +++ b/blockstore/context.go @@ -14,8 +14,8 @@ func WithHotView(ctx context.Context) context.Context { return context.WithValue(ctx, hotView, struct{}{}) } -// GetHotView returns true if the hot view option is set in the context -func GetHotView(ctx context.Context) bool { +// IsHotView returns true if the hot view option is set in the context +func IsHotView(ctx context.Context) bool { v := ctx.Value(hotView) return v != nil } diff --git a/blockstore/splitstore/splitstore.go b/blockstore/splitstore/splitstore.go index 5c2cf7203f7..6f499b366b4 100644 --- a/blockstore/splitstore/splitstore.go +++ b/blockstore/splitstore/splitstore.go @@ -275,7 +275,7 @@ func (s *SplitStore) Has(ctx context.Context, cid cid.Cid) (bool, error) { } has, err = s.cold.Has(ctx, cid) - if has && bstore.GetHotView(ctx) { + if has && bstore.IsHotView(ctx) { s.reifyColdObject(cid) } @@ -324,7 +324,7 @@ func (s *SplitStore) Get(ctx context.Context, cid cid.Cid) (blocks.Block, error) blk, err = s.cold.Get(ctx, cid) if err == nil { - if bstore.GetHotView(ctx) { + if bstore.IsHotView(ctx) { s.reifyColdObject(cid) } @@ -378,7 +378,7 @@ func (s *SplitStore) GetSize(ctx context.Context, cid cid.Cid) (int, error) { size, err = s.cold.GetSize(ctx, cid) if err == nil { - if bstore.GetHotView(ctx) { + if bstore.IsHotView(ctx) { s.reifyColdObject(cid) } @@ -559,7 +559,7 @@ func (s *SplitStore) View(ctx context.Context, cid cid.Cid, cb func([]byte) erro err = s.cold.View(ctx, cid, cb) if err == nil { - if bstore.GetHotView(ctx) { + if bstore.IsHotView(ctx) { s.reifyColdObject(cid) } From a428f4479356260cf035add6867d3c7a20c8a307 Mon Sep 17 00:00:00 2001 From: vyzo Date: Mon, 14 Feb 2022 16:04:39 +0200 Subject: [PATCH 165/385] don't reify objects while still warming up --- blockstore/splitstore/splitstore_reify.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/blockstore/splitstore/splitstore_reify.go b/blockstore/splitstore/splitstore_reify.go index 3c65bbce807..3e6d7cd22ed 100644 --- a/blockstore/splitstore/splitstore_reify.go +++ b/blockstore/splitstore/splitstore_reify.go @@ -11,6 +11,10 @@ import ( ) func (s *SplitStore) reifyColdObject(c cid.Cid) { + if !s.isWarm() { + return + } + if isUnitaryObject(c) { return } From 6c7ababd3f145bb494691d073bab6cd4bb6a4930 Mon Sep 17 00:00:00 2001 From: vyzo Date: Mon, 14 Feb 2022 16:06:12 +0200 Subject: [PATCH 166/385] add comment about trackTxnRefs being noops if txnActive is false --- blockstore/splitstore/splitstore_reify.go | 1 + 1 file changed, 1 insertion(+) diff --git a/blockstore/splitstore/splitstore_reify.go b/blockstore/splitstore/splitstore_reify.go index 3e6d7cd22ed..daa10c51332 100644 --- a/blockstore/splitstore/splitstore_reify.go +++ b/blockstore/splitstore/splitstore_reify.go @@ -179,6 +179,7 @@ func (s *SplitStore) doReify(c cid.Cid) { } } } else { + // if txnActive is false these are noops if len(toreify) > 0 { s.trackTxnRefMany(toreify) } From 4524fbe936134f60e1005326418b6deafb002c63 Mon Sep 17 00:00:00 2001 From: vyzo Date: Mon, 14 Feb 2022 16:10:54 +0200 Subject: [PATCH 167/385] wait for reify workers to finish when closing --- blockstore/splitstore/splitstore.go | 2 ++ blockstore/splitstore/splitstore_reify.go | 2 ++ 2 files changed, 4 insertions(+) diff --git a/blockstore/splitstore/splitstore.go b/blockstore/splitstore/splitstore.go index 6f499b366b4..a351df76a46 100644 --- a/blockstore/splitstore/splitstore.go +++ b/blockstore/splitstore/splitstore.go @@ -162,6 +162,7 @@ type SplitStore struct { txnSync bool // background cold object reification + reifyWorkers sync.WaitGroup reifyMx sync.Mutex reifyCond sync.Cond reifyPend map[cid.Cid]struct{} @@ -707,6 +708,7 @@ func (s *SplitStore) Close() error { } s.reifyCond.Broadcast() + s.reifyWorkers.Wait() s.cancel() return multierr.Combine(s.markSetEnv.Close(), s.debug.Close()) } diff --git a/blockstore/splitstore/splitstore_reify.go b/blockstore/splitstore/splitstore_reify.go index daa10c51332..cb86c9789e9 100644 --- a/blockstore/splitstore/splitstore_reify.go +++ b/blockstore/splitstore/splitstore_reify.go @@ -41,6 +41,7 @@ func (s *SplitStore) reifyOrchestrator() { defer close(workch) for i := 0; i < workers; i++ { + s.reifyWorkers.Add(1) go s.reifyWorker(workch) } @@ -70,6 +71,7 @@ func (s *SplitStore) reifyOrchestrator() { } func (s *SplitStore) reifyWorker(workch chan cid.Cid) { + defer s.reifyWorkers.Done() for c := range workch { s.doReify(c) } From 6bcade5e6decb3dfd1671cc0247fba308834cce3 Mon Sep 17 00:00:00 2001 From: vyzo Date: Mon, 14 Feb 2022 16:13:54 +0200 Subject: [PATCH 168/385] add comment about bigness of reification batch --- blockstore/splitstore/splitstore_reify.go | 1 + 1 file changed, 1 insertion(+) diff --git a/blockstore/splitstore/splitstore_reify.go b/blockstore/splitstore/splitstore_reify.go index cb86c9789e9..14648a65217 100644 --- a/blockstore/splitstore/splitstore_reify.go +++ b/blockstore/splitstore/splitstore_reify.go @@ -146,6 +146,7 @@ func (s *SplitStore) doReify(c cid.Cid) { log.Debugf("reifying %d objects rooted at %s", len(toreify), c) + // this should not get too big, maybe some 100s of objects. batch := make([]blocks.Block, 0, len(toreify)) for _, c := range toreify { blk, err := s.cold.Get(s.ctx, c) From 2c06eb76d6b7afaf00159bd5c96ea60484de30f1 Mon Sep 17 00:00:00 2001 From: zenground0 Date: Mon, 14 Feb 2022 09:47:18 -0500 Subject: [PATCH 169/385] Improve MineBlocksMustPost use it in PaychAPI itest --- itests/kit/blockminer.go | 96 +++++++++++++++++++++------------------- itests/paych_api_test.go | 2 +- 2 files changed, 52 insertions(+), 46 deletions(-) diff --git a/itests/kit/blockminer.go b/itests/kit/blockminer.go index 91ddc2e26e0..cae3d26e35e 100644 --- a/itests/kit/blockminer.go +++ b/itests/kit/blockminer.go @@ -10,6 +10,7 @@ import ( "github.com/filecoin-project/go-bitfield" "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/dline" "github.com/filecoin-project/lotus/api" aminer "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/types" @@ -82,11 +83,49 @@ func (p *partitionTracker) recordIfPost(t *testing.T, bm *BlockMiner, smsg *type return } +func (bm *BlockMiner) forcePoSt(ctx context.Context, ts *types.TipSet, dlinfo *dline.Info) { + + tracker := newPartitionTracker(ctx, dlinfo.Index, bm) + if !tracker.done(bm.t) { // need to wait for post + bm.t.Logf("expect %d partitions proved but only see %d", len(tracker.partitions), tracker.count(bm.t)) + poolEvts, err := bm.miner.FullNode.MpoolSub(ctx) //subscribe before checking pending so we don't miss any events + require.NoError(bm.t, err) + + // First check pending messages we'll mine this epoch + msgs, err := bm.miner.FullNode.MpoolPending(ctx, types.EmptyTSK) + require.NoError(bm.t, err) + for _, msg := range msgs { + tracker.recordIfPost(bm.t, bm, msg) + } + + // post not yet in mpool, wait for it + if !tracker.done(bm.t) { + bm.t.Logf("post missing from mpool, block mining suspended until it arrives") + POOL: + for { + bm.t.Logf("mpool event wait loop at block height %d, ts: %s", ts.Height(), ts.Key()) + select { + case <-ctx.Done(): + return + case evt := <-poolEvts: + bm.t.Logf("pool event: %d", evt.Type) + if evt.Type == api.MpoolAdd { + bm.t.Logf("incoming message %v", evt.Message) + if tracker.recordIfPost(bm.t, bm, evt.Message) { + break POOL + } + } + } + } + bm.t.Logf("done waiting on mpool") + } + } +} + // Like MineBlocks but refuses to mine until the window post scheduler has wdpost messages in the mempool // and everything shuts down if a post fails. It also enforces that every block mined succeeds func (bm *BlockMiner) MineBlocksMustPost(ctx context.Context, blocktime time.Duration) { - - time.Sleep(3 * time.Second) + time.Sleep(time.Second) // wrap context in a cancellable context. ctx, bm.cancel = context.WithCancel(ctx) @@ -94,8 +133,6 @@ func (bm *BlockMiner) MineBlocksMustPost(ctx context.Context, blocktime time.Dur go func() { defer bm.wg.Done() - activeDeadlines := make(map[int]struct{}) - _ = activeDeadlines ts, err := bm.miner.FullNode.ChainHead(ctx) require.NoError(bm.t, err) wait := make(chan bool) @@ -103,7 +140,7 @@ func (bm *BlockMiner) MineBlocksMustPost(ctx context.Context, blocktime time.Dur require.NoError(bm.t, err) // read current out curr := <-chg - require.Equal(bm.t, ts.Height(), curr[0].Val.Height()) + require.Equal(bm.t, ts.Height(), curr[0].Val.Height(), "failed sanity check: are multiple miners mining with must post?") for { select { case <-time.After(blocktime): @@ -111,52 +148,15 @@ func (bm *BlockMiner) MineBlocksMustPost(ctx context.Context, blocktime time.Dur return } nulls := atomic.SwapInt64(&bm.nextNulls, 0) - require.Equal(bm.t, int64(0), nulls, "Injecting > 0 null blocks while `MustPost` mining is currently unsupported") // Wake up and figure out if we are at the end of an active deadline ts, err := bm.miner.FullNode.ChainHead(ctx) require.NoError(bm.t, err) - tsk := ts.Key() - dlinfo, err := bm.miner.FullNode.StateMinerProvingDeadline(ctx, bm.miner.ActorAddr, tsk) + dlinfo, err := bm.miner.FullNode.StateMinerProvingDeadline(ctx, bm.miner.ActorAddr, ts.Key()) require.NoError(bm.t, err) - if ts.Height()+1 == dlinfo.Last() { // Last epoch in dline, we need to check that miner has posted - - tracker := newPartitionTracker(ctx, dlinfo.Index, bm) - if !tracker.done(bm.t) { // need to wait for post - bm.t.Logf("expect %d partitions proved but only see %d", len(tracker.partitions), tracker.count(bm.t)) - poolEvts, err := bm.miner.FullNode.MpoolSub(ctx) - require.NoError(bm.t, err) - - // First check pending messages we'll mine this epoch - msgs, err := bm.miner.FullNode.MpoolPending(ctx, types.EmptyTSK) - require.NoError(bm.t, err) - for _, msg := range msgs { - tracker.recordIfPost(bm.t, bm, msg) - } - - // post not yet in mpool, wait for it - if !tracker.done(bm.t) { - bm.t.Logf("post missing from mpool, block mining suspended until it arrives") - POOL: - for { - bm.t.Logf("mpool event wait loop at block height %d, ts: %s", ts.Height(), ts.Key()) - select { - case <-ctx.Done(): - return - case evt := <-poolEvts: - bm.t.Logf("pool event: %d", evt.Type) - if evt.Type == api.MpoolAdd { - bm.t.Logf("incoming message %v", evt.Message) - if tracker.recordIfPost(bm.t, bm, evt.Message) { - break POOL - } - } - } - } - bm.t.Logf("done waiting on mpool") - } - } + if ts.Height()+1+abi.ChainEpoch(nulls) >= dlinfo.Last() { // Next block brings us past the last epoch in dline, we need to wait for miner to post + bm.forcePoSt(ctx, ts, dlinfo) } var target abi.ChainEpoch @@ -173,6 +173,12 @@ func (bm *BlockMiner) MineBlocksMustPost(ctx context.Context, blocktime time.Dur Done: reportSuccessFn, }) success = <-wait + if !success { + // if we are mining a new null block and it brings us past deadline boundary we need to wait for miner to post + if ts.Height()+1+abi.ChainEpoch(nulls+i) >= dlinfo.Last() { + bm.forcePoSt(ctx, ts, dlinfo) + } + } } // Wait until it shows up on the given full nodes ChainHead diff --git a/itests/paych_api_test.go b/itests/paych_api_test.go index a07c499f9cf..7e135a9bea7 100644 --- a/itests/paych_api_test.go +++ b/itests/paych_api_test.go @@ -51,7 +51,7 @@ func TestPaymentChannelsAPI(t *testing.T) { Miner(&miner, &paymentCreator, kit.WithAllSubsystems()). Start(). InterconnectAll() - bms := ens.BeginMining(blockTime) + bms := ens.BeginMiningMustPost(blockTime) bm := bms[0] // send some funds to register the receiver From b260c849f750ff2ecebd71f99520f210f7dc2b91 Mon Sep 17 00:00:00 2001 From: vyzo Date: Mon, 14 Feb 2022 19:43:07 +0200 Subject: [PATCH 170/385] deps: update go-libp2p-resource-manager to v0.1.4 --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index f22400ded5a..aa80f0bdc45 100644 --- a/go.mod +++ b/go.mod @@ -118,7 +118,7 @@ require ( github.com/libp2p/go-libp2p-pubsub v0.6.1 github.com/libp2p/go-libp2p-quic-transport v0.16.1 github.com/libp2p/go-libp2p-record v0.1.3 - github.com/libp2p/go-libp2p-resource-manager v0.1.3 + github.com/libp2p/go-libp2p-resource-manager v0.1.4 github.com/libp2p/go-libp2p-routing-helpers v0.2.3 github.com/libp2p/go-libp2p-swarm v0.10.1 github.com/libp2p/go-libp2p-tls v0.3.1 diff --git a/go.sum b/go.sum index 6b725b5df74..292747fc834 100644 --- a/go.sum +++ b/go.sum @@ -1158,8 +1158,9 @@ github.com/libp2p/go-libp2p-record v0.1.2/go.mod h1:pal0eNcT5nqZaTV7UGhqeGqxFgGd github.com/libp2p/go-libp2p-record v0.1.3 h1:R27hoScIhQf/A8XJZ8lYpnqh9LatJ5YbHs28kCIfql0= github.com/libp2p/go-libp2p-record v0.1.3/go.mod h1:yNUff/adKIfPnYQXgp6FQmNu3gLJ6EMg7+/vv2+9pY4= github.com/libp2p/go-libp2p-resource-manager v0.1.0/go.mod h1:wJPNjeE4XQlxeidwqVY5G6DLOKqFK33u2n8blpl0I6Y= -github.com/libp2p/go-libp2p-resource-manager v0.1.3 h1:Umf0tW6WNXSb6Uoma0YT56azB5iikL/aeGAP7s7+f5o= github.com/libp2p/go-libp2p-resource-manager v0.1.3/go.mod h1:wJPNjeE4XQlxeidwqVY5G6DLOKqFK33u2n8blpl0I6Y= +github.com/libp2p/go-libp2p-resource-manager v0.1.4 h1:RcxMD0pytOUimx3BqTVs6IqItb3H5Qg44SD7XyT68lw= +github.com/libp2p/go-libp2p-resource-manager v0.1.4/go.mod h1:wJPNjeE4XQlxeidwqVY5G6DLOKqFK33u2n8blpl0I6Y= github.com/libp2p/go-libp2p-routing v0.0.1/go.mod h1:N51q3yTr4Zdr7V8Jt2JIktVU+3xBBylx1MZeVA6t1Ys= github.com/libp2p/go-libp2p-routing v0.1.0/go.mod h1:zfLhI1RI8RLEzmEaaPwzonRvXeeSHddONWkcTcB54nE= github.com/libp2p/go-libp2p-routing-helpers v0.2.3 h1:xY61alxJ6PurSi+MXbywZpelvuU4U4p/gPTxjqCqTzY= From a9ec40884491533e923569ecb32cf566803d88fb Mon Sep 17 00:00:00 2001 From: vyzo Date: Mon, 14 Feb 2022 19:46:05 +0200 Subject: [PATCH 171/385] collect resource manager metrics --- metrics/metrics.go | 107 +++++++++++++++++++++++++++++++++ node/modules/lp2p/rcmgr.go | 120 +++++++++++++++++++++++++++++++++++++ 2 files changed, 227 insertions(+) diff --git a/metrics/metrics.go b/metrics/metrics.go index b4032bb1d35..400e76537c5 100644 --- a/metrics/metrics.go +++ b/metrics/metrics.go @@ -47,6 +47,12 @@ var ( WorkerHostname, _ = tag.NewKey("worker_hostname") StorageID, _ = tag.NewKey("storage_id") SectorState, _ = tag.NewKey("sector_state") + + // rcmgr + ServiceID, _ = tag.NewKey("svc") + ProtocolID, _ = tag.NewKey("proto") + Direction, _ = tag.NewKey("direction") + UseFD, _ = tag.NewKey("use_fd") ) // Measures @@ -143,6 +149,22 @@ var ( SplitstoreCompactionHot = stats.Int64("splitstore/hot", "Number of hot blocks in last compaction", stats.UnitDimensionless) SplitstoreCompactionCold = stats.Int64("splitstore/cold", "Number of cold blocks in last compaction", stats.UnitDimensionless) SplitstoreCompactionDead = stats.Int64("splitstore/dead", "Number of dead blocks in last compaction", stats.UnitDimensionless) + + // rcmgr + RcmgrAllowConn = stats.Int64("rcmgr/allow_conn", "Number of allowed connections", stats.UnitDimensionless) + RcmgrBlockConn = stats.Int64("rcmgr/block_conn", "Number of blocked connections", stats.UnitDimensionless) + RcmgrAllowStream = stats.Int64("rcmgr/allow_stream", "Number of allowed streams", stats.UnitDimensionless) + RcmgrBlockStream = stats.Int64("rcmgr/block_stream", "Number of blocked streams", stats.UnitDimensionless) + RcmgrAllowPeer = stats.Int64("rcmgr/allow_peer", "Number of allowed peer connections", stats.UnitDimensionless) + RcmgrBlockPeer = stats.Int64("rcmgr/block_peer", "Number of blocked peer connections", stats.UnitDimensionless) + RcmgrAllowProto = stats.Int64("rcmgr/allow_proto", "Number of allowed streams attached to a protocol", stats.UnitDimensionless) + RcmgrBlockProto = stats.Int64("rcmgr/block_proto", "Number of blocked blocked streams attached to a protocol", stats.UnitDimensionless) + RcmgrBlockProtoPeer = stats.Int64("rcmgr/block_proto", "Number of blocked blocked streams attached to a protocol for a specific peer", stats.UnitDimensionless) + RcmgrAllowSvc = stats.Int64("rcmgr/allow_svc", "Number of allowed streams attached to a service", stats.UnitDimensionless) + RcmgrBlockSvc = stats.Int64("rcmgr/block_svc", "Number of blocked blocked streams attached to a service", stats.UnitDimensionless) + RcmgrBlockSvcPeer = stats.Int64("rcmgr/block_svc", "Number of blocked blocked streams attached to a service for a specific peer", stats.UnitDimensionless) + RcmgrAllowMem = stats.Int64("rcmgr/allow_mem", "Number of allowed memory reservations", stats.UnitDimensionless) + RcmgrBlockMem = stats.Int64("rcmgr/block_mem", "Number of blocked memory reservations", stats.UnitDimensionless) ) var ( @@ -496,6 +518,76 @@ var ( Measure: GraphsyncSendingPeersPending, Aggregation: view.LastValue(), } + + // rcmgr + RcmgrAllowConnView = &view.View{ + Measure: RcmgrAllowConn, + Aggregation: view.Count(), + TagKeys: []tag.Key{Direction, UseFD}, + } + RcmgrBlockConnView = &view.View{ + Measure: RcmgrBlockConn, + Aggregation: view.Count(), + TagKeys: []tag.Key{Direction, UseFD}, + } + RcmgrAllowStreamView = &view.View{ + Measure: RcmgrAllowStream, + Aggregation: view.Count(), + TagKeys: []tag.Key{PeerID, Direction}, + } + RcmgrBlockStreamView = &view.View{ + Measure: RcmgrBlockStream, + Aggregation: view.Count(), + TagKeys: []tag.Key{PeerID, Direction}, + } + RcmgrAllowPeerView = &view.View{ + Measure: RcmgrAllowPeer, + Aggregation: view.Count(), + TagKeys: []tag.Key{PeerID}, + } + RcmgrBlockPeerView = &view.View{ + Measure: RcmgrBlockPeer, + Aggregation: view.Count(), + TagKeys: []tag.Key{PeerID}, + } + RcmgrAllowProtoView = &view.View{ + Measure: RcmgrAllowProto, + Aggregation: view.Count(), + TagKeys: []tag.Key{ProtocolID}, + } + RcmgrBlockProtoView = &view.View{ + Measure: RcmgrBlockProto, + Aggregation: view.Count(), + TagKeys: []tag.Key{ProtocolID}, + } + RcmgrBlockProtoPeerView = &view.View{ + Measure: RcmgrBlockProtoPeer, + Aggregation: view.Count(), + TagKeys: []tag.Key{ProtocolID, PeerID}, + } + RcmgrAllowSvcView = &view.View{ + Measure: RcmgrAllowSvc, + Aggregation: view.Count(), + TagKeys: []tag.Key{ServiceID}, + } + RcmgrBlockSvcView = &view.View{ + Measure: RcmgrBlockSvc, + Aggregation: view.Count(), + TagKeys: []tag.Key{ServiceID}, + } + RcmgrBlockSvcPeerView = &view.View{ + Measure: RcmgrBlockSvcPeer, + Aggregation: view.Count(), + TagKeys: []tag.Key{ServiceID, PeerID}, + } + RcmgrAllowMemView = &view.View{ + Measure: RcmgrAllowMem, + Aggregation: view.Count(), + } + RcmgrBlockMemView = &view.View{ + Measure: RcmgrBlockMem, + Aggregation: view.Count(), + } ) // DefaultViews is an array of OpenCensus views for metric gathering purposes @@ -517,6 +609,21 @@ var DefaultViews = func() []*view.View { GraphsyncSendingTotalMemoryAllocatedView, GraphsyncSendingTotalPendingAllocationsView, GraphsyncSendingPeersPendingView, + + RcmgrAllowConnView, + RcmgrBlockConnView, + RcmgrAllowStreamView, + RcmgrBlockStreamView, + RcmgrAllowPeerView, + RcmgrBlockPeerView, + RcmgrAllowProtoView, + RcmgrBlockProtoView, + RcmgrBlockProtoPeerView, + RcmgrAllowSvcView, + RcmgrBlockSvcView, + RcmgrBlockSvcPeerView, + RcmgrAllowMemView, + RcmgrBlockMemView, } views = append(views, blockstore.DefaultViews...) views = append(views, rpcmetrics.DefaultViews...) diff --git a/node/modules/lp2p/rcmgr.go b/node/modules/lp2p/rcmgr.go index 8b286ff5ee6..71ed4e75445 100644 --- a/node/modules/lp2p/rcmgr.go +++ b/node/modules/lp2p/rcmgr.go @@ -11,9 +11,15 @@ import ( "github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p-core/network" + "github.com/libp2p/go-libp2p-core/peer" + "github.com/libp2p/go-libp2p-core/protocol" rcmgr "github.com/libp2p/go-libp2p-resource-manager" + "github.com/filecoin-project/lotus/metrics" "github.com/filecoin-project/lotus/node/repo" + + "go.opencensus.io/stats" + "go.opencensus.io/tag" ) func ResourceManager(lc fx.Lifecycle, repo repo.LockedRepo) (network.ResourceManager, error) { @@ -43,6 +49,8 @@ func ResourceManager(lc fx.Lifecycle, repo repo.LockedRepo) (network.ResourceMan // TODO: also set appropriate default limits for lotus protocols libp2p.SetDefaultServiceLimits(limiter) + opts = append(opts, rcmgr.WithMetrics(rcmgrMetrics{})) + if os.Getenv("LOTUS_DEBUG_RCMGR") != "" { debugPath := filepath.Join(repoPath, "debug") if err := os.MkdirAll(debugPath, 0755); err != nil { @@ -70,3 +78,115 @@ func ResourceManagerOption(mgr network.ResourceManager) Libp2pOpts { Opts: []libp2p.Option{libp2p.ResourceManager(mgr)}, } } + +type rcmgrMetrics struct{} + +func (r rcmgrMetrics) AllowConn(dir network.Direction, usefd bool) { + ctx := context.Background() + if dir == network.DirInbound { + ctx, _ = tag.New(ctx, tag.Upsert(metrics.Direction, "inbound")) + } else { + ctx, _ = tag.New(ctx, tag.Upsert(metrics.Direction, "outbound")) + } + if usefd { + ctx, _ = tag.New(ctx, tag.Upsert(metrics.UseFD, "true")) + } else { + ctx, _ = tag.New(ctx, tag.Upsert(metrics.UseFD, "false")) + } + stats.Record(ctx, metrics.RcmgrAllowConn.M(1)) +} + +func (r rcmgrMetrics) BlockConn(dir network.Direction, usefd bool) { + ctx := context.Background() + if dir == network.DirInbound { + ctx, _ = tag.New(ctx, tag.Upsert(metrics.Direction, "inbound")) + } else { + ctx, _ = tag.New(ctx, tag.Upsert(metrics.Direction, "outbound")) + } + if usefd { + ctx, _ = tag.New(ctx, tag.Upsert(metrics.UseFD, "true")) + } else { + ctx, _ = tag.New(ctx, tag.Upsert(metrics.UseFD, "false")) + } + stats.Record(ctx, metrics.RcmgrBlockConn.M(1)) +} + +func (r rcmgrMetrics) AllowStream(p peer.ID, dir network.Direction) { + ctx := context.Background() + if dir == network.DirInbound { + ctx, _ = tag.New(ctx, tag.Upsert(metrics.Direction, "inbound")) + } else { + ctx, _ = tag.New(ctx, tag.Upsert(metrics.Direction, "outbound")) + } + ctx, _ = tag.New(ctx, tag.Upsert(metrics.PeerID, p.Pretty())) + stats.Record(ctx, metrics.RcmgrAllowStream.M(1)) +} + +func (r rcmgrMetrics) BlockStream(p peer.ID, dir network.Direction) { + ctx := context.Background() + if dir == network.DirInbound { + ctx, _ = tag.New(ctx, tag.Upsert(metrics.Direction, "inbound")) + } else { + ctx, _ = tag.New(ctx, tag.Upsert(metrics.Direction, "outbound")) + } + ctx, _ = tag.New(ctx, tag.Upsert(metrics.PeerID, p.Pretty())) + stats.Record(ctx, metrics.RcmgrBlockStream.M(1)) +} + +func (r rcmgrMetrics) AllowPeer(p peer.ID) { + ctx := context.Background() + ctx, _ = tag.New(ctx, tag.Upsert(metrics.PeerID, p.Pretty())) + stats.Record(ctx, metrics.RcmgrAllowPeer.M(1)) +} + +func (r rcmgrMetrics) BlockPeer(p peer.ID) { + ctx := context.Background() + ctx, _ = tag.New(ctx, tag.Upsert(metrics.PeerID, p.Pretty())) + stats.Record(ctx, metrics.RcmgrBlockPeer.M(1)) +} + +func (r rcmgrMetrics) AllowProtocol(proto protocol.ID) { + ctx := context.Background() + ctx, _ = tag.New(ctx, tag.Upsert(metrics.ProtocolID, string(proto))) + stats.Record(ctx, metrics.RcmgrAllowProto.M(1)) +} + +func (r rcmgrMetrics) BlockProtocol(proto protocol.ID) { + ctx := context.Background() + ctx, _ = tag.New(ctx, tag.Upsert(metrics.ProtocolID, string(proto))) + stats.Record(ctx, metrics.RcmgrBlockProto.M(1)) +} + +func (r rcmgrMetrics) BlockProtocolPeer(proto protocol.ID, p peer.ID) { + ctx := context.Background() + ctx, _ = tag.New(ctx, tag.Upsert(metrics.ProtocolID, string(proto))) + ctx, _ = tag.New(ctx, tag.Upsert(metrics.PeerID, p.Pretty())) + stats.Record(ctx, metrics.RcmgrBlockProtoPeer.M(1)) +} + +func (r rcmgrMetrics) AllowService(svc string) { + ctx := context.Background() + ctx, _ = tag.New(ctx, tag.Upsert(metrics.ServiceID, svc)) + stats.Record(ctx, metrics.RcmgrAllowSvc.M(1)) +} + +func (r rcmgrMetrics) BlockService(svc string) { + ctx := context.Background() + ctx, _ = tag.New(ctx, tag.Upsert(metrics.ServiceID, svc)) + stats.Record(ctx, metrics.RcmgrBlockSvc.M(1)) +} + +func (r rcmgrMetrics) BlockServicePeer(svc string, p peer.ID) { + ctx := context.Background() + ctx, _ = tag.New(ctx, tag.Upsert(metrics.ServiceID, svc)) + ctx, _ = tag.New(ctx, tag.Upsert(metrics.PeerID, p.Pretty())) + stats.Record(ctx, metrics.RcmgrBlockSvcPeer.M(1)) +} + +func (r rcmgrMetrics) AllowMemory(size int) { + stats.Record(context.Background(), metrics.RcmgrAllowMem.M(1)) +} + +func (r rcmgrMetrics) BlockMemory(size int) { + stats.Record(context.Background(), metrics.RcmgrBlockMem.M(1)) +} From f61eb23f8f6ff69af8b83fe3e398c6a40177eada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 14 Feb 2022 19:56:02 +0100 Subject: [PATCH 172/385] api: separate method for paych funding --- api/api_full.go | 9 +++--- api/mocks/mock_full.go | 15 ++++++++++ api/proxy_gen.go | 13 ++++++++ api/v0api/v1_wrapper.go | 5 +--- build/openrpc/full.json.gz | Bin 26979 -> 27021 bytes build/openrpc/miner.json.gz | Bin 12903 -> 12906 bytes build/openrpc/worker.json.gz | Bin 3960 -> 3959 bytes cli/paych.go | 12 +++++--- documentation/en/api-v1-unstable-methods.md | 31 ++++++++++++++++++-- markets/retrievaladapter/client.go | 1 - node/impl/paych/paych.go | 19 ++++++++---- paychmgr/manager.go | 12 +++++++- paychmgr/simple.go | 6 ++-- 13 files changed, 98 insertions(+), 25 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index 853d4928390..6fd34ddfbab 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -690,14 +690,16 @@ type FullNode interface { // The Paych methods are for interacting with and managing payment channels // PaychGet gets or creates a payment channel between address pair - // - If opts.Reserve is false, the specified amount will be added to the channel through on-chain send for future use - // - If opts.Reserve is true, the specified amount will be reserved for use. If there aren't enough non-reserved funds + // The specified amount will be reserved for use. If there aren't enough non-reserved funds // available, funds will be added through an on-chain message. // - When opts.OffChain is true, this call will not cause any messages to be sent to the chain (no automatic // channel creation/funds adding). If the operation can't be performed without sending a message an error will be // returned. Note that even when this option is specified, this call can be blocked by previous operations on the // channel waiting for on-chain operations. - PaychGet(ctx context.Context, from, to address.Address, amt types.BigInt, opts PaychGetOpts) (*ChannelInfo, error) //perm:sign + PaychGet(ctx context.Context, from, to address.Address, amt types.BigInt, opts PaychGetOpts) (*ChannelInfo, error) //perm:sign + // PaychFund gets or creates a payment channel between address pair. + // The specified amount will be added to the channel through on-chain send for future use + PaychFund(ctx context.Context, from, to address.Address, amt types.BigInt) (*ChannelInfo, error) //perm:sign PaychGetWaitReady(context.Context, cid.Cid) (address.Address, error) //perm:sign PaychAvailableFunds(ctx context.Context, ch address.Address) (*ChannelAvailableFunds, error) //perm:sign PaychAvailableFundsByFromTo(ctx context.Context, from, to address.Address) (*ChannelAvailableFunds, error) //perm:sign @@ -837,7 +839,6 @@ const ( ) type PaychGetOpts struct { - Reserve bool OffChain bool } diff --git a/api/mocks/mock_full.go b/api/mocks/mock_full.go index 5d42ba3c918..ab120abdd22 100644 --- a/api/mocks/mock_full.go +++ b/api/mocks/mock_full.go @@ -1975,6 +1975,21 @@ func (mr *MockFullNodeMockRecorder) PaychCollect(arg0, arg1 interface{}) *gomock return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PaychCollect", reflect.TypeOf((*MockFullNode)(nil).PaychCollect), arg0, arg1) } +// PaychFund mocks base method. +func (m *MockFullNode) PaychFund(arg0 context.Context, arg1, arg2 address.Address, arg3 big.Int) (*api.ChannelInfo, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PaychFund", arg0, arg1, arg2, arg3) + ret0, _ := ret[0].(*api.ChannelInfo) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// PaychFund indicates an expected call of PaychFund. +func (mr *MockFullNodeMockRecorder) PaychFund(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PaychFund", reflect.TypeOf((*MockFullNode)(nil).PaychFund), arg0, arg1, arg2, arg3) +} + // PaychGet mocks base method. func (m *MockFullNode) PaychGet(arg0 context.Context, arg1, arg2 address.Address, arg3 big.Int, arg4 api.PaychGetOpts) (*api.ChannelInfo, error) { m.ctrl.T.Helper() diff --git a/api/proxy_gen.go b/api/proxy_gen.go index c90ec4cddb5..0f849343058 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -306,6 +306,8 @@ type FullNodeStruct struct { PaychCollect func(p0 context.Context, p1 address.Address) (cid.Cid, error) `perm:"sign"` + PaychFund func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (*ChannelInfo, error) `perm:"sign"` + PaychGet func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 PaychGetOpts) (*ChannelInfo, error) `perm:"sign"` PaychGetWaitReady func(p0 context.Context, p1 cid.Cid) (address.Address, error) `perm:"sign"` @@ -2185,6 +2187,17 @@ func (s *FullNodeStub) PaychCollect(p0 context.Context, p1 address.Address) (cid return *new(cid.Cid), ErrNotSupported } +func (s *FullNodeStruct) PaychFund(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (*ChannelInfo, error) { + if s.Internal.PaychFund == nil { + return nil, ErrNotSupported + } + return s.Internal.PaychFund(p0, p1, p2, p3) +} + +func (s *FullNodeStub) PaychFund(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (*ChannelInfo, error) { + return nil, ErrNotSupported +} + func (s *FullNodeStruct) PaychGet(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 PaychGetOpts) (*ChannelInfo, error) { if s.Internal.PaychGet == nil { return nil, ErrNotSupported diff --git a/api/v0api/v1_wrapper.go b/api/v0api/v1_wrapper.go index 1c22eb920ad..3f2dd837391 100644 --- a/api/v0api/v1_wrapper.go +++ b/api/v0api/v1_wrapper.go @@ -338,10 +338,7 @@ func (w *WrapperV1Full) clientRetrieve(ctx context.Context, order RetrievalOrder } func (w *WrapperV1Full) PaychGet(ctx context.Context, from, to address.Address, amt types.BigInt) (*api.ChannelInfo, error) { - return w.FullNode.PaychGet(ctx, from, to, amt, api.PaychGetOpts{ - Reserve: true, // v0 always reserves - OffChain: false, - }) + return w.FullNode.PaychFund(ctx, from, to, amt) } var _ FullNode = &WrapperV1Full{} diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index b486a5123c56815d472f15994443f8b2b91bb98b..676ffbf4fe668ccd3033379c9a6d6d2fbafb78c8 100644 GIT binary patch delta 23020 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 bs7O=V`{O5aBzyf6009609MB4oXG{eEiOJL` diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 5e9c824f58ab6dd0fcb0a1415e25b8e609bb088a..eef2701f28055a067fc6541177f878cc1d65172b 100644 GIT binary patch delta 9997 zcmV+oC-T_mWa?zF76O0ub?xb?lP|R=HksjhZP^uMYQcd#cYf^G~I{f?Tjw?t}0nC zr^rc>`Ga2u*ad$O1dl|z-5>OalcWB)KN{bLo%5djv6XY!lPl-R0vUG~j(yLNwvuYb zC}b+;6dzuqIcEGJ^TNKO7mjVuI$+fUUvFJO*89Ylh+Xdk2Jf%It0i204Zpwmgtsnr zFv<0eVr=Coa}N1Znw=a5)@{~3)|Kt*w|r=~rXBkX@gFV(6<2$YcO>v!$!lwIR8 zsU3H9UGI2((2ghEHL&g3HD`GIbbH(JjrZ3A>m7HsL?b0$@c5Aox90_Tzn?;Gi=Tax zI2Dopl^_to?8x^No=NG?*-w2=rn^etk5P{>;Jb9yElG|(r?||2R%Lq8?e(=|&4A>; zD1Zj%7dU?in!vJ+JB=~8f|Mb|MNBvje~GxUUV|^r9~|{FOpd)=tts+Rs)EId5Xdq( zUvH;tY*9=O-#=1BOk|3Wd`4zAw>s>*GqAjb#I%=$M~YT`e)(hpF?qkTjYS8n2J8|+ z^uc!S4*wJ(uh-yJNIzoCa;#B=+1xI{bNLo(OP$!}x}?O>g=Q8VL3uTyrtn^kIKQr+xPhEm!|% zKmM~?Z|vpj|E9|s+RXZc8Sbw)qxBjMdiMkEsk(uPu&#pnG0y$Rxd0Oi&P+rop5f@L zK1zSYMxolP73@u;<|1wV)5@qeO?mh5>#thui&b%MQr^rqEMgp3w&tC6^{(D+z(X6z zI*@?D?R8>UwFfefKmw{c;HBU|$1y8>fngT^>)nR3yW0N}OaJ%PyM;miwLt&<>#tgM zc!{*40xwZEzH3WlV$SXzcA}|uXbkS%KiB07>BURO6PyLglL6e~c=6~@} zuH2_^?o!)9A5SW&cKEt{>F(>T|HRb-I_4$+4tW!UkYMh#Kti?D#307ET=yfKIBVj9 zIdrCQj(}lX7Bbiv0bA(E>D!NhKYCb7N#wR!(ld#5mOrIrpSh!~P2n7l5FEG&{)3Dq z{dR=mUB7R-Gk1YUy(2jNHo$|?Xn$zV*591|KQnhQT|#qYKK3!5oBwDX?P_fp%ro_+ z{5|`q+Oc-C*7d%@KQaFk)iCoO%~Wilqxt@R%BAa;{w5@+ zmd+<=RkrLI^y(V?4_{SUH}-l>#4hODOz^G91-L|%IH7> zFfq}iu=6W6197R}0KaoXs10V&z!s*Ei5#TJ0S=-LM)%Ni`I~QShq(TPR>p{!XdKYx6MsB?g8Dk+YuyO038H~O+obI;3aqVDY7<< zQ+RJ<^M;GF4R9@7nH9?`(@S~>PTCi6pZMqG-Z=~3szBZO}V_kW;f*l{U<9CDD! z_`xpl9KM;&hA%oIzF^q1px@KY4H2(14lw0kGs?7sECjuq9)0YBwTotJi}mOMI!mx# z35U^u#sY!(XJ_Jr{#mn+llb=RK~JJkC^pFDf)hx@0xbiXur@Mjm_cm00MA0%W-N*? z0k{HPF;4zK55Q%A93S40GYY1bZQQwFO(?dK12n?~y9+LRt=IYEnxk=doRc95f&zP! zlcfnz0v=?O_X#{5!;I`+*+=rEv02fL5^YX!qg1yjwh882q1}zpj+0Od8h=L_xpR_l z)G*klXf`IaTZdX1>#e}N??!+p zSqTHtuk`0u#8*bO0pXRA-G=C9u-^*qP6T(NXDxxV?{Kzc-|`evSY1p*8d3v4U^CMGs`P9FrzwMDVP z?jEe5afi&H6{a4q`Fbe?pV(6i=q?W98M@76+gFVy=H`;OvCZc|p?~gC4ho%PH=Wd_ zj6dw{taZ*$e6@}}R%jL(ncQ{FkXE?`%?OWMv3XI>BYRcCD9V)g_ z9P|AS9qm0a;}<+>x_@x6fi95a-PH6*ODDF)Q-l~-{DxpEaXGr?=xsqyH-8RY`ekJ@ zrA)A4L3a_oRAYxx^s|*I653yic`%14FykqLxi;OSTHc_`_}-Fr52q4I(_T2qh}-o> zTyp7d$`>?=NxAqhOtJe}Swc*zuMpi*o-KSabEUPL=c+J2Pq`okcyN^3#qOq znO$gA<>jc#Brk6&A`H!Do)i#nNKMoeP^v3Q2K%jwynhrG8R&XmX4Vy=4MwYF)Uqo~ z`oZO5jZh3)msbNBw_BI}HZZ-bY*w>%F(s!v#l_4snKJk#rW3sSi{JmC>KmBj zdql$PXMd+$Ic&N>4j+}qHoayH|MpH3*h-;vPf*nI+q%8e{_nQ^*T-*<-+ur1|K6kD z{)etUj^4V?mw&x8{(AiF-G{5*Z|-~hHPlp|Dm(Wd2oAL5d5dZzFtNuo|h;V zQO;8g=frj?Hmc1faw%q^peMku!K+^+Z{@B3=YKXQM?ZqCGE4tO9m;mC@_F;C4!OWY z)AfAL%NwOim>6rvVJ<=pC|$q{6wDpCTDTixGzN$J3nVfvmdQ%0OBoNT6!O1B2EzB4 z%zYC6<$u=5rDvzw@u1`X^6R7|(h|?y6Y&907LX8Rc~1u^kK(FGV-uCrC@-i|X>1uY z?thAxW35ht@zQ?^SPRm+BF6E!FVel%u6Eq*Xz!rgY_{l`8yN~QP-pHH68#dt|FqY} zf_F19;GdA|!nx#2d}hwW1*$VN{t$3M9rXAh%)LtQ-d|t8YkvsgOf-Kg$wv=virTa0 zHRf;Xy52qD|6J?(G5_b^T1WE|;OF zxzz8N_Q;Nm40TC%H&7r+_aizauTbV`Lz&YVGGp z8PmXW49nyzd1R-+o?W+_l_|e=)pRauTFN}naaiSrz*;CNZ4CM%pFcII$z#m~vBY9yH6j`@&uJ8d)M52+Xme=GjG4fTz}7vl1RVM8-<0XIuTC?A1)Xo(PN;^G-G z90Xm&F~1ywr^qW6KFDfbt$%7lwAW=3G&VpLQSOC6#5iL|iO>$?FF5EZ z)kLX6BH2CKQY8@y!_tF>WKSt2a<{ABKhf%U@6%Z55p0cuR4) z^@E+-vIoyt_MioU^Feo2ZZ;9kn=%zl9MkMDNCN7 zRUQiyOy=*{*RO;#!Rr}SJcSQ)jaOHQ=B{1`gqo?@8Rcs`g*u}>OQTBSt_qx-VAJ(8 zGkL0f@as2(=L@PG7q5W6q&1FSH;TU6nI*H(dB1>SoF9%hrV7hM6$lMfid0dbSj7%hJ!V^4^OT$n%$e?ymOWnlw~ zQ$Olpw~XEnuw2$`L)f0tqZaF1tZ%Wt#ri$M`o5mAc_WTwHA2QRLc2rvya01mSP%Np z;(3ebEuOb{zE61G&Da?uAnYR|$br;@u;0<~FEZ#r}VN!v0>y4l{vfpX__&p?D3nk5Jh@zDF8s2GQf(w;0}Hc#GjJhVK)G_cQir z3H-Wn?E83FISn}KST3Pf3e&wqhz~sye?o#S3tl+3J#(ukDoMC%2K?pSElyu*4MA%N zc4P?hG)gT4JYBLrkT{d-)7moydp5|}6qbJl$!VRaW6yeZ?3p0Jm9I%_*4vgf z>$TRbwPt&4%_91wR{!zc12bQ;y+~zB{iO=~wHB|ncw4l1!;IaN0=6#^ti6pSpi#=Y zO>Nt%ZpVT)o3UQeF0?kQwOM;(vvza-Kx<1{TcTo1Mj0D?9g&%BUoJ(XQ~cW@RtTN{i_&rhAxvlav}uf1l*;YG(p}VlS7N*2&U{P^o0c zy?1L_@CXmh*zb6!TI=0f@4d6$q29EsRjmbkp%!eQ=kE0nVY*IUMubWw3sy4)Bhq}+ z#;Z-aXpPri8m~6XqP1Hu+HQ4o>lR$`Q~6Lcldq6aMeBu{nu3L-nlogv-nF)@wPkx~ z%TPNPe`{^p%eQI0+}aH>u&z5D3kg-SX#$H*uvufDSDcM47_@eB)*7_EG-#prC`w7w zYjOx?<3fS81eYD&C+`1dy8Syo9{v%YjpPd5?xMxwDf(I+6tdAVVWk~ zXa6sTnPFY6PtdtT)J;}hc+Tk4o@(4MqcVUuwr{7lLn|p;lz^(Ql;aXb$<_6S60B|g ze}M7U32L37*1`+C8D;Ft_H^>fSRnHh!+9Od35aCj&eXQ8*WeXqfWY+f`%|8gPg0e` z55ZO$i!Na`8;4RHnCs<=8EQccxZ*xw5@W6{9}jRk9>f2(&p+IwQg zFL*F^;a~$@Aji9@>5-OBY|DZaIgBfQLok)N{3OQg%5!@8nr319PaW-dgjV4qCKrfu zlVkt8sZ2DJU$sm$+WQg(FC}KDvcW1#AsjQ6E_$+%iiCG+9GDytRTUOO5iQ$QnaGu; z5tTX>Zsi(Kw$-@u2BYuKf4L-qi?qI!kj8Q{QEo_Ntj4u8-Mvl>PUQEhP zByN_8`b|2T_Z|o9k`U#;s`RabSliZ)C*M!+e5hw^9QIO!c>dZ4YwcD$6gx#lzTEWn zmWOXde3(D{4pL)riE>w-Qp9r{?d%pRxZUyoy!q@g6_WIhfW@&W!;2G>&>oJ#MdKaxc9Qw0f*g;9jH-N zzCgqj>#g;`(4&(Dhhb>z>{Jy3J(9T~7^Pbo_(I-`q0eW^UxA0f!Y&2&46M969s~v< zMH@^J2QfdWNYEnv~%=4)<6X{&+bj0!e{Y0M^t3qAnz_< z{BfTK`k_N=^98)xN*(KY>U$>dZYKsf(u4n14h8P1TJK0)X1gYDE`pN@T#?eoEKn31FHOD{DR-o%Fo@!f0t^9m7vrd~&ve{(5It!1J5=8|kmpNsget=O$x zo)3nj%uHrB&cS}&>C!KEz18$2Qp@=h72 zUW7Mz^cjM@siDh_^U9vC9O`|Jz-=38eO8=0%FKX{X;uATYm!tm@zx~OZH8PWJy1fV z;=pT&e@q3jSB_C_+_jCn7Ay8RH{<#eE$#a{b6G*4u`Fvrt{E3MV67;#+H2I||M9jY ziXiCBv6n$2DmbISv=O)V6gf*wAmu?Gn;aMmh)D-LEU>Wv1|&CRihyYo&$kfmT>CE_ z0^TH3c}Pq^?2sV4X5o7j$@#P_V8FGDK&UMYe=(rNRHNCn%>ABgw-buU)AgLpIgpUrs@AY`%SZfV^lPc46#pl++3=YvrK%P*}?z7(D8a0e?YEPq`NI&A#ppp*Elnp3jjJ>bp5 z!GK0%3K&pqM*E@+7O7s?bTHS9O-=ntCwRrCg=Egm9kl@rXOcGY;zTp-xb$_0y-jWi zTvK}qDQ0@S2`0Um#wNS1a{gS(Imk^Te+p!=?lM)JkUaGJi-FC<6Koa-edE*`Du5wn zQ%O;?SDeCVQQ?YHM0_9v-<=%xy z1Dd9TTo;)D2h@1z4Rb$#iA*rv00{m>j>~h+AULs2WPn#9_=bsz4GxwNEY}vre+IjI zu!6=NGJ{r_>b~Z|HwZqlrxws%9L5oa4SEDryj7ZMQ2uU=k* zeV*lN%Q=9S#U`rrAf)6rs$_r24}DqbBMQpqXK1wbBMWrllUpQCe~)wXnA}S=tEKVm zeYq7}!qrzHRJTl8p@qy#G*i%RMlwgI<#em)wa5Eb@_OZ5rbasRF_jt=ld-Prk!loY zr`+p|R-_n=hesp5qxt28`0pn!0qDB+44_9i@(TVlS7ce&#p(aq0gMX9gc@|4S_W z-&gMz2KmcAB5w!p4~pz zvt#0Yjg32DH~-|lITq(}cC^InS4b4t%6}?In2zjNNL{!@)Ztcp(CcW|w!eSV`x58S zrSF~87Ke^@ZqKSKceJ+##rGneBpA}i z6?Wp6*oXKFf8qIpdS5ImTCp2v1XB#H3k#XNd3NnHVN8egp<`|Qp)6O&E6S~kOXJ~6 z+1(u;0#$j<6M(X>M#r&i8a2&sV*?^IJr13jeT=cN>b%h>0HgaV}XW zzYM%UJG3q#G3_NmuG;~tA@K7N3$wP}2G6LLe~v=*P#4BAV{hwcHO59*QNe`ok$F%f z_hqiRPK+xZ#keEIujxRbHCPVVKc+AZ}?~j`}=_Y-y%nx~B&mdz3Dhew~ zS|mcx`;&MPc5&FIY&V#)-R=W99~|{__e#27R%X2|S{{W`OYE`yxkA&=={IHdeP-KY zf0xBpuWW{1n4s4xY;}blWbLXHD)`nk&us&y$3#hG<216}fA-PxR5MPewsNM}+QC`r zj>wQu5bM}VZ!6n1WP6ykDbW)EN}*A4H)51R-n16EerqDPYt;iYcTKT%_<`qHDM&qU zqbZs98O}FIKIdL~kcl1}OXErpN{Okce|9vQbtmKT^Z?EJ`oX|FLI=}6G7cti)H|9D zrf>+yT1WeGc`j8YKUzBIb+k|L(PKjVK7r&anqUJ7yB(x?e01#fN=o#tW!VqccKTM? zqzIo*B;cHic_)`X0&;4> z@EuNgywGny^85v)i)%jRfA#fNe`bnv7HAU8<=3iCkuJAJlOBlTBflH8#j?TOUTAJB z6UVq1Y>oN;pg)`(^~e3ucq>uTwCF0%7rfe2O->bLVl68lUd@^NLA|-E8`4|HZflO+ z%i4T+bdFe2P!q)N&{XEM&C_H9J!bU?gf81o(l1r^y zH>iBb)R0>V|0-9IQ8Sr}yk?i_C^b9TS#6F6t?>`!8>QDQ+Y_XA2HxYWnh_o_Irgdn zn(R7d-=(@9T@(Je;r6r)>!JRclQvPx?RIQW2xSsx%nD#bYh9!BPP zvi)?7$#-rep&xJIx=d^-e`HfBxRh+6N{A^oGCOsPTO?D@_}h0RD@^qJ;UaPSJj4%(Ikq70Vpy!B&cENf|A)LH<)J=2|=(R#u3~+%?ec^_hw| zm@*O9J9?+v(L4HWN4rGO)Q-RQI(>Gbqu)N2O`!0YsJ1s=G~e`Iza@M;69k7HZHYmo}aE%*|?jNaVseFP|e;~iKWN(kSa|2*kd_!zW6rs3X?sL@1H(`p4{8p?)-g85c)zU>*JH) zEHeRuSaCsCXx6HZ~^{*gF`FN5g|bcRV>5&t~voGD9Q2pr!4M7)riMN~fHQqKf9o2(5gMBDOvxOI*U-IVXn~;h z=3alpbc&x4@`m{zmuvDD#8f-hy^~wCW38w6^n-5qpxe9FC&#_sv3~S#t)u;ByVM)@ zh3!&pE9?4UBa&cR=|b7!g>5Bjc1O`nP4??Y%4C%#I|S08ek99&b}kU+@7m0EmXL|H z2`M_De|U*xC*KGqsc>l73!7a}x*59^1U6n#NbA@){=SNVOM)_gvDm=z$CNFcw2=xH z&hOO@Oq`VE0uz_@PID&iyXK#zmoyR`?QBkL2VEl9UOPqv7a~`_YoE~aVzF_t0WIyg zcQhCu9ZmGnWH9KkTO!ic>kf_vBme8G20vbW0o{K8NV`q&;u}h6nk)ZgFx|thPiSeg5$oxk3-}nn@bTiy7m6+X z%{wVl=g(X~2U-@gu)EZbyU9x*FTU^x-$558T6pSc-9*FV{&+mn<824m8f@O9`P9*R ze+dq{`ceOA&>i;%F(#sy8{{J-`_$3;304NZ$zU=%>P<#5R-%`;#mXT0U54Yyq(2x= zdht&axx6h_hR-FNqi2`Rqy3T1@&3r>WM5?SsS|*yH|6Ly3#O?{y9HC#=C=)|s(j>v z=`*sD1k-0^r8zJyDVt4$X?fY)4wzQ@e+o%3eMVN2VESyVq`|aT158tBzFW_>SAX8KwA%R05Ge>S!?N4Tkz; zFwm3Ip?CGkU^E;x%+F|i)SV2DMo0ZobzH44rnPXj5iwQ8)m?~b5?G&GOq1yPf4pKE zf!Gv~Rhqwj)Rvt_L^xklyj|aVRe_~MjM}z)&GVBkInvNy~%(QXN=a$SQRz9O-rl9lr zBvXo|b>`+0rZU{woq?%x`;E@d>oAfZ>kOwiS<{|oXBoNS&a6pT?E2QYX%1G)3Te~0 zT0uw~n432yq$yAIS%owSu+J%^F@&}6k%LwiHsG2cDc!Cq?MsBZT~lh;f0QcXYrCfO z+-ph_U~Siz_9t-Pt}nIgOYQp7%UNG?&>Rt$XVBlFO&fUKmo&aM#dNzK><=G$ZBtD5 zHN`aMytatCFH+kgYKy2XqW+MGx+bny-M@v>=U#hlvjW3agF zR=5q^+spb1dyRNM;UoX~e{r=IJ6H9NcEbPWsap9(7RnqK=+RW!d>=3_J-fwc^n3b6 zenVor{Dr~9Jpb>WxZ>T zxO8Z~`_D~n+d_~;o=gsu?9udRZj9fwAT&h!>4l+ZZ=8dkSBU=`e?!%wGo&HG%??;~ zLDEu#S8$3C!}kioG<-DAABfQ`52dkwFurSJX)x%k?*3bUsS6Vu(sUn^w==rnyQ*Zp zoFXSh<_~@uU>AQt5Ihp;c7Mwr}ce7$uAS??2HB6htG7`(p*uaS7S(WKUx7XK>H3O3W zq5vA4U*LZrXadVN?li{W3Q~p;7ct>D{3YVXdJVofe{iU0m>he#T2thsR0WF@A&_No zzTQsP*rJ#mzJH{Mn8*|#`HakLZgtpqXJB~=iD@qhj})!?{PM{HV)A}v8;cHD4cH}u z=!5Ot9sVgoUa!HckbcCNBIhrPW$d1TCV=j ze*9;(-q_34|4o-Ow3+n>Gu&TqM(Z^i^zH}RQ*{FoVO<6DW1Rbsa{(q4oSBGFJj2mf zeUyKQjY73oE7+Sx%|+V!rRr9tfQL4a zbszzQ+v~)zY7b-{fdo`@z)Qh_j$>B%0>do+*Sig6ceVc|mj3UncMF63Yk~gz*I%{j z@Dgc71zw_TeAkx9#GLafCeYcuCx&e@L|_tl>7vmf5}V3%MyjgCp86-FZj+$}=6|D} zT)9u-+@-dIKAu!k?eKN^(%siv|B0&wbj(Zs9r7jyA;H{ffrM(Qi9w8Sx$Z|ean{5I zbLdRr909|&EM%}T0=CeR)3+Z1fAp}FlE`hdq-PTAEPqPLK66J|o5DF9Avkam{0A9J z`t1nAyMEtvXYK-zdPi{jZGZ=((SOjKt-m?_e`fArx`gJ)eC%U9H~-N(+SS@Hm}lxs z`Fr+JwPWpOt?PY*e`5Y8s$u3mnyJ`8NAvytluPe(m0lM632gYdpReX;1XBzx{7pzs zEuBx$s%+Ua=+!my*=%Op`z%&)@Y@BDfHes(n80O^9Nv%{61)aEJQy}{v42ZlV9&q| zQDebu8TS>~8~^136H*9XnFv~71vi!r&DUV&*h^uty#O$9*Hd@nQnc)VIU>k`l+l3% zU}B<2VdqzD2I5k`0eN??!;f zSqTHtuk`0u#8*bO0pXRA-G=C9u-^*qZUlFdwFJ(-!`YI3%Tq{UbukTTWCa5aY#yFq zljqeJ2L|IbYsUmrEc#jRTYt@V_qtr10xM0-j?+59CUBT+xrk7{M2xK2fp}($$y|&% zq5k$(WC9#eI|OGGU>D46XNgQO-2e!@{M-(J;KVkO0bV^Uu(1G`nAqSseGn|y7R3g; zd$5AW9WsMfn0mbC>!lEUVoxogyEu$z=r)sWUp1PTn@irtHlG27CV%=M2ZheDn@;Ld z#vk@});i}WzFNl~D>RFYOzyg7NUPj}W`xJB*t{rbl6Aw_O|^`5$6nbk;Xq2T8eiW503*N_;tocS|wA_BDh%74Zn($<> zY*%G6RhC9nu9UWrNkzPDt8wkjNg|DNDiorG7^YQ3ZJS(DS-&wYCXVo&^DNURgvPTZ*2uhFyE@j%TbR(UbatE5*p2&C?MRFf+(j@)X)$) z`>l$+92FVnEh5r$?nPYMV(q$cVKDAkoDgZ)-TUVn~?O!6|bt`Kc7S}miNU18D> zE*EQrV$iz08pycay6m@s>3t4Nx0rE0(DjU@IFT%I0*QgFQ%K>p1BpA6NR0|)WD(0k z3=>jFy=M;nhtE!V+T02u=aB#1FEX=P&DO<~obD7CGtXqo;Fp+A@aivq|AVS;V2a)0Hp=>j=?R2tj#nlb#_J569Kh0;AiQOj@Z_D=i1+xA}{zde5Y{ont4kAC|f zy81YJ>pEZl_0IU~@way$u6n<@@9mG*kItv_```bE&MN1@?P)>qpAP%F8L4<)qF6*Z zPcfVm+ojm3HkZhyn1zC#0KW#Wev!PDxBj2ooPQks2)4>B{TFp8+qKH)&96G-0uxQw z^EoeXlqz9jtR08B2r-~^0WVN6ci?K_Zivws9PTfW$h24{E2%DJJfu>{{}LGp-(xcO zN%)ulStFO8oodH}j{nQAlafeFJabRP2RvCoLXhP>9i%*pt0Ij}R8FJ3ph~5&Wz4uM zUVo0YItj*0|0!TCNb8Ci$K$?8_gcH!akrzrgKo3gqGxVoD8xXWxmQT^OZ@)RUKCD}63;?jGD9*-8vDHXH@88Eh7)Z7!meGVDfhGKPnYs>UKp zx>>7{V0t^|L(=WE&5%E&VkrEr`0qBn=atNLxuT=OTt9iAm34hUEmqpOn098b}7XlHZj2$IHN4y$W2wIiPdC3ShQqxOD zxS4dM6tiu0ueQ2ZTit8N$TZH_&?9v89J{g1mpaKrDO%Yl9EA^gQI28{CPlsAprce1 zr3#5;_h?I%L?jGL4;qp^rIg6su73YStKXFim9+~7?SetOV6d|VgEE&|q->y1GB!s> z3~S|mkO>;~3XCR*ZKKR+n%}nAXj^QwEjHQ~8*Ph?w#7#G+KzYivknq=0Ri2!g%czJ z0eh3G6ng@0Ka(dF9{~rGM-?`Ihq(n(E)jJ$o-L9lp_W0yIH`gP2nq-nr`Hs`rMTSs z!A@=2gJ&#z(1O7EpgYPqcUtJgRoz;8S6Q|6xWcn>bPwO*`5B?y*-2dJ131NpCku!P zpX+tNYQQgDK+{BKFxTyX)lhc55J|3bs_~V@kD#kjkBD*1xZ5gB z@>KcY*KY{V7gRegUIBecYaBg2lcW}L0h^N+7dHWAlTH^zAYMOXw@4__;;))&EdFXl ziN#-ARN;WvR)Jdu-g^ZeWRtQNT>;FK5E#J$QIpabEq_tQo)8bYFo72ShAz>{!Uhzl ze$>Hk8ND4~xvbfSusx$kE!MYK-(r1>_4|bN$dEPo4<(>hVdp7rY3GeLqYUz66Xw=HYd zYpq#p&Gy)uMf6Fn{^Pp`X1-*5k;;_%OBMEOEnaK!wrKGN8M`M1Y+oW+dmBkWqm*@< z+O}2QjsYm!^H;EJEhhnksug@h_vFVxf&EF{&OA&d2{wPmd>+e2H1 z+PPSNYtvr5O&fG`Yd6Hey6$u=Bvi?!2`oCnW{rJbaW=MK(AvpaYtZ)6poQ9_C?!p= z-LbKM#uz{w#MjLEk5Jiuc4nlpX6$mD`!*}HHOPBmkXsCI zG2FxOepcO$HKBNkuGUj`<8sxhgyBgl^24)##5=)5dFN-PDCQiZl^|Q{94#5=a@=~FMrj2Vs!35L>kozr|Hl~uvQO(wXDqe3y zYbLi6C%83tiduM-vCYsEH1GV@Yx^zP)KSAIojg7KLRQc;k$CzFe?zhL#8XIrAzw-4 zw@(qY&dAJu4PJ>>KF?+@qWP9G#ZAtHI7+qDY*^mu;zh={rU_O&oXRwk0DFaebv^`V zGeGP>xgRiH07UHdd;#1QG!WNx_Cn`|AWRp?Vfum|yf?rDwk(bl4q`Ic0k$J%(+oJg zyOwR-0X9Fkz|wZm4e?v^F-E+9TW;Q61QMxFzBQ!i>b*f#uuxjD^NvWUZRzVTJH-@4 zaXNRgo?6&loM2NsX2{mjIDu2`csS_y#4pCF?LtdSoHpCca$_h0-g&xzA_vbfGFj99 zNSs(05vm<)GrimE544VU;n?@sWV5C4+BuveD;aI=Xjc?E^!>^<7OaVXuHNlv?}-_| z;KA61gAH_n9Pg&4M_M|uEelfQFs}Fw!Bpb%lNhrr&*|lBnuYB@b+q3RT7`?4Tp-F# zj{WbZGSN(a)iTj&?@JWCl$f2$2CFQEaLiP?=*dDV65gqCU~)uMRagi`v}{*pB3G71 zRO(c?m1{uRR^!SWjJ`jA=aK|2()v_%d|Ke^Exd+!R};(b>b55`)}F71pwR zb?5GLuixo%5BdYd7BYi7-?eV9uN`X!WL<;?*EZlFXaY8);LFkO+;=L)@_A|{>;9Jwk?iFKiuflCc9ds>&CL zm}0%P9vFIbvfwZbZJnK}LZC-77X+hpD+6E1dolF+O!+JD5Lnoyz@CAXcgKUkAf#x6 zDdHgJ2Nel=q#+pkaMu9DMF&FyYl+)RP?oVuSs8k^yPWrbVpVylXKcz7-}57)?;lsl zpbWdAb-H$-Coxr(I)kEIy(wOzL;sOt?arW`qvx>(DyVsOZ}JpAi_bZtBJ&1$cLC#% z`!vuG9a5Vw;MG>@SkF`6GkJGAF~E@?{I7B-a8K2$m$5G>5CHz+kp=5S@}p#$QlNm~ zcC{wTcY&&Zgd7F>!PP=6sR4o>tj&QJ4fnLo0}3%Cz6g)XzxP7b5ZrI(Hvzr~dkMoRI1Ybx^3kaH%>@znR7A6wfo zL1&J=3=&bn83m?|xV5LqSz-by5AxXLz*s;`I^bb}jRi0uxgk>oOq+PVg=pv6f9VkL zCYj1ZVgh1^1lctU-=j#*r)2>Hu3ZE|ZDELi0WGE)&8B7U_guT3P@E5jn3?>`NITtTkSj_3@5p{TUX62$6Vzv$5hk9 zg7ugR$`|EPLE}OO+V9x&gKW{(_jEaxLVWecc;EZ9pA7pCc#O5saW?ZCc0m=TgINZURs+H>#n7 z0gc8KFre6s_C*;iQoXS0V6GXPn);JY@QO_f$()%xY6BR~ByHlwiDuYw>FW-Ao7@n% zruGt2%=CB@OnNbmO?F%5{JE5~pPNR16v$%TWvVzKdFb~S1Dl5@*enkE#;G+_07J^A zlA>m>IEB%o!WE~8_U>rS$sg}@1-$S^fyzo3YvROCun8O{`iy6nPnWIPfp})hy$g>9 zG))J&E;0cQsPWJn=6?PXnP9pB5d4W8m*<*6aAKRt0Ix*w4HFX^94sMNt}Tjx4R-fn z1&upo2CXpFea(Y!5PV`!EugzNj3Wvg^a!YUt4=?*o)2;}oB~m))yy(alIk{> zc_ckhf`Q^?9zRkPs(QQ7(=PPXRqbJJ29$e_-Kr(?g7=G+*iTg~Qe;j}QF}dKy}Snd zJj>OVa{w)iO;qPWNXczf$^MWJ`?AtU6qL=+&}i#N7U;s0TqI6^ALZsTxtC~GOXJ!5 zax1umtFJ<+Zke<~3z?T_rl8x5WR6bD=~mHekN2(Q^~$+SjdbQ?Dm5r3V_nxH)hNzR zxz`!3NHG`>k4Ab&^UDeG-%nh~bM}D;se@ZBWuaP|N436;Y`c1K+TxF_+vD6+CYKq9 zbuH}{6e?`U@v6puospTXpz)%a!WwkE%v}XN4|{eK_d%ZoL{=UTrykuFdgxEn3}wt?2@CUi~OO2*+(byM3-_ z$He;@8+XEP{>giDEY9QXXo=UakSMT~|5T7L9oeyvx^Ri8!>#t9*U_$RfB&ZUCC;Hs z-#e)-4jt{>o^vVw9TPKs_ZlyeOW|_mk#(Sf(of|a03(hg-#>17e zyE{Ats`8pA0A*i|j$_%%cODLIcPC2l*;Ix-DnTmGCxoW#00f#O+1IhDhL|);!5kDaH76zJnw@2F~tNroA<=9`64!R>RmJ%M4ArY4xB@^Ku+MZZ6WUC zdAwzWTwTIFKYB;|WaDTPtdIt&kK0Z4&-^i046gV*t5nKvn5@S2KCd=C>=iFMV^kk zJ-r}C-+=1AFs_E`R0q3P%Jo3i>ovu&|| z%VMinHbXB=&}$X8y2AFdc2x=$d~2HLwgJ;)qNK8M8rkkY`)GNp8K+ZQIa6%y;H-2< zWJoB8b!?@#mF*g`J;>UW=m`L&(5Sc@F-jqCT8mu2HIdu3>VcWNrr0|C!1JsWq@K6Y zl+61K=NlxSb1yx}M30T7ais^P#8gy&I~vWplks?ZfM$LDU|=4hgJ~Zb2NO8z9nA() zID})ZqkXwNm#UH}~*Rnuy*az8Nzei=7^VT9#E9sH3RGFZQ?^CAXFwXrfGxC^!&MFG* z30y$~(+$s+dwUPD1*eSjNk{u|75{yST;$v{UM74n`G3E-{6bkN3JEJ^)&xwdJRRd( z8)e8HOKB{ zZ9Y62Wo^M1-{2G(7Icunx;kbzMyO!=dUl$ywfsUq&oU1Rj~SA%(a;QkH`%r1QtQ?Y zDjza6lBs9>?K_ecCi?wwk+^+wnzJ=N zC;BFN^jTtX1u?e^2MeC~UjE9_v>Ji2j38IQnCzW4qE*Z0PqIqx2yy+0=(%m&RV=y_ zry<{)lSEejsDgp^spgnxDd{SfInslz6xWh6T4;m(r&P?fcs8t65R%_S zBCdDzPPe0X^xKYhiJ+++f9-Yp>_SJseJYzk;W1HdZ@g%}>AikS_;@A=4m;Wslki6p zHNtV*8wV${C&K$+&ow+hU8%CMo|AJcGy&a{s4GYTdXw=hKLPZUF)S(p%#&O!R5DTi zMmBFtXJx2n@2kYpV|z#yCVlL&oH<{78+nDvp2zo3A3;y*cY}- zwXLk{hmA;rX{8Hgix;+)sM#GwGd0<-A1RYnmh2EngZhyy``Nibn7?Z?+gU;;)+VIr zfZ~58lAU}bl%&F;WiM=YJ<&6EDF|%5qL9|HZ~T1~1D6D4{$jC#z(FI+;`1COD}08I@;Ns*bcfxuDy1Q2rfjfeAhmq<;7y-Vgp**aqnm_ zK02D{qsd^ z+DHD^R}Fr=_yW59{*iW@;KetT&@@;6$zZyNU7yg>W+T?qIT!FTe&OTAmoF4s_?vf9 zq|TqYfDW`QWMOxy9e0zLK3;s`559vgO0@9Q(YlF-$Nlkmq{rJ1t~J=aNAszp^%8#^ zboHbD(V#o-4Ps10FE_|XNcO3t^%JZNdXvFqbkv)SVyr|jZ;O>d^1BSjlSzLtob=+K zCUSXOtPGz^Hb>7cn@9U2o8$eF&B?yV=2IsCQ*X-AZ5B*Zmv#%Ls?Bd3OjY^F1=D9_ zB?+d_$VziyT2eNf2GjDgxg9XA^c8=SVET-#B*FCASV@CvuLhW=(0sR^X^rN~gXyTN zkGj31zQp9#;3I5Jm!N6C*X#Cr!@*Hc&tOK^mDo9u^D|2E6R89ufz;7p&>IZ($zY%- zr9YM7tV_^3M>9F30pqw2U?UrcM^Y9nH*imSU2((~qciDCt zA$Qky+SS}$+iBl&S8Yd-E?f_6cyj*3M>@y)u&~`&ABaG zB*5CPFYQm@zFl8x*O%J$rI)k5TzYnk&*=B`i~dI7 z#%ew!w-3u0irp?VB78Hj%6NSAo>V_GCbp$nsZ5~1r@6$#sx<&3+o%-_5r*TLBYe%s zWkQ7%KSxYsC4v~ycEuu%F@-Px4o3u~*UI!&rEo{JD{=fOAwwPZzhgoZNmp~;bM3Y^%w^l z*sxOU{5iaQk>0b$L2#GCTA+gd9eZ>to!4URXK>Zez>Lj@reTpE9vP;+V)ta4wN2Jjep9}~)q zvyZLmX_RMTl3Ao|gaTw39`=1~0CQbi2V7ES(x;ARV*^YU0D-@v178wA;KDJm4&FS> zO??hbVwkLnjD{Up)YRG6Qy1xX*jQ6xopk~bF#rOeS*|(q=biMz`y)JKQjVqzW%3j0 z7^x4wG4FpbRHXLlMD_2m?f&EZ_}2{| z9*~>*vH5y2zV@TPK8AmNOEYkrA?0Iao!!f4$S~aSNbmV0lw(c(jBSUtQ<1fy1V5u6 z>4cBt>uYLS=1&y$mmKC9BM(^?woKoK=iO}5$MJQT@jdc!hQd;U-3;NOIvn=pH0^a- zjpTphI+qeuG8}Z}fjZE-LpBpmFp*5Ik&jKaO9`qORy1X#jrs#+)K9UJOm2!5Ejuo~ z;b^34y^)e0nnZF_tn`j0oBgB9=Ab>YIc$$?j@lxdOKELPb;q_%de*JinC6lWYfP(> zZ`znvNBRCvRSt=<(GfWW{l}hqmVVGM`R^yOpnG&-k2(T7}K0J zKP)ocgFL@6?RVvVR~e`UE_V+;Hq_(-YpNyJ4oEG!b&+(&bYHu`9 zhiZRVU{d>?_CQR%!y!lXIU%Rq4><#)E;~%HhX!+#=6MIP7dEdNJtGq&5w_V*qNNbpz*CwPnBzjaK%^KKa3Tev1I``O%ZqEhb?K!ch)Ruo0YO$vz z_LO$CuVPQ>*n3I^hE?n@wP)d8>@SJ^C9%Ksa`u-zJj28f&x_yTg;;oP%P~H2#I#ui z`|Ouq#SzoC9x+XUS7A}xBDKPz3X3W%>a(<{0bzd$Q`&~TS8*ypoC96l65Pjv25*GEQvYP+p1(|} z7?q0gv~^2BgWXbINEn2nS{w%9vvZHHq6j&h(GU_P>xtse8ObO?zo{MAMd>DrXhp3G zRMLiMMb9TNzXgb*5emGfzz|1#99+b>nK`}FH0fBCt} zle(6zVW$AM;p1+bzqK6$-xjdb)U>g<<>Gy}R)XR-Oe00m+am_O-TGvm7@2mAO#a^z#wJ8)hktkjBxCE)hfC1W~&A!1q<3bBp9H&j**2bGlq zsLUED;BqUpUclv7?)n8>eg-2Wf8cUkN2XWmdx{))wLKO1Kg5#%_v-yzC;v6af4qGQ z(_0=np2cHt0`&{jAEJJBSd99=VhbZ5Uxz2#vB8P>Go=sthH8d%Q@}mnLUBB*Rf^gM zpe|lf6^>On*4OD+wNaU4wViw3v&K=OGB=7QX6z6yKb%CavDh=RN{SsKe~;sfSz)A$ zeckF*@)`J@&auaJoMM~vOSZG3wwLHQpV~I70i5z)WGlY}mQ`@nBTP)paM#B?EbEyo zSHI-l|I|tq(Uh}K_mtR87H)rw+s|u9 zwX^B(AKt!g=Ir@S=gYTk%Wl>5XWrWUR;R#m$HH-y_Bl6>qoP?{fA7K6G#CsA)ma~> zE#4648_#4n@RY1`p+$gl0m`2XxCIIyQgBhj)t#&x7=K4DO!bzo`wEbQg&`MPlcr(z{?ewP@~XFjxlmopubITTx z7w6!@b{no5c~Y;et2XHk`BAmo+XE1^Qy^8jmG>tg$^ zekJJ_i{FOS#B%gI9|VM&7NB$NVSqdgNVHGq11}&X+}+z#Vqe>Gl-dms5-o6AK%hNF***07Oo}n~CFC+wehLxELNpJ;s3s zHmnpoe-1BSr1z{bxz33bpVn_CB?-I8%3(yFxhQpe#iH~Zruv*ykis&2cy?oGqjW}} zL5dL2Za$6?oyW;qBKe&jcKc_?z?`r)WVIVcU#`%sN9+quU(GbNCwK${_Od zu3ZCB-W9OII(V1ER_R|6nQ?=FA_f`*1tqOrfdl~#TA{#g00$YVuC|=@2!EeWeN5Rn zDVhYsC8F@}WqN;=i=)q1HCE~Lh~92Jw&R+aaJa(ZzBGrc4z@eocr14Fv{B(>xY(%9 zrhV(WeZr}>N=b!N6;4$+RpC^R|<+s8s(XoWELqKp#T|%hkYL#z+BhX0hg4S^r_?7*Z`9SK;W=}6{&qXQT;n?yZ<;p{&j?vMMRc&gj!J;1oSX1sbxD;#B!kY_k z9(nWLsMwodlBvV#xLJ|na}U{LhAihcFU-DIa=4r7xSVdxX(PuXikRDC6jGV07>56J ze7YvZj2E~^R=}oUmowsc_$&6Ez|&X9x+IuLc!YnSu|1wId{ajjJl7P7C0zSVB;y}f z56DgZ*nGVhU;EKtAH%=Cr5U)*kn%CI&hF(iWEgIEr1$(0%CV+?#OAhmlk%ue`Tc&Tr^KLfj@>Ze#qCO5^3mK~Sg za5Pf2-bhIgO(MA|R(i*h&HmA4bI=~y9JWU`M{SYKrL;Dtx?|fWJ?qwMOmj(xHKtX` zH*HL-^0C#J9+8!-F+CzH^%+x6*{s``^2>i_GsbkMQOFw8BeIe;rblBXZ%mavjA_oA z9~PPJL7v~3_PcVws|?fvm%9fa8)|ZaHB}X*t0+BfpvWc6$Z{oiPK){J=lD@IwKp25 zL$yCFFsXe_Q?#Bu(lj|M9dcJ5Y5iWmW`6p^L3gAL`UADUyItL1O!u;@wTNj|yLx{J zG0hs*V~c6lx*k_d6DD>V-h3#quU%Oi_6Gfo@sHDLwES{`i9ICkym37o?L0I+9PK<7 zJsj<RJRI#jwmcN=gr##m+|1i%H=) z7g)c(+*L+BP3dZBz>x4k0Z3>AM_>5b%}rVKNkq7F25IO?g|pzhVAH8WzJ^VpJ^ zwUtMd%$(^wo@5r<(tYOU1x%H|*@GF=%JgfUo$tfQ_O;H<^rmduQ|~Ne>vCt=BrKKQ z7&rBqRbC;j+pg{)q&3XVYZKBO5x95WJ_MF&LYRi8Lwb)Y< zdrCXnSFxvb>^-Fd!z%Wd+Ou#k_Ls!|lGtB*Ir~c*wtFWkTky>F^;ufffUv)WDQ&~vt2h-PP6a$+NX4muHk}Gs zE;(Z#ys%RVAvE$T=hHs_MW|Ud-Z;+5u^YQM~}+Ri=iS>vcsnHxnDGj<4tuPi>pk08V)?vXx%~%PKhP5hf;Pxa(scmi5e) zODlQzKedv|tz(I@yoi;F=GeqK4xcLIMXU+J&EeH_>jYYDgYLHst)`^7Dq3CPQ&o{* zSok99uY%Smtfxycam9h=pT_z&3l~7p=JGgYM(hGabX&~yUU4YH0A8mJtcONh1=ia_Ve0N z?QHt{hqrH=IeWg-`SNYsvRgI%nYT8-)hTe?v2a|aea?;JsAv|~e|s=B4FSg?#;LytbY~ph*y+r4nwk`wG;ia4m~a`)wVi8EVoErkb5xQ4-#; z75du-Z}h365npOz;^pbv}-Dq-BU5_KACqo6PHf{lYoMCa61wo z=}ttfV_IOCKAKpJwun~uN}|;%-I8c^SD5}vLTTXEn^nOwlPV2v0aBBh4Kx8Qlgpc&c{S_tIYY(ow(UYEg7TINa6bf7G5t$z9*_x+X3%3~an#P<%-Y{9}E`X!Rwm z{>uD`!@EU==RtZq26s>J-_(Xnx{Jh}BC+#Q>0Pj#S~T}Gn5@a_P}}u^uqQ7N<JBY!jK#U0Se-?9;L9z|Gmu}>-XDQg3pgOV#Vu`Y80&A3$YByDXT%7I>-bY%<3 zi*s;cyA4;3JgHaKRh#sN{HWUP?Ewf{Dv+a+lkI;all~Eym~x8bx?G`9mM(v-i|xDm zm84%Rej8E~%hB(A5D;owfX=ap0rD^)(LS9Iynv8!cW+OLeQnE8s@#Rk Date: Mon, 14 Feb 2022 14:00:41 -0500 Subject: [PATCH 173/385] Fix from Magik to remove hanging behavior --- itests/kit/blockminer.go | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/itests/kit/blockminer.go b/itests/kit/blockminer.go index cae3d26e35e..a232d82e026 100644 --- a/itests/kit/blockminer.go +++ b/itests/kit/blockminer.go @@ -3,6 +3,7 @@ package kit import ( "bytes" "context" + "fmt" "sync" "sync/atomic" "testing" @@ -64,11 +65,10 @@ func (p *partitionTracker) done(t *testing.T) bool { return uint64(len(p.partitions)) == p.count(t) } -func (p *partitionTracker) recordIfPost(t *testing.T, bm *BlockMiner, smsg *types.SignedMessage) (ret bool) { +func (p *partitionTracker) recordIfPost(t *testing.T, bm *BlockMiner, msg *types.Message) (ret bool) { defer func() { ret = p.done(t) }() - msg := smsg.Message if !(msg.To == bm.miner.ActorAddr) { return } @@ -95,7 +95,26 @@ func (bm *BlockMiner) forcePoSt(ctx context.Context, ts *types.TipSet, dlinfo *d msgs, err := bm.miner.FullNode.MpoolPending(ctx, types.EmptyTSK) require.NoError(bm.t, err) for _, msg := range msgs { - tracker.recordIfPost(bm.t, bm, msg) + if tracker.recordIfPost(bm.t, bm, &msg.Message) { + fmt.Printf("found post in mempool pending\n") + } + } + + // Account for included but not yet executed messages + for _, bc := range ts.Cids() { + msgs, err := bm.miner.FullNode.ChainGetBlockMessages(ctx, bc) + require.NoError(bm.t, err) + for _, msg := range msgs.BlsMessages { + if tracker.recordIfPost(bm.t, bm, msg) { + fmt.Printf("found post in message of prev tipset\n") + } + + } + for _, msg := range msgs.SecpkMessages { + if tracker.recordIfPost(bm.t, bm, &msg.Message) { + fmt.Printf("found post in message of prev tipset\n") + } + } } // post not yet in mpool, wait for it @@ -111,7 +130,8 @@ func (bm *BlockMiner) forcePoSt(ctx context.Context, ts *types.TipSet, dlinfo *d bm.t.Logf("pool event: %d", evt.Type) if evt.Type == api.MpoolAdd { bm.t.Logf("incoming message %v", evt.Message) - if tracker.recordIfPost(bm.t, bm, evt.Message) { + if tracker.recordIfPost(bm.t, bm, &evt.Message.Message) { + fmt.Printf("found post in mempool evt\n") break POOL } } From df5bd147fadc63060187aa8795644e22402781a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 14 Feb 2022 20:07:13 +0100 Subject: [PATCH 174/385] paychmgr: Review comments Co-authored-by: Hannah Howard Co-authored-by: dirkmc --- api/api_full.go | 2 +- documentation/en/default-lotus-config.toml | 2 +- node/config/types.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index 6fd34ddfbab..d6f657ad01e 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -866,7 +866,7 @@ type ChannelAvailableFunds struct { PendingAmt types.BigInt // AvailableAmt is part of ConfirmedAmt that is available for use (pre-allocated) AvailableAmt types.BigInt - // PendingAvailableAmt is the amount of available funds that are pending confirmation on-chain +// PendingAvailableAmt is the amount of funds that are pending confirmation on-chain that will become available once confirmed PendingAvailableAmt types.BigInt // PendingWaitSentinel can be used with PaychGetWaitReady to wait for // confirmation of pending funds diff --git a/documentation/en/default-lotus-config.toml b/documentation/en/default-lotus-config.toml index 7ef8f6309a1..ad917814b0d 100644 --- a/documentation/en/default-lotus-config.toml +++ b/documentation/en/default-lotus-config.toml @@ -121,7 +121,7 @@ # env var: LOTUS_CLIENT_SIMULTANEOUSTRANSFERSFORRETRIEVAL #SimultaneousTransfersForRetrieval = 20 - # Require that retrievals perform no on-chain retrievals. Paid retrievals + # Require that retrievals perform no on-chain operations. Paid retrievals # without existing payment channels with available funds will fail instead # of automatically performing on-chain operations. # diff --git a/node/config/types.go b/node/config/types.go index 762b8b6eb27..b073735d32e 100644 --- a/node/config/types.go +++ b/node/config/types.go @@ -388,7 +388,7 @@ type Client struct { // and storage providers for retrieval deals SimultaneousTransfersForRetrieval uint64 - // Require that retrievals perform no on-chain retrievals. Paid retrievals + // Require that retrievals perform no on-chain operations. Paid retrievals // without existing payment channels with available funds will fail instead // of automatically performing on-chain operations. OffChainRetrieval bool From 36a193484568ecbbf59763239c9943683f1bfff4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 14 Feb 2022 20:16:30 +0100 Subject: [PATCH 175/385] paychmgr: Fix tests after api changes --- itests/paych_api_test.go | 1 - node/impl/paych/paych.go | 10 ++++++++-- paychmgr/manager.go | 9 ++------- paychmgr/paychget_test.go | 9 ++++----- paychmgr/simple.go | 6 +++--- 5 files changed, 17 insertions(+), 18 deletions(-) diff --git a/itests/paych_api_test.go b/itests/paych_api_test.go index 074551a8376..1a39fd606a7 100644 --- a/itests/paych_api_test.go +++ b/itests/paych_api_test.go @@ -66,7 +66,6 @@ func TestPaymentChannelsAPI(t *testing.T) { channelAmt := int64(7000) channelInfo, err := paymentCreator.PaychGet(ctx, createrAddr, receiverAddr, abi.NewTokenAmount(channelAmt), api.PaychGetOpts{ - Reserve: true, OffChain: false, }) require.NoError(t, err) diff --git a/node/impl/paych/paych.go b/node/impl/paych/paych.go index 28e50625e93..d338c6032fd 100644 --- a/node/impl/paych/paych.go +++ b/node/impl/paych/paych.go @@ -23,7 +23,10 @@ type PaychAPI struct { } func (a *PaychAPI) PaychGet(ctx context.Context, from, to address.Address, amt types.BigInt, opts api.PaychGetOpts) (*api.ChannelInfo, error) { - ch, mcid, err := a.PaychMgr.GetPaych(ctx, from, to, amt, true, opts) + ch, mcid, err := a.PaychMgr.GetPaych(ctx, from, to, amt, paychmgr.GetOpts{ + Reserve: true, + OffChain: opts.OffChain, + }) if err != nil { return nil, err } @@ -35,7 +38,10 @@ func (a *PaychAPI) PaychGet(ctx context.Context, from, to address.Address, amt t } func (a *PaychAPI) PaychFund(ctx context.Context, from, to address.Address, amt types.BigInt) (*api.ChannelInfo, error) { - ch, mcid, err := a.PaychMgr.GetPaych(ctx, from, to, amt, false, api.PaychGetOpts{OffChain: false}) + ch, mcid, err := a.PaychMgr.GetPaych(ctx, from, to, amt, paychmgr.GetOpts{ + Reserve: false, + OffChain: false, + }) if err != nil { return nil, err } diff --git a/paychmgr/manager.go b/paychmgr/manager.go index 46466266d7b..081ef4c5d19 100644 --- a/paychmgr/manager.go +++ b/paychmgr/manager.go @@ -101,17 +101,12 @@ func (pm *Manager) Stop() error { return nil } -type getOpts struct { +type GetOpts struct { Reserve bool OffChain bool } -func (pm *Manager) GetPaych(ctx context.Context, from, to address.Address, amt types.BigInt, reserve bool, o api.PaychGetOpts) (address.Address, cid.Cid, error) { - opts := getOpts{ - Reserve: reserve, - OffChain: o.OffChain, - } - +func (pm *Manager) GetPaych(ctx context.Context, from, to address.Address, amt types.BigInt, opts GetOpts) (address.Address, cid.Cid, error) { if !opts.Reserve && opts.OffChain { return address.Undef, cid.Undef, xerrors.Errorf("can't fund payment channels without on-chain operations") } diff --git a/paychmgr/paychget_test.go b/paychmgr/paychget_test.go index a508fdfc96a..0688301e883 100644 --- a/paychmgr/paychget_test.go +++ b/paychmgr/paychget_test.go @@ -19,26 +19,25 @@ import ( init2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/init" tutils "github.com/filecoin-project/specs-actors/v2/support/testing" - "github.com/filecoin-project/lotus/api" lotusinit "github.com/filecoin-project/lotus/chain/actors/builtin/init" "github.com/filecoin-project/lotus/chain/actors/builtin/paych" paychmock "github.com/filecoin-project/lotus/chain/actors/builtin/paych/mock" "github.com/filecoin-project/lotus/chain/types" ) -var onChainReserve = api.PaychGetOpts{ +var onChainReserve = GetOpts{ Reserve: true, OffChain: false, } -var onChainNoReserve = api.PaychGetOpts{ +var onChainNoReserve = GetOpts{ Reserve: false, OffChain: false, } -var offChainReserve = api.PaychGetOpts{ +var offChainReserve = GetOpts{ Reserve: true, OffChain: true, } -var offChainNoReserve = api.PaychGetOpts{ +var offChainNoReserve = GetOpts{ Reserve: false, OffChain: true, } diff --git a/paychmgr/simple.go b/paychmgr/simple.go index cc6a9286180..0eb1316af57 100644 --- a/paychmgr/simple.go +++ b/paychmgr/simple.go @@ -33,14 +33,14 @@ type fundsReq struct { ctx context.Context promise chan *paychFundsRes amt types.BigInt - opts getOpts + opts GetOpts lk sync.Mutex // merge parent, if this req is part of a merge merge *mergedFundsReq } -func newFundsReq(ctx context.Context, amt types.BigInt, opts getOpts) *fundsReq { +func newFundsReq(ctx context.Context, amt types.BigInt, opts GetOpts) *fundsReq { promise := make(chan *paychFundsRes, 1) return &fundsReq{ ctx: ctx, @@ -251,7 +251,7 @@ func (m *mergedFundsReq) failOffChainNoChannel(from, to address.Address) (*paych // address and the CID of the new add funds message. // If an operation returns an error, subsequent waiting operations will still // be attempted. -func (ca *channelAccessor) getPaych(ctx context.Context, amt types.BigInt, opts getOpts) (address.Address, cid.Cid, error) { +func (ca *channelAccessor) getPaych(ctx context.Context, amt types.BigInt, opts GetOpts) (address.Address, cid.Cid, error) { // Add the request to add funds to a queue and wait for the result freq := newFundsReq(ctx, amt, opts) ca.enqueue(ctx, freq) From f9485eb9c253e3faa9304d7ec963233a14e66867 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 14 Feb 2022 20:42:45 +0100 Subject: [PATCH 176/385] Update paychmgr/store.go Co-authored-by: dirkmc --- paychmgr/store.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paychmgr/store.go b/paychmgr/store.go index 7d6ee32be67..f3c67e5650b 100644 --- a/paychmgr/store.go +++ b/paychmgr/store.go @@ -73,7 +73,7 @@ type ChannelInfo struct { // has locally been added to the channel. It should reflect the channel's // Balance on chain as long as all operations occur on the same datastore. Amount types.BigInt - // AvailableAmount indicates how much afil is non-reverved + // AvailableAmount indicates how much afil is non-reserved AvailableAmount types.BigInt // PendingAvailableAmount is available amount that we're awaiting confirmation of PendingAvailableAmount types.BigInt From eebe78419123088d05a2b9f0733647e12860c2a1 Mon Sep 17 00:00:00 2001 From: Aayush Date: Mon, 14 Feb 2022 13:28:49 -0500 Subject: [PATCH 177/385] fix: sealer: allow enable/disabling ReplicaUpdate tasks --- cmd/lotus-miner/init.go | 15 +++++++++------ cmd/lotus-seal-worker/main.go | 8 ++++++++ cmd/lotus-seal-worker/tasks.go | 13 ++++++++----- documentation/en/cli-lotus-worker.md | 5 +++-- documentation/en/default-lotus-miner-config.toml | 3 +++ extern/sector-storage/manager.go | 4 ++++ node/config/def.go | 1 + 7 files changed, 36 insertions(+), 13 deletions(-) diff --git a/cmd/lotus-miner/init.go b/cmd/lotus-miner/init.go index ae742c66301..59ea75b10c3 100644 --- a/cmd/lotus-miner/init.go +++ b/cmd/lotus-miner/init.go @@ -467,12 +467,15 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api v1api.FullNode stor := stores.NewRemote(lstor, si, http.Header(sa), 10, &stores.DefaultPartialFileHandler{}) smgr, err := sectorstorage.New(ctx, lstor, stor, lr, si, sectorstorage.SealerConfig{ - ParallelFetchLimit: 10, - AllowAddPiece: true, - AllowPreCommit1: true, - AllowPreCommit2: true, - AllowCommit: true, - AllowUnseal: true, + ParallelFetchLimit: 10, + AllowAddPiece: true, + AllowPreCommit1: true, + AllowPreCommit2: true, + AllowCommit: true, + AllowUnseal: true, + AllowReplicaUpdate: true, + AllowProveReplicaUpdate2: true, + AllowRegenSectorKey: true, }, wsts, smsts) if err != nil { return err diff --git a/cmd/lotus-seal-worker/main.go b/cmd/lotus-seal-worker/main.go index 84ff1ccddc5..2116dd228d3 100644 --- a/cmd/lotus-seal-worker/main.go +++ b/cmd/lotus-seal-worker/main.go @@ -173,6 +173,11 @@ var runCmd = &cli.Command{ Usage: "enable prove replica update 2", Value: true, }, + &cli.BoolFlag{ + Name: "regen-sector-key", + Usage: "enable regen sector key", + Value: true, + }, &cli.IntFlag{ Name: "parallel-fetch-limit", Usage: "maximum fetch operations to run in parallel", @@ -284,6 +289,9 @@ var runCmd = &cli.Command{ if cctx.Bool("prove-replica-update2") { taskTypes = append(taskTypes, sealtasks.TTProveReplicaUpdate2) } + if cctx.Bool("regen-sector-key") { + taskTypes = append(taskTypes, sealtasks.TTRegenSectorKey) + } if len(taskTypes) == 0 { return xerrors.Errorf("no task types specified") diff --git a/cmd/lotus-seal-worker/tasks.go b/cmd/lotus-seal-worker/tasks.go index 02e5d6cfd8e..52133d09d16 100644 --- a/cmd/lotus-seal-worker/tasks.go +++ b/cmd/lotus-seal-worker/tasks.go @@ -22,11 +22,14 @@ var tasksCmd = &cli.Command{ } var allowSetting = map[sealtasks.TaskType]struct{}{ - sealtasks.TTAddPiece: {}, - sealtasks.TTPreCommit1: {}, - sealtasks.TTPreCommit2: {}, - sealtasks.TTCommit2: {}, - sealtasks.TTUnseal: {}, + sealtasks.TTAddPiece: {}, + sealtasks.TTPreCommit1: {}, + sealtasks.TTPreCommit2: {}, + sealtasks.TTCommit2: {}, + sealtasks.TTUnseal: {}, + sealtasks.TTReplicaUpdate: {}, + sealtasks.TTProveReplicaUpdate2: {}, + sealtasks.TTRegenSectorKey: {}, } var settableStr = func() string { diff --git a/documentation/en/cli-lotus-worker.md b/documentation/en/cli-lotus-worker.md index c74d8e8dad1..e610cff6206 100644 --- a/documentation/en/cli-lotus-worker.md +++ b/documentation/en/cli-lotus-worker.md @@ -46,6 +46,7 @@ OPTIONS: --commit enable commit (32G sectors: all cores or GPUs, 128GiB Memory + 64GiB swap) (default: true) --replica-update enable replica update (default: true) --prove-replica-update2 enable prove replica update 2 (default: true) + --regen-sector-key enable regen sector key (default: true) --parallel-fetch-limit value maximum fetch operations to run in parallel (default: 5) --timeout value used when 'listen' is unspecified. must be a valid duration recognized by golang's time.ParseDuration function (default: "30m") --help, -h show help (default: false) @@ -170,7 +171,7 @@ NAME: lotus-worker tasks enable - Enable a task type USAGE: - lotus-worker tasks enable [command options] [UNS|C2|PC2|PC1|AP] + lotus-worker tasks enable [command options] [UNS|C2|PC2|PC1|PR2|RU|AP|GSK] OPTIONS: --help, -h show help (default: false) @@ -183,7 +184,7 @@ NAME: lotus-worker tasks disable - Disable a task type USAGE: - lotus-worker tasks disable [command options] [UNS|C2|PC2|PC1|AP] + lotus-worker tasks disable [command options] [UNS|C2|PC2|PC1|PR2|RU|AP|GSK] OPTIONS: --help, -h show help (default: false) diff --git a/documentation/en/default-lotus-miner-config.toml b/documentation/en/default-lotus-miner-config.toml index d8c774c7589..818f0b73c8f 100644 --- a/documentation/en/default-lotus-miner-config.toml +++ b/documentation/en/default-lotus-miner-config.toml @@ -438,6 +438,9 @@ # env var: LOTUS_STORAGE_ALLOWPROVEREPLICAUPDATE2 #AllowProveReplicaUpdate2 = true + # env var: LOTUS_STORAGE_ALLOWREGENSECTORKEY + #AllowRegenSectorKey = true + # env var: LOTUS_STORAGE_RESOURCEFILTERING #ResourceFiltering = "hardware" diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index fcbfa2e69f7..897ba4f0611 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -105,6 +105,7 @@ type SealerConfig struct { AllowUnseal bool AllowReplicaUpdate bool AllowProveReplicaUpdate2 bool + AllowRegenSectorKey bool // ResourceFiltering instructs the system which resource filtering strategy // to use when evaluating tasks against this worker. An empty value defaults @@ -169,6 +170,9 @@ func New(ctx context.Context, lstor *stores.Local, stor *stores.Remote, ls store if sc.AllowProveReplicaUpdate2 { localTasks = append(localTasks, sealtasks.TTProveReplicaUpdate2) } + if sc.AllowRegenSectorKey { + localTasks = append(localTasks, sealtasks.TTRegenSectorKey) + } wcfg := WorkerConfig{ IgnoreResourceFiltering: sc.ResourceFiltering == ResourceFilteringDisabled, diff --git a/node/config/def.go b/node/config/def.go index 1573508665c..aceeaadf5df 100644 --- a/node/config/def.go +++ b/node/config/def.go @@ -139,6 +139,7 @@ func DefaultStorageMiner() *StorageMiner { AllowUnseal: true, AllowReplicaUpdate: true, AllowProveReplicaUpdate2: true, + AllowRegenSectorKey: true, // Default to 10 - tcp should still be able to figure this out, and // it's the ratio between 10gbit / 1gbit From da5ae1efe178717f1c97401f67e3fd298cb74f03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 14 Feb 2022 21:11:31 +0100 Subject: [PATCH 178/385] paychmgr: erlier checks in completeAmount --- paychmgr/simple.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/paychmgr/simple.go b/paychmgr/simple.go index 0eb1316af57..5a23c7f2c05 100644 --- a/paychmgr/simple.go +++ b/paychmgr/simple.go @@ -179,6 +179,11 @@ func (m *mergedFundsReq) completeAmount(avail types.BigInt, channelInfo *Channel break } + // don't try to fill inactive requests + if !r.isActive() { + continue + } + if r.amt.GreaterThan(types.BigSub(avail, used)) { // requests are sorted by amount ascending, so if we hit this, there aren't any more requests we can fill @@ -198,11 +203,6 @@ func (m *mergedFundsReq) completeAmount(avail types.BigInt, channelInfo *Channel break } - // don't try to fill inactive requests - if !r.isActive() { - continue - } - used = types.BigAdd(used, r.amt) r.onComplete(&paychFundsRes{channel: *channelInfo.Channel}) next = i + 1 From 60b9acc09d7d7fea061ce89ba1c6ae3fe5ae1ccf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 14 Feb 2022 21:16:41 +0100 Subject: [PATCH 179/385] gen --- api/api_full.go | 2 +- node/config/doc_gen.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index d6f657ad01e..b621dd9fbb9 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -866,7 +866,7 @@ type ChannelAvailableFunds struct { PendingAmt types.BigInt // AvailableAmt is part of ConfirmedAmt that is available for use (pre-allocated) AvailableAmt types.BigInt -// PendingAvailableAmt is the amount of funds that are pending confirmation on-chain that will become available once confirmed + // PendingAvailableAmt is the amount of funds that are pending confirmation on-chain that will become available once confirmed PendingAvailableAmt types.BigInt // PendingWaitSentinel can be used with PaychGetWaitReady to wait for // confirmation of pending funds diff --git a/node/config/doc_gen.go b/node/config/doc_gen.go index d160643c271..2a7f63180ce 100644 --- a/node/config/doc_gen.go +++ b/node/config/doc_gen.go @@ -109,7 +109,7 @@ and storage providers for retrieval deals`, Name: "OffChainRetrieval", Type: "bool", - Comment: `Require that retrievals perform no on-chain retrievals. Paid retrievals + Comment: `Require that retrievals perform no on-chain operations. Paid retrievals without existing payment channels with available funds will fail instead of automatically performing on-chain operations.`, }, From f15a1edbf274fa90986cfffc2305a6e9c6bfb3cc Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Tue, 15 Feb 2022 11:32:02 +0000 Subject: [PATCH 180/385] Protect index provider peer ID before connecting to full node Add the peer ID of index provider host to the list of protected peers before connecting to full node. Otherwise, it is possible for the connection to be reset by full node before we reach the line that adds the ID to list of protected peers via JsonRPC API. Relates to: - https://github.com/filecoin-project/index-provider/issues/177 --- markets/idxprov/mesh.go | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/markets/idxprov/mesh.go b/markets/idxprov/mesh.go index 5b580c7fda4..097513d42ec 100644 --- a/markets/idxprov/mesh.go +++ b/markets/idxprov/mesh.go @@ -23,22 +23,28 @@ type Libp2pMeshCreator struct { } func (mc Libp2pMeshCreator) Connect(ctx context.Context) error { + + // Add the index provider's host ID to list of protected peers first, before any attempt to + // connect to full node. + idxProvID := mc.idxProvHost.ID() + if err := mc.fullnodeApi.NetProtectAdd(ctx, []peer.ID{idxProvID}); err != nil { + return fmt.Errorf("failed to call NetProtectAdd on the full node, err: %w", err) + } + faddrs, err := mc.fullnodeApi.NetAddrsListen(ctx) if err != nil { return fmt.Errorf("failed to fetch full node listen addrs, err: %w", err) } - // otherwise, connect to the full node, ask it to protect the connection and protect the connection on our end too + // Connect to the full node, ask it to protect the connection and protect the connection on + // markets end too. if err := mc.idxProvHost.Connect(ctx, faddrs); err != nil { return fmt.Errorf("failed to connect index provider host with the full node: %w", err) } mc.idxProvHost.ConnManager().Protect(faddrs.ID, "index-provider-gossipsub") - if err := mc.fullnodeApi.NetProtectAdd(ctx, []peer.ID{mc.idxProvHost.ID()}); err != nil { - return fmt.Errorf("failed to call NetProtectAdd on the full node, err: %w", err) - } log.Debugw("successfully connected to full node and asked it protect indexer provider peer conn", "fullNodeInfo", faddrs.String(), - "idxProviderPeerId", mc.idxProvHost.ID()) + "idxProviderPeerId", idxProvID) return nil } From 031bfaf1204e95bf1737ee6b79f561d37c530812 Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Tue, 15 Feb 2022 12:09:28 +0000 Subject: [PATCH 181/385] Update to the head of go-fil-markets#673 Update to the head of the PR that introduces indexing integration in `go-fil-markets` so that failure to connect to full node is logged only instead of crashing markets process. Relates to: - https://github.com/filecoin-project/go-fil-markets/pull/673 - https://github.com/filecoin-project/index-provider/issues/177 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 66ed2a45aa2..0d57b3b50a5 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,7 @@ require ( github.com/filecoin-project/go-data-transfer v1.14.0 github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 - github.com/filecoin-project/go-fil-markets v1.19.1-0.20220210121001-44fb837759c1 + github.com/filecoin-project/go-fil-markets v1.19.1-0.20220215120226-a0db7a73d4fd github.com/filecoin-project/go-indexer-core v0.2.8 github.com/filecoin-project/go-jsonrpc v0.1.5 github.com/filecoin-project/go-legs v0.3.0 diff --git a/go.sum b/go.sum index e1edde31d99..613d3ab5152 100644 --- a/go.sum +++ b/go.sum @@ -336,8 +336,8 @@ github.com/filecoin-project/go-fil-commcid v0.1.0 h1:3R4ds1A9r6cr8mvZBfMYxTS88Oq github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7LXep5bFEVOVmQWHJvl2mgsGo= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8= -github.com/filecoin-project/go-fil-markets v1.19.1-0.20220210121001-44fb837759c1 h1:gGfvTCfHDCqEfVhGZSIALKtzF3D4p5Lhm4wH4KGv+60= -github.com/filecoin-project/go-fil-markets v1.19.1-0.20220210121001-44fb837759c1/go.mod h1:Q7EWzO9s4sg2KYBUJduTYdtVhVhusDuH2W0keyyub3I= +github.com/filecoin-project/go-fil-markets v1.19.1-0.20220215120226-a0db7a73d4fd h1:RO4M6fD9L6+OGqgk6OnMrFJcN5JkcMo3MX40vqxUfmQ= +github.com/filecoin-project/go-fil-markets v1.19.1-0.20220215120226-a0db7a73d4fd/go.mod h1:Q7EWzO9s4sg2KYBUJduTYdtVhVhusDuH2W0keyyub3I= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= From 0b7addc031e78f6e0e9a9325e268eafab43ce54f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 15 Feb 2022 14:19:42 +0100 Subject: [PATCH 182/385] lotus-miner sectors list --initial-pledge --- cmd/lotus-miner/sectors.go | 16 +++++++++++++--- documentation/en/cli-lotus-miner.md | 17 +++++++++-------- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/cmd/lotus-miner/sectors.go b/cmd/lotus-miner/sectors.go index c779f5a8ba1..d8c3e9c7cc2 100644 --- a/cmd/lotus-miner/sectors.go +++ b/cmd/lotus-miner/sectors.go @@ -161,7 +161,7 @@ var sectorsStatusCmd = &cli.Command{ fmt.Printf("Expiration:\t\t%v\n", status.Expiration) fmt.Printf("DealWeight:\t\t%v\n", status.DealWeight) fmt.Printf("VerifiedDealWeight:\t\t%v\n", status.VerifiedDealWeight) - fmt.Printf("InitialPledge:\t\t%v\n", status.InitialPledge) + fmt.Printf("InitialPledge:\t\t%v\n", types.FIL(status.InitialPledge)) fmt.Printf("\nExpiration Info\n") fmt.Printf("OnTime:\t\t%v\n", status.OnTime) fmt.Printf("Early:\t\t%v\n", status.Early) @@ -294,8 +294,14 @@ var sectorsListCmd = &cli.Command{ Aliases: []string{"e"}, }, &cli.BoolFlag{ - Name: "seal-time", - Usage: "display how long it took for the sector to be sealed", + Name: "initial-pledge", + Usage: "display initial pledge", + Aliases: []string{"p"}, + }, + &cli.BoolFlag{ + Name: "seal-time", + Usage: "display how long it took for the sector to be sealed", + Aliases: []string{"t"}, }, &cli.StringFlag{ Name: "states", @@ -405,6 +411,7 @@ var sectorsListCmd = &cli.Command{ tablewriter.Col("Deals"), tablewriter.Col("DealWeight"), tablewriter.Col("VerifiedPower"), + tablewriter.Col("Pledge"), tablewriter.NewLineCol("Error"), tablewriter.NewLineCol("RecoveryTimeout")) @@ -483,6 +490,9 @@ var sectorsListCmd = &cli.Command{ m["RecoveryTimeout"] = color.YellowString(lcli.EpochTime(head.Height(), st.Early)) } } + if inSSet && cctx.Bool("initial-pledge") { + m["Pledge"] = types.FIL(st.InitialPledge).Short() + } } if !fast && deals > 0 { diff --git a/documentation/en/cli-lotus-miner.md b/documentation/en/cli-lotus-miner.md index 1fd3e91a305..848a9c8649a 100644 --- a/documentation/en/cli-lotus-miner.md +++ b/documentation/en/cli-lotus-miner.md @@ -1621,14 +1621,15 @@ USAGE: lotus-miner sectors list [command options] [arguments...] OPTIONS: - --show-removed, -r show removed sectors (default: false) - --color, -c use color in display output (default: depends on output being a TTY) - --fast, -f don't show on-chain info for better performance (default: false) - --events, -e display number of events the sector has received (default: false) - --seal-time display how long it took for the sector to be sealed (default: false) - --states value filter sectors by a comma-separated list of states - --unproven, -u only show sectors which aren't in the 'Proving' state (default: false) - --help, -h show help (default: false) + --show-removed, -r show removed sectors (default: false) + --color, -c use color in display output (default: depends on output being a TTY) + --fast, -f don't show on-chain info for better performance (default: false) + --events, -e display number of events the sector has received (default: false) + --initial-pledge, -p display initial pledge (default: false) + --seal-time, -t display how long it took for the sector to be sealed (default: false) + --states value filter sectors by a comma-separated list of states + --unproven, -u only show sectors which aren't in the 'Proving' state (default: false) + --help, -h show help (default: false) ``` From 9c00af1b860f8b4d5fd2213b2e2ac6c01744ae22 Mon Sep 17 00:00:00 2001 From: vyzo Date: Tue, 15 Feb 2022 16:08:31 +0200 Subject: [PATCH 183/385] don't track peer ids in rcmgr metrics --- node/modules/lp2p/rcmgr.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/node/modules/lp2p/rcmgr.go b/node/modules/lp2p/rcmgr.go index 71ed4e75445..0bc4dd6b215 100644 --- a/node/modules/lp2p/rcmgr.go +++ b/node/modules/lp2p/rcmgr.go @@ -118,7 +118,6 @@ func (r rcmgrMetrics) AllowStream(p peer.ID, dir network.Direction) { } else { ctx, _ = tag.New(ctx, tag.Upsert(metrics.Direction, "outbound")) } - ctx, _ = tag.New(ctx, tag.Upsert(metrics.PeerID, p.Pretty())) stats.Record(ctx, metrics.RcmgrAllowStream.M(1)) } @@ -129,19 +128,16 @@ func (r rcmgrMetrics) BlockStream(p peer.ID, dir network.Direction) { } else { ctx, _ = tag.New(ctx, tag.Upsert(metrics.Direction, "outbound")) } - ctx, _ = tag.New(ctx, tag.Upsert(metrics.PeerID, p.Pretty())) stats.Record(ctx, metrics.RcmgrBlockStream.M(1)) } func (r rcmgrMetrics) AllowPeer(p peer.ID) { ctx := context.Background() - ctx, _ = tag.New(ctx, tag.Upsert(metrics.PeerID, p.Pretty())) stats.Record(ctx, metrics.RcmgrAllowPeer.M(1)) } func (r rcmgrMetrics) BlockPeer(p peer.ID) { ctx := context.Background() - ctx, _ = tag.New(ctx, tag.Upsert(metrics.PeerID, p.Pretty())) stats.Record(ctx, metrics.RcmgrBlockPeer.M(1)) } @@ -160,7 +156,6 @@ func (r rcmgrMetrics) BlockProtocol(proto protocol.ID) { func (r rcmgrMetrics) BlockProtocolPeer(proto protocol.ID, p peer.ID) { ctx := context.Background() ctx, _ = tag.New(ctx, tag.Upsert(metrics.ProtocolID, string(proto))) - ctx, _ = tag.New(ctx, tag.Upsert(metrics.PeerID, p.Pretty())) stats.Record(ctx, metrics.RcmgrBlockProtoPeer.M(1)) } @@ -179,7 +174,6 @@ func (r rcmgrMetrics) BlockService(svc string) { func (r rcmgrMetrics) BlockServicePeer(svc string, p peer.ID) { ctx := context.Background() ctx, _ = tag.New(ctx, tag.Upsert(metrics.ServiceID, svc)) - ctx, _ = tag.New(ctx, tag.Upsert(metrics.PeerID, p.Pretty())) stats.Record(ctx, metrics.RcmgrBlockSvcPeer.M(1)) } From e1a36058b44089ce1da97f3a85eaf07491057cf8 Mon Sep 17 00:00:00 2001 From: hannahhoward Date: Tue, 15 Feb 2022 21:52:06 -0800 Subject: [PATCH 184/385] feat(markets): update markets to simplify client adapter --- go.mod | 2 +- go.sum | 4 ++-- markets/retrievaladapter/client.go | 33 ------------------------------ 3 files changed, 3 insertions(+), 36 deletions(-) diff --git a/go.mod b/go.mod index f22400ded5a..6b6191de617 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,7 @@ require ( github.com/filecoin-project/go-data-transfer v1.14.0 github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 - github.com/filecoin-project/go-fil-markets v1.19.0 + github.com/filecoin-project/go-fil-markets v1.19.1 github.com/filecoin-project/go-jsonrpc v0.1.5 github.com/filecoin-project/go-padreader v0.0.1 github.com/filecoin-project/go-paramfetch v0.0.4 diff --git a/go.sum b/go.sum index 6b725b5df74..3df9f4eb069 100644 --- a/go.sum +++ b/go.sum @@ -327,8 +327,8 @@ github.com/filecoin-project/go-fil-commcid v0.1.0 h1:3R4ds1A9r6cr8mvZBfMYxTS88Oq github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7LXep5bFEVOVmQWHJvl2mgsGo= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8= -github.com/filecoin-project/go-fil-markets v1.19.0 h1:kap2q2wTM6tfkVO5gMA5DD9GUeTvkDhMfhjCtEwMDM8= -github.com/filecoin-project/go-fil-markets v1.19.0/go.mod h1:qsb3apmo4RSJYCEq40QxVdU7UZospN6nFJLOBHuaIbc= +github.com/filecoin-project/go-fil-markets v1.19.1 h1:o5sziAp8zCsvIg3KYMgIpwm8gyOl4MDzEKEf0Qq5L3U= +github.com/filecoin-project/go-fil-markets v1.19.1/go.mod h1:qsb3apmo4RSJYCEq40QxVdU7UZospN6nFJLOBHuaIbc= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= diff --git a/markets/retrievaladapter/client.go b/markets/retrievaladapter/client.go index b5535bcfc43..74f02570b9e 100644 --- a/markets/retrievaladapter/client.go +++ b/markets/retrievaladapter/client.go @@ -9,8 +9,6 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" "github.com/multiformats/go-multiaddr" - mh "github.com/multiformats/go-multihash" - "golang.org/x/xerrors" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/actors/builtin/paych" @@ -19,27 +17,6 @@ import ( payapi "github.com/filecoin-project/lotus/node/impl/paych" ) -func mkPaychReusedCid(addr address.Address) cid.Cid { - c, err := cid.V1Builder{Codec: cid.Raw, MhType: mh.IDENTITY}.Sum(addr.Bytes()) - if err != nil { - panic(err) - } - return c -} - -func extractPaychReusedCid(c cid.Cid) (address.Address, error) { - if c.Prefix().Codec != cid.Raw { - return address.Undef, nil - } - - h, err := mh.Decode(c.Hash()) - if err != nil { - return address.Address{}, err - } - - return address.NewFromBytes(h.Digest) -} - type retrievalClientNode struct { forceOffChain bool @@ -72,9 +49,6 @@ func (rcn *retrievalClientNode) GetOrCreatePaymentChannel(ctx context.Context, c log.Errorw("paych get failed", "error", err) return address.Undef, cid.Undef, err } - if ci.WaitSentinel == cid.Undef { - return ci.Channel, mkPaychReusedCid(ci.Channel), nil - } return ci.Channel, ci.WaitSentinel, nil } @@ -112,13 +86,6 @@ func (rcn *retrievalClientNode) GetChainHead(ctx context.Context) (shared.TipSet } func (rcn *retrievalClientNode) WaitForPaymentChannelReady(ctx context.Context, messageCID cid.Cid) (address.Address, error) { - maybeAddr, err := extractPaychReusedCid(messageCID) - if err != nil { - return address.Address{}, xerrors.Errorf("extract paych reused CID: %w", err) - } - if maybeAddr != address.Undef { - return maybeAddr, nil - } return rcn.payAPI.PaychGetWaitReady(ctx, messageCID) } From f677995603287362a38b0009e9ae383e63f7f61a Mon Sep 17 00:00:00 2001 From: Kevin Li Date: Wed, 16 Feb 2022 15:30:07 +0800 Subject: [PATCH 185/385] feat: add MsigGetVestingSchedule to gateway api expose MsigGetVestingSchedule method to gateway api --- api/api_gateway.go | 3 ++- api/proxy_gen.go | 13 +++++++++++++ build/openrpc/full.json.gz | Bin 26596 -> 26596 bytes build/openrpc/miner.json.gz | Bin 12903 -> 12906 bytes build/openrpc/worker.json.gz | Bin 3960 -> 3959 bytes gateway/node.go | 8 ++++++++ 6 files changed, 23 insertions(+), 1 deletion(-) diff --git a/api/api_gateway.go b/api/api_gateway.go index fbe2e0cd66e..be4b3b83cb4 100644 --- a/api/api_gateway.go +++ b/api/api_gateway.go @@ -45,8 +45,9 @@ type Gateway interface { 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) + MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error) + MsigGetVestingSchedule(ctx context.Context, addr address.Address, tsk types.TipSetKey) (MsigVesting, 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) diff --git a/api/proxy_gen.go b/api/proxy_gen.go index 15866e3e50b..73aa2c774e5 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -516,6 +516,8 @@ type GatewayStruct struct { MsigGetVested func(p0 context.Context, p1 address.Address, p2 types.TipSetKey, p3 types.TipSetKey) (types.BigInt, error) `` + MsigGetVestingSchedule func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MsigVesting, error) `` + StateAccountKey func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `` StateDealProviderCollateralBounds func(p0 context.Context, p1 abi.PaddedPieceSize, p2 bool, p3 types.TipSetKey) (DealCollateralBounds, error) `` @@ -3285,6 +3287,17 @@ func (s *GatewayStub) MsigGetVested(p0 context.Context, p1 address.Address, p2 t return *new(types.BigInt), ErrNotSupported } +func (s *GatewayStruct) MsigGetVestingSchedule(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MsigVesting, error) { + if s.Internal.MsigGetVestingSchedule == nil { + return *new(MsigVesting), ErrNotSupported + } + return s.Internal.MsigGetVestingSchedule(p0, p1, p2) +} + +func (s *GatewayStub) MsigGetVestingSchedule(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MsigVesting, error) { + return *new(MsigVesting), ErrNotSupported +} + func (s *GatewayStruct) StateAccountKey(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) { if s.Internal.StateAccountKey == nil { return *new(address.Address), ErrNotSupported diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 5c79a80e3e9e646222aeb1c9fc8c962552c94a0e..b5d1d4e4464a584400b4cded18780eb4da7dc33e 100644 GIT binary patch delta 25257 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 P00960JXiX4)_Vc~Wqsl( delta 11212 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 diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index 97250a33588a13a8b77fb10f5d6d27feb9f798a6..137ab7e5791107dc6bcf074716703814e7a65a87 100644 GIT binary patch delta 2868 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 Date: Fri, 18 Feb 2022 12:19:09 +0200 Subject: [PATCH 207/385] add reification limit --- blockstore/splitstore/splitstore_reify.go | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/blockstore/splitstore/splitstore_reify.go b/blockstore/splitstore/splitstore_reify.go index 6529007471d..85c4fa2894e 100644 --- a/blockstore/splitstore/splitstore_reify.go +++ b/blockstore/splitstore/splitstore_reify.go @@ -1,6 +1,7 @@ package splitstore import ( + "errors" "runtime" "sync/atomic" @@ -10,13 +11,12 @@ import ( cid "github.com/ipfs/go-cid" ) -var EnableReification = false +var ( + errReifyLimit = errors.New("reification limit reached") + ReifyLimit = 16384 +) func (s *SplitStore) reifyColdObject(c cid.Cid) { - if !EnableReification { - return - } - if !s.isWarm() { return } @@ -104,12 +104,18 @@ func (s *SplitStore) doReify(c cid.Cid) { s.txnLk.RLock() defer s.txnLk.RUnlock() + count := 0 err := s.walkObjectIncomplete(c, newTmpVisitor(), func(c cid.Cid) error { if isUnitaryObject(c) { return errStopWalk } + count++ + if count > ReifyLimit { + return errReifyLimit + } + s.reifyMx.Lock() _, inProgress := s.reifyInProgress[c] if !inProgress { @@ -150,6 +156,11 @@ func (s *SplitStore) doReify(c cid.Cid) { }) if err != nil { + if xerrors.Is(err, errReifyLimit) { + log.Debug("reification aborted; reify limit reached") + return + } + log.Warnf("error walking cold object for reification (cid: %s): %s", c, err) return } From 2795995989848153a80f1c1d1ca524f4636ea5cf Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 18 Feb 2022 12:19:19 +0200 Subject: [PATCH 208/385] add reification limit test --- blockstore/splitstore/splitstore_test.go | 101 ++++++++++++++++++++++- 1 file changed, 100 insertions(+), 1 deletion(-) diff --git a/blockstore/splitstore/splitstore_test.go b/blockstore/splitstore/splitstore_test.go index c7f9cb6fc2f..ee30400a4b6 100644 --- a/blockstore/splitstore/splitstore_test.go +++ b/blockstore/splitstore/splitstore_test.go @@ -495,8 +495,102 @@ func testSplitStoreReification(t *testing.T, f func(context.Context, blockstore. } } +func testSplitStoreReificationLimit(t *testing.T, f func(context.Context, blockstore.Blockstore, cid.Cid) error) { + ds := dssync.MutexWrap(datastore.NewMapDatastore()) + hot := newMockStore() + cold := newMockStore() + + mkRandomBlock := func() blocks.Block { + data := make([]byte, 128) + _, err := rand.Read(data) + if err != nil { + t.Fatal(err) + } + + return blocks.NewBlock(data) + } + + block1 := mkRandomBlock() + block2 := mkRandomBlock() + block3 := mkRandomBlock() + + hdr := mock.MkBlock(nil, 0, 0) + hdr.Messages = block1.Cid() + hdr.ParentMessageReceipts = block2.Cid() + hdr.ParentStateRoot = block3.Cid() + block4, err := hdr.ToStorageBlock() + if err != nil { + t.Fatal(err) + } + + allBlocks := []blocks.Block{block1, block2, block3, block4} + for _, blk := range allBlocks { + err := cold.Put(context.Background(), blk) + if err != nil { + t.Fatal(err) + } + } + + path, err := ioutil.TempDir("", "splitstore.*") + if err != nil { + t.Fatal(err) + } + + t.Cleanup(func() { + _ = os.RemoveAll(path) + }) + + ss, err := Open(path, ds, hot, cold, &Config{MarkSetType: "map"}) + if err != nil { + t.Fatal(err) + } + defer ss.Close() //nolint + + ss.warmupEpoch = 1 + go ss.reifyOrchestrator() + + waitForReification := func() { + for { + ss.reifyMx.Lock() + ready := len(ss.reifyPend) == 0 && len(ss.reifyInProgress) == 0 + ss.reifyMx.Unlock() + + if ready { + return + } + + time.Sleep(time.Millisecond) + } + } + + // do a hot access -- nothing should be reified as the limit should be exceeded + oldReifyLimit := ReifyLimit + ReifyLimit = 2 + t.Cleanup(func() { + ReifyLimit = oldReifyLimit + }) + + err = f(blockstore.WithHotView(context.Background()), ss, block4.Cid()) + if err != nil { + t.Fatal(err) + } + + waitForReification() + + for _, blk := range allBlocks { + has, err := hot.Has(context.Background(), blk.Cid()) + if err != nil { + t.Fatal(err) + } + + if has { + t.Fatal("block unexpectedly reified") + } + } + +} + func TestSplitStoreReification(t *testing.T) { - EnableReification = true t.Log("test reification with Has") testSplitStoreReification(t, func(ctx context.Context, s blockstore.Blockstore, c cid.Cid) error { _, err := s.Has(ctx, c) @@ -516,6 +610,11 @@ func TestSplitStoreReification(t *testing.T) { testSplitStoreReification(t, func(ctx context.Context, s blockstore.Blockstore, c cid.Cid) error { return s.View(ctx, c, func(_ []byte) error { return nil }) }) + t.Log("test reification limit") + testSplitStoreReificationLimit(t, func(ctx context.Context, s blockstore.Blockstore, c cid.Cid) error { + _, err := s.Has(ctx, c) + return err + }) } type mockChain struct { From a7b1d8653378bb114558a92737757c3fed6e34e2 Mon Sep 17 00:00:00 2001 From: vyzo Date: Fri, 18 Feb 2022 12:27:46 +0200 Subject: [PATCH 209/385] make cidset (in memory) visitors smarter; no need to ever visit unitary objects --- blockstore/splitstore/visitor.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/blockstore/splitstore/visitor.go b/blockstore/splitstore/visitor.go index 9dfbb78e704..4a78f1db1b5 100644 --- a/blockstore/splitstore/visitor.go +++ b/blockstore/splitstore/visitor.go @@ -26,6 +26,10 @@ type tmpVisitor struct { var _ ObjectVisitor = (*tmpVisitor)(nil) func (v *tmpVisitor) Visit(c cid.Cid) (bool, error) { + if isUnitaryObject(c) { + return false, nil + } + return v.set.Visit(c), nil } @@ -45,6 +49,10 @@ func newConcurrentVisitor() *concurrentVisitor { } func (v *concurrentVisitor) Visit(c cid.Cid) (bool, error) { + if isUnitaryObject(c) { + return false, nil + } + v.mx.Lock() defer v.mx.Unlock() From 1c397305313e21754d0283e9de0b95767631bc43 Mon Sep 17 00:00:00 2001 From: "florian@eyesr.fr" Date: Fri, 18 Feb 2022 15:46:40 +0000 Subject: [PATCH 210/385] Fix #8095 Clear the list of miner addresses and successfull get-asked before asking for new ones Previous behavior : if get-ask failed for miner(s), the faulty miner will be retried each time, so you have to stop the command and start again to change this faulty miner (instead of removing from the list on the new attempt) --- cli/client.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cli/client.go b/cli/client.go index 634bd18e5b4..64114fa171b 100644 --- a/cli/client.go +++ b/cli/client.go @@ -667,6 +667,8 @@ uiLoop: state = "miner" case "miner": + maddrs = maddrs[:0] + ask = ask[:0] afmt.Print("Miner Addresses (f0.. f0..), none to find: ") _maddrsStr, _, err := rl.ReadLine() @@ -802,7 +804,8 @@ uiLoop: dealCount, err = strconv.ParseInt(string(dealcStr), 10, 64) if err != nil { - return err + printErr(xerrors.Errorf("reading deal count: invalid number")) + continue } color.Blue(".. Picking miners") @@ -859,12 +862,13 @@ uiLoop: a, err := api.ClientQueryAsk(ctx, *mi.PeerId, maddr) if err != nil { - printErr(xerrors.Errorf("failed to query ask: %w", err)) + printErr(xerrors.Errorf("failed to query ask for miner %s: %w", maddr.String(), err)) state = "miner" continue uiLoop } ask = append(ask, *a) + } // TODO: run more validation From 393479ea69d845fe8793a970921720e6c848d7a2 Mon Sep 17 00:00:00 2001 From: Aayush Date: Tue, 15 Feb 2022 18:00:39 -0500 Subject: [PATCH 211/385] Fvm: impl VerifyConsensusFault --- chain/vm/fvm.go | 203 +++++++++++++++++++++++++++++++++++++++++++- extern/filecoin-ffi | 2 +- 2 files changed, 200 insertions(+), 5 deletions(-) diff --git a/chain/vm/fvm.go b/chain/vm/fvm.go index 1e394a20258..f98c043dd69 100644 --- a/chain/vm/fvm.go +++ b/chain/vm/fvm.go @@ -1,10 +1,16 @@ package vm import ( + "bytes" "context" + "github.com/filecoin-project/lotus/chain/state" + cbor "github.com/ipfs/go-ipld-cbor" + + "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/exitcode" + "github.com/filecoin-project/lotus/lib/sigs" "golang.org/x/xerrors" @@ -13,20 +19,209 @@ import ( ffi "github.com/filecoin-project/filecoin-ffi" ffi_cgo "github.com/filecoin-project/filecoin-ffi/cgo" + "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/ipfs/go-cid" ) var _ VMI = (*FVM)(nil) +var _ ffi_cgo.Externs = (*FvmExtern)(nil) type FvmExtern struct { Rand blockstore.Blockstore + epoch abi.ChainEpoch + lbState LookbackStateGetter + base cid.Cid +} + +// Similar to the one in syscalls.go used by the Lotus VM, except it never errors +// Errors are logged and "no fault" is returned, which is functionally what go-actors does anyway +func (x *FvmExtern) VerifyConsensusFault(ctx context.Context, a, b, extra []byte) *ffi_cgo.ConsensusFaultWithGas { + ret := &ffi_cgo.ConsensusFaultWithGas{ + // TODO: is this gonna be a problem on the receiving end? should we return address.NewIDAddress(0) instead? + Target: address.Undef, + Type: ffi_cgo.ConsensusFaultNone, + } + + // Note that block syntax is not validated. Any validly signed block will be accepted pursuant to the below conditions. + // Whether or not it could ever have been accepted in a chain is not checked/does not matter here. + // for that reason when checking block parent relationships, rather than instantiating a Tipset to do so + // (which runs a syntactic check), we do it directly on the CIDs. + + // (0) cheap preliminary checks + + // can blocks be decoded properly? + var blockA, blockB types.BlockHeader + if decodeErr := blockA.UnmarshalCBOR(bytes.NewReader(a)); decodeErr != nil { + log.Info("invalid consensus fault: cannot decode first block header: %w", decodeErr) + return ret + } + + if decodeErr := blockB.UnmarshalCBOR(bytes.NewReader(b)); decodeErr != nil { + log.Info("invalid consensus fault: cannot decode second block header: %w", decodeErr) + return ret + } + + // Commented out from the Lotus VM code: FvmExtern only supports v14 and onwards + // workaround chain halt + //if build.IsNearUpgrade(blockA.Height, build.UpgradeOrangeHeight) { + // return nil, xerrors.Errorf("consensus reporting disabled around Upgrade Orange") + //} + //if build.IsNearUpgrade(blockB.Height, build.UpgradeOrangeHeight) { + // return nil, xerrors.Errorf("consensus reporting disabled around Upgrade Orange") + //} + + // are blocks the same? + if blockA.Cid().Equals(blockB.Cid()) { + log.Info("invalid consensus fault: submitted blocks are the same") + return ret + } + // (1) check conditions necessary to any consensus fault + + // were blocks mined by same miner? + if blockA.Miner != blockB.Miner { + log.Info("invalid consensus fault: blocks not mined by the same miner") + return ret + } + + ret.Target = blockA.Miner + + // block a must be earlier or equal to block b, epoch wise (ie at least as early in the chain). + if blockB.Height < blockA.Height { + log.Info("invalid consensus fault: first block must not be of higher height than second") + return ret + } + + ret.Epoch = blockB.Height + + faultType := ffi_cgo.ConsensusFaultNone + + // (2) check for the consensus faults themselves + // (a) double-fork mining fault + if blockA.Height == blockB.Height { + faultType = ffi_cgo.ConsensusFaultDoubleForkMining + } + + // (b) time-offset mining fault + // strictly speaking no need to compare heights based on double fork mining check above, + // but at same height this would be a different fault. + if types.CidArrsEqual(blockA.Parents, blockB.Parents) && blockA.Height != blockB.Height { + faultType = ffi_cgo.ConsensusFaultTimeOffsetMining + } + + // (c) parent-grinding fault + // Here extra is the "witness", a third block that shows the connection between A and B as + // A's sibling and B's parent. + // Specifically, since A is of lower height, it must be that B was mined omitting A from its tipset + // + // B + // | + // [A, C] + var blockC types.BlockHeader + if len(extra) > 0 { + if decodeErr := blockC.UnmarshalCBOR(bytes.NewReader(extra)); decodeErr != nil { + log.Info("invalid consensus fault: cannot decode extra: %w", decodeErr) + // just to match Lotus VM consensus, zero out any already-set faults + faultType = ffi_cgo.ConsensusFaultNone + return ret + } + + if types.CidArrsEqual(blockA.Parents, blockC.Parents) && blockA.Height == blockC.Height && + types.CidArrsContains(blockB.Parents, blockC.Cid()) && !types.CidArrsContains(blockB.Parents, blockA.Cid()) { + faultType = ffi_cgo.ConsensusFaultParentGrinding + } + } + + // (3) return if no consensus fault by now + if faultType == ffi_cgo.ConsensusFaultNone { + log.Info("invalid consensus fault: no fault detected") + return ret + } + + // else + // (4) expensive final checks + + // check blocks are properly signed by their respective miner + // note we do not need to check extra's: it is a parent to block b + // which itself is signed, so it was willingly included by the miner + gasUsed, sigErr := x.VerifyBlockSig(ctx, &blockA) + ret.GasUsed += gasUsed + if sigErr != nil { + log.Info("invalid consensus fault: cannot verify first block sig: %w", sigErr) + return ret + } + + gasUsed, sigErr = x.VerifyBlockSig(ctx, &blockB) + ret.GasUsed += gasUsed + if sigErr != nil { + log.Info("invalid consensus fault: cannot verify second block sig: %w", sigErr) + return ret + } + + ret.Type = faultType + + return ret +} + +func (x *FvmExtern) VerifyBlockSig(ctx context.Context, blk *types.BlockHeader) (int64, error) { + waddr, gasUsed, err := x.workerKeyAtLookback(ctx, blk.Miner, blk.Height) + if err != nil { + return gasUsed, err + } + + return gasUsed, sigs.CheckBlockSignature(ctx, blk, waddr) } -func (x *FvmExtern) VerifyConsensusFault(ctx context.Context, h1, h2, extra []byte) (*ffi_cgo.ConsensusFault, error) { - // TODO - panic("unimplemented") +func (x *FvmExtern) workerKeyAtLookback(ctx context.Context, minerId address.Address, height abi.ChainEpoch) (address.Address, int64, error) { + // Commented out from the Lotus VM code: FvmExtern only supports v14 and onwards + //if x.networkVersion >= network.Version7 && height < x.epoch-policy.ChainFinality { + // return address.Undef, xerrors.Errorf("cannot get worker key (currEpoch %d, height %d)", ss.epoch, height) + //} + + gasUsed := int64(0) + gasAdder := func(gc GasCharge) { + // technically not overflow safe, but that's fine + gasUsed += gc.Total() + } + + cstWithoutGas := cbor.NewCborStore(x.Blockstore) + cbb := &gasChargingBlocks{gasAdder, PricelistByEpoch(x.epoch), x.Blockstore} + cstWithGas := cbor.NewCborStore(cbb) + + lbState, err := x.lbState(ctx, height) + if err != nil { + return address.Undef, gasUsed, err + } + // get appropriate miner actor + act, err := lbState.GetActor(minerId) + if err != nil { + return address.Undef, gasUsed, err + } + + // use that to get the miner state + mas, err := miner.Load(adt.WrapStore(ctx, cstWithGas), act) + if err != nil { + return address.Undef, gasUsed, err + } + + info, err := mas.Info() + if err != nil { + return address.Undef, gasUsed, err + } + + stateTree, err := state.LoadStateTree(cstWithoutGas, x.base) + if err != nil { + return address.Undef, gasUsed, err + } + + raddr, err := ResolveToKeyAddr(stateTree, cstWithGas, info.Worker) + if err != nil { + return address.Undef, gasUsed, err + } + + return raddr, gasUsed, nil } type FVM struct { @@ -35,7 +230,7 @@ type FVM struct { func NewFVM(ctx context.Context, opts *VMOpts) (*FVM, error) { fvm, err := ffi.CreateFVM(0, - &FvmExtern{Rand: opts.Rand, Blockstore: opts.Bstore}, + &FvmExtern{Rand: opts.Rand, Blockstore: opts.Bstore, lbState: opts.LookbackState, base: opts.StateBase, epoch: opts.Epoch}, opts.Epoch, opts.BaseFee, opts.FilVested, opts.NetworkVersion, opts.StateBase, ) if err != nil { diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index d65d3770c90..9ff2301105f 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit d65d3770c90ebdb8b3282f11fdf10a84c3ef0355 +Subproject commit 9ff2301105fcf25101f1fcda52e6417f3e2ca60b From 5be125ad1afe01ef6f3eff58eca9091623571bf5 Mon Sep 17 00:00:00 2001 From: Aayush Date: Wed, 16 Feb 2022 23:21:06 -0500 Subject: [PATCH 212/385] address review feedback --- chain/vm/fvm.go | 68 +++++++++++++++++++------------------------------ 1 file changed, 26 insertions(+), 42 deletions(-) diff --git a/chain/vm/fvm.go b/chain/vm/fvm.go index f98c043dd69..962b27be6c3 100644 --- a/chain/vm/fvm.go +++ b/chain/vm/fvm.go @@ -4,6 +4,8 @@ import ( "bytes" "context" + "github.com/filecoin-project/go-state-types/big" + "github.com/filecoin-project/lotus/chain/state" cbor "github.com/ipfs/go-ipld-cbor" @@ -36,13 +38,12 @@ type FvmExtern struct { base cid.Cid } -// Similar to the one in syscalls.go used by the Lotus VM, except it never errors +// VerifyConsensusFault is similar to the one in syscalls.go used by the Lotus VM, except it never errors // Errors are logged and "no fault" is returned, which is functionally what go-actors does anyway -func (x *FvmExtern) VerifyConsensusFault(ctx context.Context, a, b, extra []byte) *ffi_cgo.ConsensusFaultWithGas { - ret := &ffi_cgo.ConsensusFaultWithGas{ - // TODO: is this gonna be a problem on the receiving end? should we return address.NewIDAddress(0) instead? - Target: address.Undef, - Type: ffi_cgo.ConsensusFaultNone, +func (x *FvmExtern) VerifyConsensusFault(ctx context.Context, a, b, extra []byte) (*ffi_cgo.ConsensusFault, int64) { + totalGas := int64(0) + ret := &ffi_cgo.ConsensusFault{ + Type: ffi_cgo.ConsensusFaultNone, } // Note that block syntax is not validated. Any validly signed block will be accepted pursuant to the below conditions. @@ -56,42 +57,31 @@ func (x *FvmExtern) VerifyConsensusFault(ctx context.Context, a, b, extra []byte var blockA, blockB types.BlockHeader if decodeErr := blockA.UnmarshalCBOR(bytes.NewReader(a)); decodeErr != nil { log.Info("invalid consensus fault: cannot decode first block header: %w", decodeErr) - return ret + return ret, totalGas } if decodeErr := blockB.UnmarshalCBOR(bytes.NewReader(b)); decodeErr != nil { log.Info("invalid consensus fault: cannot decode second block header: %w", decodeErr) - return ret + return ret, totalGas } - // Commented out from the Lotus VM code: FvmExtern only supports v14 and onwards - // workaround chain halt - //if build.IsNearUpgrade(blockA.Height, build.UpgradeOrangeHeight) { - // return nil, xerrors.Errorf("consensus reporting disabled around Upgrade Orange") - //} - //if build.IsNearUpgrade(blockB.Height, build.UpgradeOrangeHeight) { - // return nil, xerrors.Errorf("consensus reporting disabled around Upgrade Orange") - //} - // are blocks the same? if blockA.Cid().Equals(blockB.Cid()) { log.Info("invalid consensus fault: submitted blocks are the same") - return ret + return ret, totalGas } // (1) check conditions necessary to any consensus fault // were blocks mined by same miner? if blockA.Miner != blockB.Miner { log.Info("invalid consensus fault: blocks not mined by the same miner") - return ret + return ret, totalGas } - ret.Target = blockA.Miner - // block a must be earlier or equal to block b, epoch wise (ie at least as early in the chain). if blockB.Height < blockA.Height { log.Info("invalid consensus fault: first block must not be of higher height than second") - return ret + return ret, totalGas } ret.Epoch = blockB.Height @@ -123,9 +113,7 @@ func (x *FvmExtern) VerifyConsensusFault(ctx context.Context, a, b, extra []byte if len(extra) > 0 { if decodeErr := blockC.UnmarshalCBOR(bytes.NewReader(extra)); decodeErr != nil { log.Info("invalid consensus fault: cannot decode extra: %w", decodeErr) - // just to match Lotus VM consensus, zero out any already-set faults - faultType = ffi_cgo.ConsensusFaultNone - return ret + return ret, totalGas } if types.CidArrsEqual(blockA.Parents, blockC.Parents) && blockA.Height == blockC.Height && @@ -137,7 +125,7 @@ func (x *FvmExtern) VerifyConsensusFault(ctx context.Context, a, b, extra []byte // (3) return if no consensus fault by now if faultType == ffi_cgo.ConsensusFaultNone { log.Info("invalid consensus fault: no fault detected") - return ret + return ret, totalGas } // else @@ -146,23 +134,24 @@ func (x *FvmExtern) VerifyConsensusFault(ctx context.Context, a, b, extra []byte // check blocks are properly signed by their respective miner // note we do not need to check extra's: it is a parent to block b // which itself is signed, so it was willingly included by the miner - gasUsed, sigErr := x.VerifyBlockSig(ctx, &blockA) - ret.GasUsed += gasUsed + gasA, sigErr := x.VerifyBlockSig(ctx, &blockA) + totalGas += gasA if sigErr != nil { log.Info("invalid consensus fault: cannot verify first block sig: %w", sigErr) - return ret + return ret, totalGas } - gasUsed, sigErr = x.VerifyBlockSig(ctx, &blockB) - ret.GasUsed += gasUsed + gas2, sigErr := x.VerifyBlockSig(ctx, &blockB) + totalGas += gas2 if sigErr != nil { log.Info("invalid consensus fault: cannot verify second block sig: %w", sigErr) - return ret + return ret, totalGas } ret.Type = faultType - - return ret + ret.Target = blockA.Miner + + return ret, totalGas } func (x *FvmExtern) VerifyBlockSig(ctx context.Context, blk *types.BlockHeader) (int64, error) { @@ -175,11 +164,6 @@ func (x *FvmExtern) VerifyBlockSig(ctx context.Context, blk *types.BlockHeader) } func (x *FvmExtern) workerKeyAtLookback(ctx context.Context, minerId address.Address, height abi.ChainEpoch) (address.Address, int64, error) { - // Commented out from the Lotus VM code: FvmExtern only supports v14 and onwards - //if x.networkVersion >= network.Version7 && height < x.epoch-policy.ChainFinality { - // return address.Undef, xerrors.Errorf("cannot get worker key (currEpoch %d, height %d)", ss.epoch, height) - //} - gasUsed := int64(0) gasAdder := func(gc GasCharge) { // technically not overflow safe, but that's fine @@ -261,11 +245,11 @@ func (vm *FVM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet }, GasCosts: &GasOutputs{ // TODO: do the other optional fields eventually - BaseFeeBurn: abi.TokenAmount{}, - OverEstimationBurn: abi.TokenAmount{}, + BaseFeeBurn: big.Zero(), + OverEstimationBurn: big.Zero(), MinerPenalty: ret.MinerPenalty, MinerTip: ret.MinerTip, - Refund: abi.TokenAmount{}, + Refund: big.Zero(), GasRefund: 0, GasBurned: 0, }, From e2a93a3febfea5b42ebb5f7bb48a38ae7007ad41 Mon Sep 17 00:00:00 2001 From: Elijah Seed-Arita Date: Fri, 18 Feb 2022 11:09:56 -1000 Subject: [PATCH 213/385] add itests ensemble mocknet getter --- itests/kit/ensemble.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/itests/kit/ensemble.go b/itests/kit/ensemble.go index 0227ee81e70..6a0158429aa 100644 --- a/itests/kit/ensemble.go +++ b/itests/kit/ensemble.go @@ -151,6 +151,11 @@ func NewEnsemble(t *testing.T, opts ...EnsembleOpt) *Ensemble { return n } +// Mocknet returns the underlying mocknet. +func (n *Ensemble) Mocknet() mocknet.Mocknet { + return n.mn +} + // FullNode enrolls a new full node. func (n *Ensemble) FullNode(full *TestFullNode, opts ...NodeOpt) *Ensemble { options := DefaultNodeOpts From cdd2d5cc6a1d7c414a2827b8362f9210164bf554 Mon Sep 17 00:00:00 2001 From: Cory Schwartz Date: Fri, 18 Feb 2022 15:37:53 -0800 Subject: [PATCH 214/385] update template --- .circleci/template.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/.circleci/template.yml b/.circleci/template.yml index 8f5995d56d1..9feecc3b544 100644 --- a/.circleci/template.yml +++ b/.circleci/template.yml @@ -705,6 +705,17 @@ jobs: - packer/build: template: tools/packer/lotus.pkr.hcl args: "-var ci_workspace_bins=./linux-butterflynet -var lotus_network=butterflynet -var git_tag=$CIRCLE_TAG" + publish-packer-snap: + description: build packer image with snap. mainnet only. + executor: + name: packer/default + packer-version: 1.6.6 + steps: + - checkout + - attach_workspace: + at: "." + - packer/build: + template: tools/packer/lotus-snap.pkr.hcl publish-dockerhub: description: publish to dockerhub machine: @@ -898,3 +909,13 @@ workflows: - publish-dockerhub: name: publish-dockerhub-nightly tag: nightly + monthly: + triggers: + - schedule: + cron: "0 0 1 * *" + filters: + branches: + only: + - master + jobs: + - publish-packer-snap From 9bb9bb56828df5886def1e72c8bfbaa3e7bf801d Mon Sep 17 00:00:00 2001 From: Peter Rabbitson Date: Sat, 19 Feb 2022 16:25:18 +0100 Subject: [PATCH 215/385] Retract force-pushed v1.14.0 to work around stale gomod caches --- go.mod | 2 ++ 1 file changed, 2 insertions(+) diff --git a/go.mod b/go.mod index aa80f0bdc45..293a17bc4da 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,8 @@ module github.com/filecoin-project/lotus go 1.16 +retract v1.14.0 // Accidentally force-pushed tag, use v1.14.1+ instead. + require ( contrib.go.opencensus.io/exporter/prometheus v0.4.0 github.com/BurntSushi/toml v0.4.1 From 26707a5e032fbaed063b3e5f28ada5cf817d8545 Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Mon, 21 Feb 2022 11:51:25 +0400 Subject: [PATCH 216/385] make add piece idempotent --- extern/storage-sealing/input.go | 24 ++++++++++-------------- extern/storage-sealing/sealing.go | 8 ++++++++ 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/extern/storage-sealing/input.go b/extern/storage-sealing/input.go index 13dc40f0f87..184a1e9e3ab 100644 --- a/extern/storage-sealing/input.go +++ b/extern/storage-sealing/input.go @@ -311,28 +311,25 @@ func (m *Sealing) SectorAddPieceToAny(ctx context.Context, size abi.UnpaddedPiec } m.inputLk.Lock() - if _, exist := m.pendingPieces[proposalCID(deal)]; exist { + if pp, exist := m.pendingPieces[proposalCID(deal)]; exist { m.inputLk.Unlock() - return api.SectorOffset{}, xerrors.Errorf("piece for deal %s already pending", proposalCID(deal)) + select { + case res := <-pp.resCh: + return api.SectorOffset{Sector: res.sn, Offset: res.offset.Padded()}, res.err + case <-ctx.Done(): + return api.SectorOffset{}, ctx.Err() + } } - resCh := make(chan struct { - sn abi.SectorNumber - offset abi.UnpaddedPieceSize - err error - }, 1) - + resCh := make(chan *pieceAcceptResp, 1) m.pendingPieces[proposalCID(deal)] = &pendingPiece{ + resCh: resCh, size: size, deal: deal, data: data, assigned: false, accepted: func(sn abi.SectorNumber, offset abi.UnpaddedPieceSize, err error) { - resCh <- struct { - sn abi.SectorNumber - offset abi.UnpaddedPieceSize - err error - }{sn: sn, offset: offset, err: err} + resCh <- &pieceAcceptResp{sn, offset, err} }, } @@ -344,7 +341,6 @@ func (m *Sealing) SectorAddPieceToAny(ctx context.Context, size abi.UnpaddedPiec }() res := <-resCh - return api.SectorOffset{Sector: res.sn, Offset: res.offset.Padded()}, res.err } diff --git a/extern/storage-sealing/sealing.go b/extern/storage-sealing/sealing.go index 81f6b38e93c..66ad6ca8e83 100644 --- a/extern/storage-sealing/sealing.go +++ b/extern/storage-sealing/sealing.go @@ -140,7 +140,15 @@ func (o *openSector) dealFitsInLifetime(dealEnd abi.ChainEpoch, expF func(sn abi return expiration >= dealEnd, nil } +type pieceAcceptResp struct { + sn abi.SectorNumber + offset abi.UnpaddedPieceSize + err error +} + type pendingPiece struct { + resCh chan *pieceAcceptResp + size abi.UnpaddedPieceSize deal api.PieceDealInfo From 12458710040b4377670122a3b4118c0ba3232f50 Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Mon, 21 Feb 2022 11:56:49 +0400 Subject: [PATCH 217/385] guard with ctx --- extern/storage-sealing/input.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/extern/storage-sealing/input.go b/extern/storage-sealing/input.go index 184a1e9e3ab..d24e0612c1d 100644 --- a/extern/storage-sealing/input.go +++ b/extern/storage-sealing/input.go @@ -340,8 +340,12 @@ func (m *Sealing) SectorAddPieceToAny(ctx context.Context, size abi.UnpaddedPiec } }() - res := <-resCh - return api.SectorOffset{Sector: res.sn, Offset: res.offset.Padded()}, res.err + select { + case res := <-resCh: + return api.SectorOffset{Sector: res.sn, Offset: res.offset.Padded()}, res.err + case <-ctx.Done(): + return api.SectorOffset{}, ctx.Err() + } } func (m *Sealing) MatchPendingPiecesToOpenSectors(ctx context.Context) error { From c2522e8ca95e3bf224c2b058518158681fd6105f Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Mon, 21 Feb 2022 13:51:43 +0400 Subject: [PATCH 218/385] idempotent add piece --- extern/storage-sealing/input.go | 20 ++++++++++++-------- extern/storage-sealing/sealing.go | 4 +++- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/extern/storage-sealing/input.go b/extern/storage-sealing/input.go index d24e0612c1d..7243c472b92 100644 --- a/extern/storage-sealing/input.go +++ b/extern/storage-sealing/input.go @@ -314,25 +314,28 @@ func (m *Sealing) SectorAddPieceToAny(ctx context.Context, size abi.UnpaddedPiec if pp, exist := m.pendingPieces[proposalCID(deal)]; exist { m.inputLk.Unlock() select { - case res := <-pp.resCh: + case <-pp.doneCh: + res := pp.resp.Load().(*pieceAcceptResp) return api.SectorOffset{Sector: res.sn, Offset: res.offset.Padded()}, res.err case <-ctx.Done(): return api.SectorOffset{}, ctx.Err() } } - resCh := make(chan *pieceAcceptResp, 1) - m.pendingPieces[proposalCID(deal)] = &pendingPiece{ - resCh: resCh, + doneCh := make(chan struct{}, 1) + pp := &pendingPiece{ + doneCh: doneCh, size: size, deal: deal, data: data, assigned: false, - accepted: func(sn abi.SectorNumber, offset abi.UnpaddedPieceSize, err error) { - resCh <- &pieceAcceptResp{sn, offset, err} - }, + } + pp.accepted = func(sn abi.SectorNumber, offset abi.UnpaddedPieceSize, err error) { + pp.resp.Store(&pieceAcceptResp{sn, offset, err}) + close(pp.doneCh) } + m.pendingPieces[proposalCID(deal)] = pp go func() { defer m.inputLk.Unlock() if err := m.updateInput(ctx, sp); err != nil { @@ -341,7 +344,8 @@ func (m *Sealing) SectorAddPieceToAny(ctx context.Context, size abi.UnpaddedPiec }() select { - case res := <-resCh: + case <-doneCh: + res := pp.resp.Load().(*pieceAcceptResp) return api.SectorOffset{Sector: res.sn, Offset: res.offset.Padded()}, res.err case <-ctx.Done(): return api.SectorOffset{}, ctx.Err() diff --git a/extern/storage-sealing/sealing.go b/extern/storage-sealing/sealing.go index 66ad6ca8e83..abfed55c79e 100644 --- a/extern/storage-sealing/sealing.go +++ b/extern/storage-sealing/sealing.go @@ -4,6 +4,7 @@ import ( "context" "errors" "sync" + "sync/atomic" "time" "github.com/ipfs/go-cid" @@ -147,7 +148,8 @@ type pieceAcceptResp struct { } type pendingPiece struct { - resCh chan *pieceAcceptResp + doneCh chan struct{} + resp atomic.Value size abi.UnpaddedPieceSize deal api.PieceDealInfo From 3fd83e9345edd6a95de9c5fe6ee8dea969fa96cf Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Mon, 21 Feb 2022 13:57:29 +0400 Subject: [PATCH 219/385] dagstore size bloating fix --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4d25bb40ed9..50608e5d268 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/elastic/gosigar v0.14.1 github.com/etclabscore/go-openrpc-reflect v0.0.36 github.com/fatih/color v1.13.0 - github.com/filecoin-project/dagstore v0.5.2-0.20220218091406-7e3dada33cf4 + github.com/filecoin-project/dagstore v0.5.2-0.20220221082516-6beb25bc4425 github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200910194244-f640612a1a1f github.com/filecoin-project/go-address v0.0.6 github.com/filecoin-project/go-bitfield v0.2.4 diff --git a/go.sum b/go.sum index 08f2c4b3980..b2d87d3c2c6 100644 --- a/go.sum +++ b/go.sum @@ -299,8 +299,8 @@ github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGE github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/filecoin-project/dagstore v0.5.1/go.mod h1:OdlK3x5m3Mol874WC2bI79H4H2+leN+FabwWdW2D/wY= -github.com/filecoin-project/dagstore v0.5.2-0.20220218091406-7e3dada33cf4 h1:zyE+eiIhkkTSi5zL5bDeHTfumikCER8uxKjyQJeEHV4= -github.com/filecoin-project/dagstore v0.5.2-0.20220218091406-7e3dada33cf4/go.mod h1:cVH6pCuJaOZzn2sCWQ2BtqnivvG/69acZJ0UA3mGagg= +github.com/filecoin-project/dagstore v0.5.2-0.20220221082516-6beb25bc4425 h1:OQxAqlQVzH9/WUAMue7LWQorL1KXgiEbJTuKRxPuxlo= +github.com/filecoin-project/dagstore v0.5.2-0.20220221082516-6beb25bc4425/go.mod h1:mdqKzYrRBHf1pRMthYfMv3n37oOw0Tkx7+TxPt240M0= github.com/filecoin-project/go-address v0.0.3/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= github.com/filecoin-project/go-address v0.0.5/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= github.com/filecoin-project/go-address v0.0.6 h1:DWQtj38ax+ogHwyH3VULRIoT8E6loyXqsk/p81xoY7M= From c3817652dccfd964d9c731ea6201745e7f676973 Mon Sep 17 00:00:00 2001 From: Darko Brdareski Date: Mon, 21 Feb 2022 11:28:45 +0100 Subject: [PATCH 220/385] Add cli tests for mempool --- cli/mpool.go | 61 +++--- cli/mpool_test.go | 522 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 559 insertions(+), 24 deletions(-) create mode 100644 cli/mpool_test.go diff --git a/cli/mpool.go b/cli/mpool.go index adefd25a88d..0224b15d2b9 100644 --- a/cli/mpool.go +++ b/cli/mpool.go @@ -60,6 +60,8 @@ var MpoolPending = &cli.Command{ }, }, Action: func(cctx *cli.Context) error { + afmt := NewAppFmt(cctx.App) + api, closer, err := GetFullNodeAPI(cctx) if err != nil { return err @@ -72,7 +74,7 @@ var MpoolPending = &cli.Command{ if tos := cctx.String("to"); tos != "" { a, err := address.NewFromString(tos) if err != nil { - return fmt.Errorf("given 'to' address %q was invalid: %w", tos, err) + return xerrors.Errorf("given 'to' address %q was invalid: %w", tos, err) } toa = a } @@ -80,7 +82,7 @@ var MpoolPending = &cli.Command{ if froms := cctx.String("from"); froms != "" { a, err := address.NewFromString(froms) if err != nil { - return fmt.Errorf("given 'from' address %q was invalid: %w", froms, err) + return xerrors.Errorf("given 'from' address %q was invalid: %w", froms, err) } froma = a } @@ -119,13 +121,13 @@ var MpoolPending = &cli.Command{ } if cctx.Bool("cids") { - fmt.Println(msg.Cid()) + afmt.Println(msg.Cid()) } else { out, err := json.MarshalIndent(msg, "", " ") if err != nil { return err } - fmt.Println(string(out)) + afmt.Println(string(out)) } } @@ -216,6 +218,8 @@ var MpoolStat = &cli.Command{ }, }, Action: func(cctx *cli.Context) error { + afmt := NewAppFmt(cctx.App) + api, closer, err := GetFullNodeAPI(cctx) if err != nil { return err @@ -234,6 +238,7 @@ var MpoolStat = &cli.Command{ currTs := ts for i := 0; i < cctx.Int("basefee-lookback"); i++ { currTs, err = api.ChainGetTipSet(ctx, currTs.Parents()) + if err != nil { return xerrors.Errorf("walking chain: %w", err) } @@ -296,7 +301,7 @@ var MpoolStat = &cli.Command{ for a, bkt := range buckets { act, err := api.StateGetActor(ctx, a, ts.Key()) if err != nil { - fmt.Printf("%s, err: %s\n", a, err) + afmt.Printf("%s, err: %s\n", a, err) continue } @@ -350,11 +355,11 @@ var MpoolStat = &cli.Command{ total.belowPast += stat.belowPast total.gasLimit = big.Add(total.gasLimit, stat.gasLimit) - fmt.Printf("%s: Nonce past: %d, cur: %d, future: %d; FeeCap cur: %d, min-%d: %d, gasLimit: %s\n", stat.addr, stat.past, stat.cur, stat.future, stat.belowCurr, cctx.Int("basefee-lookback"), stat.belowPast, stat.gasLimit) + afmt.Printf("%s: Nonce past: %d, cur: %d, future: %d; FeeCap cur: %d, min-%d: %d, gasLimit: %s\n", stat.addr, stat.past, stat.cur, stat.future, stat.belowCurr, cctx.Int("basefee-lookback"), stat.belowPast, stat.gasLimit) } - fmt.Println("-----") - fmt.Printf("total: Nonce past: %d, cur: %d, future: %d; FeeCap cur: %d, min-%d: %d, gasLimit: %s\n", total.past, total.cur, total.future, total.belowCurr, cctx.Int("basefee-lookback"), total.belowPast, total.gasLimit) + afmt.Println("-----") + afmt.Printf("total: Nonce past: %d, cur: %d, future: %d; FeeCap cur: %d, min-%d: %d, gasLimit: %s\n", total.past, total.cur, total.future, total.belowCurr, cctx.Int("basefee-lookback"), total.belowPast, total.gasLimit) return nil }, @@ -385,8 +390,9 @@ var MpoolReplaceCmd = &cli.Command{ Usage: "Spend up to X FIL for this message in units of FIL. Previously when flag was `max-fee` units were in attoFIL. Applicable for auto mode", }, }, - ArgsUsage: " | ", + ArgsUsage: " | ", Action: func(cctx *cli.Context) error { + afmt := NewAppFmt(cctx.App) api, closer, err := GetFullNodeAPI(cctx) if err != nil { @@ -407,13 +413,14 @@ var MpoolReplaceCmd = &cli.Command{ msg, err := api.ChainGetMessage(ctx, mcid) if err != nil { - return fmt.Errorf("could not find referenced message: %w", err) + return xerrors.Errorf("could not find referenced message: %w", err) } from = msg.From nonce = msg.Nonce case 2: - f, err := address.NewFromString(cctx.Args().Get(0)) + arg0 := cctx.Args().Get(0) + f, err := address.NewFromString(arg0) if err != nil { return err } @@ -448,7 +455,7 @@ var MpoolReplaceCmd = &cli.Command{ } if found == nil { - return fmt.Errorf("no pending message found from %s with nonce %d", from, nonce) + return xerrors.Errorf("no pending message found from %s with nonce %d", from, nonce) } msg := found.Message @@ -460,7 +467,7 @@ var MpoolReplaceCmd = &cli.Command{ if cctx.IsSet("fee-limit") { maxFee, err := types.ParseFIL(cctx.String("fee-limit")) if err != nil { - return fmt.Errorf("parsing max-spend: %w", err) + return xerrors.Errorf("parsing max-spend: %w", err) } mss = &lapi.MessageSendSpec{ MaxFee: abi.TokenAmount(maxFee), @@ -472,7 +479,7 @@ var MpoolReplaceCmd = &cli.Command{ msg.GasPremium = abi.NewTokenAmount(0) retm, err := api.GasEstimateMessageGas(ctx, &msg, mss, types.EmptyTSK) if err != nil { - return fmt.Errorf("failed to estimate gas values: %w", err) + return xerrors.Errorf("failed to estimate gas values: %w", err) } msg.GasPremium = big.Max(retm.GasPremium, minRBF) @@ -489,26 +496,26 @@ var MpoolReplaceCmd = &cli.Command{ } msg.GasPremium, err = types.BigFromString(cctx.String("gas-premium")) if err != nil { - return fmt.Errorf("parsing gas-premium: %w", err) + return xerrors.Errorf("parsing gas-premium: %w", err) } // TODO: estimate fee cap here msg.GasFeeCap, err = types.BigFromString(cctx.String("gas-feecap")) if err != nil { - return fmt.Errorf("parsing gas-feecap: %w", err) + return xerrors.Errorf("parsing gas-feecap: %w", err) } } smsg, err := api.WalletSignMessage(ctx, msg.From, &msg) if err != nil { - return fmt.Errorf("failed to sign message: %w", err) + return xerrors.Errorf("failed to sign message: %w", err) } cid, err := api.MpoolPush(ctx, smsg) if err != nil { - return fmt.Errorf("failed to push new message to mempool: %w", err) + return xerrors.Errorf("failed to push new message to mempool: %w", err) } - fmt.Println("new message cid: ", cid) + afmt.Println("new message cid: ", cid) return nil }, } @@ -531,6 +538,8 @@ var MpoolFindCmd = &cli.Command{ }, }, Action: func(cctx *cli.Context) error { + afmt := NewAppFmt(cctx.App) + api, closer, err := GetFullNodeAPI(cctx) if err != nil { return err @@ -548,7 +557,7 @@ var MpoolFindCmd = &cli.Command{ if cctx.IsSet("to") { a, err := address.NewFromString(cctx.String("to")) if err != nil { - return fmt.Errorf("'to' address was invalid: %w", err) + return xerrors.Errorf("'to' address was invalid: %w", err) } toFilter = a @@ -557,7 +566,7 @@ var MpoolFindCmd = &cli.Command{ if cctx.IsSet("from") { a, err := address.NewFromString(cctx.String("from")) if err != nil { - return fmt.Errorf("'from' address was invalid: %w", err) + return xerrors.Errorf("'from' address was invalid: %w", err) } fromFilter = a @@ -591,7 +600,7 @@ var MpoolFindCmd = &cli.Command{ return err } - fmt.Println(string(b)) + afmt.Println(string(b)) return nil }, } @@ -605,6 +614,8 @@ var MpoolConfig = &cli.Command{ return cli.ShowCommandHelp(cctx, cctx.Command.Name) } + afmt := NewAppFmt(cctx.App) + api, closer, err := GetFullNodeAPI(cctx) if err != nil { return err @@ -624,7 +635,7 @@ var MpoolConfig = &cli.Command{ return err } - fmt.Println(string(bytes)) + afmt.Println(string(bytes)) } else { cfg := new(types.MpoolConfig) bytes := []byte(cctx.Args().Get(0)) @@ -651,6 +662,8 @@ var MpoolGasPerfCmd = &cli.Command{ }, }, Action: func(cctx *cli.Context) error { + afmt := NewAppFmt(cctx.App) + api, closer, err := GetFullNodeAPI(cctx) if err != nil { return err @@ -717,7 +730,7 @@ var MpoolGasPerfCmd = &cli.Command{ gasReward := getGasReward(m) gasPerf := getGasPerf(gasReward, m.Message.GasLimit) - fmt.Printf("%s\t%d\t%s\t%f\n", m.Message.From, m.Message.Nonce, gasReward, gasPerf) + afmt.Printf("%s\t%d\t%s\t%f\n", m.Message.From, m.Message.Nonce, gasReward, gasPerf) } return nil diff --git a/cli/mpool_test.go b/cli/mpool_test.go new file mode 100644 index 00000000000..1bb45fd6247 --- /dev/null +++ b/cli/mpool_test.go @@ -0,0 +1,522 @@ +package cli + +import ( + "context" + "fmt" + "testing" + + "encoding/json" + + "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/lotus/api" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/chain/types/mock" + "github.com/filecoin-project/lotus/chain/wallet" + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" +) + +func TestStat(t *testing.T) { + + t.Run("local", func(t *testing.T) { + app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolStat)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // add blocks to the chain + first := mock.TipSet(mock.MkBlock(nil, 5, 4)) + head := mock.TipSet(mock.MkBlock(first, 15, 7)) + + // create a signed message to be returned as a pending message + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + toAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + sm := mock.MkMessage(senderAddr, toAddr, 1, w) + + // mock actor to return for the sender + actor := types.Actor{Nonce: 2, Balance: big.NewInt(200000)} + + gomock.InOrder( + mockApi.EXPECT().ChainHead(ctx).Return(head, nil), + mockApi.EXPECT().ChainGetTipSet(ctx, head.Parents()).Return(first, nil), + mockApi.EXPECT().WalletList(ctx).Return([]address.Address{senderAddr, toAddr}, nil), + mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil), + mockApi.EXPECT().StateGetActor(ctx, senderAddr, head.Key()).Return(&actor, nil), + ) + + err = app.Run([]string{"mpool", "stat", "--basefee-lookback", "1", "--local"}) + assert.NoError(t, err) + + assert.Contains(t, buf.String(), "Nonce past: 1") + }) + + t.Run("all", func(t *testing.T) { + app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolStat)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // add blocks to the chain + first := mock.TipSet(mock.MkBlock(nil, 5, 4)) + head := mock.TipSet(mock.MkBlock(first, 15, 7)) + + // create a signed message to be returned as a pending message + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + toAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + sm := mock.MkMessage(senderAddr, toAddr, 1, w) + + // mock actor to return for the sender + actor := types.Actor{Nonce: 2, Balance: big.NewInt(200000)} + + gomock.InOrder( + mockApi.EXPECT().ChainHead(ctx).Return(head, nil), + mockApi.EXPECT().ChainGetTipSet(ctx, head.Parents()).Return(first, nil), + mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil), + mockApi.EXPECT().StateGetActor(ctx, senderAddr, head.Key()).Return(&actor, nil), + ) + + err = app.Run([]string{"mpool", "stat", "--basefee-lookback", "1"}) + assert.NoError(t, err) + + assert.Contains(t, buf.String(), "Nonce past: 1") + }) +} + +func TestPending(t *testing.T) { + t.Run("all", func(t *testing.T) { + + app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolPending)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // create a signed message to be returned as a pending message + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + toAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + sm := mock.MkMessage(senderAddr, toAddr, 1, w) + + gomock.InOrder( + mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil), + ) + + err = app.Run([]string{"mpool", "pending", "--cids"}) + assert.NoError(t, err) + + assert.Contains(t, buf.String(), sm.Cid().String()) + }) + + t.Run("local", func(t *testing.T) { + + app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolPending)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // create a signed message to be returned as a pending message + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + toAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + sm := mock.MkMessage(senderAddr, toAddr, 1, w) + + gomock.InOrder( + mockApi.EXPECT().WalletList(ctx).Return([]address.Address{senderAddr}, nil), + mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil), + ) + + err = app.Run([]string{"mpool", "pending", "--local"}) + assert.NoError(t, err) + + assert.Contains(t, buf.String(), sm.Cid().String()) + }) + + t.Run("to", func(t *testing.T) { + + app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolPending)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // create a signed message to be returned as a pending message + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + toAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + sm := mock.MkMessage(senderAddr, toAddr, 1, w) + + gomock.InOrder( + mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil), + ) + + err = app.Run([]string{"mpool", "pending", "--to", sm.Message.To.String()}) + assert.NoError(t, err) + + assert.Contains(t, buf.String(), sm.Cid().String()) + }) + + t.Run("from", func(t *testing.T) { + + app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolPending)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // create a signed message to be returned as a pending message + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + toAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + sm := mock.MkMessage(senderAddr, toAddr, 1, w) + + gomock.InOrder( + mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil), + ) + + err = app.Run([]string{"mpool", "pending", "--from", sm.Message.From.String()}) + assert.NoError(t, err) + + assert.Contains(t, buf.String(), sm.Cid().String()) + }) + +} + +func TestReplace(t *testing.T) { + t.Run("manual", func(t *testing.T) { + app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolReplaceCmd)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // create a signed message to be returned as a pending message + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + toAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + sm := mock.MkMessage(senderAddr, toAddr, 1, w) + + gomock.InOrder( + mockApi.EXPECT().ChainGetMessage(ctx, sm.Cid()).Return(&sm.Message, nil), + mockApi.EXPECT().ChainHead(ctx).Return(nil, nil), + mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil), + mockApi.EXPECT().WalletSignMessage(ctx, sm.Message.From, &sm.Message).Return(sm, nil), + mockApi.EXPECT().MpoolPush(ctx, sm).Return(sm.Cid(), nil), + ) + + err = app.Run([]string{"mpool", "replace", "--gas-premium", "1", "--gas-feecap", "100", sm.Cid().String()}) + + assert.NoError(t, err) + assert.Contains(t, buf.String(), sm.Cid().String()) + }) + + t.Run("auto", func(t *testing.T) { + app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolReplaceCmd)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // create a signed message to be returned as a pending message + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + toAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + sm := mock.MkMessage(senderAddr, toAddr, 1, w) + + // gas fee param should be equal to the one passed in the cli invocation (used below) + maxFee := "1000000" + parsedFee, err := types.ParseFIL(maxFee) + if err != nil { + t.Fatal(err) + } + mss := api.MessageSendSpec{MaxFee: abi.TokenAmount(parsedFee)} + + gomock.InOrder( + mockApi.EXPECT().ChainGetMessage(ctx, sm.Cid()).Return(&sm.Message, nil), + mockApi.EXPECT().ChainHead(ctx).Return(nil, nil), + mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil), + // use gomock.any to match the message in expected api calls + // since the replace function modifies the message between calls, it would be pointless to try to match the exact argument + mockApi.EXPECT().GasEstimateMessageGas(ctx, gomock.Any(), &mss, types.EmptyTSK).Return(&sm.Message, nil), + mockApi.EXPECT().WalletSignMessage(ctx, sm.Message.From, gomock.Any()).Return(sm, nil), + mockApi.EXPECT().MpoolPush(ctx, sm).Return(sm.Cid(), nil), + ) + + err = app.Run([]string{"mpool", "replace", "--auto", "--fee-limit", maxFee, sm.Cid().String()}) + + assert.NoError(t, err) + assert.Contains(t, buf.String(), sm.Cid().String()) + }) +} + +func TestFindMsg(t *testing.T) { + t.Run("from", func(t *testing.T) { + app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolFindCmd)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // create a signed message to be returned as a pending message + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + toAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + sm := mock.MkMessage(senderAddr, toAddr, 1, w) + + gomock.InOrder( + mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil), + ) + + err = app.Run([]string{"mpool", "find", "--from", sm.Message.From.String()}) + + assert.NoError(t, err) + assert.Contains(t, buf.String(), sm.Cid().String()) + }) + + t.Run("to", func(t *testing.T) { + app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolFindCmd)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // create a signed message to be returned as a pending message + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + toAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + sm := mock.MkMessage(senderAddr, toAddr, 1, w) + + gomock.InOrder( + mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil), + ) + + err = app.Run([]string{"mpool", "find", "--to", sm.Message.To.String()}) + + assert.NoError(t, err) + assert.Contains(t, buf.String(), sm.Cid().String()) + }) + + t.Run("method", func(t *testing.T) { + app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolFindCmd)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // create a signed message to be returned as a pending message + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + toAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + sm := mock.MkMessage(senderAddr, toAddr, 1, w) + + gomock.InOrder( + mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil), + ) + + err = app.Run([]string{"mpool", "find", "--method", sm.Message.Method.String()}) + + assert.NoError(t, err) + assert.Contains(t, buf.String(), sm.Cid().String()) + }) +} + +func TestGasPerf(t *testing.T) { + t.Run("all", func(t *testing.T) { + app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolGasPerfCmd)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // add blocks to the chain + first := mock.TipSet(mock.MkBlock(nil, 5, 4)) + head := mock.TipSet(mock.MkBlock(first, 15, 7)) + + // create a signed message to be returned as a pending message + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + toAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + sm := mock.MkMessage(senderAddr, toAddr, 13, w) + + gomock.InOrder( + mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil), + mockApi.EXPECT().ChainHead(ctx).Return(head, nil), + ) + + err = app.Run([]string{"mpool", "gas-perf", "--all", "true"}) + assert.NoError(t, err) + + assert.Contains(t, buf.String(), sm.Message.From.String()) + assert.Contains(t, buf.String(), fmt.Sprint(sm.Message.Nonce)) + }) + + t.Run("local", func(t *testing.T) { + app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolGasPerfCmd)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // add blocks to the chain + first := mock.TipSet(mock.MkBlock(nil, 5, 4)) + head := mock.TipSet(mock.MkBlock(first, 15, 7)) + + // create a signed message to be returned as a pending message + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + toAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + sm := mock.MkMessage(senderAddr, toAddr, 13, w) + + gomock.InOrder( + mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil), + mockApi.EXPECT().WalletList(ctx).Return([]address.Address{senderAddr}, nil), + mockApi.EXPECT().ChainHead(ctx).Return(head, nil), + ) + + err = app.Run([]string{"mpool", "gas-perf"}) + assert.NoError(t, err) + + assert.Contains(t, buf.String(), sm.Message.From.String()) + assert.Contains(t, buf.String(), fmt.Sprint(sm.Message.Nonce)) + }) +} + +func TestConfig(t *testing.T) { + t.Run("get", func(t *testing.T) { + app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolConfig)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + + mpoolCfg := &types.MpoolConfig{PriorityAddrs: []address.Address{senderAddr}, SizeLimitHigh: 1234567, SizeLimitLow: 6, ReplaceByFeeRatio: 0.25} + gomock.InOrder( + mockApi.EXPECT().MpoolGetConfig(ctx).Return(mpoolCfg, nil), + ) + + err = app.Run([]string{"mpool", "config"}) + assert.NoError(t, err) + + assert.Contains(t, buf.String(), mpoolCfg.PriorityAddrs[0].String()) + assert.Contains(t, buf.String(), fmt.Sprint(mpoolCfg.SizeLimitHigh)) + assert.Contains(t, buf.String(), fmt.Sprint(mpoolCfg.SizeLimitLow)) + assert.Contains(t, buf.String(), fmt.Sprint(mpoolCfg.ReplaceByFeeRatio)) + }) + + t.Run("set", func(t *testing.T) { + app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolConfig)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + + mpoolCfg := &types.MpoolConfig{PriorityAddrs: []address.Address{senderAddr}, SizeLimitHigh: 234567, SizeLimitLow: 3, ReplaceByFeeRatio: 0.33} + gomock.InOrder( + mockApi.EXPECT().MpoolSetConfig(ctx, mpoolCfg).Return(nil), + ) + + bytes, err := json.Marshal(mpoolCfg) + if err != nil { + t.Fatal(err) + } + + err = app.Run([]string{"mpool", "config", string(bytes)}) + assert.NoError(t, err) + }) +} From c8cd8bb591c44a1d5dc5f2aa6355e9a0bcd19763 Mon Sep 17 00:00:00 2001 From: Darko Brdareski Date: Mon, 21 Feb 2022 12:32:53 +0100 Subject: [PATCH 221/385] Add stm annotations --- cli/mpool_test.go | 60 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/cli/mpool_test.go b/cli/mpool_test.go index 1bb45fd6247..19423349069 100644 --- a/cli/mpool_test.go +++ b/cli/mpool_test.go @@ -1,3 +1,4 @@ +//stm: #integration package cli import ( @@ -54,6 +55,7 @@ func TestStat(t *testing.T) { mockApi.EXPECT().StateGetActor(ctx, senderAddr, head.Key()).Return(&actor, nil), ) + //stm: @CLI_MEMPOOL_STAT_002 err = app.Run([]string{"mpool", "stat", "--basefee-lookback", "1", "--local"}) assert.NoError(t, err) @@ -93,6 +95,7 @@ func TestStat(t *testing.T) { mockApi.EXPECT().StateGetActor(ctx, senderAddr, head.Key()).Return(&actor, nil), ) + //stm: @CLI_MEMPOOL_STAT_001 err = app.Run([]string{"mpool", "stat", "--basefee-lookback", "1"}) assert.NoError(t, err) @@ -125,6 +128,7 @@ func TestPending(t *testing.T) { mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil), ) + //stm: @CLI_MEMPOOL_PENDING_001 err = app.Run([]string{"mpool", "pending", "--cids"}) assert.NoError(t, err) @@ -156,6 +160,7 @@ func TestPending(t *testing.T) { mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil), ) + //stm: @CLI_MEMPOOL_PENDING_002 err = app.Run([]string{"mpool", "pending", "--local"}) assert.NoError(t, err) @@ -186,6 +191,7 @@ func TestPending(t *testing.T) { mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil), ) + //stm: @CLI_MEMPOOL_PENDING_003 err = app.Run([]string{"mpool", "pending", "--to", sm.Message.To.String()}) assert.NoError(t, err) @@ -216,6 +222,7 @@ func TestPending(t *testing.T) { mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil), ) + //stm: @CLI_MEMPOOL_PENDING_004 err = app.Run([]string{"mpool", "pending", "--from", sm.Message.From.String()}) assert.NoError(t, err) @@ -252,6 +259,7 @@ func TestReplace(t *testing.T) { mockApi.EXPECT().MpoolPush(ctx, sm).Return(sm.Cid(), nil), ) + //stm: @CLI_MEMPOOL_REPLACE_002 err = app.Run([]string{"mpool", "replace", "--gas-premium", "1", "--gas-feecap", "100", sm.Cid().String()}) assert.NoError(t, err) @@ -296,11 +304,56 @@ func TestReplace(t *testing.T) { mockApi.EXPECT().MpoolPush(ctx, sm).Return(sm.Cid(), nil), ) + //stm: @CLI_MEMPOOL_REPLACE_002 err = app.Run([]string{"mpool", "replace", "--auto", "--fee-limit", maxFee, sm.Cid().String()}) assert.NoError(t, err) assert.Contains(t, buf.String(), sm.Cid().String()) }) + + t.Run("sender / nonce", func(t *testing.T) { + app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolReplaceCmd)) + defer done() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // create a signed message to be returned as a pending message + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + toAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + sm := mock.MkMessage(senderAddr, toAddr, 1, w) + + // gas fee param should be equal to the one passed in the cli invocation (used below) + maxFee := "1000000" + parsedFee, err := types.ParseFIL(maxFee) + if err != nil { + t.Fatal(err) + } + mss := api.MessageSendSpec{MaxFee: abi.TokenAmount(parsedFee)} + + gomock.InOrder( + mockApi.EXPECT().ChainHead(ctx).Return(nil, nil), + mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil), + // use gomock.any to match the message in expected api calls + // since the replace function modifies the message between calls, it would be pointless to try to match the exact argument + mockApi.EXPECT().GasEstimateMessageGas(ctx, gomock.Any(), &mss, types.EmptyTSK).Return(&sm.Message, nil), + mockApi.EXPECT().WalletSignMessage(ctx, sm.Message.From, gomock.Any()).Return(sm, nil), + mockApi.EXPECT().MpoolPush(ctx, sm).Return(sm.Cid(), nil), + ) + + //stm: @CLI_MEMPOOL_REPLACE_001 + err = app.Run([]string{"mpool", "replace", "--auto", "--fee-limit", maxFee, sm.Message.From.String(), fmt.Sprint(sm.Message.Nonce)}) + + assert.NoError(t, err) + assert.Contains(t, buf.String(), sm.Cid().String()) + }) } func TestFindMsg(t *testing.T) { @@ -327,6 +380,7 @@ func TestFindMsg(t *testing.T) { mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil), ) + //stm: @CLI_MEMPOOL_FIND_001 err = app.Run([]string{"mpool", "find", "--from", sm.Message.From.String()}) assert.NoError(t, err) @@ -356,6 +410,7 @@ func TestFindMsg(t *testing.T) { mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil), ) + //stm: @CLI_MEMPOOL_FIND_002 err = app.Run([]string{"mpool", "find", "--to", sm.Message.To.String()}) assert.NoError(t, err) @@ -385,6 +440,7 @@ func TestFindMsg(t *testing.T) { mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil), ) + //stm: @CLI_MEMPOOL_FIND_003 err = app.Run([]string{"mpool", "find", "--method", sm.Message.Method.String()}) assert.NoError(t, err) @@ -421,6 +477,7 @@ func TestGasPerf(t *testing.T) { mockApi.EXPECT().ChainHead(ctx).Return(head, nil), ) + //stm: @CLI_MEMPOOL_GAS_PERF_002 err = app.Run([]string{"mpool", "gas-perf", "--all", "true"}) assert.NoError(t, err) @@ -457,6 +514,7 @@ func TestGasPerf(t *testing.T) { mockApi.EXPECT().ChainHead(ctx).Return(head, nil), ) + //stm: @CLI_MEMPOOL_GAS_PERF_001 err = app.Run([]string{"mpool", "gas-perf"}) assert.NoError(t, err) @@ -484,6 +542,7 @@ func TestConfig(t *testing.T) { mockApi.EXPECT().MpoolGetConfig(ctx).Return(mpoolCfg, nil), ) + //stm: @CLI_MEMPOOL_CONFIG_001 err = app.Run([]string{"mpool", "config"}) assert.NoError(t, err) @@ -516,6 +575,7 @@ func TestConfig(t *testing.T) { t.Fatal(err) } + //stm: @CLI_MEMPOOL_CONFIG_002 err = app.Run([]string{"mpool", "config", string(bytes)}) assert.NoError(t, err) }) From 87c63e2cb739207a31e9ebb53fa9b35c226304da Mon Sep 17 00:00:00 2001 From: Darko Brdareski Date: Mon, 21 Feb 2022 12:33:07 +0100 Subject: [PATCH 222/385] Add stm file annotation --- cli/chain_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cli/chain_test.go b/cli/chain_test.go index 48c4af05de2..f525a0b3589 100644 --- a/cli/chain_test.go +++ b/cli/chain_test.go @@ -1,3 +1,4 @@ +//stm: #integration package cli import ( From 56926b349ae655f949152cdfe02f038325ab22fe Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Mon, 21 Feb 2022 18:27:51 +0400 Subject: [PATCH 223/385] changes as per review --- extern/storage-sealing/input.go | 6 +++--- extern/storage-sealing/sealing.go | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/extern/storage-sealing/input.go b/extern/storage-sealing/input.go index 7243c472b92..8e911860548 100644 --- a/extern/storage-sealing/input.go +++ b/extern/storage-sealing/input.go @@ -315,7 +315,7 @@ func (m *Sealing) SectorAddPieceToAny(ctx context.Context, size abi.UnpaddedPiec m.inputLk.Unlock() select { case <-pp.doneCh: - res := pp.resp.Load().(*pieceAcceptResp) + res := pp.resp return api.SectorOffset{Sector: res.sn, Offset: res.offset.Padded()}, res.err case <-ctx.Done(): return api.SectorOffset{}, ctx.Err() @@ -331,7 +331,7 @@ func (m *Sealing) SectorAddPieceToAny(ctx context.Context, size abi.UnpaddedPiec assigned: false, } pp.accepted = func(sn abi.SectorNumber, offset abi.UnpaddedPieceSize, err error) { - pp.resp.Store(&pieceAcceptResp{sn, offset, err}) + pp.resp = &pieceAcceptResp{sn, offset, err} close(pp.doneCh) } @@ -345,7 +345,7 @@ func (m *Sealing) SectorAddPieceToAny(ctx context.Context, size abi.UnpaddedPiec select { case <-doneCh: - res := pp.resp.Load().(*pieceAcceptResp) + res := pp.resp return api.SectorOffset{Sector: res.sn, Offset: res.offset.Padded()}, res.err case <-ctx.Done(): return api.SectorOffset{}, ctx.Err() diff --git a/extern/storage-sealing/sealing.go b/extern/storage-sealing/sealing.go index abfed55c79e..907d7cdfdd0 100644 --- a/extern/storage-sealing/sealing.go +++ b/extern/storage-sealing/sealing.go @@ -4,7 +4,6 @@ import ( "context" "errors" "sync" - "sync/atomic" "time" "github.com/ipfs/go-cid" @@ -149,7 +148,7 @@ type pieceAcceptResp struct { type pendingPiece struct { doneCh chan struct{} - resp atomic.Value + resp *pieceAcceptResp size abi.UnpaddedPieceSize deal api.PieceDealInfo From 675012fe1c1bfe380f77da0a43333374d65d71e1 Mon Sep 17 00:00:00 2001 From: Darko Brdareski Date: Mon, 21 Feb 2022 16:49:07 +0100 Subject: [PATCH 224/385] Fix matching for TestInspectUsage --- cli/chain_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/chain_test.go b/cli/chain_test.go index f525a0b3589..efd1db14d9e 100644 --- a/cli/chain_test.go +++ b/cli/chain_test.go @@ -325,7 +325,7 @@ func TestInspectUsage(t *testing.T) { // check for gas by sender assert.Contains(t, out, "By Sender") // check for gas by method - assert.Contains(t, out, "Send") + assert.Contains(t, out, "By Method:\nSend") }) } From 580fa86ea3f173b6d8b7689f31050b16f7ffa075 Mon Sep 17 00:00:00 2001 From: Darko Brdareski Date: Mon, 21 Feb 2022 17:57:01 +0100 Subject: [PATCH 225/385] Change annotation to #cli --- cli/chain_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/chain_test.go b/cli/chain_test.go index efd1db14d9e..0b3cce728ff 100644 --- a/cli/chain_test.go +++ b/cli/chain_test.go @@ -1,4 +1,4 @@ -//stm: #integration +//stm: #cli package cli import ( From ad4acf3baab003a142823e4be281ed579a6b3a83 Mon Sep 17 00:00:00 2001 From: Darko Brdareski Date: Mon, 21 Feb 2022 17:58:00 +0100 Subject: [PATCH 226/385] Fix lint issues --- cli/mpool_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cli/mpool_test.go b/cli/mpool_test.go index 19423349069..47ded7f1d3e 100644 --- a/cli/mpool_test.go +++ b/cli/mpool_test.go @@ -1,4 +1,4 @@ -//stm: #integration +//stm: #cli package cli import ( @@ -33,7 +33,7 @@ func TestStat(t *testing.T) { head := mock.TipSet(mock.MkBlock(first, 15, 7)) // create a signed message to be returned as a pending message - w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + w, _ := wallet.NewWallet(wallet.NewMemKeyStore()) senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) @@ -74,7 +74,7 @@ func TestStat(t *testing.T) { head := mock.TipSet(mock.MkBlock(first, 15, 7)) // create a signed message to be returned as a pending message - w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + w, _ := wallet.NewWallet(wallet.NewMemKeyStore()) senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) @@ -113,7 +113,7 @@ func TestPending(t *testing.T) { defer cancel() // create a signed message to be returned as a pending message - w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + w, _ := wallet.NewWallet(wallet.NewMemKeyStore()) senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) From 7b203eae1bfc17dbe5fb38b7dd01725338c44864 Mon Sep 17 00:00:00 2001 From: Darko Brdareski Date: Mon, 21 Feb 2022 18:35:31 +0100 Subject: [PATCH 227/385] More lint issues fixed --- cli/mpool_test.go | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/cli/mpool_test.go b/cli/mpool_test.go index 47ded7f1d3e..d9eef452ca6 100644 --- a/cli/mpool_test.go +++ b/cli/mpool_test.go @@ -144,7 +144,7 @@ func TestPending(t *testing.T) { defer cancel() // create a signed message to be returned as a pending message - w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + w, _ := wallet.NewWallet(wallet.NewMemKeyStore()) senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) @@ -176,7 +176,7 @@ func TestPending(t *testing.T) { defer cancel() // create a signed message to be returned as a pending message - w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + w, _ := wallet.NewWallet(wallet.NewMemKeyStore()) senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) @@ -207,7 +207,7 @@ func TestPending(t *testing.T) { defer cancel() // create a signed message to be returned as a pending message - w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + w, _ := wallet.NewWallet(wallet.NewMemKeyStore()) senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) @@ -240,7 +240,7 @@ func TestReplace(t *testing.T) { defer cancel() // create a signed message to be returned as a pending message - w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + w, _ := wallet.NewWallet(wallet.NewMemKeyStore()) senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) @@ -274,7 +274,7 @@ func TestReplace(t *testing.T) { defer cancel() // create a signed message to be returned as a pending message - w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + w, _ := wallet.NewWallet(wallet.NewMemKeyStore()) senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) @@ -319,7 +319,7 @@ func TestReplace(t *testing.T) { defer cancel() // create a signed message to be returned as a pending message - w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + w, _ := wallet.NewWallet(wallet.NewMemKeyStore()) senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) @@ -365,7 +365,7 @@ func TestFindMsg(t *testing.T) { defer cancel() // create a signed message to be returned as a pending message - w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + w, _ := wallet.NewWallet(wallet.NewMemKeyStore()) senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) @@ -395,7 +395,7 @@ func TestFindMsg(t *testing.T) { defer cancel() // create a signed message to be returned as a pending message - w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + w, _ := wallet.NewWallet(wallet.NewMemKeyStore()) senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) @@ -425,7 +425,7 @@ func TestFindMsg(t *testing.T) { defer cancel() // create a signed message to be returned as a pending message - w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + w, _ := wallet.NewWallet(wallet.NewMemKeyStore()) senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) @@ -461,7 +461,7 @@ func TestGasPerf(t *testing.T) { head := mock.TipSet(mock.MkBlock(first, 15, 7)) // create a signed message to be returned as a pending message - w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + w, _ := wallet.NewWallet(wallet.NewMemKeyStore()) senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) @@ -497,7 +497,7 @@ func TestGasPerf(t *testing.T) { head := mock.TipSet(mock.MkBlock(first, 15, 7)) // create a signed message to be returned as a pending message - w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + w, _ := wallet.NewWallet(wallet.NewMemKeyStore()) senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) @@ -531,7 +531,7 @@ func TestConfig(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + w, _ := wallet.NewWallet(wallet.NewMemKeyStore()) senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) @@ -559,7 +559,7 @@ func TestConfig(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + w, _ := wallet.NewWallet(wallet.NewMemKeyStore()) senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) From 04bc4405c782f390538d9c8e2c9dae6a471951c5 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 21 Feb 2022 14:29:17 +0000 Subject: [PATCH 228/385] fix: chain: check against the inclusion price at the correct height We need to use the height at which the messages will be executed, not the height of the previous tipset. This brings the gas checking for validation with the gas we actually _charge_ during message execution. This only matters for the Calico upgrade (the only upgrade where we changed the gas prices). This change could potentially cause a block at that height to be rejected if it includes a message with insufficient gas for inclusion. However, that _should_ have shown up as a miner penalty when we executed the blocks in the following tipset. Given that there were no miner penalties at 265199-265201, this change should be "safe". --- chain/consensus/filcns/filecoin.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chain/consensus/filcns/filecoin.go b/chain/consensus/filcns/filecoin.go index 0adb79191d4..3aa85c7c535 100644 --- a/chain/consensus/filcns/filecoin.go +++ b/chain/consensus/filcns/filecoin.go @@ -467,7 +467,7 @@ func (filec *FilecoinEC) checkBlockMessages(ctx context.Context, b *types.FullBl } nv := filec.sm.GetNetworkVersion(ctx, b.Header.Height) - pl := vm.PricelistByEpoch(baseTs.Height()) + pl := vm.PricelistByEpoch(b.Header.Height) var sumGasLimit int64 checkMsg := func(msg types.ChainMsg) error { m := msg.VMMessage() From 1234fcfd4f9ea8bf057b02fba72a92d80e0afff8 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 21 Feb 2022 14:39:11 +0000 Subject: [PATCH 229/385] fix: mempool: check messages against the next block's height Previously, we checked message gas/validity with the previous block's height. This doesn't affect consensus, but will help us avoid adding messages to the message pool that shouldn't be there. --- chain/messagepool/check.go | 2 +- chain/messagepool/messagepool.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/chain/messagepool/check.go b/chain/messagepool/check.go index 283c0d1194e..92cfb458a60 100644 --- a/chain/messagepool/check.go +++ b/chain/messagepool/check.go @@ -106,7 +106,7 @@ func (mp *MessagePool) checkMessages(ctx context.Context, msgs []*types.Message, curTs := mp.curTs mp.curTsLk.Unlock() - epoch := curTs.Height() + epoch := curTs.Height() + 1 var baseFee big.Int if len(curTs.Blocks()) > 0 { diff --git a/chain/messagepool/messagepool.go b/chain/messagepool/messagepool.go index 76647e331b3..1520d45b48f 100644 --- a/chain/messagepool/messagepool.go +++ b/chain/messagepool/messagepool.go @@ -628,7 +628,7 @@ func (mp *MessagePool) addLocal(ctx context.Context, m *types.SignedMessage) err // For non local messages, if the message cannot be included in the next 20 blocks it returns // a (soft) validation error. func (mp *MessagePool) verifyMsgBeforeAdd(m *types.SignedMessage, curTs *types.TipSet, local bool) (bool, error) { - epoch := curTs.Height() + epoch := curTs.Height() + 1 minGas := vm.PricelistByEpoch(epoch).OnChainMessage(m.ChainLength()) if err := m.VMMessage().ValidForBlockInclusion(minGas.Total(), build.NewestNetworkVersion); err != nil { From 8e62fec1d31ae4e087662d2e50d922fbbda3e201 Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Tue, 22 Feb 2022 13:48:39 +0400 Subject: [PATCH 230/385] address review --- extern/storage-sealing/input.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/storage-sealing/input.go b/extern/storage-sealing/input.go index 8e911860548..1ad85eb084f 100644 --- a/extern/storage-sealing/input.go +++ b/extern/storage-sealing/input.go @@ -322,7 +322,7 @@ func (m *Sealing) SectorAddPieceToAny(ctx context.Context, size abi.UnpaddedPiec } } - doneCh := make(chan struct{}, 1) + doneCh := make(chan struct{}) pp := &pendingPiece{ doneCh: doneCh, size: size, From a05a462c8c9110456c145a69ca202a57fd139940 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 22 Feb 2022 10:48:47 +0100 Subject: [PATCH 231/385] market utils: Support unixfsnode in TraverseDag --- go.mod | 1 + markets/utils/selectors.go | 2 ++ 2 files changed, 3 insertions(+) diff --git a/go.mod b/go.mod index 293a17bc4da..e8a97298eb6 100644 --- a/go.mod +++ b/go.mod @@ -100,6 +100,7 @@ require ( github.com/ipfs/go-metrics-prometheus v0.0.2 github.com/ipfs/go-path v0.0.7 github.com/ipfs/go-unixfs v0.3.1 + github.com/ipfs/go-unixfsnode v1.2.0 github.com/ipfs/interface-go-ipfs-core v0.4.0 github.com/ipld/go-car v0.3.3 github.com/ipld/go-car/v2 v2.1.1 diff --git a/markets/utils/selectors.go b/markets/utils/selectors.go index 7d40ba6dd85..e1009d1ff90 100644 --- a/markets/utils/selectors.go +++ b/markets/utils/selectors.go @@ -11,6 +11,7 @@ import ( "github.com/ipfs/go-cid" mdagipld "github.com/ipfs/go-ipld-format" + "github.com/ipfs/go-unixfsnode" dagpb "github.com/ipld/go-codec-dagpb" "github.com/ipld/go-ipld-prime" cidlink "github.com/ipld/go-ipld-prime/linking/cid" @@ -62,6 +63,7 @@ func TraverseDag( return bytes.NewBuffer(node.RawData()), nil } + unixfsnode.AddUnixFSReificationToLinkSystem(&linkSystem) // this is how we pull the start node out of the DS startLink := cidlink.Link{Cid: startFrom} From 012cf96d600c669fb90f87dec501b774a3069b12 Mon Sep 17 00:00:00 2001 From: vyzo Date: Tue, 22 Feb 2022 12:19:26 +0200 Subject: [PATCH 232/385] update go-libp2p to v0.18.0-rc5 --- go.mod | 4 ++-- go.sum | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 293a17bc4da..0fae1713ce2 100644 --- a/go.mod +++ b/go.mod @@ -110,7 +110,7 @@ require ( github.com/kelseyhightower/envconfig v1.4.0 github.com/libp2p/go-buffer-pool v0.0.2 github.com/libp2p/go-eventbus v0.2.1 - github.com/libp2p/go-libp2p v0.18.0-rc4 + github.com/libp2p/go-libp2p v0.18.0-rc5 github.com/libp2p/go-libp2p-connmgr v0.3.1 // indirect github.com/libp2p/go-libp2p-core v0.14.0 github.com/libp2p/go-libp2p-discovery v0.6.0 @@ -122,7 +122,7 @@ require ( github.com/libp2p/go-libp2p-record v0.1.3 github.com/libp2p/go-libp2p-resource-manager v0.1.4 github.com/libp2p/go-libp2p-routing-helpers v0.2.3 - github.com/libp2p/go-libp2p-swarm v0.10.1 + github.com/libp2p/go-libp2p-swarm v0.10.2 github.com/libp2p/go-libp2p-tls v0.3.1 github.com/libp2p/go-libp2p-yamux v0.8.2 github.com/libp2p/go-maddr-filter v0.1.0 diff --git a/go.sum b/go.sum index 292747fc834..417267e376f 100644 --- a/go.sum +++ b/go.sum @@ -995,8 +995,8 @@ github.com/libp2p/go-libp2p v0.14.4/go.mod h1:EIRU0Of4J5S8rkockZM7eJp2S0UrCyi55m github.com/libp2p/go-libp2p v0.16.0/go.mod h1:ump42BsirwAWxKzsCiFnTtN1Yc+DuPu76fyMX364/O4= github.com/libp2p/go-libp2p v0.17.0/go.mod h1:Fkin50rsGdv5mm5BshBUtPRZknt9esfmYXBOYcwOTgw= github.com/libp2p/go-libp2p v0.18.0-rc1/go.mod h1:RgYlH7IIWHXREimC92bw5Lg1V2R5XmSzuLHb5fTnr+8= -github.com/libp2p/go-libp2p v0.18.0-rc4 h1:OUsSbeu7q+Ck/bV9wHDxFzb08ORqBupHhpCmRBhWrJ8= -github.com/libp2p/go-libp2p v0.18.0-rc4/go.mod h1:wzmsk1ioOq9FGQys2BN5BIw4nugP6+R+CyW3JbPEbbs= +github.com/libp2p/go-libp2p v0.18.0-rc5 h1:88wWDHb9nNo0vBNCupLde3OTnFAkugOCNkrDfl3ivK4= +github.com/libp2p/go-libp2p v0.18.0-rc5/go.mod h1:aZPS5l84bDvCvP4jkyEUT/J6YOpUq33Fgqrs3K59mpI= github.com/libp2p/go-libp2p-asn-util v0.0.0-20200825225859-85005c6cf052/go.mod h1:nRMRTab+kZuk0LnKZpxhOVH/ndsdr2Nr//Zltc/vwgo= github.com/libp2p/go-libp2p-asn-util v0.1.0 h1:rABPCO77SjdbJ/eJ/ynIo8vWICy1VEnL5JAxJbQLo1E= github.com/libp2p/go-libp2p-asn-util v0.1.0/go.mod h1:wu+AnM9Ii2KgO5jMmS1rz9dvzTdj8BXqsPR9HR0XB7I= @@ -1182,8 +1182,8 @@ github.com/libp2p/go-libp2p-swarm v0.5.3/go.mod h1:NBn7eNW2lu568L7Ns9wdFrOhgRlkR github.com/libp2p/go-libp2p-swarm v0.8.0/go.mod h1:sOMp6dPuqco0r0GHTzfVheVBh6UEL0L1lXUZ5ot2Fvc= github.com/libp2p/go-libp2p-swarm v0.9.0/go.mod h1:2f8d8uxTJmpeqHF/1ujjdXZp+98nNIbujVOMEZxCbZ8= github.com/libp2p/go-libp2p-swarm v0.10.0/go.mod h1:71ceMcV6Rg/0rIQ97rsZWMzto1l9LnNquef+efcRbmA= -github.com/libp2p/go-libp2p-swarm v0.10.1 h1:lXW3pgGt+BVmkzcFX61erX7l6Lt+WAamNhwa2Kf3eJM= -github.com/libp2p/go-libp2p-swarm v0.10.1/go.mod h1:Pdkq0QU5a+qu+oyqIV3bknMsnzk9lnNyKvB9acJ5aZs= +github.com/libp2p/go-libp2p-swarm v0.10.2 h1:UaXf+CTq6Ns1N2V1EgqJ9Q3xaRsiN7ImVlDMpirMAWw= +github.com/libp2p/go-libp2p-swarm v0.10.2/go.mod h1:Pdkq0QU5a+qu+oyqIV3bknMsnzk9lnNyKvB9acJ5aZs= github.com/libp2p/go-libp2p-testing v0.0.1/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= github.com/libp2p/go-libp2p-testing v0.0.2/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= github.com/libp2p/go-libp2p-testing v0.0.3/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= @@ -1299,8 +1299,9 @@ github.com/libp2p/go-tcp-transport v0.2.3/go.mod h1:9dvr03yqrPyYGIEN6Dy5UvdJZjyP github.com/libp2p/go-tcp-transport v0.2.4/go.mod h1:9dvr03yqrPyYGIEN6Dy5UvdJZjyPFvl1S/igQ5QD1SU= github.com/libp2p/go-tcp-transport v0.2.7/go.mod h1:lue9p1b3VmZj1MhhEGB/etmvF/nBQ0X9CW2DutBT3MM= github.com/libp2p/go-tcp-transport v0.4.0/go.mod h1:0y52Rwrn4076xdJYu/51/qJIdxz+EWDAOG2S45sV3VI= -github.com/libp2p/go-tcp-transport v0.5.0 h1:3ZPW8HAuyRAuFzyabE0hSrCXKKSWzROnZZX7DtcIatY= github.com/libp2p/go-tcp-transport v0.5.0/go.mod h1:UPPL0DIjQqiWRwVAb+CEQlaAG0rp/mCqJfIhFcLHc4Y= +github.com/libp2p/go-tcp-transport v0.5.1 h1:edOOs688VLZAozWC7Kj5/6HHXKNwi9M6wgRmmLa8M6Q= +github.com/libp2p/go-tcp-transport v0.5.1/go.mod h1:UPPL0DIjQqiWRwVAb+CEQlaAG0rp/mCqJfIhFcLHc4Y= github.com/libp2p/go-testutil v0.0.1/go.mod h1:iAcJc/DKJQanJ5ws2V+u5ywdL2n12X1WbbEG+Jjy69I= github.com/libp2p/go-testutil v0.1.0/go.mod h1:81b2n5HypcVyrCg/MJx4Wgfp/VHojytjVe/gLzZ2Ehc= github.com/libp2p/go-ws-transport v0.0.5/go.mod h1:Qbl4BxPfXXhhd/o0wcrgoaItHqA9tnZjoFZnxykuaXU= From f0f2b3e1f42d1f32db295e115ff5230013d99353 Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Tue, 22 Feb 2022 14:22:51 +0400 Subject: [PATCH 233/385] changes as per review --- extern/storage-sealing/input.go | 41 +++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/extern/storage-sealing/input.go b/extern/storage-sealing/input.go index 1ad85eb084f..c999badfde2 100644 --- a/extern/storage-sealing/input.go +++ b/extern/storage-sealing/input.go @@ -313,15 +313,35 @@ func (m *Sealing) SectorAddPieceToAny(ctx context.Context, size abi.UnpaddedPiec m.inputLk.Lock() if pp, exist := m.pendingPieces[proposalCID(deal)]; exist { m.inputLk.Unlock() - select { - case <-pp.doneCh: - res := pp.resp + + // we already have a pre-existing add piece call for this deal, let's wait for it to finish and see if it's successful + for { + res, err := waitAddPieceResp(ctx, pp) + if err != nil { + return api.SectorOffset{}, err + } + // there was an error waiting for a pre-existing add piece call, let's retry + if res.err != nil { + m.inputLk.Lock() + pp = m.addPendingPiece(ctx, size, data, deal, sp) + m.inputLk.Unlock() + continue + } + // all good, return the response return api.SectorOffset{Sector: res.sn, Offset: res.offset.Padded()}, res.err - case <-ctx.Done(): - return api.SectorOffset{}, ctx.Err() } } + pp := m.addPendingPiece(ctx, size, data, deal, sp) + m.inputLk.Unlock() + res, err := waitAddPieceResp(ctx, pp) + if err != nil { + return api.SectorOffset{}, err + } + return api.SectorOffset{Sector: res.sn, Offset: res.offset.Padded()}, res.err +} + +func (m *Sealing) addPendingPiece(ctx context.Context, size abi.UnpaddedPieceSize, data storage.Data, deal api.PieceDealInfo, sp abi.RegisteredSealProof) *pendingPiece { doneCh := make(chan struct{}) pp := &pendingPiece{ doneCh: doneCh, @@ -337,18 +357,21 @@ func (m *Sealing) SectorAddPieceToAny(ctx context.Context, size abi.UnpaddedPiec m.pendingPieces[proposalCID(deal)] = pp go func() { - defer m.inputLk.Unlock() if err := m.updateInput(ctx, sp); err != nil { log.Errorf("%+v", err) } }() + return pp +} + +func waitAddPieceResp(ctx context.Context, pp *pendingPiece) (*pieceAcceptResp, error) { select { - case <-doneCh: + case <-pp.doneCh: res := pp.resp - return api.SectorOffset{Sector: res.sn, Offset: res.offset.Padded()}, res.err + return res, nil case <-ctx.Done(): - return api.SectorOffset{}, ctx.Err() + return nil, ctx.Err() } } From 10c939bc36635cc5aea0970034e14e03b1f655e0 Mon Sep 17 00:00:00 2001 From: Darko Brdareski Date: Tue, 22 Feb 2022 14:54:56 +0100 Subject: [PATCH 234/385] Remove leftover logging from sync_manager_test --- chain/sync_manager_test.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/chain/sync_manager_test.go b/chain/sync_manager_test.go index d91ab1788b3..bbd690d230c 100644 --- a/chain/sync_manager_test.go +++ b/chain/sync_manager_test.go @@ -247,7 +247,6 @@ func TestSyncManagerBucketSet(t *testing.T) { ts2 := mock.TipSet(mock.MkBlock(ts1, 1, 0)) bucket1 := newSyncTargetBucket(ts1, ts2) bucketSet := syncBucketSet{buckets: []*syncTargetBucket{bucket1}} - fmt.Println("bucketSet: ", bucketSet.String()) // inserting a tipset (potential sync target) from an existing chain, should add to an existing bucket //stm: @CHAIN_SYNCER_ADD_SYNC_TARGET_001 @@ -255,7 +254,6 @@ func TestSyncManagerBucketSet(t *testing.T) { bucketSet.Insert(ts3) require.Equal(t, 1, len(bucketSet.buckets)) require.Equal(t, 3, len(bucketSet.buckets[0].tips)) - fmt.Println("bucketSet: ", bucketSet.String()) // inserting a tipset from new chain, should create a new bucket ts4fork := mock.TipSet(mock.MkBlock(nil, 1, 1)) @@ -263,7 +261,6 @@ func TestSyncManagerBucketSet(t *testing.T) { require.Equal(t, 2, len(bucketSet.buckets)) require.Equal(t, 3, len(bucketSet.buckets[0].tips)) require.Equal(t, 1, len(bucketSet.buckets[1].tips)) - fmt.Println("bucketSet: ", bucketSet.String()) // Pop removes the best bucket (best sync target), e.g. bucket1 //stm: @CHAIN_SYNCER_SELECT_SYNC_TARGET_001 From fce9ff237a92cf75b51abd92474e1da7cd01b442 Mon Sep 17 00:00:00 2001 From: TheMenko Date: Tue, 22 Feb 2022 15:35:46 +0100 Subject: [PATCH 235/385] add fmt output checks --- cli/wallet.go | 36 +++++++++++++++++++--------- cli/wallet_test.go | 59 +++++++++++++++++++++++++++++++++------------- 2 files changed, 67 insertions(+), 28 deletions(-) diff --git a/cli/wallet.go b/cli/wallet.go index 9faa10677dd..c14bf814260 100644 --- a/cli/wallet.go +++ b/cli/wallet.go @@ -56,6 +56,8 @@ var walletNew = &cli.Command{ defer closer() ctx := ReqContext(cctx) + afmt := NewAppFmt(cctx.App) + t := cctx.Args().First() if t == "" { t = "secp256k1" @@ -66,7 +68,7 @@ var walletNew = &cli.Command{ return err } - fmt.Println(nk.String()) + afmt.Println(nk.String()) return nil }, @@ -187,6 +189,8 @@ var walletBalance = &cli.Command{ defer closer() ctx := ReqContext(cctx) + afmt := NewAppFmt(cctx.App) + var addr address.Address if cctx.Args().First() != "" { addr, err = address.NewFromString(cctx.Args().First()) @@ -203,9 +207,9 @@ var walletBalance = &cli.Command{ } if balance.Equals(types.NewInt(0)) { - fmt.Printf("%s (warning: may display 0 if chain sync in progress)\n", types.FIL(balance)) + afmt.Printf("%s (warning: may display 0 if chain sync in progress)\n", types.FIL(balance)) } else { - fmt.Printf("%s\n", types.FIL(balance)) + afmt.Printf("%s\n", types.FIL(balance)) } return nil @@ -223,12 +227,14 @@ var walletGetDefault = &cli.Command{ defer closer() ctx := ReqContext(cctx) + afmt := NewAppFmt(cctx.App) + addr, err := api.WalletDefaultAddress(ctx) if err != nil { return err } - fmt.Printf("%s\n", addr.String()) + afmt.Printf("%s\n", addr.String()) return nil }, } @@ -270,6 +276,8 @@ var walletExport = &cli.Command{ defer closer() ctx := ReqContext(cctx) + afmt := NewAppFmt(cctx.App) + if !cctx.Args().Present() { return fmt.Errorf("must specify key to export") } @@ -289,7 +297,7 @@ var walletExport = &cli.Command{ return err } - fmt.Println(hex.EncodeToString(b)) + afmt.Println(hex.EncodeToString(b)) return nil }, } @@ -444,6 +452,8 @@ var walletVerify = &cli.Command{ defer closer() ctx := ReqContext(cctx) + afmt := NewAppFmt(cctx.App) + if !cctx.Args().Present() || cctx.NArg() != 3 { return fmt.Errorf("must specify signing address, message, and signature to verify") } @@ -476,10 +486,10 @@ var walletVerify = &cli.Command{ return err } if ok { - fmt.Println("valid") + afmt.Println("valid") return nil } - fmt.Println("invalid") + afmt.Println("invalid") return NewCliError("CLI Verify called with invalid signature") }, } @@ -547,6 +557,8 @@ var walletMarketWithdraw = &cli.Command{ defer closer() ctx := ReqContext(cctx) + afmt := NewAppFmt(cctx.App) + var wallet address.Address if cctx.String("wallet") != "" { wallet, err = address.NewFromString(cctx.String("wallet")) @@ -622,7 +634,7 @@ var walletMarketWithdraw = &cli.Command{ return xerrors.Errorf("fund manager withdraw error: %w", err) } - fmt.Printf("WithdrawBalance message cid: %s\n", smsg) + afmt.Printf("WithdrawBalance message cid: %s\n", smsg) // wait for it to get mined into a block wait, err := api.StateWaitMsg(ctx, smsg, uint64(cctx.Int("confidence"))) @@ -632,7 +644,7 @@ var walletMarketWithdraw = &cli.Command{ // check it executed successfully if wait.Receipt.ExitCode != 0 { - fmt.Println(cctx.App.Writer, "withdrawal failed!") + afmt.Println(cctx.App.Writer, "withdrawal failed!") return err } @@ -647,7 +659,7 @@ var walletMarketWithdraw = &cli.Command{ return err } - fmt.Printf("Successfully withdrew %s \n", types.FIL(withdrawn)) + afmt.Printf("Successfully withdrew %s \n", types.FIL(withdrawn)) if withdrawn.LessThan(amt) { fmt.Printf("Note that this is less than the requested amount of %s \n", types.FIL(amt)) } @@ -681,6 +693,8 @@ var walletMarketAdd = &cli.Command{ defer closer() ctx := ReqContext(cctx) + afmt := NewAppFmt(cctx.App) + // Get amount param if !cctx.Args().Present() { return fmt.Errorf("must pass amount to add") @@ -722,7 +736,7 @@ var walletMarketAdd = &cli.Command{ return xerrors.Errorf("add balance error: %w", err) } - fmt.Printf("AddBalance message cid: %s\n", smsg) + afmt.Printf("AddBalance message cid: %s\n", smsg) return nil }, diff --git a/cli/wallet_test.go b/cli/wallet_test.go index f6861b37f8c..dbd998cf141 100644 --- a/cli/wallet_test.go +++ b/cli/wallet_test.go @@ -2,6 +2,9 @@ package cli import ( "context" + "encoding/hex" + "encoding/json" + "fmt" "testing" "github.com/filecoin-project/go-address" @@ -13,23 +16,26 @@ import ( types "github.com/filecoin-project/lotus/chain/types" "github.com/golang/mock/gomock" "github.com/ipfs/go-cid" + "github.com/multiformats/go-multihash" "github.com/stretchr/testify/assert" ) func TestWalletNew(t *testing.T) { - app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletNew)) + app, mockApi, buffer, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletNew)) defer done() ctx, cancel := context.WithCancel(context.Background()) defer cancel() keyType := types.KeyType("secp256k1") - address := address.Address{} + address, err := address.NewFromString("t0123") + assert.NoError(t, err) mockApi.EXPECT().WalletNew(ctx, keyType).Return(address, nil) - err := app.Run([]string{"wallet", "new"}) + err = app.Run([]string{"wallet", "new"}) assert.NoError(t, err) + assert.Contains(t, buffer.String(), address.String()) } func TestWalletList(t *testing.T) { @@ -109,7 +115,7 @@ func TestWalletList(t *testing.T) { } func TestWalletBalance(t *testing.T) { - app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletBalance)) + app, mockApi, buffer, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletBalance)) defer done() ctx, cancel := context.WithCancel(context.Background()) @@ -124,21 +130,24 @@ func TestWalletBalance(t *testing.T) { err = app.Run([]string{"wallet", "balance", "f01234"}) assert.NoError(t, err) + assert.Contains(t, buffer.String(), balance.String()) } func TestWalletGetDefault(t *testing.T) { - app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletGetDefault)) + app, mockApi, buffer, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletGetDefault)) defer done() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - addr := address.Address{} + addr, err := address.NewFromString("t0123") + assert.NoError(t, err) mockApi.EXPECT().WalletDefaultAddress(ctx).Return(addr, nil) - err := app.Run([]string{"wallet", "default"}) + err = app.Run([]string{"wallet", "default"}) assert.NoError(t, err) + assert.Contains(t, buffer.String(), addr.String()) } func TestWalletSetDefault(t *testing.T) { @@ -158,7 +167,7 @@ func TestWalletSetDefault(t *testing.T) { } func TestWalletExport(t *testing.T) { - app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletExport)) + app, mockApi, buffer, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletExport)) defer done() ctx, cancel := context.WithCancel(context.Background()) @@ -167,12 +176,19 @@ func TestWalletExport(t *testing.T) { addr, err := address.NewIDAddress(1234) assert.NoError(t, err) - keyInfo := types.KeyInfo{} + keyInfo := types.KeyInfo{ + Type: types.KTSecp256k1, + PrivateKey: []byte("0x000000000000000000001"), + } mockApi.EXPECT().WalletExport(ctx, addr).Return(&keyInfo, nil) + ki, err := json.Marshal(keyInfo) + assert.NoError(t, err) + err = app.Run([]string{"wallet", "export", "f01234"}) assert.NoError(t, err) + assert.Contains(t, buffer.String(), hex.EncodeToString(ki)) } func TestWalletSign(t *testing.T) { @@ -182,10 +198,12 @@ func TestWalletSign(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - addr, err := address.NewIDAddress(1234) + addr, err := address.NewFromString("f01234") + assert.NoError(t, err) + + msg, err := hex.DecodeString("01") assert.NoError(t, err) - msg := []byte{1} signature := crypto.Signature{} mockApi.EXPECT().WalletSign(ctx, addr, msg).Return(&signature, nil) @@ -195,7 +213,7 @@ func TestWalletSign(t *testing.T) { } func TestWalletVerify(t *testing.T) { - app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletVerify)) + app, mockApi, buffer, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletVerify)) defer done() ctx, cancel := context.WithCancel(context.Background()) @@ -214,6 +232,7 @@ func TestWalletVerify(t *testing.T) { err = app.Run([]string{"wallet", "verify", "f01234", "01", "01"}) assert.NoError(t, err) + assert.Contains(t, buffer.String(), "valid") } func TestWalletDelete(t *testing.T) { @@ -233,7 +252,7 @@ func TestWalletDelete(t *testing.T) { } func TestWalletMarketWithdraw(t *testing.T) { - app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletMarket)) + app, mockApi, buffer, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletMarket)) defer done() ctx, cancel := context.WithCancel(context.Background()) @@ -247,7 +266,9 @@ func TestWalletMarketWithdraw(t *testing.T) { Locked: big.NewInt(10), } - cid := cid.Cid{} + h, err := hex.DecodeString("12209cbc07c3f991725836a3aa2a581ca2029198aa420b9d99bc0e131d9f3e2cbe47") + assert.NoError(t, err) + cid := cid.NewCidV0(multihash.Multihash(h)) msgLookup := api.MsgLookup{} var networkVers apitypes.NetworkVersion @@ -264,10 +285,11 @@ func TestWalletMarketWithdraw(t *testing.T) { err = app.Run([]string{"wallet", "market", "withdraw", "--wallet", addr.String()}) assert.NoError(t, err) + assert.Contains(t, buffer.String(), fmt.Sprintf("WithdrawBalance message cid: %s", cid)) } func TestWalletMarketAdd(t *testing.T) { - app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletMarket)) + app, mockApi, buffer, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletMarket)) defer done() ctx, cancel := context.WithCancel(context.Background()) @@ -276,13 +298,16 @@ func TestWalletMarketAdd(t *testing.T) { toAddr := address.Address{} defaultAddr := address.Address{} - cid := cid.Cid{} + h, err := hex.DecodeString("12209cbc07c3f991725836a3aa2a581ca2029198aa420b9d99bc0e131d9f3e2cbe47") + assert.NoError(t, err) + cid := cid.NewCidV0(multihash.Multihash(h)) gomock.InOrder( mockApi.EXPECT().WalletDefaultAddress(ctx).Return(defaultAddr, nil), mockApi.EXPECT().MarketAddBalance(ctx, defaultAddr, toAddr, big.NewInt(80)).Return(cid, nil), ) - err := app.Run([]string{"wallet", "market", "add", "0.000000000000000080", "--address", toAddr.String()}) + err = app.Run([]string{"wallet", "market", "add", "0.000000000000000080", "--address", toAddr.String()}) assert.NoError(t, err) + assert.Contains(t, buffer.String(), fmt.Sprintf("AddBalance message cid: %s", cid)) } From cd64eba76c34592ffd621acfec893fe59e417734 Mon Sep 17 00:00:00 2001 From: TheMenko Date: Tue, 22 Feb 2022 16:00:01 +0100 Subject: [PATCH 236/385] add stm annotations --- cli/wallet_test.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/cli/wallet_test.go b/cli/wallet_test.go index dbd998cf141..e56b2cdbe95 100644 --- a/cli/wallet_test.go +++ b/cli/wallet_test.go @@ -1,3 +1,4 @@ +//stm: #cli package cli import ( @@ -33,6 +34,7 @@ func TestWalletNew(t *testing.T) { mockApi.EXPECT().WalletNew(ctx, keyType).Return(address, nil) + //stm: @CLI_WALLET_NEW_001 err = app.Run([]string{"wallet", "new"}) assert.NoError(t, err) assert.Contains(t, buffer.String(), address.String()) @@ -68,6 +70,7 @@ func TestWalletList(t *testing.T) { mockApi.EXPECT().StateGetActor(ctx, addr, key).Return(&actor, nil), ) + //stm: @CLI_WALLET_LIST_001 err := app.Run([]string{"wallet", "list", "addr-only"}) assert.NoError(t, err) }) @@ -86,6 +89,7 @@ func TestWalletList(t *testing.T) { mockApi.EXPECT().StateLookupID(ctx, addr, key).Return(addr, nil), ) + //stm: @CLI_WALLET_LIST_002 err := app.Run([]string{"wallet", "list", "--id"}) assert.NoError(t, err) }) @@ -109,6 +113,7 @@ func TestWalletList(t *testing.T) { mockApi.EXPECT().StateMarketBalance(ctx, addr, key).Return(balance, nil), ) + //stm: @CLI_WALLET_LIST_003 err := app.Run([]string{"wallet", "list", "--market"}) assert.NoError(t, err) }) @@ -128,6 +133,7 @@ func TestWalletBalance(t *testing.T) { mockApi.EXPECT().WalletBalance(ctx, addr).Return(balance, nil) + //stm: @CLI_WALLET_BALANCE_001 err = app.Run([]string{"wallet", "balance", "f01234"}) assert.NoError(t, err) assert.Contains(t, buffer.String(), balance.String()) @@ -145,6 +151,7 @@ func TestWalletGetDefault(t *testing.T) { mockApi.EXPECT().WalletDefaultAddress(ctx).Return(addr, nil) + //stm: @CLI_WALLET_GET_DEFAULT_001 err = app.Run([]string{"wallet", "default"}) assert.NoError(t, err) assert.Contains(t, buffer.String(), addr.String()) @@ -162,6 +169,7 @@ func TestWalletSetDefault(t *testing.T) { mockApi.EXPECT().WalletSetDefault(ctx, addr).Return(nil) + //stm: @CLI_WALLET_SET_DEFAULT_001 err = app.Run([]string{"wallet", "set-default", "f01234"}) assert.NoError(t, err) } @@ -186,6 +194,7 @@ func TestWalletExport(t *testing.T) { ki, err := json.Marshal(keyInfo) assert.NoError(t, err) + //stm: @CLI_WALLET_EXPORT_001 err = app.Run([]string{"wallet", "export", "f01234"}) assert.NoError(t, err) assert.Contains(t, buffer.String(), hex.EncodeToString(ki)) @@ -208,6 +217,7 @@ func TestWalletSign(t *testing.T) { mockApi.EXPECT().WalletSign(ctx, addr, msg).Return(&signature, nil) + //stm: @CLI_WALLET_SIGN_001 err = app.Run([]string{"wallet", "sign", "f01234", "01"}) assert.NoError(t, err) } @@ -230,6 +240,7 @@ func TestWalletVerify(t *testing.T) { mockApi.EXPECT().WalletVerify(ctx, addr, msg, &signature).Return(true, nil) + //stm: @CLI_WALLET_VERIFY_001 err = app.Run([]string{"wallet", "verify", "f01234", "01", "01"}) assert.NoError(t, err) assert.Contains(t, buffer.String(), "valid") @@ -247,6 +258,7 @@ func TestWalletDelete(t *testing.T) { mockApi.EXPECT().WalletDelete(ctx, addr).Return(nil) + //stm: @CLI_WALLET_DELETE_001 err = app.Run([]string{"wallet", "delete", "f01234"}) assert.NoError(t, err) } @@ -283,6 +295,7 @@ func TestWalletMarketWithdraw(t *testing.T) { mockApi.EXPECT().StateNetworkVersion(ctx, types.TipSetKey{}).Return(networkVers, nil), ) + //stm: @CLI_WALLET_MARKET_WITHDRAW_001 err = app.Run([]string{"wallet", "market", "withdraw", "--wallet", addr.String()}) assert.NoError(t, err) assert.Contains(t, buffer.String(), fmt.Sprintf("WithdrawBalance message cid: %s", cid)) @@ -307,6 +320,7 @@ func TestWalletMarketAdd(t *testing.T) { mockApi.EXPECT().MarketAddBalance(ctx, defaultAddr, toAddr, big.NewInt(80)).Return(cid, nil), ) + //stm: @CLI_WALLET_MARKET_ADD_001 err = app.Run([]string{"wallet", "market", "add", "0.000000000000000080", "--address", toAddr.String()}) assert.NoError(t, err) assert.Contains(t, buffer.String(), fmt.Sprintf("AddBalance message cid: %s", cid)) From a54d2fd19d58d0fc486477440a4d0bb518c45278 Mon Sep 17 00:00:00 2001 From: Darko Brdareski Date: Tue, 22 Feb 2022 17:08:04 +0100 Subject: [PATCH 237/385] Update cli docs --- documentation/en/cli-lotus.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/en/cli-lotus.md b/documentation/en/cli-lotus.md index e7ebf8af69e..3be25a29534 100644 --- a/documentation/en/cli-lotus.md +++ b/documentation/en/cli-lotus.md @@ -1643,7 +1643,7 @@ NAME: lotus mpool replace - replace a message in the mempool USAGE: - lotus mpool replace [command options] | + lotus mpool replace [command options] | OPTIONS: --gas-feecap value gas feecap for new message (burn and pay to miner, attoFIL/GasUnit) From e2cbad6ff4e248a44056aadf7a9813dfb298cbe5 Mon Sep 17 00:00:00 2001 From: "eben.xie" Date: Wed, 23 Feb 2022 10:49:53 +0800 Subject: [PATCH 238/385] [Describe]: when excute cmd "lotus-bench sealing" without "benchmark-existing-sectorbuilder", panic will occur [BugFix]: [FeatureAdd]: [CodeReview]: [ModifyDesc]: [Author]: [BugID]: --- cmd/lotus-bench/main.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cmd/lotus-bench/main.go b/cmd/lotus-bench/main.go index b0e71b90e93..c6fdd5e32eb 100644 --- a/cmd/lotus-bench/main.go +++ b/cmd/lotus-bench/main.go @@ -276,6 +276,13 @@ var sealBenchCmd = &cli.Command{ if err != nil { return xerrors.Errorf("failed to run seals: %w", err) } + for _, s := range extendedSealedSectors { + sealedSectors = append(sealedSectors, proof.SectorInfo{ + SealedCID: s.SealedCID, + SectorNumber: s.SectorNumber, + SealProof: s.SealProof, + }) + } } else { // TODO: implement sbfs.List() and use that for all cases (preexisting sectorbuilder or not) From 375d9fdfc9e3278f6e751be093af12f2e237a68c Mon Sep 17 00:00:00 2001 From: Geoff Stuart Date: Tue, 22 Feb 2022 21:25:30 -0500 Subject: [PATCH 239/385] Added cli command for verifier to sing RemoveDataCapProposal --- .../actors/builtin/verifreg/actor.go.template | 5 + .../actors/builtin/verifreg/state.go.template | 9 ++ chain/actors/builtin/verifreg/util.go | 23 +++++ chain/actors/builtin/verifreg/v0.go | 9 ++ chain/actors/builtin/verifreg/v2.go | 9 ++ chain/actors/builtin/verifreg/v3.go | 9 ++ chain/actors/builtin/verifreg/v4.go | 9 ++ chain/actors/builtin/verifreg/v5.go | 9 ++ chain/actors/builtin/verifreg/v6.go | 9 ++ chain/actors/builtin/verifreg/v7.go | 8 ++ chain/actors/builtin/verifreg/verifreg.go | 7 ++ cli/filplus.go | 94 +++++++++++++++++++ 12 files changed, 200 insertions(+) diff --git a/chain/actors/builtin/verifreg/actor.go.template b/chain/actors/builtin/verifreg/actor.go.template index 9ea8e155aec..7ca133af955 100644 --- a/chain/actors/builtin/verifreg/actor.go.template +++ b/chain/actors/builtin/verifreg/actor.go.template @@ -16,6 +16,7 @@ import ( "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/types" + verifreg7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/verifreg" ) func init() { @@ -62,6 +63,9 @@ func GetActorCodeID(av actors.Version) (cid.Cid, error) { return cid.Undef, xerrors.Errorf("unknown actor version %d", av) } +type RemoveDataCapProposal = verifreg7.RemoveDataCapProposal +type RmDcProposalID = verifreg7.RmDcProposalID +const SignatureDomainSeparation_RemoveDataCap = verifreg7.SignatureDomainSeparation_RemoveDataCap type State interface { cbor.Marshaler @@ -69,6 +73,7 @@ type State interface { RootKey() (address.Address, error) VerifiedClientDataCap(address.Address) (bool, abi.StoragePower, error) VerifierDataCap(address.Address) (bool, abi.StoragePower, error) + RemoveDataCapProposalID(verifier address.Address, client address.Address) (bool, uint64, error) ForEachVerifier(func(addr address.Address, dcap abi.StoragePower) error) error ForEachClient(func(addr address.Address, dcap abi.StoragePower) error) error GetState() interface{} diff --git a/chain/actors/builtin/verifreg/state.go.template b/chain/actors/builtin/verifreg/state.go.template index b59cfb6289d..4dfc11469a5 100644 --- a/chain/actors/builtin/verifreg/state.go.template +++ b/chain/actors/builtin/verifreg/state.go.template @@ -61,6 +61,10 @@ func (s *state{{.v}}) VerifierDataCap(addr address.Address) (bool, abi.StoragePo return getDataCap(s.store, actors.Version{{.v}}, s.verifiers, addr) } +func (s *state{{.v}}) RemoveDataCapProposalID(verifier address.Address, client address.Address) (bool, uint64, error) { + return getRemoveDataCapProposalID(s.store, actors.Version{{.v}}, s.removeDataCapProposalIDs, verifier, client) +} + func (s *state{{.v}}) ForEachVerifier(cb func(addr address.Address, dcap abi.StoragePower) error) error { return forEachCap(s.store, actors.Version{{.v}}, s.verifiers, cb) } @@ -77,6 +81,11 @@ func (s *state{{.v}}) verifiers() (adt.Map, error) { return adt{{.v}}.AsMap(s.store, s.Verifiers{{if (ge .v 3)}}, builtin{{.v}}.DefaultHamtBitwidth{{end}}) } +func (s *state{{.v}}) removeDataCapProposalIDs() (adt.Map, error) { + {{if le .v 6}}return nil, nil + {{else}}return adt{{.v}}.AsMap(s.store, s.RemoveDataCapProposalIDs, builtin{{.v}}.DefaultHamtBitwidth){{end}} +} + func (s *state{{.v}}) GetState() interface{} { return &s.State } \ No newline at end of file diff --git a/chain/actors/builtin/verifreg/util.go b/chain/actors/builtin/verifreg/util.go index 16e50c50a77..8d63e28c999 100644 --- a/chain/actors/builtin/verifreg/util.go +++ b/chain/actors/builtin/verifreg/util.go @@ -6,6 +6,7 @@ import ( "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/specs-actors/v7/actors/builtin/verifreg" "golang.org/x/xerrors" ) @@ -50,3 +51,25 @@ func forEachCap(store adt.Store, ver actors.Version, root rootFunc, cb func(addr return cb(a, dcap) }) } + +func getRemoveDataCapProposalID(store adt.Store, ver actors.Version, root rootFunc, verifier address.Address, client address.Address) (bool, uint64, error) { + if verifier.Protocol() != address.ID { + return false, 0, xerrors.Errorf("can only look up ID addresses") + } + if client.Protocol() != address.ID { + return false, 0, xerrors.Errorf("can only look up ID addresses") + } + vh, err := root() + if err != nil { + return false, 0, xerrors.Errorf("loading verifreg: %w", err) + } + + var id verifreg.RmDcProposalID + if found, err := vh.Get(abi.NewAddrPairKey(verifier, client), &id); err != nil { + return false, 0, xerrors.Errorf("looking up addr pair: %w", err) + } else if !found { + return false, 0, nil + } + + return true, id.ProposalID, nil +} diff --git a/chain/actors/builtin/verifreg/v0.go b/chain/actors/builtin/verifreg/v0.go index e70b0e3c92d..dcd34c72a21 100644 --- a/chain/actors/builtin/verifreg/v0.go +++ b/chain/actors/builtin/verifreg/v0.go @@ -53,6 +53,10 @@ func (s *state0) VerifierDataCap(addr address.Address) (bool, abi.StoragePower, return getDataCap(s.store, actors.Version0, s.verifiers, addr) } +func (s *state0) RemoveDataCapProposalID(verifier address.Address, client address.Address) (bool, uint64, error) { + return getRemoveDataCapProposalID(s.store, actors.Version0, s.removeDataCapProposalIDs, verifier, client) +} + func (s *state0) ForEachVerifier(cb func(addr address.Address, dcap abi.StoragePower) error) error { return forEachCap(s.store, actors.Version0, s.verifiers, cb) } @@ -69,6 +73,11 @@ func (s *state0) verifiers() (adt.Map, error) { return adt0.AsMap(s.store, s.Verifiers) } +func (s *state0) removeDataCapProposalIDs() (adt.Map, error) { + return nil, nil + +} + func (s *state0) GetState() interface{} { return &s.State } diff --git a/chain/actors/builtin/verifreg/v2.go b/chain/actors/builtin/verifreg/v2.go index 0bcbe02121d..dfe25f0540b 100644 --- a/chain/actors/builtin/verifreg/v2.go +++ b/chain/actors/builtin/verifreg/v2.go @@ -53,6 +53,10 @@ func (s *state2) VerifierDataCap(addr address.Address) (bool, abi.StoragePower, return getDataCap(s.store, actors.Version2, s.verifiers, addr) } +func (s *state2) RemoveDataCapProposalID(verifier address.Address, client address.Address) (bool, uint64, error) { + return getRemoveDataCapProposalID(s.store, actors.Version2, s.removeDataCapProposalIDs, verifier, client) +} + func (s *state2) ForEachVerifier(cb func(addr address.Address, dcap abi.StoragePower) error) error { return forEachCap(s.store, actors.Version2, s.verifiers, cb) } @@ -69,6 +73,11 @@ func (s *state2) verifiers() (adt.Map, error) { return adt2.AsMap(s.store, s.Verifiers) } +func (s *state2) removeDataCapProposalIDs() (adt.Map, error) { + return nil, nil + +} + func (s *state2) GetState() interface{} { return &s.State } diff --git a/chain/actors/builtin/verifreg/v3.go b/chain/actors/builtin/verifreg/v3.go index 32003ca3a30..c71c69f924b 100644 --- a/chain/actors/builtin/verifreg/v3.go +++ b/chain/actors/builtin/verifreg/v3.go @@ -54,6 +54,10 @@ func (s *state3) VerifierDataCap(addr address.Address) (bool, abi.StoragePower, return getDataCap(s.store, actors.Version3, s.verifiers, addr) } +func (s *state3) RemoveDataCapProposalID(verifier address.Address, client address.Address) (bool, uint64, error) { + return getRemoveDataCapProposalID(s.store, actors.Version3, s.removeDataCapProposalIDs, verifier, client) +} + func (s *state3) ForEachVerifier(cb func(addr address.Address, dcap abi.StoragePower) error) error { return forEachCap(s.store, actors.Version3, s.verifiers, cb) } @@ -70,6 +74,11 @@ func (s *state3) verifiers() (adt.Map, error) { return adt3.AsMap(s.store, s.Verifiers, builtin3.DefaultHamtBitwidth) } +func (s *state3) removeDataCapProposalIDs() (adt.Map, error) { + return nil, nil + +} + func (s *state3) GetState() interface{} { return &s.State } diff --git a/chain/actors/builtin/verifreg/v4.go b/chain/actors/builtin/verifreg/v4.go index b752e747bb3..d3adc5169db 100644 --- a/chain/actors/builtin/verifreg/v4.go +++ b/chain/actors/builtin/verifreg/v4.go @@ -54,6 +54,10 @@ func (s *state4) VerifierDataCap(addr address.Address) (bool, abi.StoragePower, return getDataCap(s.store, actors.Version4, s.verifiers, addr) } +func (s *state4) RemoveDataCapProposalID(verifier address.Address, client address.Address) (bool, uint64, error) { + return getRemoveDataCapProposalID(s.store, actors.Version4, s.removeDataCapProposalIDs, verifier, client) +} + func (s *state4) ForEachVerifier(cb func(addr address.Address, dcap abi.StoragePower) error) error { return forEachCap(s.store, actors.Version4, s.verifiers, cb) } @@ -70,6 +74,11 @@ func (s *state4) verifiers() (adt.Map, error) { return adt4.AsMap(s.store, s.Verifiers, builtin4.DefaultHamtBitwidth) } +func (s *state4) removeDataCapProposalIDs() (adt.Map, error) { + return nil, nil + +} + func (s *state4) GetState() interface{} { return &s.State } diff --git a/chain/actors/builtin/verifreg/v5.go b/chain/actors/builtin/verifreg/v5.go index 6fefd711540..2af501af394 100644 --- a/chain/actors/builtin/verifreg/v5.go +++ b/chain/actors/builtin/verifreg/v5.go @@ -54,6 +54,10 @@ func (s *state5) VerifierDataCap(addr address.Address) (bool, abi.StoragePower, return getDataCap(s.store, actors.Version5, s.verifiers, addr) } +func (s *state5) RemoveDataCapProposalID(verifier address.Address, client address.Address) (bool, uint64, error) { + return getRemoveDataCapProposalID(s.store, actors.Version5, s.removeDataCapProposalIDs, verifier, client) +} + func (s *state5) ForEachVerifier(cb func(addr address.Address, dcap abi.StoragePower) error) error { return forEachCap(s.store, actors.Version5, s.verifiers, cb) } @@ -70,6 +74,11 @@ func (s *state5) verifiers() (adt.Map, error) { return adt5.AsMap(s.store, s.Verifiers, builtin5.DefaultHamtBitwidth) } +func (s *state5) removeDataCapProposalIDs() (adt.Map, error) { + return nil, nil + +} + func (s *state5) GetState() interface{} { return &s.State } diff --git a/chain/actors/builtin/verifreg/v6.go b/chain/actors/builtin/verifreg/v6.go index b2c5078e758..454c9478f4d 100644 --- a/chain/actors/builtin/verifreg/v6.go +++ b/chain/actors/builtin/verifreg/v6.go @@ -54,6 +54,10 @@ func (s *state6) VerifierDataCap(addr address.Address) (bool, abi.StoragePower, return getDataCap(s.store, actors.Version6, s.verifiers, addr) } +func (s *state6) RemoveDataCapProposalID(verifier address.Address, client address.Address) (bool, uint64, error) { + return getRemoveDataCapProposalID(s.store, actors.Version6, s.removeDataCapProposalIDs, verifier, client) +} + func (s *state6) ForEachVerifier(cb func(addr address.Address, dcap abi.StoragePower) error) error { return forEachCap(s.store, actors.Version6, s.verifiers, cb) } @@ -70,6 +74,11 @@ func (s *state6) verifiers() (adt.Map, error) { return adt6.AsMap(s.store, s.Verifiers, builtin6.DefaultHamtBitwidth) } +func (s *state6) removeDataCapProposalIDs() (adt.Map, error) { + return nil, nil + +} + func (s *state6) GetState() interface{} { return &s.State } diff --git a/chain/actors/builtin/verifreg/v7.go b/chain/actors/builtin/verifreg/v7.go index 9b2ca928ab5..3bcfa10bd25 100644 --- a/chain/actors/builtin/verifreg/v7.go +++ b/chain/actors/builtin/verifreg/v7.go @@ -54,6 +54,10 @@ func (s *state7) VerifierDataCap(addr address.Address) (bool, abi.StoragePower, return getDataCap(s.store, actors.Version7, s.verifiers, addr) } +func (s *state7) RemoveDataCapProposalID(verifier address.Address, client address.Address) (bool, uint64, error) { + return getRemoveDataCapProposalID(s.store, actors.Version7, s.removeDataCapProposalIDs, verifier, client) +} + func (s *state7) ForEachVerifier(cb func(addr address.Address, dcap abi.StoragePower) error) error { return forEachCap(s.store, actors.Version7, s.verifiers, cb) } @@ -70,6 +74,10 @@ func (s *state7) verifiers() (adt.Map, error) { return adt7.AsMap(s.store, s.Verifiers, builtin7.DefaultHamtBitwidth) } +func (s *state7) removeDataCapProposalIDs() (adt.Map, error) { + return adt7.AsMap(s.store, s.RemoveDataCapProposalIDs, builtin7.DefaultHamtBitwidth) +} + func (s *state7) GetState() interface{} { return &s.State } diff --git a/chain/actors/builtin/verifreg/verifreg.go b/chain/actors/builtin/verifreg/verifreg.go index f6281334dda..b69a0f83e8c 100644 --- a/chain/actors/builtin/verifreg/verifreg.go +++ b/chain/actors/builtin/verifreg/verifreg.go @@ -27,6 +27,7 @@ import ( "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/types" + verifreg7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/verifreg" ) func init() { @@ -151,12 +152,18 @@ func GetActorCodeID(av actors.Version) (cid.Cid, error) { return cid.Undef, xerrors.Errorf("unknown actor version %d", av) } +type RemoveDataCapProposal = verifreg7.RemoveDataCapProposal +type RmDcProposalID = verifreg7.RmDcProposalID + +const SignatureDomainSeparation_RemoveDataCap = verifreg7.SignatureDomainSeparation_RemoveDataCap + type State interface { cbor.Marshaler RootKey() (address.Address, error) VerifiedClientDataCap(address.Address) (bool, abi.StoragePower, error) VerifierDataCap(address.Address) (bool, abi.StoragePower, error) + RemoveDataCapProposalID(verifier address.Address, client address.Address) (bool, uint64, error) ForEachVerifier(func(addr address.Address, dcap abi.StoragePower) error) error ForEachClient(func(addr address.Address, dcap abi.StoragePower) error) error GetState() interface{} diff --git a/cli/filplus.go b/cli/filplus.go index 02aac0b7b0b..ba2fc43a09e 100644 --- a/cli/filplus.go +++ b/cli/filplus.go @@ -1,7 +1,9 @@ package cli import ( + "bytes" "context" + "encoding/hex" "fmt" verifreg4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/verifreg" @@ -34,6 +36,7 @@ var filplusCmd = &cli.Command{ filplusListClientsCmd, filplusCheckClientCmd, filplusCheckNotaryCmd, + filplusSignRemoveDataCapProposal, }, } @@ -274,3 +277,94 @@ func checkNotary(ctx context.Context, api v0api.FullNode, vaddr address.Address) return st.VerifierDataCap(vid) } + +var filplusSignRemoveDataCapProposal = &cli.Command{ + Name: "sign-remove-data-cap-proposal", + Usage: "TODO", + Flags: []cli.Flag{ + &cli.Int64Flag{ + Name: "id", + Usage: "specify the id of the Remove Data Cap Proposal", + Required: false, + }, + }, + Action: func(cctx *cli.Context) error { + if cctx.Args().Len() != 3 { + return fmt.Errorf("must specify three arguments: verifier address, client address, and allowance to remove") + } + + verifier, err := address.NewFromString(cctx.Args().Get(0)) + if err != nil { + return err + } + + client, err := address.NewFromString(cctx.Args().Get(1)) + if err != nil { + return err + } + + allowanceToRemove, err := types.BigFromString(cctx.Args().Get(2)) + if err != nil { + return err + } + + api, closer, err := GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := ReqContext(cctx) + + found, _, err := checkNotary(ctx, api, verifier) + if err != nil { + return err + } + + if !found { + return xerrors.New("verifier address must be a notary") + } + + id := cctx.Uint64("id") + if id == 0 { + act, err := api.StateGetActor(ctx, verifreg.Address, types.EmptyTSK) + if err != nil { + return err + } + + apibs := blockstore.NewAPIBlockstore(api) + store := adt.WrapStore(ctx, cbor.NewCborStore(apibs)) + + st, err := verifreg.Load(store, act) + if err != nil { + return err + } + _, id, err = st.RemoveDataCapProposalID(verifier, client) + if err != nil { + return err + } + } + + // TODO: This should be abstracted over actor versions + params := verifreg.RemoveDataCapProposal{ + RemovalProposalID: verifreg.RmDcProposalID{ProposalID: id}, + DataCapAmount: allowanceToRemove, + VerifiedClient: client, + } + + paramBuf := new(bytes.Buffer) + paramBuf.WriteString(verifreg.SignatureDomainSeparation_RemoveDataCap) + err = params.MarshalCBOR(paramBuf) + if err != nil { + return err + } + + msg, err := api.WalletSign(ctx, verifier, paramBuf.Bytes()) + if err != nil { + return err + } + + fmt.Println(hex.EncodeToString(msg.Data)) + + return nil + }, +} From 23147378a35a28ef2dc0a19a1b5de060d54e0332 Mon Sep 17 00:00:00 2001 From: Geoff Stuart Date: Tue, 22 Feb 2022 22:04:50 -0500 Subject: [PATCH 240/385] Added cli command for vrk to send RemoveVerifiedClientDataCap message --- .../actors/builtin/verifreg/actor.go.template | 8 +- chain/actors/builtin/verifreg/verifreg.go | 2 + cli/filplus.go | 6 +- cmd/lotus-shed/verifreg.go | 116 ++++++++++++++++++ 4 files changed, 127 insertions(+), 5 deletions(-) diff --git a/chain/actors/builtin/verifreg/actor.go.template b/chain/actors/builtin/verifreg/actor.go.template index 7ca133af955..adc15694850 100644 --- a/chain/actors/builtin/verifreg/actor.go.template +++ b/chain/actors/builtin/verifreg/actor.go.template @@ -63,9 +63,11 @@ func GetActorCodeID(av actors.Version) (cid.Cid, error) { return cid.Undef, xerrors.Errorf("unknown actor version %d", av) } -type RemoveDataCapProposal = verifreg7.RemoveDataCapProposal -type RmDcProposalID = verifreg7.RmDcProposalID -const SignatureDomainSeparation_RemoveDataCap = verifreg7.SignatureDomainSeparation_RemoveDataCap +type RemoveDataCapProposal = verifreg{{.latestVersion}}.RemoveDataCapProposal +type RemoveDataCapRequest = verifreg{{.latestVersion}}.RemoveDataCapRequest +type RemoveDataCapParams = verifreg{{.latestVersion}}.RemoveDataCapParams +type RmDcProposalID = verifreg{{.latestVersion}}.RmDcProposalID +const SignatureDomainSeparation_RemoveDataCap = verifreg{{.latestVersion}}.SignatureDomainSeparation_RemoveDataCap type State interface { cbor.Marshaler diff --git a/chain/actors/builtin/verifreg/verifreg.go b/chain/actors/builtin/verifreg/verifreg.go index b69a0f83e8c..cb26e324b47 100644 --- a/chain/actors/builtin/verifreg/verifreg.go +++ b/chain/actors/builtin/verifreg/verifreg.go @@ -153,6 +153,8 @@ func GetActorCodeID(av actors.Version) (cid.Cid, error) { } type RemoveDataCapProposal = verifreg7.RemoveDataCapProposal +type RemoveDataCapRequest = verifreg7.RemoveDataCapRequest +type RemoveDataCapParams = verifreg7.RemoveDataCapParams type RmDcProposalID = verifreg7.RmDcProposalID const SignatureDomainSeparation_RemoveDataCap = verifreg7.SignatureDomainSeparation_RemoveDataCap diff --git a/cli/filplus.go b/cli/filplus.go index ba2fc43a09e..12584b2b849 100644 --- a/cli/filplus.go +++ b/cli/filplus.go @@ -358,12 +358,14 @@ var filplusSignRemoveDataCapProposal = &cli.Command{ return err } - msg, err := api.WalletSign(ctx, verifier, paramBuf.Bytes()) + sig, err := api.WalletSign(ctx, verifier, paramBuf.Bytes()) if err != nil { return err } - fmt.Println(hex.EncodeToString(msg.Data)) + sigBytes := append([]byte{byte(sig.Type)}, sig.Data...) + + fmt.Println(hex.EncodeToString(sigBytes)) return nil }, diff --git a/cmd/lotus-shed/verifreg.go b/cmd/lotus-shed/verifreg.go index 03be5f916e2..4220d230217 100644 --- a/cmd/lotus-shed/verifreg.go +++ b/cmd/lotus-shed/verifreg.go @@ -1,8 +1,11 @@ package main import ( + "encoding/hex" "fmt" + "github.com/filecoin-project/go-state-types/crypto" + "github.com/filecoin-project/go-state-types/big" "github.com/urfave/cli/v2" @@ -35,6 +38,7 @@ var verifRegCmd = &cli.Command{ verifRegListClientsCmd, verifRegCheckClientCmd, verifRegCheckVerifierCmd, + verifRegRemoveVerifiedClientDataCapCmd, }, } @@ -409,3 +413,115 @@ var verifRegCheckVerifierCmd = &cli.Command{ return nil }, } + +var verifRegRemoveVerifiedClientDataCapCmd = &cli.Command{ + Name: "remove-verified-client-data-cap", + Usage: "Remove data cap from verified client", + ArgsUsage: " ", + Action: func(cctx *cli.Context) error { + if cctx.Args().Len() != 7 { + return fmt.Errorf("must specify seven arguments: sender, client, allowance to remove, verifier 1 ID, verifier 1 signature, verifier 2 ID, verifier 2 signature") + } + + srv, err := lcli.GetFullNodeServices(cctx) + if err != nil { + return err + } + defer srv.Close() //nolint:errcheck + + api := srv.FullNodeAPI() + ctx := lcli.ReqContext(cctx) + + sender, err := address.NewFromString(cctx.Args().Get(0)) + if err != nil { + return err + } + + client, err := address.NewFromString(cctx.Args().Get(1)) + if err != nil { + return err + } + + allowanceToRemove, err := types.BigFromString(cctx.Args().Get(2)) + if err != nil { + return err + } + + verifier1Addr, err := address.NewFromString(cctx.Args().Get(3)) + if err != nil { + return err + } + + verifier1Sig, err := hex.DecodeString(cctx.Args().Get(4)) + if err != nil { + return err + } + + verifier2Addr, err := address.NewFromString(cctx.Args().Get(5)) + if err != nil { + return err + } + + verifier2Sig, err := hex.DecodeString(cctx.Args().Get(6)) + if err != nil { + return err + } + + var sig1 crypto.Signature + if err := sig1.UnmarshalBinary(verifier1Sig); err != nil { + return xerrors.Errorf("couldn't unmarshal sig: %w", err) + } + + var sig2 crypto.Signature + if err := sig2.UnmarshalBinary(verifier2Sig); err != nil { + return xerrors.Errorf("couldn't unmarshal sig: %w", err) + } + + params, err := actors.SerializeParams(&verifreg.RemoveDataCapParams{ + VerifiedClientToRemove: client, + DataCapAmountToRemove: allowanceToRemove, + VerifierRequest1: verifreg.RemoveDataCapRequest{ + Verifier: verifier1Addr, + VerifierSignature: sig1, + }, + VerifierRequest2: verifreg.RemoveDataCapRequest{ + Verifier: verifier2Addr, + VerifierSignature: sig2, + }, + }) + if err != nil { + return err + } + + vrk, err := api.StateVerifiedRegistryRootKey(ctx, types.EmptyTSK) + if err != nil { + return err + } + + proto, err := api.MsigPropose(ctx, vrk, verifreg.Address, big.Zero(), sender, uint64(verifreg.Methods.RemoveVerifiedClientDataCap), params) + if err != nil { + return err + } + + sm, _, err := srv.PublishMessage(ctx, proto, false) + if err != nil { + return err + } + + msgCid := sm.Cid() + + fmt.Printf("message sent, now waiting on cid: %s\n", msgCid) + + mwait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")), build.Finality, true) + if err != nil { + return err + } + + if mwait.Receipt.ExitCode != 0 { + return fmt.Errorf("failed to removed verified data cap: %d", mwait.Receipt.ExitCode) + } + + //TODO: Internal msg might still have failed + return nil + }, +} From 5a5d1bf9aab0c8809518e7773889bb655362c380 Mon Sep 17 00:00:00 2001 From: Geoff Stuart Date: Tue, 22 Feb 2022 22:06:02 -0500 Subject: [PATCH 241/385] Updated cli docs --- documentation/en/cli-lotus.md | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/documentation/en/cli-lotus.md b/documentation/en/cli-lotus.md index e7ebf8af69e..eca4e5a811e 100644 --- a/documentation/en/cli-lotus.md +++ b/documentation/en/cli-lotus.md @@ -1234,12 +1234,13 @@ USAGE: lotus filplus command [command options] [arguments...] COMMANDS: - grant-datacap give allowance to the specified verified client address - list-notaries list all notaries - list-clients list all verified clients - check-client-datacap check verified client remaining bytes - check-notary-datacap check a notary's remaining bytes - help, h Shows a list of commands or help for one command + grant-datacap give allowance to the specified verified client address + list-notaries list all notaries + list-clients list all verified clients + check-client-datacap check verified client remaining bytes + check-notary-datacap check a notary's remaining bytes + sign-remove-data-cap-proposal TODO + help, h Shows a list of commands or help for one command OPTIONS: --help, -h show help (default: false) @@ -1313,6 +1314,20 @@ OPTIONS: ``` +### lotus filplus sign-remove-data-cap-proposal +``` +NAME: + lotus filplus sign-remove-data-cap-proposal - TODO + +USAGE: + lotus filplus sign-remove-data-cap-proposal [command options] [arguments...] + +OPTIONS: + --id value specify the id of the Remove Data Cap Proposal (default: 0) + --help, -h show help (default: false) + +``` + ## lotus paych ``` NAME: From e9715cae3b0ca76a965640ed4a7ca18dce92922d Mon Sep 17 00:00:00 2001 From: Geoff Stuart Date: Tue, 22 Feb 2022 22:58:51 -0500 Subject: [PATCH 242/385] Small fixes --- cli/filplus.go | 55 +++++++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/cli/filplus.go b/cli/filplus.go index 12584b2b849..845b3948e6b 100644 --- a/cli/filplus.go +++ b/cli/filplus.go @@ -293,31 +293,52 @@ var filplusSignRemoveDataCapProposal = &cli.Command{ return fmt.Errorf("must specify three arguments: verifier address, client address, and allowance to remove") } + api, closer, err := GetFullNodeAPI(cctx) + if err != nil { + return xerrors.Errorf("failed to get full node api: %w", err) + } + defer closer() + ctx := ReqContext(cctx) + + act, err := api.StateGetActor(ctx, verifreg.Address, types.EmptyTSK) + if err != nil { + return xerrors.Errorf("failed to get verifreg actor: %w", err) + } + + apibs := blockstore.NewAPIBlockstore(api) + store := adt.WrapStore(ctx, cbor.NewCborStore(apibs)) + + st, err := verifreg.Load(store, act) + if err != nil { + return xerrors.Errorf("failed to load verified registry state: %w", err) + } + verifier, err := address.NewFromString(cctx.Args().Get(0)) if err != nil { return err } + verifierIdAddr, err := api.StateLookupID(ctx, verifier, types.EmptyTSK) + if err != nil { + return err + } client, err := address.NewFromString(cctx.Args().Get(1)) if err != nil { return err } - - allowanceToRemove, err := types.BigFromString(cctx.Args().Get(2)) + clientIdAddr, err := api.StateLookupID(ctx, client, types.EmptyTSK) if err != nil { return err } - api, closer, err := GetFullNodeAPI(cctx) + allowanceToRemove, err := types.BigFromString(cctx.Args().Get(2)) if err != nil { return err } - defer closer() - ctx := ReqContext(cctx) found, _, err := checkNotary(ctx, api, verifier) if err != nil { - return err + return xerrors.Errorf("failed to check notary status: %w", err) } if !found { @@ -326,21 +347,9 @@ var filplusSignRemoveDataCapProposal = &cli.Command{ id := cctx.Uint64("id") if id == 0 { - act, err := api.StateGetActor(ctx, verifreg.Address, types.EmptyTSK) + _, id, err = st.RemoveDataCapProposalID(verifierIdAddr, clientIdAddr) if err != nil { - return err - } - - apibs := blockstore.NewAPIBlockstore(api) - store := adt.WrapStore(ctx, cbor.NewCborStore(apibs)) - - st, err := verifreg.Load(store, act) - if err != nil { - return err - } - _, id, err = st.RemoveDataCapProposalID(verifier, client) - if err != nil { - return err + return xerrors.Errorf("failed find remove data cap proposal id: %w", err) } } @@ -348,19 +357,19 @@ var filplusSignRemoveDataCapProposal = &cli.Command{ params := verifreg.RemoveDataCapProposal{ RemovalProposalID: verifreg.RmDcProposalID{ProposalID: id}, DataCapAmount: allowanceToRemove, - VerifiedClient: client, + VerifiedClient: clientIdAddr, } paramBuf := new(bytes.Buffer) paramBuf.WriteString(verifreg.SignatureDomainSeparation_RemoveDataCap) err = params.MarshalCBOR(paramBuf) if err != nil { - return err + return xerrors.Errorf("failed to marshall paramBuf: %w", err) } sig, err := api.WalletSign(ctx, verifier, paramBuf.Bytes()) if err != nil { - return err + return xerrors.Errorf("failed to sign message: %w", err) } sigBytes := append([]byte{byte(sig.Type)}, sig.Data...) From c3b406c5c23c7f6576d439c48ea259bc390353b0 Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Wed, 23 Feb 2022 14:10:38 +0000 Subject: [PATCH 243/385] Update indexing and markets dependencies Update indexing dependencies to latest along with go-fil-markets dependency, to the head of: - https://github.com/filecoin-project/go-fil-markets/pull/673 --- go.mod | 8 ++++---- go.sum | 23 ++++++++++------------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/go.mod b/go.mod index 50608e5d268..1316d48817a 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/elastic/gosigar v0.14.1 github.com/etclabscore/go-openrpc-reflect v0.0.36 github.com/fatih/color v1.13.0 - github.com/filecoin-project/dagstore v0.5.2-0.20220221082516-6beb25bc4425 + github.com/filecoin-project/dagstore v0.5.2 github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200910194244-f640612a1a1f github.com/filecoin-project/go-address v0.0.6 github.com/filecoin-project/go-bitfield v0.2.4 @@ -36,16 +36,16 @@ require ( github.com/filecoin-project/go-data-transfer v1.14.0 github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 - github.com/filecoin-project/go-fil-markets v1.19.1-0.20220215120226-a0db7a73d4fd + github.com/filecoin-project/go-fil-markets v1.19.2-0.20220223140554-a6e18af5929a github.com/filecoin-project/go-jsonrpc v0.1.5 - github.com/filecoin-project/go-legs v0.3.0 + github.com/filecoin-project/go-legs v0.3.4 github.com/filecoin-project/go-padreader v0.0.1 github.com/filecoin-project/go-paramfetch v0.0.3-0.20220111000201-e42866db1a53 github.com/filecoin-project/go-state-types v0.1.3 github.com/filecoin-project/go-statemachine v1.0.1 github.com/filecoin-project/go-statestore v0.2.0 github.com/filecoin-project/go-storedcounter v0.1.0 - github.com/filecoin-project/index-provider v0.3.0 + github.com/filecoin-project/index-provider v0.3.1 github.com/filecoin-project/specs-actors v0.9.14 github.com/filecoin-project/specs-actors/v2 v2.3.6 github.com/filecoin-project/specs-actors/v3 v3.1.1 diff --git a/go.sum b/go.sum index b2d87d3c2c6..4df7ba31c52 100644 --- a/go.sum +++ b/go.sum @@ -298,9 +298,8 @@ github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/filecoin-project/dagstore v0.5.1/go.mod h1:OdlK3x5m3Mol874WC2bI79H4H2+leN+FabwWdW2D/wY= -github.com/filecoin-project/dagstore v0.5.2-0.20220221082516-6beb25bc4425 h1:OQxAqlQVzH9/WUAMue7LWQorL1KXgiEbJTuKRxPuxlo= -github.com/filecoin-project/dagstore v0.5.2-0.20220221082516-6beb25bc4425/go.mod h1:mdqKzYrRBHf1pRMthYfMv3n37oOw0Tkx7+TxPt240M0= +github.com/filecoin-project/dagstore v0.5.2 h1:Nd6oXdnolbbVhpMpkYT5PJHOjQp4OBSntHpMV5pxj3c= +github.com/filecoin-project/dagstore v0.5.2/go.mod h1:mdqKzYrRBHf1pRMthYfMv3n37oOw0Tkx7+TxPt240M0= github.com/filecoin-project/go-address v0.0.3/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= github.com/filecoin-project/go-address v0.0.5/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= github.com/filecoin-project/go-address v0.0.6 h1:DWQtj38ax+ogHwyH3VULRIoT8E6loyXqsk/p81xoY7M= @@ -336,8 +335,8 @@ github.com/filecoin-project/go-fil-commcid v0.1.0 h1:3R4ds1A9r6cr8mvZBfMYxTS88Oq github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7LXep5bFEVOVmQWHJvl2mgsGo= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8= -github.com/filecoin-project/go-fil-markets v1.19.1-0.20220215120226-a0db7a73d4fd h1:RO4M6fD9L6+OGqgk6OnMrFJcN5JkcMo3MX40vqxUfmQ= -github.com/filecoin-project/go-fil-markets v1.19.1-0.20220215120226-a0db7a73d4fd/go.mod h1:Q7EWzO9s4sg2KYBUJduTYdtVhVhusDuH2W0keyyub3I= +github.com/filecoin-project/go-fil-markets v1.19.2-0.20220223140554-a6e18af5929a h1:R0g6Dg7jeY1YYULvXdynJNSq9EaBj1dA6+BNuzytLNE= +github.com/filecoin-project/go-fil-markets v1.19.2-0.20220223140554-a6e18af5929a/go.mod h1:OeR49x+NPMfZMMgOresxzecMAgUB+lna2kwJABPwnt8= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= @@ -345,13 +344,12 @@ github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0/go.mod h1:7aWZdaQ1b16BVoQUYR+ github.com/filecoin-project/go-hamt-ipld/v3 v3.0.1/go.mod h1:gXpNmr3oQx8l3o7qkGyDjJjYSRX7hp/FGOStdqrWyDI= github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0 h1:rVVNq0x6RGQIzCo1iiJlGFm9AGIZzeifggxtKMU7zmI= github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0/go.mod h1:bxmzgT8tmeVQA1/gvBwFmYdT8SOFUwB3ovSUfG1Ux0g= -github.com/filecoin-project/go-indexer-core v0.2.4/go.mod h1:MSe5aRWmfRB+5syR4yDV+OApgJU+MUJ4rl9VUuzwCfc= github.com/filecoin-project/go-indexer-core v0.2.8/go.mod h1:IagNfTdFuX4057kla43PjRCn3yBuUiZgIxuA0hTUamY= github.com/filecoin-project/go-jsonrpc v0.1.5 h1:ckxqZ09ivBAVf5CSmxxrqqNHC7PJm3GYGtYKiNQ+vGk= github.com/filecoin-project/go-jsonrpc v0.1.5/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4= -github.com/filecoin-project/go-legs v0.2.7/go.mod h1:NrdELuDbtAH8/xqRMgyOYms67aliQajExInLS6g8zFM= -github.com/filecoin-project/go-legs v0.3.0 h1:1rDNdPdXbgetmmvRcYZV5YIplIO8LtBVQ7ZttKCrTrM= github.com/filecoin-project/go-legs v0.3.0/go.mod h1:x6nwM+DuN7NzlPndOoJuiHYCX+pze6+efPRx17nIA7M= +github.com/filecoin-project/go-legs v0.3.4 h1:yid2IivTJ8JeF1ROA8jxNKNKJshU/HO1sRo5lEMNOUc= +github.com/filecoin-project/go-legs v0.3.4/go.mod h1:P7ZPHqFG96OFaT11rnXyTdcxRdGkaH1dRyPxJSOiSuM= github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20/go.mod h1:mPn+LRRd5gEKNAtc+r3ScpW2JRU/pj4NBKdADYWHiak= github.com/filecoin-project/go-padreader v0.0.1 h1:8h2tVy5HpoNbr2gBRr+WD6zV6VD6XHig+ynSGJg8ZOs= github.com/filecoin-project/go-padreader v0.0.1/go.mod h1:VYVPJqwpsfmtoHnAmPx6MUwmrK6HIcDqZJiuZhtmfLQ= @@ -373,8 +371,8 @@ github.com/filecoin-project/go-statestore v0.2.0 h1:cRRO0aPLrxKQCZ2UOQbzFGn4WDNd github.com/filecoin-project/go-statestore v0.2.0/go.mod h1:8sjBYbS35HwPzct7iT4lIXjLlYyPor80aU7t7a/Kspo= github.com/filecoin-project/go-storedcounter v0.1.0 h1:Mui6wSUBC+cQGHbDUBcO7rfh5zQkWJM/CpAZa/uOuus= github.com/filecoin-project/go-storedcounter v0.1.0/go.mod h1:4ceukaXi4vFURIoxYMfKzaRF5Xv/Pinh2oTnoxpv+z8= -github.com/filecoin-project/index-provider v0.3.0 h1:+oU4whsKq2x2Z/sQfd2gVGDrARrOZVpR/irlGsKaxSc= -github.com/filecoin-project/index-provider v0.3.0/go.mod h1:3m4D2O+o649LfrsgNCZqTiiY6r+t9qF5g55jhB3PPLo= +github.com/filecoin-project/index-provider v0.3.1 h1:ySGk2FnDbUEhq6QwakeU/p8tKnIoUm6JIpXPQ8RG1iM= +github.com/filecoin-project/index-provider v0.3.1/go.mod h1:o8ineTLWnwtfBv7SnELpncza6SBU295esxOaXsTCl2I= github.com/filecoin-project/specs-actors v0.9.13/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= github.com/filecoin-project/specs-actors v0.9.14 h1:68PVstg2UB3ZsMLF+DKFTAs/YKsqhKWynkr0IqmVRQY= github.com/filecoin-project/specs-actors v0.9.14/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= @@ -398,8 +396,8 @@ github.com/filecoin-project/specs-actors/v7 v7.0.0-rc1 h1:FuDaXIbcw2hRsFI8SDTmsG github.com/filecoin-project/specs-actors/v7 v7.0.0-rc1/go.mod h1:TA5FwCna+Yi36POaT7SLKXsgEDvJwc0V/L6ZsO19B9M= github.com/filecoin-project/specs-storage v0.1.1-0.20211228030229-6d460d25a0c9 h1:oUYOvF7EvdXS0Zmk9mNkaB6Bu0l+WXBYPzVodKMiLug= github.com/filecoin-project/specs-storage v0.1.1-0.20211228030229-6d460d25a0c9/go.mod h1:Tb88Zq+IBJbvAn3mS89GYj3jdRThBTE/771HCVZdRJU= -github.com/filecoin-project/storetheindex v0.3.0 h1:M9C4BFLCKn6FJn2N/8q0VbX00hEjEWUuvJpscqKwqzQ= -github.com/filecoin-project/storetheindex v0.3.0/go.mod h1:GhUmP8+nINxDRUqxQvTc3Fqc7Yp6w0dW/uTaYYIzd68= +github.com/filecoin-project/storetheindex v0.3.2 h1:KsTJer5Di/iapSrOWtbFTPMt5kS7Y3n3C9kOYH93gEA= +github.com/filecoin-project/storetheindex v0.3.2/go.mod h1:d7y0FHAwPPSIdg+Oh7xV5B9TLebL7rvoKu591N/l2ZU= github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg= github.com/filecoin-project/test-vectors/schema v0.0.5/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= @@ -924,7 +922,6 @@ github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20211210234204-ce2a1c70cd github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20211210234204-ce2a1c70cd73/go.mod h1:2PJ0JgxyB08t0b2WKrcuqI3di0V+5n6RS/LTUJhkoxY= github.com/ipld/go-ipld-selector-text-lite v0.0.1 h1:lNqFsQpBHc3p5xHob2KvEg/iM5dIFn6iw4L/Hh+kS1Y= github.com/ipld/go-ipld-selector-text-lite v0.0.1/go.mod h1:U2CQmFb+uWzfIEF3I1arrDa5rwtj00PrpiwwCO+k1RM= -github.com/ipld/go-storethehash v0.0.0-20210915160027-d72ca9b0968c/go.mod h1:PwE6iq8TiWJRI3zMGA1RtkFAnrDMK93dLA5SUeu0lH8= github.com/ipld/go-storethehash v0.0.1/go.mod h1:w8cQfWInks8lvvbQTiKbCPusU9v0sqiViBihTHbavpQ= github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52 h1:QG4CGBqCeuBo6aZlGAamSkxWdgWfZGeE49eUOWJPA4c= github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52/go.mod h1:fdg+/X9Gg4AsAIzWpEHwnqd+QY3b7lajxyjE1m4hkq4= From b802ddb848608df5ad0f7c055d7b6cfc6befe90c Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Wed, 23 Feb 2022 14:41:55 +0000 Subject: [PATCH 244/385] Upgrade dependency to markets --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1316d48817a..d9dd613ee3e 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,7 @@ require ( github.com/filecoin-project/go-data-transfer v1.14.0 github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 - github.com/filecoin-project/go-fil-markets v1.19.2-0.20220223140554-a6e18af5929a + github.com/filecoin-project/go-fil-markets v1.19.2-0.20220223141410-2460e15e07a8 github.com/filecoin-project/go-jsonrpc v0.1.5 github.com/filecoin-project/go-legs v0.3.4 github.com/filecoin-project/go-padreader v0.0.1 diff --git a/go.sum b/go.sum index 4df7ba31c52..5f2f91e56d7 100644 --- a/go.sum +++ b/go.sum @@ -335,8 +335,8 @@ github.com/filecoin-project/go-fil-commcid v0.1.0 h1:3R4ds1A9r6cr8mvZBfMYxTS88Oq github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7LXep5bFEVOVmQWHJvl2mgsGo= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8= -github.com/filecoin-project/go-fil-markets v1.19.2-0.20220223140554-a6e18af5929a h1:R0g6Dg7jeY1YYULvXdynJNSq9EaBj1dA6+BNuzytLNE= -github.com/filecoin-project/go-fil-markets v1.19.2-0.20220223140554-a6e18af5929a/go.mod h1:OeR49x+NPMfZMMgOresxzecMAgUB+lna2kwJABPwnt8= +github.com/filecoin-project/go-fil-markets v1.19.2-0.20220223141410-2460e15e07a8 h1:cuV4t78W8tUgmqvsc6T6qbWuycg7GzPcNsTdAOxrTns= +github.com/filecoin-project/go-fil-markets v1.19.2-0.20220223141410-2460e15e07a8/go.mod h1:OeR49x+NPMfZMMgOresxzecMAgUB+lna2kwJABPwnt8= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= From abe04c33c1183c7e94ac222183acaaf31dfd5c16 Mon Sep 17 00:00:00 2001 From: zenground0 Date: Wed, 23 Feb 2022 09:56:47 -0700 Subject: [PATCH 245/385] Fix fault tracker to handle snap deals --- api/api_storage.go | 2 +- api/proxy_gen.go | 8 +- api/version.go | 2 +- build/openrpc/miner.json.gz | Bin 12906 -> 12929 bytes cmd/lotus-miner/proving.go | 4 +- documentation/en/api-v0-methods-miner.md | 3 + extern/sector-storage/faults.go | 96 ++++++++++++----------- extern/sector-storage/mock/mock.go | 2 +- node/impl/storminer.go | 4 +- storage/wdpost_run.go | 4 +- storage/wdpost_run_test.go | 2 +- 11 files changed, 69 insertions(+), 58 deletions(-) diff --git a/api/api_storage.go b/api/api_storage.go index a66f22d0484..da66a9a0358 100644 --- a/api/api_storage.go +++ b/api/api_storage.go @@ -256,7 +256,7 @@ type StorageMiner interface { // the path specified when calling CreateBackup is within the base path CreateBackup(ctx context.Context, fpath string) error //perm:admin - CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, sectors []storage.SectorRef, expensive bool) (map[abi.SectorNumber]string, error) //perm:admin + CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, sectors []storage.SectorRef, update []bool, expensive bool) (map[abi.SectorNumber]string, error) //perm:admin ComputeProof(ctx context.Context, ssi []builtin.ExtendedSectorInfo, rand abi.PoStRandomness, poStEpoch abi.ChainEpoch, nv abinetwork.Version) ([]builtin.PoStProof, error) //perm:read } diff --git a/api/proxy_gen.go b/api/proxy_gen.go index 73aa2c774e5..cd3e1ad3533 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -627,7 +627,7 @@ type StorageMinerStruct struct { ActorSectorSize func(p0 context.Context, p1 address.Address) (abi.SectorSize, error) `perm:"read"` - CheckProvable func(p0 context.Context, p1 abi.RegisteredPoStProof, p2 []storage.SectorRef, p3 bool) (map[abi.SectorNumber]string, error) `perm:"admin"` + CheckProvable func(p0 context.Context, p1 abi.RegisteredPoStProof, p2 []storage.SectorRef, p3 []bool, p4 bool) (map[abi.SectorNumber]string, error) `perm:"admin"` ComputeProof func(p0 context.Context, p1 []builtin.ExtendedSectorInfo, p2 abi.PoStRandomness, p3 abi.ChainEpoch, p4 abinetwork.Version) ([]builtin.PoStProof, error) `perm:"read"` @@ -3760,14 +3760,14 @@ func (s *StorageMinerStub) ActorSectorSize(p0 context.Context, p1 address.Addres return *new(abi.SectorSize), ErrNotSupported } -func (s *StorageMinerStruct) CheckProvable(p0 context.Context, p1 abi.RegisteredPoStProof, p2 []storage.SectorRef, p3 bool) (map[abi.SectorNumber]string, error) { +func (s *StorageMinerStruct) CheckProvable(p0 context.Context, p1 abi.RegisteredPoStProof, p2 []storage.SectorRef, p3 []bool, p4 bool) (map[abi.SectorNumber]string, error) { if s.Internal.CheckProvable == nil { return *new(map[abi.SectorNumber]string), ErrNotSupported } - return s.Internal.CheckProvable(p0, p1, p2, p3) + return s.Internal.CheckProvable(p0, p1, p2, p3, p4) } -func (s *StorageMinerStub) CheckProvable(p0 context.Context, p1 abi.RegisteredPoStProof, p2 []storage.SectorRef, p3 bool) (map[abi.SectorNumber]string, error) { +func (s *StorageMinerStub) CheckProvable(p0 context.Context, p1 abi.RegisteredPoStProof, p2 []storage.SectorRef, p3 []bool, p4 bool) (map[abi.SectorNumber]string, error) { return *new(map[abi.SectorNumber]string), ErrNotSupported } diff --git a/api/version.go b/api/version.go index 228dcbd10d3..9f4f7351361 100644 --- a/api/version.go +++ b/api/version.go @@ -57,7 +57,7 @@ var ( FullAPIVersion0 = newVer(1, 5, 0) FullAPIVersion1 = newVer(2, 2, 0) - MinerAPIVersion0 = newVer(1, 3, 0) + MinerAPIVersion0 = newVer(1, 4, 0) WorkerAPIVersion0 = newVer(1, 5, 0) ) diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 4021b573d7df9e690f217a8548ac9c93933b2922..303444e99218463d0aa09b57899655163218db9a 100644 GIT binary patch delta 12156 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≀gT7 zurlaP29wcIZ!(Ip61}`FRtCxMG8}(TCjG&1(u;qZ$mMOZGJG!C96h^i9_^28j`v44 zC;K9sPn`fvy(vexSujmq+AWx>Hot8!RplcWOrMdJB$z%UE6ssvN!e@~Ov}sWcEGgK zS4e{CGqREd(`REP4W_*sV46bn-Fl`qnlBHgqpm*c_Kx}zlUsw2ur*zRru~0juiNVl z2S+_UgBe{{V&_24&nU%Dq!Ne(Qb&V9Z!pv+gMpru4!x^S2BYDqVSYyAqwZvIG&<^! zs^e;XF|CEGjfkl#uI@rilfe4iVwyzP=M~ck#Lf^EXCo)^wW|-t!=q6G{Jm=pBEK$y z*j=`r2G`xSopw!k*LK<$-Ccj%Ns!!S+ew_?kXR!E!1)e1t|z}&nsAx(Lr&nl!zfPGFOjUlXk zj~ukJumRWnNa=P>XU}+Q93+r15{XDW==?V1M|~Ynx)auPLT6=e0%DeUaK0QCmc95%q^e)HQLv z>i#X1KKI&dn-$Pz1rz{jn-#E6SpiQBN#7GVwZd)S-d@&E*lWc52_N~-kE^xVxvF=x z6aF_()ygljQ0BNmkEY7z`+#xj*)2Y!-_tMp8-W|E`H;L-@HHcs2^CWO95IcR2x3Ir6^k^+6u$gB y91)aWE7Mn%!X4GF#PO$u3~~6{W$E61t(DQ6XirbKPyasv0RR6yEy?v4c>(~l^V~52 delta 12122 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 Date: Wed, 23 Feb 2022 12:02:26 -0500 Subject: [PATCH 246/385] Handle pre-v7 case more gracefully --- chain/actors/builtin/verifreg/util.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/chain/actors/builtin/verifreg/util.go b/chain/actors/builtin/verifreg/util.go index 8d63e28c999..197a7921535 100644 --- a/chain/actors/builtin/verifreg/util.go +++ b/chain/actors/builtin/verifreg/util.go @@ -63,6 +63,9 @@ func getRemoveDataCapProposalID(store adt.Store, ver actors.Version, root rootFu if err != nil { return false, 0, xerrors.Errorf("loading verifreg: %w", err) } + if vh == nil { + return false, 0, xerrors.Errorf("remove data cap proposal hamt not found. you are probably using an incompatible version of actors") + } var id verifreg.RmDcProposalID if found, err := vh.Get(abi.NewAddrPairKey(verifier, client), &id); err != nil { From 25912e72a14e5441b3b5d7c72348b4c7336c7bb7 Mon Sep 17 00:00:00 2001 From: Geoff Stuart Date: Wed, 23 Feb 2022 12:14:26 -0500 Subject: [PATCH 247/385] Update cli/filplus.go Co-authored-by: Aayush Rajasekaran --- cli/filplus.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/filplus.go b/cli/filplus.go index 845b3948e6b..881f5610bec 100644 --- a/cli/filplus.go +++ b/cli/filplus.go @@ -284,7 +284,7 @@ var filplusSignRemoveDataCapProposal = &cli.Command{ Flags: []cli.Flag{ &cli.Int64Flag{ Name: "id", - Usage: "specify the id of the Remove Data Cap Proposal", + Usage: "specify the RemoveDataCapProposal ID (will look up on chain if unspecified)", Required: false, }, }, From ef68fdb261c4387017a10c88bb59df56eb2e816e Mon Sep 17 00:00:00 2001 From: Geoff Stuart Date: Wed, 23 Feb 2022 12:16:42 -0500 Subject: [PATCH 248/385] Update cmd/lotus-shed/verifreg.go Co-authored-by: Aayush Rajasekaran --- cmd/lotus-shed/verifreg.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/lotus-shed/verifreg.go b/cmd/lotus-shed/verifreg.go index 4220d230217..9777788cb60 100644 --- a/cmd/lotus-shed/verifreg.go +++ b/cmd/lotus-shed/verifreg.go @@ -417,7 +417,7 @@ var verifRegCheckVerifierCmd = &cli.Command{ var verifRegRemoveVerifiedClientDataCapCmd = &cli.Command{ Name: "remove-verified-client-data-cap", Usage: "Remove data cap from verified client", - ArgsUsage: " ", + ArgsUsage: " ", Action: func(cctx *cli.Context) error { if cctx.Args().Len() != 7 { return fmt.Errorf("must specify seven arguments: sender, client, allowance to remove, verifier 1 ID, verifier 1 signature, verifier 2 ID, verifier 2 signature") From aad376296ea4aab180cb35981055dcc80169f0db Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 23 Feb 2022 19:22:47 +0000 Subject: [PATCH 249/385] fvm: set gas costs to nil for implicit messages This is what the lotus VM does. --- chain/vm/fvm.go | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/chain/vm/fvm.go b/chain/vm/fvm.go index 962b27be6c3..6b410ff93b1 100644 --- a/chain/vm/fvm.go +++ b/chain/vm/fvm.go @@ -277,16 +277,7 @@ func (vm *FVM) ApplyImplicitMessage(ctx context.Context, cmsg *types.Message) (* ExitCode: exitcode.ExitCode(ret.ExitCode), GasUsed: ret.GasUsed, }, - GasCosts: &GasOutputs{ - // TODO: do the other optional fields eventually - BaseFeeBurn: abi.TokenAmount{}, - OverEstimationBurn: abi.TokenAmount{}, - MinerPenalty: ret.MinerPenalty, - MinerTip: ret.MinerTip, - Refund: abi.TokenAmount{}, - GasRefund: 0, - GasBurned: 0, - }, + GasCosts: nil, // TODO: do these eventually, not consensus critical ActorErr: nil, ExecutionTrace: types.ExecutionTrace{}, From 420c5fb568b74d83146039cac39b81b69dd13c54 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 23 Feb 2022 19:23:20 +0000 Subject: [PATCH 250/385] fvm: time message execution --- chain/vm/fvm.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/chain/vm/fvm.go b/chain/vm/fvm.go index 6b410ff93b1..743e0fdeeb1 100644 --- a/chain/vm/fvm.go +++ b/chain/vm/fvm.go @@ -3,9 +3,11 @@ package vm import ( "bytes" "context" + "time" "github.com/filecoin-project/go-state-types/big" + "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/state" cbor "github.com/ipfs/go-ipld-cbor" @@ -150,7 +152,7 @@ func (x *FvmExtern) VerifyConsensusFault(ctx context.Context, a, b, extra []byte ret.Type = faultType ret.Target = blockA.Miner - + return ret, totalGas } @@ -227,6 +229,7 @@ func NewFVM(ctx context.Context, opts *VMOpts) (*FVM, error) { } func (vm *FVM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, error) { + start := build.Clock.Now() msgBytes, err := cmsg.VMMessage().Serialize() if err != nil { return nil, xerrors.Errorf("serializing msg: %w", err) @@ -256,16 +259,16 @@ func (vm *FVM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet // TODO: do these eventually, not consensus critical ActorErr: nil, ExecutionTrace: types.ExecutionTrace{}, - Duration: 0, + Duration: time.Since(start), }, nil } func (vm *FVM) ApplyImplicitMessage(ctx context.Context, cmsg *types.Message) (*ApplyRet, error) { + start := build.Clock.Now() msgBytes, err := cmsg.VMMessage().Serialize() if err != nil { return nil, xerrors.Errorf("serializing msg: %w", err) } - ret, err := vm.fvm.ApplyImplicitMessage(msgBytes) if err != nil { return nil, xerrors.Errorf("applying msg: %w", err) @@ -281,7 +284,7 @@ func (vm *FVM) ApplyImplicitMessage(ctx context.Context, cmsg *types.Message) (* // TODO: do these eventually, not consensus critical ActorErr: nil, ExecutionTrace: types.ExecutionTrace{}, - Duration: 0, + Duration: time.Since(start), }, nil } From fd8cb44e675b08e033dc5f9b4e1ee67e3bbd5cd1 Mon Sep 17 00:00:00 2001 From: Aayush Date: Thu, 24 Feb 2022 10:27:37 -0500 Subject: [PATCH 251/385] fix: client: calculate commps for pieces bigger than 32GB --- node/impl/client/client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/impl/client/client.go b/node/impl/client/client.go index 7848c84f92d..1730b7a7a1b 100644 --- a/node/impl/client/client.go +++ b/node/impl/client/client.go @@ -1272,7 +1272,7 @@ func (a *API) ClientCalcCommP(ctx context.Context, inpath string) (*api.CommPRet // // IF/WHEN this changes in the future we will have to be able to calculate // "old style" commP, and thus will need to introduce a version switch or similar - arbitraryProofType := abi.RegisteredSealProof_StackedDrg32GiBV1_1 + arbitraryProofType := abi.RegisteredSealProof_StackedDrg64GiBV1_1 rdr, err := os.Open(inpath) if err != nil { From 9bb936b75cd033fe88b9233e1b7e7be90f3a1953 Mon Sep 17 00:00:00 2001 From: Aayush Date: Tue, 22 Feb 2022 22:01:21 -0500 Subject: [PATCH 252/385] chore: refactor: rename NewVM to NewLotusVM --- chain/gen/genesis/genesis.go | 4 ++-- chain/gen/genesis/miners.go | 4 ++-- chain/stmgr/forks_test.go | 6 +++--- chain/stmgr/stmgr.go | 2 +- chain/vm/vm.go | 2 +- cmd/lotus-sim/simulation/blockbuilder/blockbuilder.go | 2 +- conformance/driver.go | 4 ++-- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/chain/gen/genesis/genesis.go b/chain/gen/genesis/genesis.go index 6ab101e7893..bb3d7d47792 100644 --- a/chain/gen/genesis/genesis.go +++ b/chain/gen/genesis/genesis.go @@ -494,9 +494,9 @@ func VerifyPreSealedData(ctx context.Context, cs *store.ChainStore, sys vm.Sysca NetworkVersion: nv, BaseFee: types.NewInt(0), } - vm, err := vm.NewVM(ctx, &vmopt) + vm, err := vm.NewLotusVM(ctx, &vmopt) if err != nil { - return cid.Undef, xerrors.Errorf("failed to create NewVM: %w", err) + return cid.Undef, xerrors.Errorf("failed to create NewLotusVM: %w", err) } for mi, m := range template.Miners { diff --git a/chain/gen/genesis/miners.go b/chain/gen/genesis/miners.go index 2749181470c..b705c6afed7 100644 --- a/chain/gen/genesis/miners.go +++ b/chain/gen/genesis/miners.go @@ -98,9 +98,9 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sys vm.Syscal BaseFee: types.NewInt(0), } - vm, err := vm.NewVM(ctx, vmopt) + vm, err := vm.NewLotusVM(ctx, vmopt) if err != nil { - return cid.Undef, xerrors.Errorf("failed to create NewVM: %w", err) + return cid.Undef, xerrors.Errorf("failed to create NewLotusVM: %w", err) } if len(miners) == 0 { diff --git a/chain/stmgr/forks_test.go b/chain/stmgr/forks_test.go index 4fad1e4fc8f..fbf7b6785b0 100644 --- a/chain/stmgr/forks_test.go +++ b/chain/stmgr/forks_test.go @@ -167,7 +167,7 @@ func TestForkHeightTriggers(t *testing.T) { inv.Register(nil, testActor{}) sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (*vm.VM, error) { - nvm, err := vm.NewVM(ctx, vmopt) + nvm, err := vm.NewLotusVM(ctx, vmopt) if err != nil { return nil, err } @@ -282,7 +282,7 @@ func testForkRefuseCall(t *testing.T, nullsBefore, nullsAfter int) { inv.Register(nil, testActor{}) sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (*vm.VM, error) { - nvm, err := vm.NewVM(ctx, vmopt) + nvm, err := vm.NewLotusVM(ctx, vmopt) if err != nil { return nil, err } @@ -501,7 +501,7 @@ func TestForkPreMigration(t *testing.T) { inv.Register(nil, testActor{}) sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (*vm.VM, error) { - nvm, err := vm.NewVM(ctx, vmopt) + nvm, err := vm.NewLotusVM(ctx, vmopt) if err != nil { return nil, err } diff --git a/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index 45dd52ec88b..ed007b756ff 100644 --- a/chain/stmgr/stmgr.go +++ b/chain/stmgr/stmgr.go @@ -142,7 +142,7 @@ func NewStateManager(cs *store.ChainStore, exec Executor, sys vm.SyscallBuilder, latestVersion: lastVersion, stateMigrations: stateMigrations, expensiveUpgrades: expensiveUpgrades, - newVM: vm.NewVM, + newVM: vm.NewLotusVM, Syscalls: sys, cs: cs, tsExec: exec, diff --git a/chain/vm/vm.go b/chain/vm/vm.go index 3e2b76fe61c..ca9855b104b 100644 --- a/chain/vm/vm.go +++ b/chain/vm/vm.go @@ -234,7 +234,7 @@ type VMOpts struct { LookbackState LookbackStateGetter } -func NewVM(ctx context.Context, opts *VMOpts) (*VM, error) { +func NewLotusVM(ctx context.Context, opts *VMOpts) (*VM, error) { buf := blockstore.NewBuffered(opts.Bstore) cst := cbor.NewCborStore(buf) state, err := state.LoadStateTree(cst, opts.StateBase) diff --git a/cmd/lotus-sim/simulation/blockbuilder/blockbuilder.go b/cmd/lotus-sim/simulation/blockbuilder/blockbuilder.go index fb822eb6e77..7aaaf0ec7c6 100644 --- a/cmd/lotus-sim/simulation/blockbuilder/blockbuilder.go +++ b/cmd/lotus-sim/simulation/blockbuilder/blockbuilder.go @@ -92,7 +92,7 @@ func NewBlockBuilder(ctx context.Context, logger *zap.SugaredLogger, sm *stmgr.S BaseFee: abi.NewTokenAmount(0), LookbackState: stmgr.LookbackStateGetterForTipset(sm, parentTs), } - bb.vm, err = vm.NewVM(bb.ctx, vmopt) + bb.vm, err = vm.NewLotusVM(bb.ctx, vmopt) if err != nil { return nil, err } diff --git a/conformance/driver.go b/conformance/driver.go index a065d15305d..6af4372d2ec 100644 --- a/conformance/driver.go +++ b/conformance/driver.go @@ -160,7 +160,7 @@ func (d *Driver) ExecuteTipset(bs blockstore.Blockstore, ds ds.Batching, params return big.Zero(), nil } - return vm.NewVM(ctx, vmopt) + return vm.NewLotusVM(ctx, vmopt) }) postcid, receiptsroot, err := tse.ApplyBlocks(context.Background(), @@ -226,7 +226,7 @@ func (d *Driver) ExecuteMessage(bs blockstore.Blockstore, params ExecuteMessageP NetworkVersion: params.NetworkVersion, } - lvm, err := vm.NewVM(context.TODO(), vmOpts) + lvm, err := vm.NewLotusVM(context.TODO(), vmOpts) if err != nil { return nil, cid.Undef, err } From b6682f4bbe24cf398c65f0f1aa201cfeed081203 Mon Sep 17 00:00:00 2001 From: Aayush Date: Tue, 22 Feb 2022 22:43:14 -0500 Subject: [PATCH 253/385] feat: use either lotus vm or fvm consistently --- chain/stmgr/call.go | 14 ++++++++++++-- chain/stmgr/stmgr.go | 10 +++++----- chain/vm/vmi.go | 9 +++++++++ 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/chain/stmgr/call.go b/chain/stmgr/call.go index 31639701dad..955e0bcc895 100644 --- a/chain/stmgr/call.go +++ b/chain/stmgr/call.go @@ -112,7 +112,12 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types. ) } - fromActor, err := vmi.StateTree().GetActor(msg.From) + stTree, err := sm.StateTree(bstate) + if err != nil { + return nil, err + } + + fromActor, err := stTree.GetActor(msg.From) if err != nil { return nil, xerrors.Errorf("call raw get actor: %s", err) } @@ -219,7 +224,12 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, pri } } - fromActor, err := vmi.StateTree().GetActor(msg.From) + stTree, err := sm.StateTree(state) + if err != nil { + return nil, err + } + + fromActor, err := stTree.GetActor(msg.From) if err != nil { return nil, xerrors.Errorf("call raw get actor: %s", err) } diff --git a/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index ed007b756ff..fd58af8b269 100644 --- a/chain/stmgr/stmgr.go +++ b/chain/stmgr/stmgr.go @@ -84,7 +84,7 @@ type StateManager struct { compWait map[string]chan struct{} stlk sync.Mutex genesisMsigLk sync.Mutex - newVM func(context.Context, *vm.VMOpts) (*vm.VM, error) + newVM func(context.Context, *vm.VMOpts) (vm.VMI, error) Syscalls vm.SyscallBuilder preIgnitionVesting []msig0.State postIgnitionVesting []msig0.State @@ -142,7 +142,7 @@ func NewStateManager(cs *store.ChainStore, exec Executor, sys vm.SyscallBuilder, latestVersion: lastVersion, stateMigrations: stateMigrations, expensiveUpgrades: expensiveUpgrades, - newVM: vm.NewLotusVM, + newVM: vm.NewVM, Syscalls: sys, cs: cs, tsExec: exec, @@ -347,12 +347,12 @@ func (sm *StateManager) ValidateChain(ctx context.Context, ts *types.TipSet) err return nil } -func (sm *StateManager) SetVMConstructor(nvm func(context.Context, *vm.VMOpts) (*vm.VM, error)) { +func (sm *StateManager) SetVMConstructor(nvm func(context.Context, *vm.VMOpts) (vm.VMI, error)) { sm.newVM = nvm } -func (sm *StateManager) VMConstructor() func(context.Context, *vm.VMOpts) (*vm.VM, error) { - return func(ctx context.Context, opts *vm.VMOpts) (*vm.VM, error) { +func (sm *StateManager) VMConstructor() func(context.Context, *vm.VMOpts) (vm.VMI, error) { + return func(ctx context.Context, opts *vm.VMOpts) (vm.VMI, error) { return sm.newVM(ctx, opts) } } diff --git a/chain/vm/vmi.go b/chain/vm/vmi.go index 4903354d221..b180f84f20a 100644 --- a/chain/vm/vmi.go +++ b/chain/vm/vmi.go @@ -2,6 +2,7 @@ package vm import ( "context" + "os" "github.com/filecoin-project/lotus/chain/types" "github.com/ipfs/go-cid" @@ -12,3 +13,11 @@ type VMI interface { ApplyImplicitMessage(ctx context.Context, msg *types.Message) (*ApplyRet, error) Flush(ctx context.Context) (cid.Cid, error) } + +func NewVM(ctx context.Context, opts *VMOpts) (VMI, error) { + if os.Getenv("LOTUS_USE_FVM_DOESNT_WORK_YET") == "1" { + return NewFVM(ctx, opts) + } + + return NewLotusVM(ctx, opts) +} From d58babe32cd24ef06da10e91e7b101ecb1f501a5 Mon Sep 17 00:00:00 2001 From: Aayush Date: Wed, 23 Feb 2022 18:17:05 -0500 Subject: [PATCH 254/385] fix: set FilVested when constructing VmOpts --- chain/gen/genesis/genesis.go | 3 ++- chain/gen/genesis/miners.go | 3 ++- chain/stmgr/call.go | 12 ++++++++++++ chain/stmgr/utils.go | 6 ++++++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/chain/gen/genesis/genesis.go b/chain/gen/genesis/genesis.go index bb3d7d47792..78b06637ce4 100644 --- a/chain/gen/genesis/genesis.go +++ b/chain/gen/genesis/genesis.go @@ -491,8 +491,9 @@ func VerifyPreSealedData(ctx context.Context, cs *store.ChainStore, sys vm.Sysca Actors: filcns.NewActorRegistry(), Syscalls: mkFakedSigSyscalls(sys), CircSupplyCalc: csc, + FilVested: big.Zero(), NetworkVersion: nv, - BaseFee: types.NewInt(0), + BaseFee: big.Zero(), } vm, err := vm.NewLotusVM(ctx, &vmopt) if err != nil { diff --git a/chain/gen/genesis/miners.go b/chain/gen/genesis/miners.go index b705c6afed7..93861e6812b 100644 --- a/chain/gen/genesis/miners.go +++ b/chain/gen/genesis/miners.go @@ -95,7 +95,8 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sys vm.Syscal Syscalls: mkFakedSigSyscalls(sys), CircSupplyCalc: csc, NetworkVersion: nv, - BaseFee: types.NewInt(0), + BaseFee: big.Zero(), + FilVested: big.Zero(), } vm, err := vm.NewLotusVM(ctx, vmopt) diff --git a/chain/stmgr/call.go b/chain/stmgr/call.go index 955e0bcc895..fd5f7cd05aa 100644 --- a/chain/stmgr/call.go +++ b/chain/stmgr/call.go @@ -72,6 +72,11 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types. return nil, fmt.Errorf("failed to handle fork: %w", err) } + filVested, err := sm.GetFilVested(ctx, pheight+1) + if err != nil { + return nil, err + } + vmopt := &vm.VMOpts{ StateBase: bstate, Epoch: pheight + 1, @@ -82,6 +87,7 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types. CircSupplyCalc: sm.GetVMCirculatingSupply, NetworkVersion: sm.GetNetworkVersion(ctx, pheight+1), BaseFee: types.NewInt(0), + FilVested: filVested, LookbackState: LookbackStateGetterForTipset(sm, ts), } @@ -201,6 +207,11 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, pri ) } + filVested, err := sm.GetFilVested(ctx, ts.Height()+1) + if err != nil { + return nil, err + } + vmopt := &vm.VMOpts{ StateBase: state, Epoch: ts.Height() + 1, @@ -211,6 +222,7 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, pri CircSupplyCalc: sm.GetVMCirculatingSupply, NetworkVersion: sm.GetNetworkVersion(ctx, ts.Height()+1), BaseFee: ts.Blocks()[0].ParentBaseFee, + FilVested: filVested, LookbackState: LookbackStateGetterForTipset(sm, ts), } vmi, err := sm.newVM(ctx, vmopt) diff --git a/chain/stmgr/utils.go b/chain/stmgr/utils.go index 2a84c777b3a..49dd4700a21 100644 --- a/chain/stmgr/utils.go +++ b/chain/stmgr/utils.go @@ -79,6 +79,11 @@ func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch, // future. It's not guaranteed to be accurate... but that's fine. } + filVested, err := sm.GetFilVested(ctx, height) + if err != nil { + return cid.Undef, nil, err + } + r := rand.NewStateRand(sm.cs, ts.Cids(), sm.beacon, sm.GetNetworkVersion) vmopt := &vm.VMOpts{ StateBase: base, @@ -90,6 +95,7 @@ func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch, CircSupplyCalc: sm.GetVMCirculatingSupply, NetworkVersion: sm.GetNetworkVersion(ctx, height), BaseFee: ts.Blocks()[0].ParentBaseFee, + FilVested: filVested, LookbackState: LookbackStateGetterForTipset(sm, ts), } vmi, err := sm.newVM(ctx, vmopt) From 2ba34add2a0bc5d39067477f74f42f1a848401f5 Mon Sep 17 00:00:00 2001 From: Aayush Date: Thu, 24 Feb 2022 12:19:59 -0500 Subject: [PATCH 255/385] stmgr: call needs to flush VM before fetching nonce --- chain/stmgr/call.go | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/chain/stmgr/call.go b/chain/stmgr/call.go index fd5f7cd05aa..fb7f33d0347 100644 --- a/chain/stmgr/call.go +++ b/chain/stmgr/call.go @@ -5,6 +5,12 @@ import ( "errors" "fmt" + cbor "github.com/ipfs/go-ipld-cbor" + + "github.com/filecoin-project/lotus/chain/state" + + "github.com/filecoin-project/lotus/blockstore" + "github.com/filecoin-project/lotus/chain/rand" "github.com/filecoin-project/go-address" @@ -64,6 +70,7 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types. pheight = ts.Height() - 1 } + vmHeight := pheight + 1 bstate := ts.ParentState() // Run the (not expensive) migration. @@ -72,14 +79,14 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types. return nil, fmt.Errorf("failed to handle fork: %w", err) } - filVested, err := sm.GetFilVested(ctx, pheight+1) + filVested, err := sm.GetFilVested(ctx, vmHeight) if err != nil { return nil, err } vmopt := &vm.VMOpts{ StateBase: bstate, - Epoch: pheight + 1, + Epoch: vmHeight, Rand: rand.NewStateRand(sm.cs, ts.Cids(), sm.beacon, sm.GetNetworkVersion), Bstore: sm.cs.StateBlockstore(), Actors: sm.tsExec.NewActorRegistry(), @@ -186,13 +193,15 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, pri } } - state, _, err := sm.TipSetState(ctx, ts) + vmHeight := ts.Height() + 1 + + stateCid, _, err := sm.TipSetState(ctx, ts) if err != nil { return nil, xerrors.Errorf("computing tipset state: %w", err) } // Technically, the tipset we're passing in here should be ts+1, but that may not exist. - state, err = sm.HandleStateForks(ctx, state, ts.Height(), nil, ts) + stateCid, err = sm.HandleStateForks(ctx, stateCid, ts.Height(), nil, ts) if err != nil { return nil, fmt.Errorf("failed to handle fork: %w", err) } @@ -207,16 +216,17 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, pri ) } - filVested, err := sm.GetFilVested(ctx, ts.Height()+1) + filVested, err := sm.GetFilVested(ctx, vmHeight) if err != nil { return nil, err } + buffStore := blockstore.NewBuffered(sm.cs.StateBlockstore()) vmopt := &vm.VMOpts{ - StateBase: state, - Epoch: ts.Height() + 1, + StateBase: stateCid, + Epoch: vmHeight, Rand: r, - Bstore: sm.cs.StateBlockstore(), + Bstore: buffStore, Actors: sm.tsExec.NewActorRegistry(), Syscalls: sm.Syscalls, CircSupplyCalc: sm.GetVMCirculatingSupply, @@ -236,9 +246,14 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, pri } } - stTree, err := sm.StateTree(state) + stateCid, err = vmi.Flush(ctx) if err != nil { - return nil, err + return nil, xerrors.Errorf("flushing vm: %w", err) + } + + stTree, err := state.LoadStateTree(cbor.NewCborStore(buffStore), stateCid) + if err != nil { + return nil, xerrors.Errorf("loading state tree: %w", err) } fromActor, err := stTree.GetActor(msg.From) From 83bf0c5a117dc5e65febbdf99ca40d5c2196a22a Mon Sep 17 00:00:00 2001 From: Geoff Stuart Date: Thu, 24 Feb 2022 12:40:13 -0500 Subject: [PATCH 256/385] Review fixes --- cli/filplus.go | 13 +++++++++--- cmd/lotus-shed/verifreg.go | 41 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/cli/filplus.go b/cli/filplus.go index 881f5610bec..b3a98d48774 100644 --- a/cli/filplus.go +++ b/cli/filplus.go @@ -280,7 +280,7 @@ func checkNotary(ctx context.Context, api v0api.FullNode, vaddr address.Address) var filplusSignRemoveDataCapProposal = &cli.Command{ Name: "sign-remove-data-cap-proposal", - Usage: "TODO", + Usage: "allows a notary to sign a Remove Data Cap Proposal", Flags: []cli.Flag{ &cli.Int64Flag{ Name: "id", @@ -290,7 +290,7 @@ var filplusSignRemoveDataCapProposal = &cli.Command{ }, Action: func(cctx *cli.Context) error { if cctx.Args().Len() != 3 { - return fmt.Errorf("must specify three arguments: verifier address, client address, and allowance to remove") + return fmt.Errorf("must specify three arguments: notary address, client address, and allowance to remove") } api, closer, err := GetFullNodeAPI(cctx) @@ -336,6 +336,14 @@ var filplusSignRemoveDataCapProposal = &cli.Command{ return err } + _, dataCap, err := st.VerifiedClientDataCap(clientIdAddr) + if err != nil { + return xerrors.Errorf("failed to find verified client data cap: %w", err) + } + if dataCap.LessThanEqual(big.Zero()) { + return xerrors.Errorf("client data cap %s is less than amount requested to be removed %s", dataCap.String(), allowanceToRemove.String()) + } + found, _, err := checkNotary(ctx, api, verifier) if err != nil { return xerrors.Errorf("failed to check notary status: %w", err) @@ -353,7 +361,6 @@ var filplusSignRemoveDataCapProposal = &cli.Command{ } } - // TODO: This should be abstracted over actor versions params := verifreg.RemoveDataCapProposal{ RemovalProposalID: verifreg.RmDcProposalID{ProposalID: id}, DataCapAmount: allowanceToRemove, diff --git a/cmd/lotus-shed/verifreg.go b/cmd/lotus-shed/verifreg.go index 9777788cb60..4a0664e90f5 100644 --- a/cmd/lotus-shed/verifreg.go +++ b/cmd/lotus-shed/verifreg.go @@ -4,6 +4,8 @@ import ( "encoding/hex" "fmt" + "github.com/filecoin-project/lotus/chain/actors/builtin/multisig" + "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/big" @@ -498,6 +500,45 @@ var verifRegRemoveVerifiedClientDataCapCmd = &cli.Command{ return err } + vrkState, err := api.StateGetActor(ctx, vrk, types.EmptyTSK) + if err != nil { + return err + } + + apibs := blockstore.NewAPIBlockstore(api) + store := adt.WrapStore(ctx, cbor.NewCborStore(apibs)) + + st, err := multisig.Load(store, vrkState) + if err != nil { + return err + } + + signers, err := st.Signers() + if err != nil { + return err + } + + senderIsSigner := false + senderIdAddr, err := address.IDFromAddress(sender) + if err != nil { + return err + } + + for _, signer := range signers { + signerIdAddr, err := address.IDFromAddress(signer) + if err != nil { + return err + } + + if signerIdAddr == senderIdAddr { + senderIsSigner = true + } + } + + if !senderIsSigner { + return fmt.Errorf("sender must be a vrk signer") + } + proto, err := api.MsigPropose(ctx, vrk, verifreg.Address, big.Zero(), sender, uint64(verifreg.Methods.RemoveVerifiedClientDataCap), params) if err != nil { return err From 4293023731e89148d9aaf6bddc7884b3fc548374 Mon Sep 17 00:00:00 2001 From: Geoff Stuart Date: Thu, 24 Feb 2022 12:43:02 -0500 Subject: [PATCH 257/385] Updated cli docs --- documentation/en/cli-lotus.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/documentation/en/cli-lotus.md b/documentation/en/cli-lotus.md index eca4e5a811e..d136fe290f1 100644 --- a/documentation/en/cli-lotus.md +++ b/documentation/en/cli-lotus.md @@ -1239,7 +1239,7 @@ COMMANDS: list-clients list all verified clients check-client-datacap check verified client remaining bytes check-notary-datacap check a notary's remaining bytes - sign-remove-data-cap-proposal TODO + sign-remove-data-cap-proposal allows a notary to sign a Remove Data Cap Proposal help, h Shows a list of commands or help for one command OPTIONS: @@ -1317,13 +1317,13 @@ OPTIONS: ### lotus filplus sign-remove-data-cap-proposal ``` NAME: - lotus filplus sign-remove-data-cap-proposal - TODO + lotus filplus sign-remove-data-cap-proposal - allows a notary to sign a Remove Data Cap Proposal USAGE: lotus filplus sign-remove-data-cap-proposal [command options] [arguments...] OPTIONS: - --id value specify the id of the Remove Data Cap Proposal (default: 0) + --id value specify the RemoveDataCapProposal ID (will look up on chain if unspecified) (default: 0) --help, -h show help (default: false) ``` From e0382c546d06aaf667a9d2efd795c8462936ee24 Mon Sep 17 00:00:00 2001 From: Geoff Stuart Date: Thu, 24 Feb 2022 13:07:10 -0500 Subject: [PATCH 258/385] Update cmd/lotus-shed/verifreg.go Co-authored-by: Aayush Rajasekaran --- cmd/lotus-shed/verifreg.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/lotus-shed/verifreg.go b/cmd/lotus-shed/verifreg.go index 4a0664e90f5..fb2598fda7c 100644 --- a/cmd/lotus-shed/verifreg.go +++ b/cmd/lotus-shed/verifreg.go @@ -422,7 +422,7 @@ var verifRegRemoveVerifiedClientDataCapCmd = &cli.Command{ ArgsUsage: " ", Action: func(cctx *cli.Context) error { if cctx.Args().Len() != 7 { - return fmt.Errorf("must specify seven arguments: sender, client, allowance to remove, verifier 1 ID, verifier 1 signature, verifier 2 ID, verifier 2 signature") + return fmt.Errorf("must specify seven arguments: sender, client, allowance to remove, verifier 1 address, verifier 1 signature, verifier 2 address, verifier 2 signature") } srv, err := lcli.GetFullNodeServices(cctx) From 367146f03207cff32bad2537cf295c5c6d6a4031 Mon Sep 17 00:00:00 2001 From: zenground0 Date: Thu, 24 Feb 2022 15:20:21 -0700 Subject: [PATCH 259/385] add rdi flag for abort upgrade --- cmd/lotus-miner/sectors.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cmd/lotus-miner/sectors.go b/cmd/lotus-miner/sectors.go index d8c3e9c7cc2..89e282d0041 100644 --- a/cmd/lotus-miner/sectors.go +++ b/cmd/lotus-miner/sectors.go @@ -1540,6 +1540,12 @@ var sectorsSnapAbortCmd = &cli.Command{ return lcli.ShowHelp(cctx, xerrors.Errorf("must pass sector number")) } + really := cctx.Bool("really-do-it") + if !really { + //nolint:golint + return fmt.Errorf("--really-do-it must be specified for this action to have an effect; you have been warned") + } + nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx) if err != nil { return err From 77bf46d018039d1709730f05ab0cb87920d63643 Mon Sep 17 00:00:00 2001 From: zenground0 Date: Thu, 24 Feb 2022 15:46:15 -0700 Subject: [PATCH 260/385] Tiny clean up --- chain/wallet/multi_test.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/chain/wallet/multi_test.go b/chain/wallet/multi_test.go index 54ff240c5c4..d6fdf6656b2 100644 --- a/chain/wallet/multi_test.go +++ b/chain/wallet/multi_test.go @@ -61,14 +61,13 @@ func TestMultiWallet(t *testing.T) { t.Fatal(err) } + if addr != a1 { + t.Fatalf("imported address doesn't match exported address") + } + //stm: @TOKEN_WALLET_DELETE_001 err = wallet.WalletDelete(ctx, a1) if err != nil { t.Fatal(err) } - - if addr != a1 { - t.Fatalf("imported address doesn't match exported address") - } - } From dac551800507d836d3cdeddc187d109535914053 Mon Sep 17 00:00:00 2001 From: llifezou <46102475+llifezou@users.noreply.github.com> Date: Fri, 25 Feb 2022 11:12:18 +0800 Subject: [PATCH 261/385] Update extern/sector-storage/worker_local.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Łukasz Magiera --- extern/sector-storage/worker_local.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/sector-storage/worker_local.go b/extern/sector-storage/worker_local.go index 0eb8bd9a658..3c01ba337d5 100644 --- a/extern/sector-storage/worker_local.go +++ b/extern/sector-storage/worker_local.go @@ -273,7 +273,7 @@ func (l *LocalWorker) asyncCall(ctx context.Context, sector storage.SectorRef, r log.Errorf("get hostname err: %+v", err) } - err = xerrors.Errorf("%s [Hostname: %s]", err.Error(), hostname) + err = xerrors.Errorf("%w [Hostname: %s]", err.Error(), hostname) } if doReturn(ctx, rt, ci, l.ret, res, toCallError(err)) { From 52756128da643dc3193738a354d97733eecb038c Mon Sep 17 00:00:00 2001 From: jennijuju Date: Fri, 25 Feb 2022 10:28:47 -0500 Subject: [PATCH 262/385] add flag usage --- cmd/lotus-miner/sectors.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cmd/lotus-miner/sectors.go b/cmd/lotus-miner/sectors.go index 89e282d0041..24098b5581e 100644 --- a/cmd/lotus-miner/sectors.go +++ b/cmd/lotus-miner/sectors.go @@ -1535,6 +1535,12 @@ var sectorsSnapAbortCmd = &cli.Command{ Name: "abort-upgrade", Usage: "Abort the attempted (SnapDeals) upgrade of a CC sector, reverting it to as before", ArgsUsage: "", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "really-do-it", + Usage: "pass this flag if you know what you are doing", + }, + }, Action: func(cctx *cli.Context) error { if cctx.Args().Len() != 1 { return lcli.ShowHelp(cctx, xerrors.Errorf("must pass sector number")) From 865c7e587cd6ec0ae8c6a51b7e32f072aae8ed18 Mon Sep 17 00:00:00 2001 From: jennijuju Date: Fri, 25 Feb 2022 10:48:08 -0500 Subject: [PATCH 263/385] make gen --- documentation/en/cli-lotus-miner.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/documentation/en/cli-lotus-miner.md b/documentation/en/cli-lotus-miner.md index 848a9c8649a..f455aeacefb 100644 --- a/documentation/en/cli-lotus-miner.md +++ b/documentation/en/cli-lotus-miner.md @@ -1826,7 +1826,8 @@ USAGE: lotus-miner sectors abort-upgrade [command options] OPTIONS: - --help, -h show help (default: false) + --really-do-it pass this flag if you know what you are doing (default: false) + --help, -h show help (default: false) ``` From 254f821564f439548512471dc347816bc517a7c3 Mon Sep 17 00:00:00 2001 From: jennijuju Date: Fri, 25 Feb 2022 21:03:46 -0500 Subject: [PATCH 264/385] get actor v7 (same commit as v7-rc1) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7b6e72575aa..344bcd7e275 100644 --- a/go.mod +++ b/go.mod @@ -52,7 +52,7 @@ require ( github.com/filecoin-project/specs-actors/v4 v4.0.1 github.com/filecoin-project/specs-actors/v5 v5.0.4 github.com/filecoin-project/specs-actors/v6 v6.0.1 - github.com/filecoin-project/specs-actors/v7 v7.0.0-rc1 + github.com/filecoin-project/specs-actors/v7 v7.0.0 github.com/filecoin-project/specs-storage v0.2.0 github.com/filecoin-project/test-vectors/schema v0.0.5 github.com/gbrlsnchs/jwt/v3 v3.0.1 diff --git a/go.sum b/go.sum index 417267e376f..15fa2807b00 100644 --- a/go.sum +++ b/go.sum @@ -380,8 +380,8 @@ github.com/filecoin-project/specs-actors/v6 v6.0.1 h1:laxvHNsvrq83Y9n+W7znVCePi3 github.com/filecoin-project/specs-actors/v6 v6.0.1/go.mod h1:V1AYfi5GkHXipx1mnVivoICZh3wtwPxDVuds+fbfQtk= github.com/filecoin-project/specs-actors/v7 v7.0.0-20211117170924-fd07a4c7dff9/go.mod h1:p6LIOFezA1rgRLMewbvdi3Pp6SAu+q9FtJ9CAleSjrE= github.com/filecoin-project/specs-actors/v7 v7.0.0-20211222192039-c83bea50c402/go.mod h1:p6LIOFezA1rgRLMewbvdi3Pp6SAu+q9FtJ9CAleSjrE= -github.com/filecoin-project/specs-actors/v7 v7.0.0-rc1 h1:FuDaXIbcw2hRsFI8SDTmsGGCE+NumpF6aiBoU/2X5W4= -github.com/filecoin-project/specs-actors/v7 v7.0.0-rc1/go.mod h1:TA5FwCna+Yi36POaT7SLKXsgEDvJwc0V/L6ZsO19B9M= +github.com/filecoin-project/specs-actors/v7 v7.0.0 h1:FQN7tjt3o68hfb3qLFSJBoLMuOFY0REkFVLO/zXj8RU= +github.com/filecoin-project/specs-actors/v7 v7.0.0/go.mod h1:TA5FwCna+Yi36POaT7SLKXsgEDvJwc0V/L6ZsO19B9M= github.com/filecoin-project/specs-storage v0.2.0 h1:Y4UDv0apRQ3zI2GiPPubi8JblpUZZphEdaJUxCutfyg= github.com/filecoin-project/specs-storage v0.2.0/go.mod h1:Tb88Zq+IBJbvAn3mS89GYj3jdRThBTE/771HCVZdRJU= github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg= From 92c07f877bd97a18f082caf2cb84e7e1b7c1618e Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Sun, 27 Feb 2022 20:03:45 -0500 Subject: [PATCH 265/385] fix: shed: diff command --- cmd/lotus-shed/diff.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/lotus-shed/diff.go b/cmd/lotus-shed/diff.go index bcaa041227e..d576f73b4eb 100644 --- a/cmd/lotus-shed/diff.go +++ b/cmd/lotus-shed/diff.go @@ -35,7 +35,7 @@ var diffStateTrees = &cli.Command{ return xerrors.Errorf("expected two state-tree roots") } - argA := cctx.Args().Get(1) + argA := cctx.Args().Get(0) rootA, err := cid.Parse(argA) if err != nil { return xerrors.Errorf("first state-tree root (%q) is not a CID: %w", argA, err) From 8a9ea66bdf002387c0fbe7f44c28b82d2fbe5fb0 Mon Sep 17 00:00:00 2001 From: Bhaskara Ram <39507881+bhaskarvilles@users.noreply.github.com> Date: Mon, 28 Feb 2022 12:40:43 +0530 Subject: [PATCH 266/385] node-fetch is vulnerable to Exposure of Sensitive Information to an Unauthorized Actor upgrade to node-fetch npm package --- lotuspond/front/package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lotuspond/front/package-lock.json b/lotuspond/front/package-lock.json index 252a42a6d4f..9bc04c8a38f 100644 --- a/lotuspond/front/package-lock.json +++ b/lotuspond/front/package-lock.json @@ -6630,7 +6630,7 @@ "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", "requires": { - "node-fetch": "^1.0.1", + "node-fetch": "^2.6.7", "whatwg-fetch": ">=0.10.0" } }, From 296ae4305fa224c285d7ee8c1d8facbb7f28ecfc Mon Sep 17 00:00:00 2001 From: duzy555666 <965876239@qq.com> Date: Mon, 28 Feb 2022 16:51:15 +0800 Subject: [PATCH 267/385] avoid panic --- cmd/lotus-miner/sealing.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/cmd/lotus-miner/sealing.go b/cmd/lotus-miner/sealing.go index 16b02f7bbe0..2f97c1e073c 100644 --- a/cmd/lotus-miner/sealing.go +++ b/cmd/lotus-miner/sealing.go @@ -39,9 +39,12 @@ func barString(total, y, g float64) string { yBars := int(math.Round(y / total * barCols)) gBars := int(math.Round(g / total * barCols)) eBars := int(barCols) - yBars - gBars - return color.YellowString(strings.Repeat("|", yBars)) + - color.GreenString(strings.Repeat("|", gBars)) + - strings.Repeat(" ", eBars) + var barString = color.YellowString(strings.Repeat("|", yBars)) + + color.GreenString(strings.Repeat("|", gBars)) + if eBars >= 0 { + barString += strings.Repeat(" ", eBars) + } + return barString } var sealingWorkersCmd = &cli.Command{ From 686ada0582a30c19e9f185f9f97ade7bd6ad34aa Mon Sep 17 00:00:00 2001 From: Rjan Date: Mon, 28 Feb 2022 15:19:53 +0100 Subject: [PATCH 268/385] Make `--lite` option visibile in the cli --- cmd/lotus/daemon.go | 1 - documentation/en/cli-lotus.md | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/lotus/daemon.go b/cmd/lotus/daemon.go index 813a0a9bd9f..6c4ac2bcf0a 100644 --- a/cmd/lotus/daemon.go +++ b/cmd/lotus/daemon.go @@ -121,7 +121,6 @@ var DaemonCmd = &cli.Command{ &cli.BoolFlag{ Name: "lite", Usage: "start lotus in lite mode", - Hidden: true, }, &cli.StringFlag{ Name: "pprof", diff --git a/documentation/en/cli-lotus.md b/documentation/en/cli-lotus.md index 9a8ff028d50..5499459128a 100644 --- a/documentation/en/cli-lotus.md +++ b/documentation/en/cli-lotus.md @@ -63,6 +63,7 @@ OPTIONS: --import-chain value on first run, load chain from given file or url and validate --import-snapshot value import chain state from a given chain export file or url --halt-after-import halt the process after importing chain from file (default: false) + --lite start lotus in lite mode (default: false) --pprof value specify name of file for writing cpu profile to --profile value specify type of node --manage-fdlimit manage open file limit (default: true) From c9e2c1b1d763a249b4b83ce89ac5aa35f36510d2 Mon Sep 17 00:00:00 2001 From: Rjan Date: Mon, 28 Feb 2022 17:14:05 +0100 Subject: [PATCH 269/385] Make --lite --- cmd/lotus/daemon.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/lotus/daemon.go b/cmd/lotus/daemon.go index 6c4ac2bcf0a..f285ba74e63 100644 --- a/cmd/lotus/daemon.go +++ b/cmd/lotus/daemon.go @@ -119,8 +119,8 @@ var DaemonCmd = &cli.Command{ Usage: "halt the process after importing chain from file", }, &cli.BoolFlag{ - Name: "lite", - Usage: "start lotus in lite mode", + Name: "lite", + Usage: "start lotus in lite mode", }, &cli.StringFlag{ Name: "pprof", From 0708268c759fef8bfa39d7c9937ceb32c72ce75c Mon Sep 17 00:00:00 2001 From: TheMenko Date: Tue, 1 Mar 2022 02:21:22 +0100 Subject: [PATCH 270/385] add assert to output for wallet list --- cli/wallet.go | 4 +++- cli/wallet_test.go | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/cli/wallet.go b/cli/wallet.go index c14bf814260..7da0c31b592 100644 --- a/cli/wallet.go +++ b/cli/wallet.go @@ -102,6 +102,8 @@ var walletList = &cli.Command{ defer closer() ctx := ReqContext(cctx) + afmt := NewAppFmt(cctx.App) + addrs, err := api.WalletList(ctx) if err != nil { return err @@ -122,7 +124,7 @@ var walletList = &cli.Command{ for _, addr := range addrs { if cctx.Bool("addr-only") { - fmt.Println(addr.String()) + afmt.Println(addr.String()) } else { a, err := api.StateGetActor(ctx, addr, types.EmptyTSK) if err != nil { diff --git a/cli/wallet_test.go b/cli/wallet_test.go index e56b2cdbe95..9fb5ac22ceb 100644 --- a/cli/wallet_test.go +++ b/cli/wallet_test.go @@ -58,7 +58,7 @@ func TestWalletList(t *testing.T) { t.Run("wallet-list-addr-only", func(t *testing.T) { - app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletList)) + app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletList)) defer done() ctx, cancel := context.WithCancel(context.Background()) @@ -67,12 +67,12 @@ func TestWalletList(t *testing.T) { gomock.InOrder( mockApi.EXPECT().WalletList(ctx).Return(addresses, nil), mockApi.EXPECT().WalletDefaultAddress(ctx).Return(addr, nil), - mockApi.EXPECT().StateGetActor(ctx, addr, key).Return(&actor, nil), ) //stm: @CLI_WALLET_LIST_001 - err := app.Run([]string{"wallet", "list", "addr-only"}) + err := app.Run([]string{"wallet", "list", "--addr-only"}) assert.NoError(t, err) + assert.Contains(t, buf.String(), addr.String()) }) t.Run("wallet-list-id", func(t *testing.T) { From 4a5b0b87ea6deeab7938571019b93aecafa59a96 Mon Sep 17 00:00:00 2001 From: TheMenko Date: Tue, 1 Mar 2022 02:34:52 +0100 Subject: [PATCH 271/385] add assert to output for wallet sign --- cli/wallet.go | 4 +++- cli/wallet_test.go | 10 ++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/cli/wallet.go b/cli/wallet.go index 7da0c31b592..752a80bfbd9 100644 --- a/cli/wallet.go +++ b/cli/wallet.go @@ -413,6 +413,8 @@ var walletSign = &cli.Command{ defer closer() ctx := ReqContext(cctx) + afmt := NewAppFmt(cctx.App) + if !cctx.Args().Present() || cctx.NArg() != 2 { return fmt.Errorf("must specify signing address and message to sign") } @@ -437,7 +439,7 @@ var walletSign = &cli.Command{ sigBytes := append([]byte{byte(sig.Type)}, sig.Data...) - fmt.Println(hex.EncodeToString(sigBytes)) + afmt.Println(hex.EncodeToString(sigBytes)) return nil }, } diff --git a/cli/wallet_test.go b/cli/wallet_test.go index 9fb5ac22ceb..22b3bc3e4fa 100644 --- a/cli/wallet_test.go +++ b/cli/wallet_test.go @@ -201,7 +201,7 @@ func TestWalletExport(t *testing.T) { } func TestWalletSign(t *testing.T) { - app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletSign)) + app, mockApi, buffer, done := NewMockAppWithFullAPI(t, WithCategory("wallet", walletSign)) defer done() ctx, cancel := context.WithCancel(context.Background()) @@ -213,13 +213,19 @@ func TestWalletSign(t *testing.T) { msg, err := hex.DecodeString("01") assert.NoError(t, err) - signature := crypto.Signature{} + signature := crypto.Signature{ + Type: crypto.SigTypeSecp256k1, + Data: []byte{0x01}, + } mockApi.EXPECT().WalletSign(ctx, addr, msg).Return(&signature, nil) + sigBytes := append([]byte{byte(signature.Type)}, signature.Data...) + //stm: @CLI_WALLET_SIGN_001 err = app.Run([]string{"wallet", "sign", "f01234", "01"}) assert.NoError(t, err) + assert.Contains(t, buffer.String(), hex.EncodeToString(sigBytes)) } func TestWalletVerify(t *testing.T) { From f138ae8882bd0e18bb792166dfd9993abda61681 Mon Sep 17 00:00:00 2001 From: zenground0 Date: Tue, 1 Mar 2022 10:52:09 -0700 Subject: [PATCH 272/385] Less verbose sector manager logging --- extern/sector-storage/manager.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index 897ba4f0611..28e0715591c 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -763,7 +763,7 @@ func (m *Manager) Remove(ctx context.Context, sector storage.SectorRef) error { func (m *Manager) ReplicaUpdate(ctx context.Context, sector storage.SectorRef, pieces []abi.PieceInfo) (out storage.ReplicaUpdateOut, err error) { ctx, cancel := context.WithCancel(ctx) defer cancel() - log.Errorf("manager is doing replica update") + log.Debugf("manager is doing replica update") wk, wait, cancel, err := m.getWork(ctx, sealtasks.TTReplicaUpdate, sector, pieces) if err != nil { return storage.ReplicaUpdateOut{}, xerrors.Errorf("getWork: %w", err) From e0922a7dd23dc93fd6549f447911c92c244a5cea Mon Sep 17 00:00:00 2001 From: Jiaying Wang <42981373+jennijuju@users.noreply.github.com> Date: Tue, 1 Mar 2022 21:56:12 -0500 Subject: [PATCH 273/385] pay for the collateral difference needed if the miner available balance is insufficient --- extern/storage-sealing/states_replica_update.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/storage-sealing/states_replica_update.go b/extern/storage-sealing/states_replica_update.go index 8683a11d84d..bede7a5fa81 100644 --- a/extern/storage-sealing/states_replica_update.go +++ b/extern/storage-sealing/states_replica_update.go @@ -168,7 +168,7 @@ func (m *Sealing) handleSubmitReplicaUpdate(ctx statemachine.Context, sector Sec log.Errorf("no good address to send replica update message from: %+v", err) return ctx.Send(SectorSubmitReplicaUpdateFailed{}) } - mcid, err := m.Api.SendMsg(ctx.Context(), from, m.maddr, miner.Methods.ProveReplicaUpdates, big.Zero(), big.Int(m.feeCfg.MaxCommitGasFee), enc.Bytes()) + mcid, err := m.Api.SendMsg(ctx.Context(), from, m.maddr, miner.Methods.ProveReplicaUpdates, collateral, big.Int(m.feeCfg.MaxCommitGasFee), enc.Bytes()) if err != nil { log.Errorf("handleSubmitReplicaUpdate: error sending message: %+v", err) return ctx.Send(SectorSubmitReplicaUpdateFailed{}) From 769b0f30efadd2ad0a09bde72736270d14394ebc Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Wed, 2 Mar 2022 11:04:50 +0000 Subject: [PATCH 274/385] Address review comments - Add comment to clarify the reason for loop in testkit - Trim common prefix in state printed in CLI commands for better readability - Upgrade to a tagged release of `go-fil-markets` that includes indexing work; see: https://github.com/filecoin-project/go-fil-markets/pull/673 - Fix typo in CLI usage. - Add comments to note that it is safe to use fx `OnStart` context when starting the provider engine. - Fix string concatenation in error message formatting. --- cmd/lotus-miner/dagstore.go | 6 ++++-- cmd/lotus-miner/index_provider.go | 2 +- extern/filecoin-ffi | 2 +- go.mod | 2 +- go.sum | 4 ++-- itests/kit/client.go | 1 + markets/dagstore/wrapper.go | 2 +- node/modules/storageminer_idxprov.go | 3 +++ 8 files changed, 14 insertions(+), 8 deletions(-) diff --git a/cmd/lotus-miner/dagstore.go b/cmd/lotus-miner/dagstore.go index 46642459a86..b35dcbe5037 100644 --- a/cmd/lotus-miner/dagstore.go +++ b/cmd/lotus-miner/dagstore.go @@ -3,6 +3,7 @@ package main import ( "fmt" "os" + "strings" "github.com/fatih/color" "github.com/ipfs/go-cid" @@ -259,10 +260,11 @@ func printTableShards(shards []api.DagstoreShardInfo) error { m := map[string]interface{}{ "Key": s.Key, "State": func() string { + trimmedState := strings.TrimPrefix(s.State, "ShardState") if c, ok := colors[s.State]; ok { - return color.New(c).Sprint(s.State) + return color.New(c).Sprint(trimmedState) } - return s.State + return trimmedState }(), "Error": s.Error, } diff --git a/cmd/lotus-miner/index_provider.go b/cmd/lotus-miner/index_provider.go index cf97e35bf15..b784ad69594 100644 --- a/cmd/lotus-miner/index_provider.go +++ b/cmd/lotus-miner/index_provider.go @@ -60,7 +60,7 @@ var indexProvAnnounceCmd = &cli.Command{ var indexProvAnnounceAllCmd = &cli.Command{ Name: "announce-all", - Usage: "Announce all active deals to indexers so they can download its indices", + Usage: "Announce all active deals to indexers so they can download the indices", Flags: []cli.Flag{ &cli.BoolFlag{ Name: "color", diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index 5ec5d805c01..e660df5616e 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit 5ec5d805c01ea85224f6448dd6c6fa0a2a73c028 +Subproject commit e660df5616e397b2d8ac316f45ddfa7a44637971 diff --git a/go.mod b/go.mod index eac65352403..9c5310fedd1 100644 --- a/go.mod +++ b/go.mod @@ -38,7 +38,7 @@ require ( github.com/filecoin-project/go-data-transfer v1.14.0 github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 - github.com/filecoin-project/go-fil-markets v1.19.2-0.20220223141410-2460e15e07a8 + github.com/filecoin-project/go-fil-markets v1.20.0 github.com/filecoin-project/go-jsonrpc v0.1.5 github.com/filecoin-project/go-legs v0.3.4 github.com/filecoin-project/go-padreader v0.0.1 diff --git a/go.sum b/go.sum index 41205175913..3a83f7e02ff 100644 --- a/go.sum +++ b/go.sum @@ -335,8 +335,8 @@ github.com/filecoin-project/go-fil-commcid v0.1.0 h1:3R4ds1A9r6cr8mvZBfMYxTS88Oq github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7LXep5bFEVOVmQWHJvl2mgsGo= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8= -github.com/filecoin-project/go-fil-markets v1.19.2-0.20220223141410-2460e15e07a8 h1:cuV4t78W8tUgmqvsc6T6qbWuycg7GzPcNsTdAOxrTns= -github.com/filecoin-project/go-fil-markets v1.19.2-0.20220223141410-2460e15e07a8/go.mod h1:OeR49x+NPMfZMMgOresxzecMAgUB+lna2kwJABPwnt8= +github.com/filecoin-project/go-fil-markets v1.20.0 h1:kP9A2otcRe4mTfL++GF0+d4PoFDI92E38lhM8GXFT9I= +github.com/filecoin-project/go-fil-markets v1.20.0/go.mod h1:OeR49x+NPMfZMMgOresxzecMAgUB+lna2kwJABPwnt8= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= diff --git a/itests/kit/client.go b/itests/kit/client.go index 6ac3b6fec4b..8b03617f617 100644 --- a/itests/kit/client.go +++ b/itests/kit/client.go @@ -112,6 +112,7 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode *TestFullNode) require.NoError(t, err) path := filepath.Join(tmpdir, "outfile.dat") + // Wait for client retrieve to succeed. for { out = clientCLI.RunCmd("client", "retrieve", dataCid.String(), path) fmt.Println("retrieve:\n", out) diff --git a/markets/dagstore/wrapper.go b/markets/dagstore/wrapper.go index a711db93e91..1085a53cc11 100644 --- a/markets/dagstore/wrapper.go +++ b/markets/dagstore/wrapper.go @@ -419,7 +419,7 @@ func (w *Wrapper) GetPiecesContainingBlock(blockCID cid.Cid) ([]cid.Cid, error) c, err := cid.Parse(k.String()) if err != nil { prefix := fmt.Sprintf("getting pieces containing block %s:", blockCID) - return nil, xerrors.Errorf(prefix+" converting shard key %s to piece cid: %w", k, err) + return nil, xerrors.Errorf("%s converting shard key %s to piece cid: %w", prefix, k, err) } pieceCids = append(pieceCids, c) diff --git a/node/modules/storageminer_idxprov.go b/node/modules/storageminer_idxprov.go index 649c5b09433..ad98f033f6e 100644 --- a/node/modules/storageminer_idxprov.go +++ b/node/modules/storageminer_idxprov.go @@ -54,6 +54,9 @@ func IndexProvider(cfg config.IndexProviderConfig) func(params IdxProv, marketHo args.Lifecycle.Append(fx.Hook{ OnStart: func(ctx context.Context) error { + // Note that the OnStart context is cancelled after startup. Its use in e.Start is + // to start up gossipsub publishers and restore cache, all of which are completed + // before e.Start returns. Therefore, it is fine to reuse the give context. if err := e.Start(ctx); err != nil { return xerrors.Errorf("starting indexer provider engine: %w", err) } From 963caf2e9d493b73ccc43bfe41311ed5504381f1 Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Wed, 2 Mar 2022 11:40:02 +0000 Subject: [PATCH 275/385] Fix `gen-check` --- documentation/en/cli-lotus-miner.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/en/cli-lotus-miner.md b/documentation/en/cli-lotus-miner.md index f73b21314d4..382fe426546 100644 --- a/documentation/en/cli-lotus-miner.md +++ b/documentation/en/cli-lotus-miner.md @@ -1154,7 +1154,7 @@ USAGE: COMMANDS: announce Announce a deal to indexers so they can download its index - announce-all Announce all active deals to indexers so they can download its indices + announce-all Announce all active deals to indexers so they can download the indices help, h Shows a list of commands or help for one command OPTIONS: @@ -1179,7 +1179,7 @@ OPTIONS: ### lotus-miner index announce-all ``` NAME: - lotus-miner index announce-all - Announce all active deals to indexers so they can download its indices + lotus-miner index announce-all - Announce all active deals to indexers so they can download the indices USAGE: lotus-miner index announce-all [command options] [arguments...] From 444a2bf3550b2d6a093a2922b6758df08cfb1dd1 Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Wed, 2 Mar 2022 13:45:09 +0000 Subject: [PATCH 276/385] Integrate the latest index-provider with config to disable announcements Integrate the latest `index-provider` and reflect the changes to engine configuration. Note that this commit disables announcements of indices on the network by default as requested for initial merge to master. Introduce dedicated index provider configuration parameters with documentation and defaults that match the defaults in index-provider. Re-generate code as needed. --- .../en/default-lotus-miner-config.toml | 50 +++++++++++++------ go.mod | 6 +-- go.sum | 17 +++++-- node/config/def.go | 7 ++- node/config/doc_gen.go | 43 ++++++++++++++++ node/config/types.go | 29 +++++++++-- node/modules/storageminer_idxprov.go | 39 ++++++++------- 7 files changed, 146 insertions(+), 45 deletions(-) diff --git a/documentation/en/default-lotus-miner-config.toml b/documentation/en/default-lotus-miner-config.toml index fe202833b7a..00370a9cc9d 100644 --- a/documentation/en/default-lotus-miner-config.toml +++ b/documentation/en/default-lotus-miner-config.toml @@ -266,24 +266,46 @@ [IndexProvider] - # env var: LOTUS_INDEXPROVIDER_LINKCACHESIZE - #LinkCacheSize = 1024 - - # env var: LOTUS_INDEXPROVIDER_LINKEDCHUNKSIZE - #LinkedChunkSize = 16384 + # Enable set whether to enable indexing announcement to the network and expose endpoints that + # allow indexer nodes to process announcements. Disabled by default. + # + # type: bool + # env var: LOTUS_INDEXPROVIDER_ENABLE + #Enable = false - # env var: LOTUS_INDEXPROVIDER_PUBSUBTOPIC - #PubSubTopic = "/indexer/ingest/mainnet" + # EntriesCacheCapacity sets the maximum capacity to use for caching the indexing advertisement + # entries. Defaults to 1024 if not specified. The cache is evicted using LRU policy. The + # maximum storage used by the cache is a factor of EntriesCacheCapacity, EntriesChunkSize and + # the length of multihashes being advertised. For example, advertising 128-bit long multihashes + # with the default EntriesCacheCapacity, and EntriesChunkSize means the cache size can grow to + # 256MiB when full. + # + # type: int + # env var: LOTUS_INDEXPROVIDER_ENTRIESCACHECAPACITY + #EntriesCacheCapacity = 1024 - # env var: LOTUS_INDEXPROVIDER_PURGELINKCACHE - #PurgeLinkCache = false + # EntriesChunkSize sets the maximum number of multihashes to include in a single entries chunk. + # Defaults to 16384 if not specified. Note that chunks are chained together for indexing + # advertisements that include more multihashes than the configured EntriesChunkSize. + # + # type: int + # env var: LOTUS_INDEXPROVIDER_ENTRIESCHUNKSIZE + #EntriesChunkSize = 16384 - # env var: LOTUS_INDEXPROVIDER_PUBLISHERKIND - #PublisherKind = "dtsync" + # TopicName sets the topic name on which the changes to the advertised content are announced. + # Defaults to '/indexer/ingest/mainnet' if not specified. + # + # type: string + # env var: LOTUS_INDEXPROVIDER_TOPICNAME + #TopicName = "/indexer/ingest/mainnet" - [IndexProvider.HttpPublisher] - # env var: LOTUS_INDEXPROVIDER_HTTPPUBLISHER_LISTENMULTIADDR - #ListenMultiaddr = "/ip4/0.0.0.0/tcp/3104/http" + # PurgeCacheOnStart sets whether to clear any cached entries chunks when the provider engine + # starts. By default, the cache is rehydrated from previously cached entries stored in + # datastore if any is present. + # + # type: bool + # env var: LOTUS_INDEXPROVIDER_PURGECACHEONSTART + #PurgeCacheOnStart = false [Sealing] diff --git a/go.mod b/go.mod index 9c5310fedd1..1c06ecbb119 100644 --- a/go.mod +++ b/go.mod @@ -40,14 +40,14 @@ require ( github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 github.com/filecoin-project/go-fil-markets v1.20.0 github.com/filecoin-project/go-jsonrpc v0.1.5 - github.com/filecoin-project/go-legs v0.3.4 + github.com/filecoin-project/go-legs v0.3.7 github.com/filecoin-project/go-padreader v0.0.1 github.com/filecoin-project/go-paramfetch v0.0.4 github.com/filecoin-project/go-state-types v0.1.3 github.com/filecoin-project/go-statemachine v1.0.1 github.com/filecoin-project/go-statestore v0.2.0 github.com/filecoin-project/go-storedcounter v0.1.0 - github.com/filecoin-project/index-provider v0.3.1 + github.com/filecoin-project/index-provider v0.4.0 github.com/filecoin-project/specs-actors v0.9.14 github.com/filecoin-project/specs-actors/v2 v2.3.6 github.com/filecoin-project/specs-actors/v3 v3.1.1 @@ -150,7 +150,7 @@ require ( github.com/uber/jaeger-client-go v2.25.0+incompatible // indirect github.com/urfave/cli/v2 v2.3.0 github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba - github.com/whyrusleeping/cbor-gen v0.0.0-20211110122933-f57984553008 + github.com/whyrusleeping/cbor-gen v0.0.0-20220224212727-7a699437a831 github.com/whyrusleeping/ledger-filecoin-go v0.9.1-0.20201010031517-c3dcc1bddce4 github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 github.com/whyrusleeping/pubsub v0.0.0-20190708150250-92bcb0691325 diff --git a/go.sum b/go.sum index 3a83f7e02ff..bab2875808e 100644 --- a/go.sum +++ b/go.sum @@ -348,8 +348,9 @@ github.com/filecoin-project/go-indexer-core v0.2.8/go.mod h1:IagNfTdFuX4057kla43 github.com/filecoin-project/go-jsonrpc v0.1.5 h1:ckxqZ09ivBAVf5CSmxxrqqNHC7PJm3GYGtYKiNQ+vGk= github.com/filecoin-project/go-jsonrpc v0.1.5/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4= github.com/filecoin-project/go-legs v0.3.0/go.mod h1:x6nwM+DuN7NzlPndOoJuiHYCX+pze6+efPRx17nIA7M= -github.com/filecoin-project/go-legs v0.3.4 h1:yid2IivTJ8JeF1ROA8jxNKNKJshU/HO1sRo5lEMNOUc= github.com/filecoin-project/go-legs v0.3.4/go.mod h1:P7ZPHqFG96OFaT11rnXyTdcxRdGkaH1dRyPxJSOiSuM= +github.com/filecoin-project/go-legs v0.3.7 h1:yfm7fx+iy1nPtgPEQ6kQjvhoJOVbXide50STYdy+yos= +github.com/filecoin-project/go-legs v0.3.7/go.mod h1:pgekGm8/gKY5zCtQ/qGAoSjGP92wTLFqpO3GPHeu8YU= github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20/go.mod h1:mPn+LRRd5gEKNAtc+r3ScpW2JRU/pj4NBKdADYWHiak= github.com/filecoin-project/go-padreader v0.0.1 h1:8h2tVy5HpoNbr2gBRr+WD6zV6VD6XHig+ynSGJg8ZOs= github.com/filecoin-project/go-padreader v0.0.1/go.mod h1:VYVPJqwpsfmtoHnAmPx6MUwmrK6HIcDqZJiuZhtmfLQ= @@ -371,8 +372,9 @@ github.com/filecoin-project/go-statestore v0.2.0 h1:cRRO0aPLrxKQCZ2UOQbzFGn4WDNd github.com/filecoin-project/go-statestore v0.2.0/go.mod h1:8sjBYbS35HwPzct7iT4lIXjLlYyPor80aU7t7a/Kspo= github.com/filecoin-project/go-storedcounter v0.1.0 h1:Mui6wSUBC+cQGHbDUBcO7rfh5zQkWJM/CpAZa/uOuus= github.com/filecoin-project/go-storedcounter v0.1.0/go.mod h1:4ceukaXi4vFURIoxYMfKzaRF5Xv/Pinh2oTnoxpv+z8= -github.com/filecoin-project/index-provider v0.3.1 h1:ySGk2FnDbUEhq6QwakeU/p8tKnIoUm6JIpXPQ8RG1iM= github.com/filecoin-project/index-provider v0.3.1/go.mod h1:o8ineTLWnwtfBv7SnELpncza6SBU295esxOaXsTCl2I= +github.com/filecoin-project/index-provider v0.4.0 h1:laCdWms1OvgHwxkU0DSfkzqPQBRAMPO2TKes5s0TdHo= +github.com/filecoin-project/index-provider v0.4.0/go.mod h1:SDfBxhD9/wet7e5wv1J4IZjWfVkln/k4oTzMcNccLZA= github.com/filecoin-project/specs-actors v0.9.13/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= github.com/filecoin-project/specs-actors v0.9.14 h1:68PVstg2UB3ZsMLF+DKFTAs/YKsqhKWynkr0IqmVRQY= github.com/filecoin-project/specs-actors v0.9.14/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= @@ -396,8 +398,9 @@ github.com/filecoin-project/specs-actors/v7 v7.0.0 h1:FQN7tjt3o68hfb3qLFSJBoLMuO github.com/filecoin-project/specs-actors/v7 v7.0.0/go.mod h1:TA5FwCna+Yi36POaT7SLKXsgEDvJwc0V/L6ZsO19B9M= github.com/filecoin-project/specs-storage v0.2.0 h1:Y4UDv0apRQ3zI2GiPPubi8JblpUZZphEdaJUxCutfyg= github.com/filecoin-project/specs-storage v0.2.0/go.mod h1:Tb88Zq+IBJbvAn3mS89GYj3jdRThBTE/771HCVZdRJU= -github.com/filecoin-project/storetheindex v0.3.2 h1:KsTJer5Di/iapSrOWtbFTPMt5kS7Y3n3C9kOYH93gEA= github.com/filecoin-project/storetheindex v0.3.2/go.mod h1:d7y0FHAwPPSIdg+Oh7xV5B9TLebL7rvoKu591N/l2ZU= +github.com/filecoin-project/storetheindex v0.3.5 h1:KoS9TvjPm6zIZfUH8atAHJbVHOO7GTP1MdTG+v0eE+Q= +github.com/filecoin-project/storetheindex v0.3.5/go.mod h1:0r3d0kSpK63O6AvLr1CjAINLi+nWD49clzcnKV+GLpI= github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg= github.com/filecoin-project/test-vectors/schema v0.0.5/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= @@ -1056,6 +1059,7 @@ github.com/libp2p/go-libp2p v0.14.4/go.mod h1:EIRU0Of4J5S8rkockZM7eJp2S0UrCyi55m github.com/libp2p/go-libp2p v0.16.0/go.mod h1:ump42BsirwAWxKzsCiFnTtN1Yc+DuPu76fyMX364/O4= github.com/libp2p/go-libp2p v0.17.0/go.mod h1:Fkin50rsGdv5mm5BshBUtPRZknt9esfmYXBOYcwOTgw= github.com/libp2p/go-libp2p v0.18.0-rc1/go.mod h1:RgYlH7IIWHXREimC92bw5Lg1V2R5XmSzuLHb5fTnr+8= +github.com/libp2p/go-libp2p v0.18.0-rc3/go.mod h1:WYL+Xw1iuwi6rdfzw5VIEpD+HqzYucHZ6fcUuumbI3M= github.com/libp2p/go-libp2p v0.18.0-rc5 h1:88wWDHb9nNo0vBNCupLde3OTnFAkugOCNkrDfl3ivK4= github.com/libp2p/go-libp2p v0.18.0-rc5/go.mod h1:aZPS5l84bDvCvP4jkyEUT/J6YOpUq33Fgqrs3K59mpI= github.com/libp2p/go-libp2p-asn-util v0.0.0-20200825225859-85005c6cf052/go.mod h1:nRMRTab+kZuk0LnKZpxhOVH/ndsdr2Nr//Zltc/vwgo= @@ -1253,6 +1257,7 @@ github.com/libp2p/go-libp2p-swarm v0.5.3/go.mod h1:NBn7eNW2lu568L7Ns9wdFrOhgRlkR github.com/libp2p/go-libp2p-swarm v0.8.0/go.mod h1:sOMp6dPuqco0r0GHTzfVheVBh6UEL0L1lXUZ5ot2Fvc= github.com/libp2p/go-libp2p-swarm v0.9.0/go.mod h1:2f8d8uxTJmpeqHF/1ujjdXZp+98nNIbujVOMEZxCbZ8= github.com/libp2p/go-libp2p-swarm v0.10.0/go.mod h1:71ceMcV6Rg/0rIQ97rsZWMzto1l9LnNquef+efcRbmA= +github.com/libp2p/go-libp2p-swarm v0.10.1/go.mod h1:Pdkq0QU5a+qu+oyqIV3bknMsnzk9lnNyKvB9acJ5aZs= github.com/libp2p/go-libp2p-swarm v0.10.2 h1:UaXf+CTq6Ns1N2V1EgqJ9Q3xaRsiN7ImVlDMpirMAWw= github.com/libp2p/go-libp2p-swarm v0.10.2/go.mod h1:Pdkq0QU5a+qu+oyqIV3bknMsnzk9lnNyKvB9acJ5aZs= github.com/libp2p/go-libp2p-testing v0.0.1/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= @@ -1928,8 +1933,9 @@ github.com/whyrusleeping/cbor-gen v0.0.0-20200826160007-0b9f6c5fb163/go.mod h1:f github.com/whyrusleeping/cbor-gen v0.0.0-20210118024343-169e9d70c0c2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20210219115102-f37d292932f2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20210303213153-67a261a1d291/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= -github.com/whyrusleeping/cbor-gen v0.0.0-20211110122933-f57984553008 h1:7WtW9D9VGpmRLuQmrPy2JobUNdka95z3MKEVpELtOjo= github.com/whyrusleeping/cbor-gen v0.0.0-20211110122933-f57984553008/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= +github.com/whyrusleeping/cbor-gen v0.0.0-20220224212727-7a699437a831 h1:9blPRrm7ebDqDm6nHXXzCSru+sp20gcA3CLu+G/kHUc= +github.com/whyrusleeping/cbor-gen v0.0.0-20220224212727-7a699437a831/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f/go.mod h1:p9UJB6dDgdPgMJZs7UjUOdulKyRr9fqkS+6JKAInPy8= github.com/whyrusleeping/go-ctrlnet v0.0.0-20180313164037-f564fbbdaa95/go.mod h1:SJqKCCPXRfBFCwXjfNT/skfsceF7+MBFLI2OrvuRA7g= @@ -2040,8 +2046,9 @@ go.uber.org/fx v1.15.0/go.mod h1:jI3RazQUhGv5KkpZIRv+kuP4CcgX3fnc0qX8bLnzbx8= go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= +go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= diff --git a/node/config/def.go b/node/config/def.go index 8024bf9a2ce..233eccdd5aa 100644 --- a/node/config/def.go +++ b/node/config/def.go @@ -11,7 +11,6 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" - ipconfig "github.com/filecoin-project/index-provider/config" miner5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/actors/builtin" @@ -185,7 +184,11 @@ func DefaultStorageMiner() *StorageMiner { }, IndexProvider: IndexProviderConfig{ - Ingest: ipconfig.NewIngest(), + Enable: false, + EntriesCacheCapacity: 1024, + EntriesChunkSize: 16384, + TopicName: "/indexer/ingest/mainnet", + PurgeCacheOnStart: false, }, Subsystems: MinerSubsystemConfig{ diff --git a/node/config/doc_gen.go b/node/config/doc_gen.go index d846f6db9d2..c9b6357d39d 100644 --- a/node/config/doc_gen.go +++ b/node/config/doc_gen.go @@ -366,6 +366,49 @@ see https://docs.filecoin.io/mine/lotus/miner-configuration/#using-filters-for-f Comment: ``, }, }, + "IndexProviderConfig": []DocField{ + { + Name: "Enable", + Type: "bool", + + Comment: `Enable set whether to enable indexing announcement to the network and expose endpoints that +allow indexer nodes to process announcements. Disabled by default.`, + }, + { + Name: "EntriesCacheCapacity", + Type: "int", + + Comment: `EntriesCacheCapacity sets the maximum capacity to use for caching the indexing advertisement +entries. Defaults to 1024 if not specified. The cache is evicted using LRU policy. The +maximum storage used by the cache is a factor of EntriesCacheCapacity, EntriesChunkSize and +the length of multihashes being advertised. For example, advertising 128-bit long multihashes +with the default EntriesCacheCapacity, and EntriesChunkSize means the cache size can grow to +256MiB when full.`, + }, + { + Name: "EntriesChunkSize", + Type: "int", + + Comment: `EntriesChunkSize sets the maximum number of multihashes to include in a single entries chunk. +Defaults to 16384 if not specified. Note that chunks are chained together for indexing +advertisements that include more multihashes than the configured EntriesChunkSize.`, + }, + { + Name: "TopicName", + Type: "string", + + Comment: `TopicName sets the topic name on which the changes to the advertised content are announced. +Defaults to '/indexer/ingest/mainnet' if not specified.`, + }, + { + Name: "PurgeCacheOnStart", + Type: "bool", + + Comment: `PurgeCacheOnStart sets whether to clear any cached entries chunks when the provider engine +starts. By default, the cache is rehydrated from previously cached entries stored in +datastore if any is present.`, + }, + }, "Libp2p": []DocField{ { Name: "ListenAddresses", diff --git a/node/config/types.go b/node/config/types.go index a2bd4e0a081..c70d99a825a 100644 --- a/node/config/types.go +++ b/node/config/types.go @@ -3,8 +3,6 @@ package config import ( "github.com/ipfs/go-cid" - "github.com/filecoin-project/index-provider/config" - "github.com/filecoin-project/lotus/chain/types" sectorstorage "github.com/filecoin-project/lotus/extern/sector-storage" ) @@ -166,7 +164,32 @@ type DealmakingConfig struct { } type IndexProviderConfig struct { - config.Ingest + + // Enable set whether to enable indexing announcement to the network and expose endpoints that + // allow indexer nodes to process announcements. Disabled by default. + Enable bool + + // EntriesCacheCapacity sets the maximum capacity to use for caching the indexing advertisement + // entries. Defaults to 1024 if not specified. The cache is evicted using LRU policy. The + // maximum storage used by the cache is a factor of EntriesCacheCapacity, EntriesChunkSize and + // the length of multihashes being advertised. For example, advertising 128-bit long multihashes + // with the default EntriesCacheCapacity, and EntriesChunkSize means the cache size can grow to + // 256MiB when full. + EntriesCacheCapacity int + + // EntriesChunkSize sets the maximum number of multihashes to include in a single entries chunk. + // Defaults to 16384 if not specified. Note that chunks are chained together for indexing + // advertisements that include more multihashes than the configured EntriesChunkSize. + EntriesChunkSize int + + // TopicName sets the topic name on which the changes to the advertised content are announced. + // Defaults to '/indexer/ingest/mainnet' if not specified. + TopicName string + + // PurgeCacheOnStart sets whether to clear any cached entries chunks when the provider engine + // starts. By default, the cache is rehydrated from previously cached entries stored in + // datastore if any is present. + PurgeCacheOnStart bool } type RetrievalPricing struct { diff --git a/node/modules/storageminer_idxprov.go b/node/modules/storageminer_idxprov.go index ad98f033f6e..c13fcb7c51a 100644 --- a/node/modules/storageminer_idxprov.go +++ b/node/modules/storageminer_idxprov.go @@ -2,10 +2,7 @@ package modules import ( "context" - "github.com/ipfs/go-datastore" - "github.com/libp2p/go-libp2p-core/peer" - "github.com/libp2p/go-libp2p-core/peerstore" "go.uber.org/fx" "github.com/filecoin-project/go-address" @@ -24,33 +21,38 @@ type IdxProv struct { fx.Lifecycle Datastore dtypes.MetadataDS - PeerID peer.ID - peerstore.Peerstore } func IndexProvider(cfg config.IndexProviderConfig) func(params IdxProv, marketHost host.Host, dt dtypes.ProviderDataTransfer, maddr dtypes.MinerAddress) (provider.Interface, error) { return func(args IdxProv, marketHost host.Host, dt dtypes.ProviderDataTransfer, maddr dtypes.MinerAddress) (provider.Interface, error) { ipds := namespace.Wrap(args.Datastore, datastore.NewKey("/index-provider")) - - pkey := args.Peerstore.PrivKey(args.PeerID) - if pkey == nil { - return nil, xerrors.Errorf("missing private key for node ID: %s", args.PeerID) + var opts = []engine.Option{ + engine.WithDatastore(ipds), + engine.WithHost(marketHost), + engine.WithRetrievalAddrs(marketHost.Addrs()...), } - var retAdds []string - for _, a := range marketHost.Addrs() { - retAdds = append(retAdds, a.String()) + llog := log.With("idxProvEnabled", cfg.Enable, "pid", marketHost.ID(), "retAddrs", marketHost.Addrs()) + // If announcements to the network are enabled, then set options for datatransfer publisher. + if cfg.Enable { + // Get the miner ID and set as extra gossip data. + // The extra data is required by the lotus-specific index-provider gossip message validators. + ma := address.Address(maddr) + opts = append(opts, + engine.WithPublisherKind(engine.DataTransferPublisher), + engine.WithDataTransfer(dt), + engine.WithExtraGossipData(ma.Bytes())) + llog = llog.With("extraGossipData", ma) + } else { + opts = append(opts, engine.WithPublisherKind(engine.NoPublisher)) } - // Get the miner ID and set as extra gossip data. - // The extra data is required by the lotus-specific index-provider gossip message validators. - ma := address.Address(maddr) - log.Infof("Using extra gossip data in index provider engine: %s", ma) - - e, err := engine.New(cfg.Ingest, pkey, dt, marketHost, ipds, retAdds, engine.WithExtraGossipData(ma.Bytes())) + // Instantiate the index provider engine. + e, err := engine.New(opts...) if err != nil { return nil, xerrors.Errorf("creating indexer provider engine: %w", err) } + llog.Info("Instantiated index provider engine") args.Lifecycle.Append(fx.Hook{ OnStart: func(ctx context.Context) error { @@ -60,6 +62,7 @@ func IndexProvider(cfg config.IndexProviderConfig) func(params IdxProv, marketHo if err := e.Start(ctx); err != nil { return xerrors.Errorf("starting indexer provider engine: %w", err) } + log.Infof("Started index provider engine") return nil }, OnStop: func(_ context.Context) error { From eb83001bbc4aae6f74dbcbca06b262d5157fa56a Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Wed, 2 Mar 2022 15:07:05 +0000 Subject: [PATCH 277/385] Fix wrong ffi commit --- extern/filecoin-ffi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index e660df5616e..5ec5d805c01 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit e660df5616e397b2d8ac316f45ddfa7a44637971 +Subproject commit 5ec5d805c01ea85224f6448dd6c6fa0a2a73c028 From 874124c4e7b82bdf316af14951aabc3030e0c458 Mon Sep 17 00:00:00 2001 From: zenground0 Date: Wed, 2 Mar 2022 09:33:33 -0700 Subject: [PATCH 278/385] Handle finalize failures in fsm --- cmd/lotus-miner/info.go | 1 + extern/storage-sealing/fsm.go | 6 ++ extern/storage-sealing/sector_state.go | 130 +++++++++++++------------ 3 files changed, 73 insertions(+), 64 deletions(-) diff --git a/cmd/lotus-miner/info.go b/cmd/lotus-miner/info.go index 46070ca966c..32219e73b4a 100644 --- a/cmd/lotus-miner/info.go +++ b/cmd/lotus-miner/info.go @@ -527,6 +527,7 @@ var stateList = []stateMeta{ {col: color.FgRed, state: sealing.SnapDealsDealsExpired}, {col: color.FgRed, state: sealing.ReplicaUpdateFailed}, {col: color.FgRed, state: sealing.ReleaseSectorKeyFailed}, + {col: color.FgRed, state: sealing.FinalizeReplicaUpdateFailed}, } func init() { diff --git a/extern/storage-sealing/fsm.go b/extern/storage-sealing/fsm.go index 251d3a74aee..8678a0fe913 100644 --- a/extern/storage-sealing/fsm.go +++ b/extern/storage-sealing/fsm.go @@ -175,6 +175,7 @@ var fsmPlanners = map[SectorState]func(events []statemachine.Event, state *Secto ), FinalizeReplicaUpdate: planOne( on(SectorFinalized{}, UpdateActivating), + on(SectorFinalizeFailed{}, FinalizeReplicaUpdateFailed), ), UpdateActivating: planOne( on(SectorUpdateActive{}, ReleaseSectorKey), @@ -267,6 +268,9 @@ var fsmPlanners = map[SectorState]func(events []statemachine.Event, state *Secto ReleaseSectorKeyFailed: planOne( on(SectorUpdateActive{}, ReleaseSectorKey), ), + FinalizeReplicaUpdateFailed: planOne( + on(SectorRetryFinalize{}, FinalizeReplicaUpdate), + ), // Post-seal @@ -536,6 +540,8 @@ func (m *Sealing) plan(events []statemachine.Event, state *SectorInfo) (func(sta return m.handleSubmitReplicaUpdateFailed, processed, nil case ReleaseSectorKeyFailed: return m.handleReleaseSectorKeyFailed, 0, err + case FinalizeReplicaUpdateFailed: + return m.handleFinalizeFailed, processed, nil case AbortUpgrade: return m.handleAbortUpgrade, processed, nil diff --git a/extern/storage-sealing/sector_state.go b/extern/storage-sealing/sector_state.go index 5c2c56171a5..0f8228d027f 100644 --- a/extern/storage-sealing/sector_state.go +++ b/extern/storage-sealing/sector_state.go @@ -3,64 +3,65 @@ package sealing type SectorState string var ExistSectorStateList = map[SectorState]struct{}{ - Empty: {}, - WaitDeals: {}, - Packing: {}, - AddPiece: {}, - AddPieceFailed: {}, - GetTicket: {}, - PreCommit1: {}, - PreCommit2: {}, - PreCommitting: {}, - PreCommitWait: {}, - SubmitPreCommitBatch: {}, - PreCommitBatchWait: {}, - WaitSeed: {}, - Committing: {}, - CommitFinalize: {}, - CommitFinalizeFailed: {}, - SubmitCommit: {}, - CommitWait: {}, - SubmitCommitAggregate: {}, - CommitAggregateWait: {}, - FinalizeSector: {}, - Proving: {}, - FailedUnrecoverable: {}, - SealPreCommit1Failed: {}, - SealPreCommit2Failed: {}, - PreCommitFailed: {}, - ComputeProofFailed: {}, - CommitFailed: {}, - PackingFailed: {}, - FinalizeFailed: {}, - DealsExpired: {}, - RecoverDealIDs: {}, - Faulty: {}, - FaultReported: {}, - FaultedFinal: {}, - Terminating: {}, - TerminateWait: {}, - TerminateFinality: {}, - TerminateFailed: {}, - Removing: {}, - RemoveFailed: {}, - Removed: {}, - SnapDealsWaitDeals: {}, - SnapDealsAddPiece: {}, - SnapDealsPacking: {}, - UpdateReplica: {}, - ProveReplicaUpdate: {}, - SubmitReplicaUpdate: {}, - ReplicaUpdateWait: {}, - UpdateActivating: {}, - ReleaseSectorKey: {}, - FinalizeReplicaUpdate: {}, - SnapDealsAddPieceFailed: {}, - SnapDealsDealsExpired: {}, - SnapDealsRecoverDealIDs: {}, - ReplicaUpdateFailed: {}, - ReleaseSectorKeyFailed: {}, - AbortUpgrade: {}, + Empty: {}, + WaitDeals: {}, + Packing: {}, + AddPiece: {}, + AddPieceFailed: {}, + GetTicket: {}, + PreCommit1: {}, + PreCommit2: {}, + PreCommitting: {}, + PreCommitWait: {}, + SubmitPreCommitBatch: {}, + PreCommitBatchWait: {}, + WaitSeed: {}, + Committing: {}, + CommitFinalize: {}, + CommitFinalizeFailed: {}, + SubmitCommit: {}, + CommitWait: {}, + SubmitCommitAggregate: {}, + CommitAggregateWait: {}, + FinalizeSector: {}, + Proving: {}, + FailedUnrecoverable: {}, + SealPreCommit1Failed: {}, + SealPreCommit2Failed: {}, + PreCommitFailed: {}, + ComputeProofFailed: {}, + CommitFailed: {}, + PackingFailed: {}, + FinalizeFailed: {}, + DealsExpired: {}, + RecoverDealIDs: {}, + Faulty: {}, + FaultReported: {}, + FaultedFinal: {}, + Terminating: {}, + TerminateWait: {}, + TerminateFinality: {}, + TerminateFailed: {}, + Removing: {}, + RemoveFailed: {}, + Removed: {}, + SnapDealsWaitDeals: {}, + SnapDealsAddPiece: {}, + SnapDealsPacking: {}, + UpdateReplica: {}, + ProveReplicaUpdate: {}, + SubmitReplicaUpdate: {}, + ReplicaUpdateWait: {}, + UpdateActivating: {}, + ReleaseSectorKey: {}, + FinalizeReplicaUpdate: {}, + SnapDealsAddPieceFailed: {}, + SnapDealsDealsExpired: {}, + SnapDealsRecoverDealIDs: {}, + ReplicaUpdateFailed: {}, + ReleaseSectorKeyFailed: {}, + FinalizeReplicaUpdateFailed: {}, + AbortUpgrade: {}, } // cmd/lotus-miner/info.go defines CLI colors corresponding to these states @@ -124,12 +125,13 @@ const ( RecoverDealIDs SectorState = "RecoverDealIDs" // snap deals error modes - SnapDealsAddPieceFailed SectorState = "SnapDealsAddPieceFailed" - SnapDealsDealsExpired SectorState = "SnapDealsDealsExpired" - SnapDealsRecoverDealIDs SectorState = "SnapDealsRecoverDealIDs" - AbortUpgrade SectorState = "AbortUpgrade" - ReplicaUpdateFailed SectorState = "ReplicaUpdateFailed" - ReleaseSectorKeyFailed SectorState = "ReleaseSectorKeyFailed" + SnapDealsAddPieceFailed SectorState = "SnapDealsAddPieceFailed" + SnapDealsDealsExpired SectorState = "SnapDealsDealsExpired" + SnapDealsRecoverDealIDs SectorState = "SnapDealsRecoverDealIDs" + AbortUpgrade SectorState = "AbortUpgrade" + ReplicaUpdateFailed SectorState = "ReplicaUpdateFailed" + ReleaseSectorKeyFailed SectorState = "ReleaseSectorKeyFailed" + FinalizeReplicaUpdateFailed SectorState = "FinalizeReplicaUpdateFailed" Faulty SectorState = "Faulty" // sector is corrupted or gone for some reason FaultReported SectorState = "FaultReported" // sector has been declared as a fault on chain From a52b4b72e9cdb97aec3f197796f3a002598dfd4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 2 Mar 2022 20:23:47 +0100 Subject: [PATCH 279/385] gomod: Use latest cbor-gen --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 1c06ecbb119..e76692d531f 100644 --- a/go.mod +++ b/go.mod @@ -150,7 +150,7 @@ require ( github.com/uber/jaeger-client-go v2.25.0+incompatible // indirect github.com/urfave/cli/v2 v2.3.0 github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba - github.com/whyrusleeping/cbor-gen v0.0.0-20220224212727-7a699437a831 + github.com/whyrusleeping/cbor-gen v0.0.0-20220302191723-37c43cae8e14 github.com/whyrusleeping/ledger-filecoin-go v0.9.1-0.20201010031517-c3dcc1bddce4 github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 github.com/whyrusleeping/pubsub v0.0.0-20190708150250-92bcb0691325 diff --git a/go.sum b/go.sum index bab2875808e..cd4618b291c 100644 --- a/go.sum +++ b/go.sum @@ -1934,8 +1934,9 @@ github.com/whyrusleeping/cbor-gen v0.0.0-20210118024343-169e9d70c0c2/go.mod h1:f github.com/whyrusleeping/cbor-gen v0.0.0-20210219115102-f37d292932f2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20210303213153-67a261a1d291/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20211110122933-f57984553008/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= -github.com/whyrusleeping/cbor-gen v0.0.0-20220224212727-7a699437a831 h1:9blPRrm7ebDqDm6nHXXzCSru+sp20gcA3CLu+G/kHUc= github.com/whyrusleeping/cbor-gen v0.0.0-20220224212727-7a699437a831/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= +github.com/whyrusleeping/cbor-gen v0.0.0-20220302191723-37c43cae8e14 h1:vo2wkP2ceHyGyZwFFtAabpot03EeSxxwAe57pOI9E/4= +github.com/whyrusleeping/cbor-gen v0.0.0-20220302191723-37c43cae8e14/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f/go.mod h1:p9UJB6dDgdPgMJZs7UjUOdulKyRr9fqkS+6JKAInPy8= github.com/whyrusleeping/go-ctrlnet v0.0.0-20180313164037-f564fbbdaa95/go.mod h1:SJqKCCPXRfBFCwXjfNT/skfsceF7+MBFLI2OrvuRA7g= From b81d189ec1fa990e75df492d046d951a6ec3f1e2 Mon Sep 17 00:00:00 2001 From: zenground0 Date: Wed, 2 Mar 2022 13:03:03 -0700 Subject: [PATCH 280/385] Log instead of error normal shutdown of state machine --- extern/storage-sealing/fsm.go | 36 ++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/extern/storage-sealing/fsm.go b/extern/storage-sealing/fsm.go index 8678a0fe913..2c50d188560 100644 --- a/extern/storage-sealing/fsm.go +++ b/extern/storage-sealing/fsm.go @@ -19,7 +19,13 @@ import ( func (m *Sealing) Plan(events []statemachine.Event, user interface{}) (interface{}, uint64, error) { next, processed, err := m.plan(events, user.(*SectorInfo)) if err != nil || next == nil { - return nil, processed, err + l := Log{ + Timestamp: uint64(time.Now().Unix()), + Message: fmt.Sprintf("state machine error: %s", err), + Kind: fmt.Sprintf("error;%T", err), + } + user.(*SectorInfo).logAppend(l) + return nil, processed, nil } return func(ctx statemachine.Context, si SectorInfo) error { @@ -313,6 +319,21 @@ var fsmPlanners = map[SectorState]func(events []statemachine.Event, state *Secto FailedUnrecoverable: final, } +func (state *SectorInfo) logAppend(l Log) { + if len(state.Log) > 8000 { + log.Warnw("truncating sector log", "sector", state.SectorNumber) + state.Log[2000] = Log{ + Timestamp: uint64(time.Now().Unix()), + Message: "truncating log (above 8000 entries)", + Kind: fmt.Sprintf("truncate"), + } + + state.Log = append(state.Log[:2000], state.Log[6000:]...) + } + + state.Log = append(state.Log, l) +} + func (m *Sealing) logEvents(events []statemachine.Event, state *SectorInfo) { for _, event := range events { log.Debugw("sector event", "sector", state.SectorNumber, "type", fmt.Sprintf("%T", event.User), "event", event.User) @@ -341,18 +362,7 @@ func (m *Sealing) logEvents(events []statemachine.Event, state *SectorInfo) { l.Trace = fmt.Sprintf("%+v", err) } - if len(state.Log) > 8000 { - log.Warnw("truncating sector log", "sector", state.SectorNumber) - state.Log[2000] = Log{ - Timestamp: uint64(time.Now().Unix()), - Message: "truncating log (above 8000 entries)", - Kind: fmt.Sprintf("truncate"), - } - - state.Log = append(state.Log[:2000], state.Log[6000:]...) - } - - state.Log = append(state.Log, l) + state.logAppend(l) } } From 8cf6f24f4d0aedb9ee904d3b37de74738db7aca1 Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Thu, 3 Mar 2022 12:57:09 +0000 Subject: [PATCH 281/385] Upgrade `go-fil-markets` to include index provider metadata changes Upgrade to the latest `go-fil-markets` that integrates concrete multicodec for the indexing metadata. --- go.mod | 4 ++-- go.sum | 16 ++++++---------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index e76692d531f..fb25f4335e3 100644 --- a/go.mod +++ b/go.mod @@ -38,7 +38,7 @@ require ( github.com/filecoin-project/go-data-transfer v1.14.0 github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 - github.com/filecoin-project/go-fil-markets v1.20.0 + github.com/filecoin-project/go-fil-markets v1.20.1 github.com/filecoin-project/go-jsonrpc v0.1.5 github.com/filecoin-project/go-legs v0.3.7 github.com/filecoin-project/go-padreader v0.0.1 @@ -47,7 +47,7 @@ require ( github.com/filecoin-project/go-statemachine v1.0.1 github.com/filecoin-project/go-statestore v0.2.0 github.com/filecoin-project/go-storedcounter v0.1.0 - github.com/filecoin-project/index-provider v0.4.0 + github.com/filecoin-project/index-provider v0.5.0 github.com/filecoin-project/specs-actors v0.9.14 github.com/filecoin-project/specs-actors/v2 v2.3.6 github.com/filecoin-project/specs-actors/v3 v3.1.1 diff --git a/go.sum b/go.sum index cd4618b291c..5af25332ef6 100644 --- a/go.sum +++ b/go.sum @@ -335,8 +335,8 @@ github.com/filecoin-project/go-fil-commcid v0.1.0 h1:3R4ds1A9r6cr8mvZBfMYxTS88Oq github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7LXep5bFEVOVmQWHJvl2mgsGo= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8= -github.com/filecoin-project/go-fil-markets v1.20.0 h1:kP9A2otcRe4mTfL++GF0+d4PoFDI92E38lhM8GXFT9I= -github.com/filecoin-project/go-fil-markets v1.20.0/go.mod h1:OeR49x+NPMfZMMgOresxzecMAgUB+lna2kwJABPwnt8= +github.com/filecoin-project/go-fil-markets v1.20.1 h1:DwrFuNIWC0a2c2ESpHtdEMH3QCpR/hoZ5DwjNT+VJ+E= +github.com/filecoin-project/go-fil-markets v1.20.1/go.mod h1:QV767KIWHrikVK8R0u2wTc5wkee4gXOf5/AfxDoQckw= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= @@ -347,8 +347,6 @@ github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0/go.mod h1:bxmzgT8tmeVQA1/gvBw github.com/filecoin-project/go-indexer-core v0.2.8/go.mod h1:IagNfTdFuX4057kla43PjRCn3yBuUiZgIxuA0hTUamY= github.com/filecoin-project/go-jsonrpc v0.1.5 h1:ckxqZ09ivBAVf5CSmxxrqqNHC7PJm3GYGtYKiNQ+vGk= github.com/filecoin-project/go-jsonrpc v0.1.5/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4= -github.com/filecoin-project/go-legs v0.3.0/go.mod h1:x6nwM+DuN7NzlPndOoJuiHYCX+pze6+efPRx17nIA7M= -github.com/filecoin-project/go-legs v0.3.4/go.mod h1:P7ZPHqFG96OFaT11rnXyTdcxRdGkaH1dRyPxJSOiSuM= github.com/filecoin-project/go-legs v0.3.7 h1:yfm7fx+iy1nPtgPEQ6kQjvhoJOVbXide50STYdy+yos= github.com/filecoin-project/go-legs v0.3.7/go.mod h1:pgekGm8/gKY5zCtQ/qGAoSjGP92wTLFqpO3GPHeu8YU= github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20/go.mod h1:mPn+LRRd5gEKNAtc+r3ScpW2JRU/pj4NBKdADYWHiak= @@ -372,9 +370,8 @@ github.com/filecoin-project/go-statestore v0.2.0 h1:cRRO0aPLrxKQCZ2UOQbzFGn4WDNd github.com/filecoin-project/go-statestore v0.2.0/go.mod h1:8sjBYbS35HwPzct7iT4lIXjLlYyPor80aU7t7a/Kspo= github.com/filecoin-project/go-storedcounter v0.1.0 h1:Mui6wSUBC+cQGHbDUBcO7rfh5zQkWJM/CpAZa/uOuus= github.com/filecoin-project/go-storedcounter v0.1.0/go.mod h1:4ceukaXi4vFURIoxYMfKzaRF5Xv/Pinh2oTnoxpv+z8= -github.com/filecoin-project/index-provider v0.3.1/go.mod h1:o8ineTLWnwtfBv7SnELpncza6SBU295esxOaXsTCl2I= -github.com/filecoin-project/index-provider v0.4.0 h1:laCdWms1OvgHwxkU0DSfkzqPQBRAMPO2TKes5s0TdHo= -github.com/filecoin-project/index-provider v0.4.0/go.mod h1:SDfBxhD9/wet7e5wv1J4IZjWfVkln/k4oTzMcNccLZA= +github.com/filecoin-project/index-provider v0.5.0 h1:k2C1RFvOvxmA2i8bhmkb3b4qun7RDRDzzs/y25/TwQg= +github.com/filecoin-project/index-provider v0.5.0/go.mod h1:KHVrP2vU3YuScb+fawObwTFoR882up9U07kk0ZrfP0c= github.com/filecoin-project/specs-actors v0.9.13/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= github.com/filecoin-project/specs-actors v0.9.14 h1:68PVstg2UB3ZsMLF+DKFTAs/YKsqhKWynkr0IqmVRQY= github.com/filecoin-project/specs-actors v0.9.14/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= @@ -398,7 +395,6 @@ github.com/filecoin-project/specs-actors/v7 v7.0.0 h1:FQN7tjt3o68hfb3qLFSJBoLMuO github.com/filecoin-project/specs-actors/v7 v7.0.0/go.mod h1:TA5FwCna+Yi36POaT7SLKXsgEDvJwc0V/L6ZsO19B9M= github.com/filecoin-project/specs-storage v0.2.0 h1:Y4UDv0apRQ3zI2GiPPubi8JblpUZZphEdaJUxCutfyg= github.com/filecoin-project/specs-storage v0.2.0/go.mod h1:Tb88Zq+IBJbvAn3mS89GYj3jdRThBTE/771HCVZdRJU= -github.com/filecoin-project/storetheindex v0.3.2/go.mod h1:d7y0FHAwPPSIdg+Oh7xV5B9TLebL7rvoKu591N/l2ZU= github.com/filecoin-project/storetheindex v0.3.5 h1:KoS9TvjPm6zIZfUH8atAHJbVHOO7GTP1MdTG+v0eE+Q= github.com/filecoin-project/storetheindex v0.3.5/go.mod h1:0r3d0kSpK63O6AvLr1CjAINLi+nWD49clzcnKV+GLpI= github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg= @@ -1579,8 +1575,9 @@ github.com/multiformats/go-multicodec v0.2.0/go.mod h1:/y4YVwkfMyry5kFbMTbLJKErh github.com/multiformats/go-multicodec v0.3.0/go.mod h1:qGGaQmioCDh+TeFOnxrbU0DaIPw8yFgAZgFG0V7p1qQ= github.com/multiformats/go-multicodec v0.3.1-0.20210902112759-1539a079fd61/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ= github.com/multiformats/go-multicodec v0.3.1-0.20211210143421-a526f306ed2c/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ= -github.com/multiformats/go-multicodec v0.4.0 h1:fbqb6ky7erjdD+/zaEBJgZWu1i8D6i/wmPywGK7sdow= github.com/multiformats/go-multicodec v0.4.0/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ= +github.com/multiformats/go-multicodec v0.4.1 h1:BSJbf+zpghcZMZrwTYBGwy0CPcVZGWiC72Cp8bBd4R4= +github.com/multiformats/go-multicodec v0.4.1/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ= github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= @@ -1933,7 +1930,6 @@ github.com/whyrusleeping/cbor-gen v0.0.0-20200826160007-0b9f6c5fb163/go.mod h1:f github.com/whyrusleeping/cbor-gen v0.0.0-20210118024343-169e9d70c0c2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20210219115102-f37d292932f2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20210303213153-67a261a1d291/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= -github.com/whyrusleeping/cbor-gen v0.0.0-20211110122933-f57984553008/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20220224212727-7a699437a831/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20220302191723-37c43cae8e14 h1:vo2wkP2ceHyGyZwFFtAabpot03EeSxxwAe57pOI9E/4= github.com/whyrusleeping/cbor-gen v0.0.0-20220302191723-37c43cae8e14/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= From 1bb65189af87631b2adc32ccc728f1af1ffee554 Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Thu, 3 Mar 2022 13:29:32 +0000 Subject: [PATCH 282/385] Upgrade to go-path `v0.2.1` and remove `replace` directive The dependency was used in the chain API. Integrated the new fetcher factory. --- go.mod | 3 +-- go.sum | 7 ++++++- node/impl/full/chain.go | 15 ++++++--------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index fb25f4335e3..14c1ce0d470 100644 --- a/go.mod +++ b/go.mod @@ -81,6 +81,7 @@ require ( github.com/ipfs/go-ds-badger2 v0.1.2 github.com/ipfs/go-ds-leveldb v0.5.0 github.com/ipfs/go-ds-measure v0.2.0 + github.com/ipfs/go-fetcher v1.6.1 github.com/ipfs/go-fs-lock v0.0.7 github.com/ipfs/go-graphsync v0.12.0 github.com/ipfs/go-ipfs-blockstore v1.1.2 @@ -176,5 +177,3 @@ require ( replace github.com/filecoin-project/filecoin-ffi => ./extern/filecoin-ffi replace github.com/filecoin-project/test-vectors => ./extern/test-vectors - -replace github.com/ipfs/go-path => github.com/ipfs/go-path v0.0.7 diff --git a/go.sum b/go.sum index 5af25332ef6..79febec3a71 100644 --- a/go.sum +++ b/go.sum @@ -746,6 +746,7 @@ github.com/ipfs/go-ds-leveldb v0.5.0/go.mod h1:d3XG9RUDzQ6V4SHi8+Xgj9j1XuEk1z82l github.com/ipfs/go-ds-measure v0.2.0 h1:sG4goQe0KDTccHMyT45CY1XyUbxe5VwTKpg2LjApYyQ= github.com/ipfs/go-ds-measure v0.2.0/go.mod h1:SEUD/rE2PwRa4IQEC5FuNAmjJCyYObZr9UvVh8V3JxE= github.com/ipfs/go-fetcher v1.5.0/go.mod h1:5pDZ0393oRF/fHiLmtFZtpMNBQfHOYNPtryWedVuSWE= +github.com/ipfs/go-fetcher v1.6.1 h1:UFuRVYX5AIllTiRhi5uK/iZkfhSpBCGX7L70nSZEmK8= github.com/ipfs/go-fetcher v1.6.1/go.mod h1:27d/xMV8bodjVs9pugh/RCjjK2OZ68UgAMspMdingNo= github.com/ipfs/go-filestore v0.1.0/go.mod h1:0KTrzoJnJ3sJDEDM09Vq8nz8H475rRyeq4i0n/bpF00= github.com/ipfs/go-filestore v1.1.0 h1:Pu4tLBi1bucu6/HU9llaOmb9yLFk/sgP+pW764zNDoE= @@ -865,8 +866,11 @@ github.com/ipfs/go-metrics-prometheus v0.0.2 h1:9i2iljLg12S78OhC6UAiXi176xvQGiZa github.com/ipfs/go-metrics-prometheus v0.0.2/go.mod h1:ELLU99AQQNi+zX6GCGm2lAgnzdSH3u5UVlCdqSXnEks= github.com/ipfs/go-mfs v0.2.1/go.mod h1:Woj80iuw4ajDnIP6+seRaoHpPsc9hmL0pk/nDNDWP88= github.com/ipfs/go-namesys v0.4.0/go.mod h1:jpJwzodyP8DZdWN6DShRjVZw6gaqMr4nQLBSxU5cR6E= -github.com/ipfs/go-path v0.0.7 h1:H06hKMquQ0aYtHiHryOMLpQC1qC3QwXwkahcEVD51Ho= github.com/ipfs/go-path v0.0.7/go.mod h1:6KTKmeRnBXgqrTvzFrPV3CamxcgvXX/4z79tfAd2Sno= +github.com/ipfs/go-path v0.0.9/go.mod h1:VpDkSBKQ9EFQOUgi54Tq/O/tGi8n1RfYNks13M3DEs8= +github.com/ipfs/go-path v0.1.1/go.mod h1:vC8q4AKOtrjJz2NnllIrmr2ZbGlF5fW2OKKyhV9ggb0= +github.com/ipfs/go-path v0.2.1 h1:R0JYCu0JBnfa6A3C42nzsNPxtKU5/fnUPhWSuzcJHws= +github.com/ipfs/go-path v0.2.1/go.mod h1:NOScsVgxfC/eIw4nz6OiGwK42PjaSJ4Y/ZFPn1Xe07I= github.com/ipfs/go-peertaskqueue v0.0.4/go.mod h1:03H8fhyeMfKNFWqzYEVyMbcPUeYrqP1MX6Kd+aN+rMQ= github.com/ipfs/go-peertaskqueue v0.1.0/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= github.com/ipfs/go-peertaskqueue v0.1.1/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= @@ -881,6 +885,7 @@ github.com/ipfs/go-unixfs v0.2.4/go.mod h1:SUdisfUjNoSDzzhGVxvCL9QO/nKdwXdr+gbMU github.com/ipfs/go-unixfs v0.2.6/go.mod h1:GTTzQvaZsTZARdNkkdjDKFFnBhmO3e5mIM1PkH/x4p0= github.com/ipfs/go-unixfs v0.3.1 h1:LrfED0OGfG98ZEegO4/xiprx2O+yS+krCMQSp7zLVv8= github.com/ipfs/go-unixfs v0.3.1/go.mod h1:h4qfQYzghiIc8ZNFKiLMFWOTzrWIAtzYQ59W/pCFf1o= +github.com/ipfs/go-unixfsnode v1.1.2/go.mod h1:5dcE2x03pyjHk4JjamXmunTMzz+VUtqvPwZjIEkfV6s= github.com/ipfs/go-unixfsnode v1.1.3/go.mod h1:ZZxUM5wXBC+G0Co9FjrYTOm+UlhZTjxLfRYdWY9veZ4= github.com/ipfs/go-unixfsnode v1.2.0 h1:tHHBJftsJyHGa8bS62PpkYNqHy/Sug3c/vxxC8NaGQY= github.com/ipfs/go-unixfsnode v1.2.0/go.mod h1:mQEgLjxkV/1mohkC4p7taRRBYPBeXu97SA3YaerT2q0= diff --git a/node/impl/full/chain.go b/node/impl/full/chain.go index ce492f94ae0..6ed9b6de42c 100644 --- a/node/impl/full/chain.go +++ b/node/impl/full/chain.go @@ -17,6 +17,7 @@ import ( "github.com/ipfs/go-blockservice" "github.com/ipfs/go-cid" + bsfetcher "github.com/ipfs/go-fetcher/impl/blockservice" offline "github.com/ipfs/go-ipfs-exchange-offline" cbor "github.com/ipfs/go-ipld-cbor" ipld "github.com/ipfs/go-ipld-format" @@ -24,6 +25,7 @@ import ( "github.com/ipfs/go-merkledag" "github.com/ipfs/go-path" "github.com/ipfs/go-path/resolver" + cidlink "github.com/ipld/go-ipld-prime/linking/cid" mh "github.com/multiformats/go-multihash" cbg "github.com/whyrusleeping/cbor-gen" @@ -557,21 +559,16 @@ func (a *ChainAPI) ChainGetNode(ctx context.Context, p string) (*api.IpldObject, bs := a.ExposedBlockstore bsvc := blockservice.New(bs, offline.Exchange(bs)) + fc := bsfetcher.NewFetcherConfig(bsvc) + r := resolver.NewBasicResolver(fc) - dag := merkledag.NewDAGService(bsvc) - - r := &resolver.Resolver{ - DAG: dag, - ResolveOnce: resolveOnce(bs, a.TsExec), - } - - node, err := r.ResolvePath(ctx, ip) + node, lnk, err := r.ResolvePath(ctx, ip) if err != nil { return nil, err } return &api.IpldObject{ - Cid: node.Cid(), + Cid: lnk.(cidlink.Link).Cid, Obj: node, }, nil } From 7dcfeee0ea8afe28625d1b10308aa164462c49ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 3 Mar 2022 14:14:12 +0000 Subject: [PATCH 283/385] use old go-path --- lib/oldpath/oldresolver/resolver.go | 198 +++++++++++++++++++++++++++ lib/oldpath/path.go | 199 ++++++++++++++++++++++++++++ node/impl/full/chain.go | 20 +-- 3 files changed, 408 insertions(+), 9 deletions(-) create mode 100644 lib/oldpath/oldresolver/resolver.go create mode 100644 lib/oldpath/path.go diff --git a/lib/oldpath/oldresolver/resolver.go b/lib/oldpath/oldresolver/resolver.go new file mode 100644 index 00000000000..e475e29be91 --- /dev/null +++ b/lib/oldpath/oldresolver/resolver.go @@ -0,0 +1,198 @@ +package oldresolver + +import ( + "context" + "errors" + "fmt" + "time" + + path "github.com/filecoin-project/lotus/lib/oldpath" + + cid "github.com/ipfs/go-cid" + ipld "github.com/ipfs/go-ipld-format" + logging "github.com/ipfs/go-log/v2" + dag "github.com/ipfs/go-merkledag" +) + +var log = logging.Logger("pathresolv") + +// ErrNoComponents is used when Paths after a protocol +// do not contain at least one component +var ErrNoComponents = errors.New( + "path must contain at least one component") + +// ErrNoLink is returned when a link is not found in a path +type ErrNoLink struct { + Name string + Node cid.Cid +} + +// Error implements the Error interface for ErrNoLink with a useful +// human readable message. +func (e ErrNoLink) Error() string { + return fmt.Sprintf("no link named %q under %s", e.Name, e.Node.String()) +} + +// ResolveOnce resolves path through a single node +type ResolveOnce func(ctx context.Context, ds ipld.NodeGetter, nd ipld.Node, names []string) (*ipld.Link, []string, error) + +// Resolver provides path resolution to IPFS +// It has a pointer to a DAGService, which is uses to resolve nodes. +// TODO: now that this is more modular, try to unify this code with the +// the resolvers in namesys +type Resolver struct { + DAG ipld.NodeGetter + + ResolveOnce ResolveOnce +} + +// NewBasicResolver constructs a new basic resolver. +func NewBasicResolver(ds ipld.DAGService) *Resolver { + return &Resolver{ + DAG: ds, + ResolveOnce: ResolveSingle, + } +} + +// ResolveToLastNode walks the given path and returns the cid of the last node +// referenced by the path +func (r *Resolver) ResolveToLastNode(ctx context.Context, fpath path.Path) (cid.Cid, []string, error) { + c, p, err := path.SplitAbsPath(fpath) + if err != nil { + return cid.Cid{}, nil, err + } + + if len(p) == 0 { + return c, nil, nil + } + + nd, err := r.DAG.Get(ctx, c) + if err != nil { + return cid.Cid{}, nil, err + } + + for len(p) > 0 { + lnk, rest, err := r.ResolveOnce(ctx, r.DAG, nd, p) + + // Note: have to drop the error here as `ResolveOnce` doesn't handle 'leaf' + // paths (so e.g. for `echo '{"foo":123}' | ipfs dag put` we wouldn't be + // able to resolve `zdpu[...]/foo`) + if lnk == nil { + break + } + + if err != nil { + if err == dag.ErrLinkNotFound { + err = ErrNoLink{Name: p[0], Node: nd.Cid()} + } + return cid.Cid{}, nil, err + } + + next, err := lnk.GetNode(ctx, r.DAG) + if err != nil { + return cid.Cid{}, nil, err + } + nd = next + p = rest + } + + if len(p) == 0 { + return nd.Cid(), nil, nil + } + + // Confirm the path exists within the object + val, rest, err := nd.Resolve(p) + if err != nil { + if err == dag.ErrLinkNotFound { + err = ErrNoLink{Name: p[0], Node: nd.Cid()} + } + return cid.Cid{}, nil, err + } + + if len(rest) > 0 { + return cid.Cid{}, nil, errors.New("path failed to resolve fully") + } + switch val.(type) { + case *ipld.Link: + return cid.Cid{}, nil, errors.New("inconsistent ResolveOnce / nd.Resolve") + default: + return nd.Cid(), p, nil + } +} + +// ResolvePath fetches the node for given path. It returns the last item +// returned by ResolvePathComponents. +func (r *Resolver) ResolvePath(ctx context.Context, fpath path.Path) (ipld.Node, error) { + // validate path + if err := fpath.IsValid(); err != nil { + return nil, err + } + + nodes, err := r.ResolvePathComponents(ctx, fpath) + if err != nil || nodes == nil { + return nil, err + } + return nodes[len(nodes)-1], err +} + +// ResolveSingle simply resolves one hop of a path through a graph with no +// extra context (does not opaquely resolve through sharded nodes) +func ResolveSingle(ctx context.Context, ds ipld.NodeGetter, nd ipld.Node, names []string) (*ipld.Link, []string, error) { + return nd.ResolveLink(names) +} + +// ResolvePathComponents fetches the nodes for each segment of the given path. +// It uses the first path component as a hash (key) of the first node, then +// resolves all other components walking the links, with ResolveLinks. +func (r *Resolver) ResolvePathComponents(ctx context.Context, fpath path.Path) ([]ipld.Node, error) { + + h, parts, err := path.SplitAbsPath(fpath) + if err != nil { + return nil, err + } + + log.Debug("resolve dag get") + nd, err := r.DAG.Get(ctx, h) + if err != nil { + return nil, err + } + + return r.ResolveLinks(ctx, nd, parts) +} + +// ResolveLinks iteratively resolves names by walking the link hierarchy. +// Every node is fetched from the DAGService, resolving the next name. +// Returns the list of nodes forming the path, starting with ndd. This list is +// guaranteed never to be empty. +// +// ResolveLinks(nd, []string{"foo", "bar", "baz"}) +// would retrieve "baz" in ("bar" in ("foo" in nd.Links).Links).Links +func (r *Resolver) ResolveLinks(ctx context.Context, ndd ipld.Node, names []string) ([]ipld.Node, error) { + result := make([]ipld.Node, 0, len(names)+1) + result = append(result, ndd) + nd := ndd // dup arg workaround + + // for each of the path components + for len(names) > 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, time.Minute) + defer cancel() + + lnk, rest, err := r.ResolveOnce(ctx, r.DAG, nd, names) + if err == dag.ErrLinkNotFound { + return result, ErrNoLink{Name: names[0], Node: nd.Cid()} + } else if err != nil { + return result, err + } + + nextnode, err := lnk.GetNode(ctx, r.DAG) + if err != nil { + return result, err + } + + nd = nextnode + result = append(result, nextnode) + names = rest + } + return result, nil +} diff --git a/lib/oldpath/path.go b/lib/oldpath/path.go new file mode 100644 index 00000000000..fe4bd67a24b --- /dev/null +++ b/lib/oldpath/path.go @@ -0,0 +1,199 @@ +package oldpath + +import ( + "fmt" + "path" + "strings" + + cid "github.com/ipfs/go-cid" +) + +// helper type so path parsing errors include the path +type pathError struct { + error error + path string +} + +func (e *pathError) Error() string { + return fmt.Sprintf("invalid path %q: %s", e.path, e.error) +} + +func (e *pathError) Unwrap() error { + return e.error +} + +func (e *pathError) Path() string { + return e.path +} + +// A Path represents an ipfs content path: +// * //path/to/file +// * /ipfs/ +// * /ipns//path/to/folder +// * etc +type Path string + +// ^^^ +// TODO: debate making this a private struct wrapped in a public interface +// would allow us to control creation, and cache segments. + +// FromString safely converts a string type to a Path type. +func FromString(s string) Path { + return Path(s) +} + +// FromCid safely converts a cid.Cid type to a Path type. +func FromCid(c cid.Cid) Path { + return Path("/ipfs/" + c.String()) +} + +// Segments returns the different elements of a path +// (elements are delimited by a /). +func (p Path) Segments() []string { + cleaned := path.Clean(string(p)) + segments := strings.Split(cleaned, "/") + + // Ignore leading slash + if len(segments[0]) == 0 { + segments = segments[1:] + } + + return segments +} + +// String converts a path to string. +func (p Path) String() string { + return string(p) +} + +// IsJustAKey returns true if the path is of the form or /ipfs/, or +// /ipld/ +func (p Path) IsJustAKey() bool { + parts := p.Segments() + return len(parts) == 2 && (parts[0] == "ipfs" || parts[0] == "ipld") +} + +// PopLastSegment returns a new Path without its final segment, and the final +// segment, separately. If there is no more to pop (the path is just a key), +// the original path is returned. +func (p Path) PopLastSegment() (Path, string, error) { + + if p.IsJustAKey() { + return p, "", nil + } + + segs := p.Segments() + newPath, err := ParsePath("/" + strings.Join(segs[:len(segs)-1], "/")) + if err != nil { + return "", "", err + } + + return newPath, segs[len(segs)-1], nil +} + +// FromSegments returns a path given its different segments. +func FromSegments(prefix string, seg ...string) (Path, error) { + return ParsePath(prefix + strings.Join(seg, "/")) +} + +// ParsePath returns a well-formed ipfs Path. +// The returned path will always be prefixed with /ipfs/ or /ipns/. +// The prefix will be added if not present in the given string. +// This function will return an error when the given string is +// not a valid ipfs path. +func ParsePath(txt string) (Path, error) { + parts := strings.Split(txt, "/") + if len(parts) == 1 { + kp, err := ParseCidToPath(txt) + if err == nil { + return kp, nil + } + } + + // if the path doesnt begin with a '/' + // we expect this to start with a hash, and be an 'ipfs' path + if parts[0] != "" { + if _, err := cid.Decode(parts[0]); err != nil { + return "", &pathError{error: err, path: txt} + } + // The case when the path starts with hash without a protocol prefix + return Path("/ipfs/" + txt), nil + } + + if len(parts) < 3 { + return "", &pathError{error: fmt.Errorf("path does not begin with '/'"), path: txt} + } + + //TODO: make this smarter + switch parts[1] { + case "ipfs", "ipld": + if parts[2] == "" { + return "", &pathError{error: fmt.Errorf("not enough path components"), path: txt} + } + // Validate Cid. + _, err := cid.Decode(parts[2]) + if err != nil { + return "", &pathError{error: fmt.Errorf("invalid CID: %s", err), path: txt} + } + case "ipns": + if parts[2] == "" { + return "", &pathError{error: fmt.Errorf("not enough path components"), path: txt} + } + default: + return "", &pathError{error: fmt.Errorf("unknown namespace %q", parts[1]), path: txt} + } + + return Path(txt), nil +} + +// ParseCidToPath takes a CID in string form and returns a valid ipfs Path. +func ParseCidToPath(txt string) (Path, error) { + if txt == "" { + return "", &pathError{error: fmt.Errorf("empty"), path: txt} + } + + c, err := cid.Decode(txt) + if err != nil { + return "", &pathError{error: err, path: txt} + } + + return FromCid(c), nil +} + +// IsValid checks if a path is a valid ipfs Path. +func (p *Path) IsValid() error { + _, err := ParsePath(p.String()) + return err +} + +// Join joins strings slices using / +func Join(pths []string) string { + return strings.Join(pths, "/") +} + +// SplitList splits strings usings / +func SplitList(pth string) []string { + return strings.Split(pth, "/") +} + +// SplitAbsPath clean up and split fpath. It extracts the first component (which +// must be a Multihash) and return it separately. +func SplitAbsPath(fpath Path) (cid.Cid, []string, error) { + parts := fpath.Segments() + if parts[0] == "ipfs" || parts[0] == "ipld" { + parts = parts[1:] + } + + // if nothing, bail. + if len(parts) == 0 { + return cid.Cid{}, nil, &pathError{error: fmt.Errorf("empty"), path: string(fpath)} + } + + c, err := cid.Decode(parts[0]) + // first element in the path is a cid + if err != nil { + return cid.Cid{}, nil, &pathError{error: fmt.Errorf("invalid CID: %s", err), path: string(fpath)} + } + + return c, parts[1:], nil +} diff --git a/node/impl/full/chain.go b/node/impl/full/chain.go index 6ed9b6de42c..61be82bc9e6 100644 --- a/node/impl/full/chain.go +++ b/node/impl/full/chain.go @@ -17,15 +17,11 @@ import ( "github.com/ipfs/go-blockservice" "github.com/ipfs/go-cid" - bsfetcher "github.com/ipfs/go-fetcher/impl/blockservice" offline "github.com/ipfs/go-ipfs-exchange-offline" cbor "github.com/ipfs/go-ipld-cbor" ipld "github.com/ipfs/go-ipld-format" logging "github.com/ipfs/go-log/v2" "github.com/ipfs/go-merkledag" - "github.com/ipfs/go-path" - "github.com/ipfs/go-path/resolver" - cidlink "github.com/ipld/go-ipld-prime/linking/cid" mh "github.com/multiformats/go-multihash" cbg "github.com/whyrusleeping/cbor-gen" @@ -38,6 +34,8 @@ import ( "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/vm" + "github.com/filecoin-project/lotus/lib/oldpath" + "github.com/filecoin-project/lotus/lib/oldpath/oldresolver" "github.com/filecoin-project/lotus/node/modules/dtypes" ) @@ -552,23 +550,27 @@ func resolveOnce(bs blockstore.Blockstore, tse stmgr.Executor) func(ctx context. } func (a *ChainAPI) ChainGetNode(ctx context.Context, p string) (*api.IpldObject, error) { - ip, err := path.ParsePath(p) + ip, err := oldpath.ParsePath(p) if err != nil { return nil, xerrors.Errorf("parsing path: %w", err) } bs := a.ExposedBlockstore bsvc := blockservice.New(bs, offline.Exchange(bs)) - fc := bsfetcher.NewFetcherConfig(bsvc) - r := resolver.NewBasicResolver(fc) + dag := merkledag.NewDAGService(bsvc) + + r := &oldresolver.Resolver{ + DAG: dag, + ResolveOnce: resolveOnce(bs, a.TsExec), + } - node, lnk, err := r.ResolvePath(ctx, ip) + node, err := r.ResolvePath(ctx, ip) if err != nil { return nil, err } return &api.IpldObject{ - Cid: lnk.(cidlink.Link).Cid, + Cid: node.Cid(), Obj: node, }, nil } From 28d751b2e0f8b0aa4b75f4f740eefcde59c8d066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 3 Mar 2022 14:20:57 +0000 Subject: [PATCH 284/385] mod tidy --- go.mod | 2 -- go.sum | 1 - 2 files changed, 3 deletions(-) diff --git a/go.mod b/go.mod index 14c1ce0d470..060613d1949 100644 --- a/go.mod +++ b/go.mod @@ -81,7 +81,6 @@ require ( github.com/ipfs/go-ds-badger2 v0.1.2 github.com/ipfs/go-ds-leveldb v0.5.0 github.com/ipfs/go-ds-measure v0.2.0 - github.com/ipfs/go-fetcher v1.6.1 github.com/ipfs/go-fs-lock v0.0.7 github.com/ipfs/go-graphsync v0.12.0 github.com/ipfs/go-ipfs-blockstore v1.1.2 @@ -101,7 +100,6 @@ require ( github.com/ipfs/go-merkledag v0.5.1 github.com/ipfs/go-metrics-interface v0.0.1 github.com/ipfs/go-metrics-prometheus v0.0.2 - github.com/ipfs/go-path v0.2.1 github.com/ipfs/go-unixfs v0.3.1 github.com/ipfs/go-unixfsnode v1.2.0 github.com/ipfs/interface-go-ipfs-core v0.5.2 diff --git a/go.sum b/go.sum index 79febec3a71..d07b83200fc 100644 --- a/go.sum +++ b/go.sum @@ -746,7 +746,6 @@ github.com/ipfs/go-ds-leveldb v0.5.0/go.mod h1:d3XG9RUDzQ6V4SHi8+Xgj9j1XuEk1z82l github.com/ipfs/go-ds-measure v0.2.0 h1:sG4goQe0KDTccHMyT45CY1XyUbxe5VwTKpg2LjApYyQ= github.com/ipfs/go-ds-measure v0.2.0/go.mod h1:SEUD/rE2PwRa4IQEC5FuNAmjJCyYObZr9UvVh8V3JxE= github.com/ipfs/go-fetcher v1.5.0/go.mod h1:5pDZ0393oRF/fHiLmtFZtpMNBQfHOYNPtryWedVuSWE= -github.com/ipfs/go-fetcher v1.6.1 h1:UFuRVYX5AIllTiRhi5uK/iZkfhSpBCGX7L70nSZEmK8= github.com/ipfs/go-fetcher v1.6.1/go.mod h1:27d/xMV8bodjVs9pugh/RCjjK2OZ68UgAMspMdingNo= github.com/ipfs/go-filestore v0.1.0/go.mod h1:0KTrzoJnJ3sJDEDM09Vq8nz8H475rRyeq4i0n/bpF00= github.com/ipfs/go-filestore v1.1.0 h1:Pu4tLBi1bucu6/HU9llaOmb9yLFk/sgP+pW764zNDoE= From 4c8015c0a1ac188b2ed3588b638b5f4f896c1d3f Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Thu, 3 Mar 2022 16:05:50 +0000 Subject: [PATCH 285/385] Update deps in lotus-soup mod and remove replace directive Update dependency to go-fil-markets in `lotus-soup` module and remove the redundant replace directive. --- testplans/lotus-soup/go.mod | 4 +--- testplans/lotus-soup/go.sum | 38 +++++++++++++++++++++---------------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/testplans/lotus-soup/go.mod b/testplans/lotus-soup/go.mod index 079ad814ebc..41847e082f9 100644 --- a/testplans/lotus-soup/go.mod +++ b/testplans/lotus-soup/go.mod @@ -9,7 +9,7 @@ require ( github.com/drand/drand v1.3.0 github.com/filecoin-project/go-address v0.0.6 github.com/filecoin-project/go-data-transfer v1.14.0 - github.com/filecoin-project/go-fil-markets v1.20.0 + github.com/filecoin-project/go-fil-markets v1.20.1 github.com/filecoin-project/go-jsonrpc v0.1.5 github.com/filecoin-project/go-state-types v0.1.3 github.com/filecoin-project/go-storedcounter v0.1.0 @@ -43,5 +43,3 @@ require ( replace github.com/filecoin-project/filecoin-ffi => ../../extern/filecoin-ffi replace github.com/filecoin-project/lotus => ../../ - -replace github.com/ipfs/go-path => github.com/ipfs/go-path v0.0.7 diff --git a/testplans/lotus-soup/go.sum b/testplans/lotus-soup/go.sum index cb0a1b762d1..51e5172a59a 100644 --- a/testplans/lotus-soup/go.sum +++ b/testplans/lotus-soup/go.sum @@ -426,10 +426,8 @@ github.com/filecoin-project/go-fil-commcid v0.1.0 h1:3R4ds1A9r6cr8mvZBfMYxTS88Oq github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7LXep5bFEVOVmQWHJvl2mgsGo= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8= -github.com/filecoin-project/go-fil-markets v1.19.2-0.20220223141410-2460e15e07a8 h1:cuV4t78W8tUgmqvsc6T6qbWuycg7GzPcNsTdAOxrTns= -github.com/filecoin-project/go-fil-markets v1.19.2-0.20220223141410-2460e15e07a8/go.mod h1:OeR49x+NPMfZMMgOresxzecMAgUB+lna2kwJABPwnt8= -github.com/filecoin-project/go-fil-markets v1.20.0 h1:kP9A2otcRe4mTfL++GF0+d4PoFDI92E38lhM8GXFT9I= -github.com/filecoin-project/go-fil-markets v1.20.0/go.mod h1:OeR49x+NPMfZMMgOresxzecMAgUB+lna2kwJABPwnt8= +github.com/filecoin-project/go-fil-markets v1.20.1 h1:DwrFuNIWC0a2c2ESpHtdEMH3QCpR/hoZ5DwjNT+VJ+E= +github.com/filecoin-project/go-fil-markets v1.20.1/go.mod h1:QV767KIWHrikVK8R0u2wTc5wkee4gXOf5/AfxDoQckw= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= @@ -440,9 +438,8 @@ github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0/go.mod h1:bxmzgT8tmeVQA1/gvBw github.com/filecoin-project/go-indexer-core v0.2.8/go.mod h1:IagNfTdFuX4057kla43PjRCn3yBuUiZgIxuA0hTUamY= github.com/filecoin-project/go-jsonrpc v0.1.5 h1:ckxqZ09ivBAVf5CSmxxrqqNHC7PJm3GYGtYKiNQ+vGk= github.com/filecoin-project/go-jsonrpc v0.1.5/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4= -github.com/filecoin-project/go-legs v0.3.0/go.mod h1:x6nwM+DuN7NzlPndOoJuiHYCX+pze6+efPRx17nIA7M= -github.com/filecoin-project/go-legs v0.3.4 h1:yid2IivTJ8JeF1ROA8jxNKNKJshU/HO1sRo5lEMNOUc= -github.com/filecoin-project/go-legs v0.3.4/go.mod h1:P7ZPHqFG96OFaT11rnXyTdcxRdGkaH1dRyPxJSOiSuM= +github.com/filecoin-project/go-legs v0.3.7 h1:yfm7fx+iy1nPtgPEQ6kQjvhoJOVbXide50STYdy+yos= +github.com/filecoin-project/go-legs v0.3.7/go.mod h1:pgekGm8/gKY5zCtQ/qGAoSjGP92wTLFqpO3GPHeu8YU= github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20/go.mod h1:mPn+LRRd5gEKNAtc+r3ScpW2JRU/pj4NBKdADYWHiak= github.com/filecoin-project/go-padreader v0.0.1 h1:8h2tVy5HpoNbr2gBRr+WD6zV6VD6XHig+ynSGJg8ZOs= github.com/filecoin-project/go-padreader v0.0.1/go.mod h1:VYVPJqwpsfmtoHnAmPx6MUwmrK6HIcDqZJiuZhtmfLQ= @@ -464,8 +461,8 @@ github.com/filecoin-project/go-statestore v0.2.0 h1:cRRO0aPLrxKQCZ2UOQbzFGn4WDNd github.com/filecoin-project/go-statestore v0.2.0/go.mod h1:8sjBYbS35HwPzct7iT4lIXjLlYyPor80aU7t7a/Kspo= github.com/filecoin-project/go-storedcounter v0.1.0 h1:Mui6wSUBC+cQGHbDUBcO7rfh5zQkWJM/CpAZa/uOuus= github.com/filecoin-project/go-storedcounter v0.1.0/go.mod h1:4ceukaXi4vFURIoxYMfKzaRF5Xv/Pinh2oTnoxpv+z8= -github.com/filecoin-project/index-provider v0.3.1 h1:ySGk2FnDbUEhq6QwakeU/p8tKnIoUm6JIpXPQ8RG1iM= -github.com/filecoin-project/index-provider v0.3.1/go.mod h1:o8ineTLWnwtfBv7SnELpncza6SBU295esxOaXsTCl2I= +github.com/filecoin-project/index-provider v0.5.0 h1:k2C1RFvOvxmA2i8bhmkb3b4qun7RDRDzzs/y25/TwQg= +github.com/filecoin-project/index-provider v0.5.0/go.mod h1:KHVrP2vU3YuScb+fawObwTFoR882up9U07kk0ZrfP0c= github.com/filecoin-project/specs-actors v0.9.13/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= github.com/filecoin-project/specs-actors v0.9.14 h1:68PVstg2UB3ZsMLF+DKFTAs/YKsqhKWynkr0IqmVRQY= github.com/filecoin-project/specs-actors v0.9.14/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= @@ -489,8 +486,8 @@ github.com/filecoin-project/specs-actors/v7 v7.0.0 h1:FQN7tjt3o68hfb3qLFSJBoLMuO github.com/filecoin-project/specs-actors/v7 v7.0.0/go.mod h1:TA5FwCna+Yi36POaT7SLKXsgEDvJwc0V/L6ZsO19B9M= github.com/filecoin-project/specs-storage v0.2.0 h1:Y4UDv0apRQ3zI2GiPPubi8JblpUZZphEdaJUxCutfyg= github.com/filecoin-project/specs-storage v0.2.0/go.mod h1:Tb88Zq+IBJbvAn3mS89GYj3jdRThBTE/771HCVZdRJU= -github.com/filecoin-project/storetheindex v0.3.2 h1:KsTJer5Di/iapSrOWtbFTPMt5kS7Y3n3C9kOYH93gEA= -github.com/filecoin-project/storetheindex v0.3.2/go.mod h1:d7y0FHAwPPSIdg+Oh7xV5B9TLebL7rvoKu591N/l2ZU= +github.com/filecoin-project/storetheindex v0.3.5 h1:KoS9TvjPm6zIZfUH8atAHJbVHOO7GTP1MdTG+v0eE+Q= +github.com/filecoin-project/storetheindex v0.3.5/go.mod h1:0r3d0kSpK63O6AvLr1CjAINLi+nWD49clzcnKV+GLpI= github.com/filecoin-project/test-vectors/schema v0.0.5/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6/go.mod h1:1i71OnUq3iUe1ma7Lr6yG6/rjvM3emb6yoL7xLFzcVQ= @@ -1088,8 +1085,11 @@ github.com/ipfs/go-metrics-interface v0.0.1/go.mod h1:6s6euYU4zowdslK0GKHmqaIZ3j github.com/ipfs/go-metrics-prometheus v0.0.2/go.mod h1:ELLU99AQQNi+zX6GCGm2lAgnzdSH3u5UVlCdqSXnEks= github.com/ipfs/go-mfs v0.2.1/go.mod h1:Woj80iuw4ajDnIP6+seRaoHpPsc9hmL0pk/nDNDWP88= github.com/ipfs/go-namesys v0.4.0/go.mod h1:jpJwzodyP8DZdWN6DShRjVZw6gaqMr4nQLBSxU5cR6E= -github.com/ipfs/go-path v0.0.7 h1:H06hKMquQ0aYtHiHryOMLpQC1qC3QwXwkahcEVD51Ho= github.com/ipfs/go-path v0.0.7/go.mod h1:6KTKmeRnBXgqrTvzFrPV3CamxcgvXX/4z79tfAd2Sno= +github.com/ipfs/go-path v0.0.9/go.mod h1:VpDkSBKQ9EFQOUgi54Tq/O/tGi8n1RfYNks13M3DEs8= +github.com/ipfs/go-path v0.1.1/go.mod h1:vC8q4AKOtrjJz2NnllIrmr2ZbGlF5fW2OKKyhV9ggb0= +github.com/ipfs/go-path v0.2.1 h1:R0JYCu0JBnfa6A3C42nzsNPxtKU5/fnUPhWSuzcJHws= +github.com/ipfs/go-path v0.2.1/go.mod h1:NOScsVgxfC/eIw4nz6OiGwK42PjaSJ4Y/ZFPn1Xe07I= github.com/ipfs/go-peertaskqueue v0.0.4/go.mod h1:03H8fhyeMfKNFWqzYEVyMbcPUeYrqP1MX6Kd+aN+rMQ= github.com/ipfs/go-peertaskqueue v0.1.0/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= github.com/ipfs/go-peertaskqueue v0.1.1/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= @@ -1104,6 +1104,7 @@ github.com/ipfs/go-unixfs v0.2.4/go.mod h1:SUdisfUjNoSDzzhGVxvCL9QO/nKdwXdr+gbMU github.com/ipfs/go-unixfs v0.2.6/go.mod h1:GTTzQvaZsTZARdNkkdjDKFFnBhmO3e5mIM1PkH/x4p0= github.com/ipfs/go-unixfs v0.3.1 h1:LrfED0OGfG98ZEegO4/xiprx2O+yS+krCMQSp7zLVv8= github.com/ipfs/go-unixfs v0.3.1/go.mod h1:h4qfQYzghiIc8ZNFKiLMFWOTzrWIAtzYQ59W/pCFf1o= +github.com/ipfs/go-unixfsnode v1.1.2/go.mod h1:5dcE2x03pyjHk4JjamXmunTMzz+VUtqvPwZjIEkfV6s= github.com/ipfs/go-unixfsnode v1.1.3/go.mod h1:ZZxUM5wXBC+G0Co9FjrYTOm+UlhZTjxLfRYdWY9veZ4= github.com/ipfs/go-unixfsnode v1.2.0 h1:tHHBJftsJyHGa8bS62PpkYNqHy/Sug3c/vxxC8NaGQY= github.com/ipfs/go-unixfsnode v1.2.0/go.mod h1:mQEgLjxkV/1mohkC4p7taRRBYPBeXu97SA3YaerT2q0= @@ -1300,6 +1301,7 @@ github.com/libp2p/go-libp2p v0.14.4/go.mod h1:EIRU0Of4J5S8rkockZM7eJp2S0UrCyi55m github.com/libp2p/go-libp2p v0.16.0/go.mod h1:ump42BsirwAWxKzsCiFnTtN1Yc+DuPu76fyMX364/O4= github.com/libp2p/go-libp2p v0.17.0/go.mod h1:Fkin50rsGdv5mm5BshBUtPRZknt9esfmYXBOYcwOTgw= github.com/libp2p/go-libp2p v0.18.0-rc1/go.mod h1:RgYlH7IIWHXREimC92bw5Lg1V2R5XmSzuLHb5fTnr+8= +github.com/libp2p/go-libp2p v0.18.0-rc3/go.mod h1:WYL+Xw1iuwi6rdfzw5VIEpD+HqzYucHZ6fcUuumbI3M= github.com/libp2p/go-libp2p v0.18.0-rc5 h1:88wWDHb9nNo0vBNCupLde3OTnFAkugOCNkrDfl3ivK4= github.com/libp2p/go-libp2p v0.18.0-rc5/go.mod h1:aZPS5l84bDvCvP4jkyEUT/J6YOpUq33Fgqrs3K59mpI= github.com/libp2p/go-libp2p-asn-util v0.0.0-20200825225859-85005c6cf052/go.mod h1:nRMRTab+kZuk0LnKZpxhOVH/ndsdr2Nr//Zltc/vwgo= @@ -1510,6 +1512,7 @@ github.com/libp2p/go-libp2p-swarm v0.5.3/go.mod h1:NBn7eNW2lu568L7Ns9wdFrOhgRlkR github.com/libp2p/go-libp2p-swarm v0.8.0/go.mod h1:sOMp6dPuqco0r0GHTzfVheVBh6UEL0L1lXUZ5ot2Fvc= github.com/libp2p/go-libp2p-swarm v0.9.0/go.mod h1:2f8d8uxTJmpeqHF/1ujjdXZp+98nNIbujVOMEZxCbZ8= github.com/libp2p/go-libp2p-swarm v0.10.0/go.mod h1:71ceMcV6Rg/0rIQ97rsZWMzto1l9LnNquef+efcRbmA= +github.com/libp2p/go-libp2p-swarm v0.10.1/go.mod h1:Pdkq0QU5a+qu+oyqIV3bknMsnzk9lnNyKvB9acJ5aZs= github.com/libp2p/go-libp2p-swarm v0.10.2 h1:UaXf+CTq6Ns1N2V1EgqJ9Q3xaRsiN7ImVlDMpirMAWw= github.com/libp2p/go-libp2p-swarm v0.10.2/go.mod h1:Pdkq0QU5a+qu+oyqIV3bknMsnzk9lnNyKvB9acJ5aZs= github.com/libp2p/go-libp2p-testing v0.0.1/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= @@ -1852,8 +1855,9 @@ github.com/multiformats/go-multicodec v0.2.0/go.mod h1:/y4YVwkfMyry5kFbMTbLJKErh github.com/multiformats/go-multicodec v0.3.0/go.mod h1:qGGaQmioCDh+TeFOnxrbU0DaIPw8yFgAZgFG0V7p1qQ= github.com/multiformats/go-multicodec v0.3.1-0.20210902112759-1539a079fd61/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ= github.com/multiformats/go-multicodec v0.3.1-0.20211210143421-a526f306ed2c/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ= -github.com/multiformats/go-multicodec v0.4.0 h1:fbqb6ky7erjdD+/zaEBJgZWu1i8D6i/wmPywGK7sdow= github.com/multiformats/go-multicodec v0.4.0/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ= +github.com/multiformats/go-multicodec v0.4.1 h1:BSJbf+zpghcZMZrwTYBGwy0CPcVZGWiC72Cp8bBd4R4= +github.com/multiformats/go-multicodec v0.4.1/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ= github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= @@ -2257,8 +2261,9 @@ github.com/whyrusleeping/cbor-gen v0.0.0-20200826160007-0b9f6c5fb163/go.mod h1:f github.com/whyrusleeping/cbor-gen v0.0.0-20210118024343-169e9d70c0c2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20210219115102-f37d292932f2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20210303213153-67a261a1d291/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= -github.com/whyrusleeping/cbor-gen v0.0.0-20211110122933-f57984553008 h1:7WtW9D9VGpmRLuQmrPy2JobUNdka95z3MKEVpELtOjo= -github.com/whyrusleeping/cbor-gen v0.0.0-20211110122933-f57984553008/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= +github.com/whyrusleeping/cbor-gen v0.0.0-20220224212727-7a699437a831/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= +github.com/whyrusleeping/cbor-gen v0.0.0-20220302191723-37c43cae8e14 h1:vo2wkP2ceHyGyZwFFtAabpot03EeSxxwAe57pOI9E/4= +github.com/whyrusleeping/cbor-gen v0.0.0-20220302191723-37c43cae8e14/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f/go.mod h1:p9UJB6dDgdPgMJZs7UjUOdulKyRr9fqkS+6JKAInPy8= github.com/whyrusleeping/go-ctrlnet v0.0.0-20180313164037-f564fbbdaa95/go.mod h1:SJqKCCPXRfBFCwXjfNT/skfsceF7+MBFLI2OrvuRA7g= @@ -2374,8 +2379,9 @@ go.uber.org/fx v1.15.0/go.mod h1:jI3RazQUhGv5KkpZIRv+kuP4CcgX3fnc0qX8bLnzbx8= go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= +go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= From 61f453fcd378757a69f9745cda9e5863ef7512f5 Mon Sep 17 00:00:00 2001 From: zenground0 Date: Tue, 8 Mar 2022 14:57:11 -0700 Subject: [PATCH 286/385] Print sector key in state sector command --- cli/state.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cli/state.go b/cli/state.go index bac7efae8eb..18d9a12bdfc 100644 --- a/cli/state.go +++ b/cli/state.go @@ -1768,6 +1768,9 @@ var StateSectorCmd = &cli.Command{ fmt.Println("SectorNumber: ", si.SectorNumber) fmt.Println("SealProof: ", si.SealProof) fmt.Println("SealedCID: ", si.SealedCID) + if si.SectorKeyCID != nil { + fmt.Println("SectorKeyCID: ", si.SectorKeyCID) + } fmt.Println("DealIDs: ", si.DealIDs) fmt.Println() fmt.Println("Activation: ", EpochTime(ts.Height(), si.Activation)) From c192637741f67c129aff0252a10bf6408ed07929 Mon Sep 17 00:00:00 2001 From: zenground0 Date: Tue, 8 Mar 2022 15:14:20 -0700 Subject: [PATCH 287/385] Fix warmup --- miner/warmup.go | 1 + 1 file changed, 1 insertion(+) diff --git a/miner/warmup.go b/miner/warmup.go index be5ac3ea7d7..3b73afbc9b7 100644 --- a/miner/warmup.go +++ b/miner/warmup.go @@ -74,6 +74,7 @@ out: SealProof: si.SealProof, SectorNumber: sector, SealedCID: si.SealedCID, + SectorKey: si.SectorKeyCID, }, }, r, ts.Height(), nv) if err != nil { From 84dbb229b65a7da17703f4ec6544eacbcd77d61b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 8 Mar 2022 22:48:08 +0100 Subject: [PATCH 288/385] shed: blockstore/vlog to car export cmds --- chain/store/snapshot.go | 6 +- cmd/lotus-shed/datastore-vlog.go | 350 ++++++++++++++++++++++++++ cmd/lotus-shed/datastore.go | 1 + cmd/lotus-shed/export.go | 374 +++++++++++++++++++++++++++- cmd/lotus-shed/shedgen/cbor_gen.go | 128 ++++++++++ cmd/lotus-shed/shedgen/rawexport.go | 7 + gen/main.go | 8 + 7 files changed, 871 insertions(+), 3 deletions(-) create mode 100644 cmd/lotus-shed/datastore-vlog.go create mode 100644 cmd/lotus-shed/shedgen/cbor_gen.go create mode 100644 cmd/lotus-shed/shedgen/rawexport.go diff --git a/chain/store/snapshot.go b/chain/store/snapshot.go index 61fa8bdc876..b9630bcbd7d 100644 --- a/chain/store/snapshot.go +++ b/chain/store/snapshot.go @@ -18,6 +18,10 @@ import ( "github.com/filecoin-project/lotus/chain/types" ) +func (cs *ChainStore) UnionStore() bstore.Blockstore { + return bstore.Union(cs.stateBlockstore, cs.chainBlockstore) +} + func (cs *ChainStore) Export(ctx context.Context, ts *types.TipSet, inclRecentRoots abi.ChainEpoch, skipOldMsgs bool, w io.Writer) error { h := &car.CarHeader{ Roots: ts.Cids(), @@ -28,7 +32,7 @@ func (cs *ChainStore) Export(ctx context.Context, ts *types.TipSet, inclRecentRo return xerrors.Errorf("failed to write car header: %s", err) } - unionBs := bstore.Union(cs.stateBlockstore, cs.chainBlockstore) + unionBs := cs.UnionStore() return cs.WalkSnapshot(ctx, ts, inclRecentRoots, skipOldMsgs, true, func(c cid.Cid) error { blk, err := unionBs.Get(ctx, c) if err != nil { diff --git a/cmd/lotus-shed/datastore-vlog.go b/cmd/lotus-shed/datastore-vlog.go new file mode 100644 index 00000000000..4a848b24fa6 --- /dev/null +++ b/cmd/lotus-shed/datastore-vlog.go @@ -0,0 +1,350 @@ +package main + +import ( + "bufio" + "encoding/binary" + "errors" + "fmt" + "hash" + "hash/crc32" + "io" + "os" + "strings" + + "github.com/dgraph-io/badger/v2/y" + block "github.com/ipfs/go-block-format" + "github.com/ipfs/go-cid" + "github.com/multiformats/go-base32" + "github.com/urfave/cli/v2" + "golang.org/x/xerrors" +) + +var datastoreVlog2CarCmd = &cli.Command{ + Name: "vlog2car", + Usage: "convert badger blockstore .vlog to .car", + Flags: []cli.Flag{ + &cli.PathFlag{ + Name: "vlog", + Usage: "vlog file", + Required: true, + }, + &cli.PathFlag{ + Name: "car", + Usage: "out car file name (no .car)", + Required: true, + }, + &cli.StringFlag{ + Name: "key-prefix", + Usage: "datastore prefix", + Value: "/blocks/", + }, + }, + Action: func(cctx *cli.Context) error { + ctx := cctx.Context + + maxSz := uint64(1 << 20) + + carb := &rawCarb{ + max: maxSz, + blocks: map[cid.Cid]block.Block{}, + } + cars := 0 + + pref := cctx.String("key-prefix") + plen := len(pref) + + { + // NOTE: Some bits of code in this code block come from https://github.com/dgraph-io/badger, which is licensed + // under Apache 2.0; See https://github.com/dgraph-io/badger/blob/master/LICENSE + + vf, err := os.Open(cctx.Path("vlog")) + if err != nil { + return xerrors.Errorf("open vlog file: %w", err) + } + + if _, err := vf.Seek(20, io.SeekStart); err != nil { + return xerrors.Errorf("seek past vlog start: %w", err) + } + + reader := bufio.NewReader(vf) + read := &safeRead{ + k: make([]byte, 10), + v: make([]byte, 10), + recordOffset: 20, + } + + loop: + for { + e, err := read.Entry(reader) + switch { + case err == io.EOF: + break loop + case err == io.ErrUnexpectedEOF || err == errTruncate: + break loop + case err != nil: + return xerrors.Errorf("entry read error: %w", err) + case e == nil: + continue + } + + if e.meta&0x40 > 0 { + e.Key = e.Key[:len(e.Key)-8] + } else if e.meta > 0 { + if e.meta&0x3f > 0 { + log.Infof("unk meta m:%x; k:%x, v:%60x", e.meta, e.Key, e.Value) + } + continue + } + + { + if plen > 0 && !strings.HasPrefix(string(e.Key), pref) { + log.Infow("no blocks prefix", "key", string(e.Key)) + continue + } + + h, err := base32.RawStdEncoding.DecodeString(string(e.Key[plen:])) + if err != nil { + return xerrors.Errorf("decode b32 ds key %x: %w", e.Key, err) + } + + c := cid.NewCidV1(cid.Raw, h) + + b, err := block.NewBlockWithCid(e.Value, c) + if err != nil { + return xerrors.Errorf("readblk: %w", err) + } + + err = carb.consume(c, b) + switch err { + case nil: + case fullCar: + root, err := carb.finalize() + if err != nil { + return xerrors.Errorf("carb finalize: %w", err) + } + + if err := carb.writeCar(ctx, fmt.Sprintf("%s%d.car", cctx.Path("car"), cars), root); err != nil { + return xerrors.Errorf("writeCar: %w", err) + } + + cars++ + + carb = &rawCarb{ + max: maxSz, + blocks: map[cid.Cid]block.Block{}, + } + + default: + return xerrors.Errorf("carb consume: %w", err) + } + } + } + + if err := vf.Close(); err != nil { + return err + } + } + + root, err := carb.finalize() + if err != nil { + return xerrors.Errorf("carb finalize: %w", err) + } + + if err := carb.writeCar(ctx, fmt.Sprintf("%s%d.car", cctx.Path("car"), cars), root); err != nil { + return xerrors.Errorf("writeCar: %w", err) + } + + return nil + + }, +} + +// NOTE: Code below comes (with slight modifications) from https://github.com/dgraph-io/badger/blob/master/value.go +// Apache 2.0; See https://github.com/dgraph-io/badger/blob/master/LICENSE + +var errTruncate = errors.New("do truncate") + +// hashReader implements io.Reader, io.ByteReader interfaces. It also keeps track of the number +// bytes read. The hashReader writes to h (hash) what it reads from r. +type hashReader struct { + r io.Reader + h hash.Hash32 + bytesRead int // Number of bytes read. +} + +func newHashReader(r io.Reader) *hashReader { + hash := crc32.New(y.CastagnoliCrcTable) + return &hashReader{ + r: r, + h: hash, + } +} + +// Read reads len(p) bytes from the reader. Returns the number of bytes read, error on failure. +func (t *hashReader) Read(p []byte) (int, error) { + n, err := t.r.Read(p) + if err != nil { + return n, err + } + t.bytesRead += n + return t.h.Write(p[:n]) +} + +// ReadByte reads exactly one byte from the reader. Returns error on failure. +func (t *hashReader) ReadByte() (byte, error) { + b := make([]byte, 1) + _, err := t.Read(b) + return b[0], err +} + +// Sum32 returns the sum32 of the underlying hash. +func (t *hashReader) Sum32() uint32 { + return t.h.Sum32() +} + +type safeRead struct { + k []byte + v []byte + + recordOffset uint32 +} + +// Entry provides Key, Value, UserMeta and ExpiresAt. This struct can be used by +// the user to set data. +type Entry struct { + Key []byte + Value []byte + UserMeta byte + ExpiresAt uint64 // time.Unix + meta byte + version uint64 + + // Fields maintained internally. + offset uint32 + skipVlog bool + hlen int // Length of the header. +} + +// Entry reads an entry from the provided reader. It also validates the checksum for every entry +// read. Returns error on failure. +func (r *safeRead) Entry(reader io.Reader) (*Entry, error) { + tee := newHashReader(reader) + var h header + hlen, err := h.DecodeFrom(tee) + if err != nil { + return nil, err + } + if h.klen > uint32(1<<16) { // Key length must be below uint16. + return nil, errTruncate + } + kl := int(h.klen) + if cap(r.k) < kl { + r.k = make([]byte, 2*kl) + } + vl := int(h.vlen) + if cap(r.v) < vl { + r.v = make([]byte, 2*vl) + } + + e := &Entry{} + e.offset = r.recordOffset + e.hlen = hlen + buf := make([]byte, h.klen+h.vlen) + if _, err := io.ReadFull(tee, buf[:]); err != nil { + if err == io.EOF { + err = errTruncate + } + return nil, err + } + e.Key = buf[:h.klen] + e.Value = buf[h.klen:] + var crcBuf [crc32.Size]byte + if _, err := io.ReadFull(reader, crcBuf[:]); err != nil { + if err == io.EOF { + err = errTruncate + } + return nil, err + } + crc := y.BytesToU32(crcBuf[:]) + if crc != tee.Sum32() { + return nil, errTruncate + } + e.meta = h.meta + e.UserMeta = h.userMeta + e.ExpiresAt = h.expiresAt + return e, nil +} + +// header is used in value log as a header before Entry. +type header struct { + klen uint32 + vlen uint32 + expiresAt uint64 + meta byte + userMeta byte +} + +const ( + // Maximum possible size of the header. The maximum size of header struct will be 18 but the + // maximum size of varint encoded header will be 21. + maxHeaderSize = 21 +) + +// Encode encodes the header into []byte. The provided []byte should be atleast 5 bytes. The +// function will panic if out []byte isn't large enough to hold all the values. +// The encoded header looks like +// +------+----------+------------+--------------+-----------+ +// | Meta | UserMeta | Key Length | Value Length | ExpiresAt | +// +------+----------+------------+--------------+-----------+ +func (h header) Encode(out []byte) int { + out[0], out[1] = h.meta, h.userMeta + index := 2 + index += binary.PutUvarint(out[index:], uint64(h.klen)) + index += binary.PutUvarint(out[index:], uint64(h.vlen)) + index += binary.PutUvarint(out[index:], h.expiresAt) + return index +} + +// Decode decodes the given header from the provided byte slice. +// Returns the number of bytes read. +func (h *header) Decode(buf []byte) int { + h.meta, h.userMeta = buf[0], buf[1] + index := 2 + klen, count := binary.Uvarint(buf[index:]) + h.klen = uint32(klen) + index += count + vlen, count := binary.Uvarint(buf[index:]) + h.vlen = uint32(vlen) + index += count + h.expiresAt, count = binary.Uvarint(buf[index:]) + return index + count +} + +// DecodeFrom reads the header from the hashReader. +// Returns the number of bytes read. +func (h *header) DecodeFrom(reader *hashReader) (int, error) { + var err error + h.meta, err = reader.ReadByte() + if err != nil { + return 0, err + } + h.userMeta, err = reader.ReadByte() + if err != nil { + return 0, err + } + klen, err := binary.ReadUvarint(reader) + if err != nil { + return 0, err + } + h.klen = uint32(klen) + vlen, err := binary.ReadUvarint(reader) + if err != nil { + return 0, err + } + h.vlen = uint32(vlen) + h.expiresAt, err = binary.ReadUvarint(reader) + if err != nil { + return 0, err + } + return reader.bytesRead, nil +} diff --git a/cmd/lotus-shed/datastore.go b/cmd/lotus-shed/datastore.go index ff740a7729d..698e63324b4 100644 --- a/cmd/lotus-shed/datastore.go +++ b/cmd/lotus-shed/datastore.go @@ -32,6 +32,7 @@ var datastoreCmd = &cli.Command{ datastoreListCmd, datastoreGetCmd, datastoreRewriteCmd, + datastoreVlog2CarCmd, }, } diff --git a/cmd/lotus-shed/export.go b/cmd/lotus-shed/export.go index 3851e492250..9583c0ac5ee 100644 --- a/cmd/lotus-shed/export.go +++ b/cmd/lotus-shed/export.go @@ -1,19 +1,38 @@ package main import ( + "bytes" "context" + "errors" "fmt" "io" "os" + "path/filepath" + "runtime" + "strings" + "sync" + "github.com/dgraph-io/badger/v2" + "github.com/dgraph-io/badger/v2/pb" + "github.com/dustin/go-humanize" + "github.com/filecoin-project/go-state-types/abi" + block "github.com/ipfs/go-block-format" + "github.com/ipfs/go-blockservice" + "github.com/ipfs/go-cid" + offline "github.com/ipfs/go-ipfs-exchange-offline" + "github.com/ipfs/go-merkledag" + "github.com/ipld/go-car" + "github.com/multiformats/go-base32" + mh "github.com/multiformats/go-multihash" "github.com/urfave/cli/v2" + "go.uber.org/zap" "golang.org/x/xerrors" - "github.com/filecoin-project/go-state-types/abi" - + "github.com/filecoin-project/lotus/blockstore" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" lcli "github.com/filecoin-project/lotus/cli" + "github.com/filecoin-project/lotus/cmd/lotus-shed/shedgen" "github.com/filecoin-project/lotus/node/repo" ) @@ -39,6 +58,9 @@ var exportChainCmd = &cli.Command{ Name: "skip-old-msgs", }, }, + Subcommands: []*cli.Command{ + exportRawCmd, + }, Action: func(cctx *cli.Context) error { if !cctx.Args().Present() { return lcli.ShowHelp(cctx, fmt.Errorf("must specify file name to write export to")) @@ -130,3 +152,351 @@ var exportChainCmd = &cli.Command{ return nil }, } + +var exportRawCmd = &cli.Command{ + Name: "raw", + Description: "Export raw blocks from repo (requires node to be offline)", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "repo", + Value: "~/.lotus", + }, + &cli.StringFlag{ + Name: "car-size", + Value: "50M", + }, + }, + Action: func(cctx *cli.Context) error { + if !cctx.Args().Present() { + return lcli.ShowHelp(cctx, fmt.Errorf("must specify file name to write export to")) + } + + ctx := context.TODO() + + r, err := repo.NewFS(cctx.String("repo")) + if err != nil { + return xerrors.Errorf("opening fs repo: %w", err) + } + + exists, err := r.Exists() + if err != nil { + return err + } + if !exists { + return xerrors.Errorf("lotus repo doesn't exist") + } + + lr, err := r.LockRO(repo.FullNode) + if err != nil { + return err + } + defer lr.Close() //nolint:errcheck + + out := cctx.Args().First() + err = os.Mkdir(out, 0755) + if err != nil { + return xerrors.Errorf("creating output dir: %w", err) + } + + maxSz, err := humanize.ParseBytes(cctx.String("car-size")) + if err != nil { + return xerrors.Errorf("parse --car-size: %w", err) + } + + cars := 0 + + carb := &rawCarb{ + max: maxSz, + blocks: map[cid.Cid]block.Block{}, + } + + { + consume := func(c cid.Cid, b block.Block) error { + err = carb.consume(c, b) + switch err { + case nil: + case fullCar: + root, err := carb.finalize() + if err != nil { + return xerrors.Errorf("carb finalize: %w", err) + } + + if err := carb.writeCar(ctx, filepath.Join(out, fmt.Sprintf("chain%d.car", cars)), root); err != nil { + return xerrors.Errorf("writeCar: %w", err) + } + + cars++ + + if cars > 10 { + return xerrors.Errorf("enough") + } + + carb = &rawCarb{ + max: maxSz, + blocks: map[cid.Cid]block.Block{}, + } + + log.Infow("gc") + go runtime.GC() + + default: + return xerrors.Errorf("carb consume: %w", err) + } + return nil + } + + { + path := filepath.Join(lr.Path(), "datastore", "chain") + opts, err := repo.BadgerBlockstoreOptions(repo.UniversalBlockstore, path, false) + if err != nil { + return err + } + + opts.Logger = &badgerLog{ + SugaredLogger: log.Desugar().WithOptions(zap.AddCallerSkip(1)).Sugar(), + skip2: log.Desugar().WithOptions(zap.AddCallerSkip(2)).Sugar(), + } + + log.Infow("open db") + + db, err := badger.Open(opts.Options) + if err != nil { + return fmt.Errorf("failed to open badger blockstore: %w", err) + } + defer db.Close() + + log.Infow("new stream") + + var wlk sync.Mutex + + str := db.NewStream() + str.NumGo = 16 + str.LogPrefix = "bstream" + str.Send = func(list *pb.KVList) (err error) { + defer func() { + if err != nil { + log.Errorw("send error", "err", err) + } + }() + + for _, kv := range list.Kv { + if kv.Key == nil || kv.Value == nil { + continue + } + if !strings.HasPrefix(string(kv.Key), "/blocks/") { + log.Infow("no blocks prefix", "key", string(kv.Key)) + continue + } + + h, err := base32.RawStdEncoding.DecodeString(string(kv.Key[len("/blocks/"):])) + if err != nil { + return xerrors.Errorf("decode b32 ds key %x: %w", kv.Key, err) + } + + c := cid.NewCidV1(cid.Raw, h) + + b, err := block.NewBlockWithCid(kv.Value, c) + if err != nil { + return xerrors.Errorf("readblk: %w", err) + } + + wlk.Lock() + err = consume(c, b) + wlk.Unlock() + if err != nil { + return xerrors.Errorf("consume stream block: %w", err) + } + } + + return nil + } + + if err := str.Orchestrate(ctx); err != nil { + return xerrors.Errorf("orchestrate stream: %w", err) + } + } + } + + log.Infow("write last") + + root, err := carb.finalize() + if err != nil { + return xerrors.Errorf("carb finalize: %w", err) + } + + if err := carb.writeCar(ctx, filepath.Join(out, fmt.Sprintf("chain%d.car", cars)), root); err != nil { + return xerrors.Errorf("writeCar: %w", err) + } + + return nil + }, +} + +var fullCar = errors.New("full") + +const maxlinks = 16 + +type rawCarb struct { + blockstore.Blockstore + + max, cur uint64 + + nodes []*shedgen.CarbNode + + blocks map[cid.Cid]block.Block +} + +func (rc *rawCarb) Has(ctx context.Context, c cid.Cid) (bool, error) { + _, has := rc.blocks[c] + return has, nil +} + +func (rc *rawCarb) Get(ctx context.Context, c cid.Cid) (block.Block, error) { + b, has := rc.blocks[c] + if !has { + return nil, blockstore.ErrNotFound + } + return b, nil +} + +func (rc *rawCarb) GetSize(ctx context.Context, c cid.Cid) (int, error) { + b, has := rc.blocks[c] + if !has { + return 0, blockstore.ErrNotFound + } + return len(b.RawData()), nil +} + +func (rc *rawCarb) checkNodes(maxl int) error { + if len(rc.nodes) == 0 { + log.Infow("add level", "l", 0) + rc.nodes = append(rc.nodes, new(shedgen.CarbNode)) + } + for i := 0; i < len(rc.nodes); i++ { + if len(rc.nodes[i].Sub) <= maxl { + break + } + if len(rc.nodes) <= i+1 { + log.Infow("add level", "l", i+1) + rc.nodes = append(rc.nodes, new(shedgen.CarbNode)) + } + + var bb bytes.Buffer + if err := rc.nodes[i].MarshalCBOR(&bb); err != nil { + return err + } + c, err := cid.Prefix{ + Version: 1, + Codec: cid.DagCBOR, + MhType: mh.SHA2_256, + MhLength: -1, + }.Sum(bb.Bytes()) + if err != nil { + return xerrors.Errorf("gen cid: %w", err) + } + + b, err := block.NewBlockWithCid(bb.Bytes(), c) + if err != nil { + return xerrors.Errorf("new block: %w", err) + } + + if i > 1 { + log.Infow("compact", "from", i, "to", i+1, "sub", c.String()) + } + + rc.nodes[i+1].Sub = append(rc.nodes[i+1].Sub, c) + rc.blocks[c] = b + rc.nodes[i] = new(shedgen.CarbNode) + rc.cur += uint64(bb.Len()) + } + + return nil +} + +func (rc *rawCarb) consume(c cid.Cid, b block.Block) error { + if err := rc.checkNodes(maxlinks); err != nil { + return err + } + if rc.cur+uint64(len(b.RawData())) > rc.max { + return fullCar + } + + rc.cur += uint64(len(b.RawData())) + + b, err := block.NewBlockWithCid(b.RawData(), c) + if err != nil { + return xerrors.Errorf("create raw block: %w", err) + } + + rc.blocks[c] = b + rc.nodes[0].Sub = append(rc.nodes[0].Sub, c) + + return nil +} + +func (rc *rawCarb) finalize() (cid.Cid, error) { + if len(rc.nodes) == 0 { + rc.nodes = append(rc.nodes, new(shedgen.CarbNode)) + } + + for i := 0; i < len(rc.nodes); i++ { + var bb bytes.Buffer + if err := rc.nodes[i].MarshalCBOR(&bb); err != nil { + return cid.Undef, err + } + c, err := cid.Prefix{ + Version: 1, + Codec: cid.DagCBOR, + MhType: mh.SHA2_256, + MhLength: -1, + }.Sum(bb.Bytes()) + if err != nil { + return cid.Undef, xerrors.Errorf("gen cid: %w", err) + } + + b, err := block.NewBlockWithCid(bb.Bytes(), c) + if err != nil { + return cid.Undef, xerrors.Errorf("new block: %w", err) + } + + log.Infow("fin", "level", i, "cid", c.String()) + + rc.blocks[c] = b + rc.nodes[i] = new(shedgen.CarbNode) + rc.cur += uint64(bb.Len()) + + if len(rc.nodes[i].Sub) <= 1 && i == len(rc.nodes)-1 { + return c, err + } + if len(rc.nodes) <= i+1 { + rc.nodes = append(rc.nodes, new(shedgen.CarbNode)) + } + rc.nodes[i+1].Sub = append(rc.nodes[i+1].Sub, c) + } + return cid.Undef, xerrors.Errorf("failed to finalize") +} + +func (rc *rawCarb) writeCar(ctx context.Context, path string, root cid.Cid) error { + f, err := os.Create(path) + if err != nil { + return xerrors.Errorf("create out car: %w", err) + } + + bs := rc + ds := merkledag.NewDAGService(blockservice.New(bs, offline.Exchange(bs))) + + log.Infow("write car", "path", path, "root", root.String(), "blocks", len(rc.blocks)) + + return car.WriteCar(ctx, ds, []cid.Cid{root}, f) +} + +var _ blockstore.Blockstore = &rawCarb{} + +type badgerLog struct { + *zap.SugaredLogger + skip2 *zap.SugaredLogger +} + +func (b *badgerLog) Warningf(format string, args ...interface{}) { + b.skip2.Warnf(format, args...) +} diff --git a/cmd/lotus-shed/shedgen/cbor_gen.go b/cmd/lotus-shed/shedgen/cbor_gen.go new file mode 100644 index 00000000000..37ed9553997 --- /dev/null +++ b/cmd/lotus-shed/shedgen/cbor_gen.go @@ -0,0 +1,128 @@ +// Code generated by github.com/whyrusleeping/cbor-gen. DO NOT EDIT. + +package shedgen + +import ( + "fmt" + "io" + "math" + "sort" + + cid "github.com/ipfs/go-cid" + cbg "github.com/whyrusleeping/cbor-gen" + xerrors "golang.org/x/xerrors" +) + +var _ = xerrors.Errorf +var _ = cid.Undef +var _ = math.E +var _ = sort.Sort + +func (t *CarbNode) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write([]byte{161}); err != nil { + return err + } + + scratch := make([]byte, 9) + + // t.Sub ([]cid.Cid) (slice) + if len("Sub") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"Sub\" was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("Sub"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("Sub")); err != nil { + return err + } + + if len(t.Sub) > cbg.MaxLength { + return xerrors.Errorf("Slice value in field t.Sub was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajArray, uint64(len(t.Sub))); err != nil { + return err + } + for _, v := range t.Sub { + if err := cbg.WriteCidBuf(scratch, w, v); err != nil { + return xerrors.Errorf("failed writing cid field t.Sub: %w", err) + } + } + return nil +} + +func (t *CarbNode) UnmarshalCBOR(r io.Reader) error { + *t = CarbNode{} + + br := cbg.GetPeeker(r) + scratch := make([]byte, 8) + + maj, extra, err := cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajMap { + return fmt.Errorf("cbor input should be of type map") + } + + if extra > cbg.MaxLength { + return fmt.Errorf("CarbNode: map struct too large (%d)", extra) + } + + var name string + n := extra + + for i := uint64(0); i < n; i++ { + + { + sval, err := cbg.ReadStringBuf(br, scratch) + if err != nil { + return err + } + + name = string(sval) + } + + switch name { + // t.Sub ([]cid.Cid) (slice) + case "Sub": + + maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + + if extra > cbg.MaxLength { + return fmt.Errorf("t.Sub: array too large (%d)", extra) + } + + if maj != cbg.MajArray { + return fmt.Errorf("expected cbor array") + } + + if extra > 0 { + t.Sub = make([]cid.Cid, extra) + } + + for i := 0; i < int(extra); i++ { + + c, err := cbg.ReadCid(br) + if err != nil { + return xerrors.Errorf("reading cid field t.Sub failed: %w", err) + } + t.Sub[i] = c + } + + default: + // Field doesn't exist on this type, so ignore it + cbg.ScanForLinks(r, func(cid.Cid) {}) + } + } + + return nil +} diff --git a/cmd/lotus-shed/shedgen/rawexport.go b/cmd/lotus-shed/shedgen/rawexport.go new file mode 100644 index 00000000000..ca430c5e6ae --- /dev/null +++ b/cmd/lotus-shed/shedgen/rawexport.go @@ -0,0 +1,7 @@ +package shedgen + +import "github.com/ipfs/go-cid" + +type CarbNode struct { + Sub []cid.Cid +} diff --git a/gen/main.go b/gen/main.go index 0018b241d62..f7b96c53798 100644 --- a/gen/main.go +++ b/gen/main.go @@ -10,6 +10,7 @@ import ( "github.com/filecoin-project/lotus/chain/exchange" "github.com/filecoin-project/lotus/chain/market" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/cmd/lotus-shed/shedgen" sectorstorage "github.com/filecoin-project/lotus/extern/sector-storage" "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "github.com/filecoin-project/lotus/node/hello" @@ -106,4 +107,11 @@ func main() { fmt.Println(err) os.Exit(1) } + err = gen.WriteMapEncodersToFile("./cmd/lotus-shed/shedgen/cbor_gen.go", "shedgen", + shedgen.CarbNode{}, + ) + if err != nil { + fmt.Println(err) + os.Exit(1) + } } From ffabb015ef8b2a79504d2138ecb7f337aae7efa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 9 Mar 2022 10:26:02 +0100 Subject: [PATCH 289/385] shed: fix lint --- cmd/lotus-shed/datastore-vlog.go | 14 +++----------- cmd/lotus-shed/export.go | 8 ++++---- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/cmd/lotus-shed/datastore-vlog.go b/cmd/lotus-shed/datastore-vlog.go index 4a848b24fa6..7f0c708a597 100644 --- a/cmd/lotus-shed/datastore-vlog.go +++ b/cmd/lotus-shed/datastore-vlog.go @@ -117,7 +117,7 @@ var datastoreVlog2CarCmd = &cli.Command{ err = carb.consume(c, b) switch err { case nil: - case fullCar: + case errFullCar: root, err := carb.finalize() if err != nil { return xerrors.Errorf("carb finalize: %w", err) @@ -217,12 +217,10 @@ type Entry struct { UserMeta byte ExpiresAt uint64 // time.Unix meta byte - version uint64 // Fields maintained internally. - offset uint32 - skipVlog bool - hlen int // Length of the header. + offset uint32 + hlen int // Length of the header. } // Entry reads an entry from the provided reader. It also validates the checksum for every entry @@ -284,12 +282,6 @@ type header struct { userMeta byte } -const ( - // Maximum possible size of the header. The maximum size of header struct will be 18 but the - // maximum size of varint encoded header will be 21. - maxHeaderSize = 21 -) - // Encode encodes the header into []byte. The provided []byte should be atleast 5 bytes. The // function will panic if out []byte isn't large enough to hold all the values. // The encoded header looks like diff --git a/cmd/lotus-shed/export.go b/cmd/lotus-shed/export.go index 9583c0ac5ee..fec4d575a7b 100644 --- a/cmd/lotus-shed/export.go +++ b/cmd/lotus-shed/export.go @@ -215,7 +215,7 @@ var exportRawCmd = &cli.Command{ err = carb.consume(c, b) switch err { case nil: - case fullCar: + case errFullCar: root, err := carb.finalize() if err != nil { return xerrors.Errorf("carb finalize: %w", err) @@ -263,7 +263,7 @@ var exportRawCmd = &cli.Command{ if err != nil { return fmt.Errorf("failed to open badger blockstore: %w", err) } - defer db.Close() + defer db.Close() // nolint:errcheck log.Infow("new stream") @@ -332,7 +332,7 @@ var exportRawCmd = &cli.Command{ }, } -var fullCar = errors.New("full") +var errFullCar = errors.New("full") const maxlinks = 16 @@ -418,7 +418,7 @@ func (rc *rawCarb) consume(c cid.Cid, b block.Block) error { return err } if rc.cur+uint64(len(b.RawData())) > rc.max { - return fullCar + return errFullCar } rc.cur += uint64(len(b.RawData())) From 49742f8fdc47e405e01e245edefd7f2f13d815ce Mon Sep 17 00:00:00 2001 From: hannahhoward Date: Wed, 9 Mar 2022 17:53:23 +0000 Subject: [PATCH 290/385] feat(deps): update to graphsync v0.13.0 with 2.0 protocol --- api/docgen/docgen.go | 2 +- api/types.go | 2 +- build/openrpc/miner.json.gz | Bin 13155 -> 13154 bytes documentation/en/api-v0-methods-miner.md | 4 ++-- go.mod | 8 ++++---- go.sum | 18 ++++++++++++------ node/impl/storminer.go | 8 ++++---- 7 files changed, 24 insertions(+), 18 deletions(-) diff --git a/api/docgen/docgen.go b/api/docgen/docgen.go index 1190b0dc406..2579610fe4a 100644 --- a/api/docgen/docgen.go +++ b/api/docgen/docgen.go @@ -122,7 +122,7 @@ func init() { addExample(api.FullAPIVersion1) addExample(api.PCHInbound) addExample(time.Minute) - addExample(graphsync.RequestID(4)) + addExample(graphsync.NewRequestID()) addExample(datatransfer.TransferID(3)) addExample(datatransfer.Ongoing) addExample(storeIDExample) diff --git a/api/types.go b/api/types.go index c688edf4b5f..7cb60bdc290 100644 --- a/api/types.go +++ b/api/types.go @@ -58,7 +58,7 @@ type MessageSendSpec struct { // GraphSyncDataTransfer provides diagnostics on a data transfer happening over graphsync type GraphSyncDataTransfer struct { // GraphSync request id for this transfer - RequestID graphsync.RequestID + RequestID *graphsync.RequestID // Graphsync state for this transfer RequestState string // If a channel ID is present, indicates whether this is the current graphsync request for this channel diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 8475edc774d242279a71b35451b62df7ffe6a875..2ef745e363f046bd79be12f9150368b0af11e933 100644 GIT binary patch delta 9169 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 E0C#yF_W%F@ diff --git a/documentation/en/api-v0-methods-miner.md b/documentation/en/api-v0-methods-miner.md index c7b04f3238c..a941d04c0f4 100644 --- a/documentation/en/api-v0-methods-miner.md +++ b/documentation/en/api-v0-methods-miner.md @@ -939,7 +939,7 @@ Response: { "ReceivingTransfers": [ { - "RequestID": 4, + "RequestID": {}, "RequestState": "string value", "IsCurrentChannelRequest": true, "ChannelID": { @@ -983,7 +983,7 @@ Response: ], "SendingTransfers": [ { - "RequestID": 4, + "RequestID": {}, "RequestState": "string value", "IsCurrentChannelRequest": true, "ChannelID": { diff --git a/go.mod b/go.mod index 060613d1949..33099071519 100644 --- a/go.mod +++ b/go.mod @@ -35,7 +35,7 @@ require ( github.com/filecoin-project/go-cbor-util v0.0.1 github.com/filecoin-project/go-commp-utils v0.1.3 github.com/filecoin-project/go-crypto v0.0.1 - github.com/filecoin-project/go-data-transfer v1.14.0 + github.com/filecoin-project/go-data-transfer v1.15.0 github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 github.com/filecoin-project/go-fil-markets v1.20.1 @@ -82,7 +82,7 @@ require ( github.com/ipfs/go-ds-leveldb v0.5.0 github.com/ipfs/go-ds-measure v0.2.0 github.com/ipfs/go-fs-lock v0.0.7 - github.com/ipfs/go-graphsync v0.12.0 + github.com/ipfs/go-graphsync v0.13.0 github.com/ipfs/go-ipfs-blockstore v1.1.2 github.com/ipfs/go-ipfs-blocksutil v0.0.1 github.com/ipfs/go-ipfs-chunker v0.0.5 @@ -101,12 +101,12 @@ require ( github.com/ipfs/go-metrics-interface v0.0.1 github.com/ipfs/go-metrics-prometheus v0.0.2 github.com/ipfs/go-unixfs v0.3.1 - github.com/ipfs/go-unixfsnode v1.2.0 + github.com/ipfs/go-unixfsnode v1.4.0 github.com/ipfs/interface-go-ipfs-core v0.5.2 github.com/ipld/go-car v0.3.3 github.com/ipld/go-car/v2 v2.1.1 github.com/ipld/go-codec-dagpb v1.3.0 - github.com/ipld/go-ipld-prime v0.14.4 + github.com/ipld/go-ipld-prime v0.16.0 github.com/ipld/go-ipld-selector-text-lite v0.0.1 github.com/jonboulle/clockwork v0.2.2 // indirect github.com/kelseyhightower/envconfig v1.4.0 diff --git a/go.sum b/go.sum index d07b83200fc..a874bda2e85 100644 --- a/go.sum +++ b/go.sum @@ -324,8 +324,9 @@ github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod github.com/filecoin-project/go-crypto v0.0.1 h1:AcvpSGGCgjaY8y1az6AMfKQWreF/pWO2JJGLl6gCq6o= github.com/filecoin-project/go-crypto v0.0.1/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= github.com/filecoin-project/go-dagaggregator-unixfs v0.2.0/go.mod h1:WTuJWgBQY0omnQqa8kRPT9O0Uj5wQOgslVMUuTeHdJ8= -github.com/filecoin-project/go-data-transfer v1.14.0 h1:4pnfJk8FYtqcdAg+QRGzaz57seUC/Tz+HJgPuGB7zdg= github.com/filecoin-project/go-data-transfer v1.14.0/go.mod h1:wNJKhaLLYBJDM3VFvgvYi4iUjPa69pz/1Q5Q4HzX2wE= +github.com/filecoin-project/go-data-transfer v1.15.0 h1:gVH7MxEgoj/qXPz+S6ggFlHlDv1mLlRZuJtTvcq8r1o= +github.com/filecoin-project/go-data-transfer v1.15.0/go.mod h1:RaJIYjh6x6z+FXKNvUULOdUZdN+JutKigfcMMbfykWA= github.com/filecoin-project/go-ds-versioning v0.0.0-20211206185234-508abd7c2aff/go.mod h1:C9/l9PnB1+mwPa26BBVpCjG/XQCB0yj/q5CK2J8X1I4= github.com/filecoin-project/go-ds-versioning v0.1.1 h1:JiyBqaQlwC+UM0WhcBtVEeT3XrX59mQhT8U3p7nu86o= github.com/filecoin-project/go-ds-versioning v0.1.1/go.mod h1:C9/l9PnB1+mwPa26BBVpCjG/XQCB0yj/q5CK2J8X1I4= @@ -410,8 +411,9 @@ github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVB github.com/franela/goblin v0.0.0-20210519012713-85d372ac71e2/go.mod h1:VzmDKDJVZI3aJmnRI9VjAn9nJ8qPPsN1fqzr9dqInIo= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= -github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss= github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= +github.com/frankban/quicktest v1.14.2 h1:SPb1KFFmM+ybpEjPUhCCkZOM5xlovT5UbrMvWnXyBns= +github.com/frankban/quicktest v1.14.2/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= @@ -551,8 +553,9 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -754,8 +757,9 @@ github.com/ipfs/go-fs-lock v0.0.6/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28 github.com/ipfs/go-fs-lock v0.0.7 h1:6BR3dajORFrFTkb5EpCUFIAypsoxpGpDSVUdFwzgL9U= github.com/ipfs/go-fs-lock v0.0.7/go.mod h1:Js8ka+FNYmgQRLrRXzU3CB/+Csr1BwrRilEcvYrHhhc= github.com/ipfs/go-graphsync v0.11.0/go.mod h1:wC+c8vGVjAHthsVIl8LKr37cUra2GOaMYcQNNmMxDqE= -github.com/ipfs/go-graphsync v0.12.0 h1:QCsVHVzb9FTkcm3NEa8GjXnUeGit1L9s08HcSVQ4m/g= github.com/ipfs/go-graphsync v0.12.0/go.mod h1:nASYWYETgsnMbQ3+DirNImOHQ8TY0a5AhAqyOY55tUg= +github.com/ipfs/go-graphsync v0.13.0 h1:8reYjVKxKocJ9jD471xs9XNuegquPrnBFuGZmCqT8zU= +github.com/ipfs/go-graphsync v0.13.0/go.mod h1:oPBU9JGNlyWHyH9lWYmyl19M++5yiXjBnNC4boh5nVU= github.com/ipfs/go-ipfs v0.11.0/go.mod h1:g68Thu2Ho11AWoHsN34P5fSK7iA6OWWRy3T/g8HLixc= github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08= github.com/ipfs/go-ipfs-blockstore v0.1.0/go.mod h1:5aD0AvHPi7mZc6Ci1WCAhiBQu2IsfTduLl+422H6Rqw= @@ -886,8 +890,9 @@ github.com/ipfs/go-unixfs v0.3.1 h1:LrfED0OGfG98ZEegO4/xiprx2O+yS+krCMQSp7zLVv8= github.com/ipfs/go-unixfs v0.3.1/go.mod h1:h4qfQYzghiIc8ZNFKiLMFWOTzrWIAtzYQ59W/pCFf1o= github.com/ipfs/go-unixfsnode v1.1.2/go.mod h1:5dcE2x03pyjHk4JjamXmunTMzz+VUtqvPwZjIEkfV6s= github.com/ipfs/go-unixfsnode v1.1.3/go.mod h1:ZZxUM5wXBC+G0Co9FjrYTOm+UlhZTjxLfRYdWY9veZ4= -github.com/ipfs/go-unixfsnode v1.2.0 h1:tHHBJftsJyHGa8bS62PpkYNqHy/Sug3c/vxxC8NaGQY= github.com/ipfs/go-unixfsnode v1.2.0/go.mod h1:mQEgLjxkV/1mohkC4p7taRRBYPBeXu97SA3YaerT2q0= +github.com/ipfs/go-unixfsnode v1.4.0 h1:9BUxHBXrbNi8mWHc6j+5C580WJqtVw9uoeEKn4tMhwA= +github.com/ipfs/go-unixfsnode v1.4.0/go.mod h1:qc7YFFZ8tABc58p62HnIYbUMwj9chhUuFWmxSokfePo= github.com/ipfs/go-verifcid v0.0.1 h1:m2HI7zIuR5TFyQ1b79Da5N9dnnCP1vcu2QqawmWlK2E= github.com/ipfs/go-verifcid v0.0.1/go.mod h1:5Hrva5KBeIog4A+UpqlaIU+DEstipcJYQQZc0g37pY0= github.com/ipfs/interface-go-ipfs-core v0.4.0/go.mod h1:UJBcU6iNennuI05amq3FQ7g0JHUkibHFAfhfUIy927o= @@ -918,8 +923,9 @@ github.com/ipld/go-ipld-prime v0.14.0/go.mod h1:9ASQLwUFLptCov6lIYc70GRB4V7UTyLD github.com/ipld/go-ipld-prime v0.14.1/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= github.com/ipld/go-ipld-prime v0.14.2/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= github.com/ipld/go-ipld-prime v0.14.3-0.20211207234443-319145880958/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= -github.com/ipld/go-ipld-prime v0.14.4 h1:bqhmume8+nbNsX4/+J6eohktfZHAI8GKrF3rQ0xgOyc= github.com/ipld/go-ipld-prime v0.14.4/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= +github.com/ipld/go-ipld-prime v0.16.0 h1:RS5hhjB/mcpeEPJvfyj0qbOj/QL+/j05heZ0qa97dVo= +github.com/ipld/go-ipld-prime v0.16.0/go.mod h1:axSCuOCBPqrH+gvXr2w9uAOulJqBPhHPT2PjoiiU1qA= github.com/ipld/go-ipld-prime-proto v0.0.0-20191113031812-e32bd156a1e5/go.mod h1:gcvzoEDBjwycpXt3LBE061wT9f46szXGHAmj9uoP6fU= github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20211210234204-ce2a1c70cd73 h1:TsyATB2ZRRQGTwafJdgEUQkmjOExRV0DNokcihZxbnQ= github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20211210234204-ce2a1c70cd73/go.mod h1:2PJ0JgxyB08t0b2WKrcuqI3di0V+5n6RS/LTUJhkoxY= diff --git a/node/impl/storminer.go b/node/impl/storminer.go index c3577d9f550..4c0f889a650 100644 --- a/node/impl/storminer.go +++ b/node/impl/storminer.go @@ -676,18 +676,18 @@ func (tc *transferConverter) convertTransfer(channelID datatransfer.ChannelID, h } var channelIDPtr *datatransfer.ChannelID if !hasChannelID { - diagnostics = append(diagnostics, fmt.Sprintf("No data transfer channel id for GraphSync request ID %d", requestID)) + diagnostics = append(diagnostics, fmt.Sprintf("No data transfer channel id for GraphSync request ID %s", requestID)) } else { channelIDPtr = &channelID if isCurrentChannelRequest && !hasState { diagnostics = append(diagnostics, fmt.Sprintf("No current request state for data transfer channel id %s", channelID)) } else if !isCurrentChannelRequest && hasState { - diagnostics = append(diagnostics, fmt.Sprintf("Graphsync request %d is a previous request on data transfer channel id %s that was restarted, but it is still running", requestID, channelID)) + diagnostics = append(diagnostics, fmt.Sprintf("Graphsync request %s is a previous request on data transfer channel id %s that was restarted, but it is still running", requestID, channelID)) } } diagnostics = append(diagnostics, tc.gsDiagnostics[requestID]...) transfer := &api.GraphSyncDataTransfer{ - RequestID: requestID, + RequestID: &requestID, RequestState: stateString, IsCurrentChannelRequest: isCurrentChannelRequest, ChannelID: channelIDPtr, @@ -717,7 +717,7 @@ func (tc *transferConverter) collectRemainingTransfers() { channelID := channelID cs := api.NewDataTransferChannel(channelState.SelfPeer(), channelState) transfer := &api.GraphSyncDataTransfer{ - RequestID: graphsync.RequestID(-1), + RequestID: nil, RequestState: "graphsync state unknown", IsCurrentChannelRequest: false, ChannelID: &channelID, From a715fb3063117263ccfde577b7ae798708105d69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 9 Mar 2022 23:25:29 +0100 Subject: [PATCH 291/385] feat: Make ClientCalcCommP multithreaded --- node/impl/client/client.go | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/node/impl/client/client.go b/node/impl/client/client.go index 1730b7a7a1b..7ecf6a776b4 100644 --- a/node/impl/client/client.go +++ b/node/impl/client/client.go @@ -47,7 +47,6 @@ import ( "github.com/filecoin-project/go-address" cborutil "github.com/filecoin-project/go-cbor-util" - "github.com/filecoin-project/go-commp-utils/ffiwrapper" "github.com/filecoin-project/go-commp-utils/writer" datatransfer "github.com/filecoin-project/go-data-transfer" @@ -1263,28 +1262,12 @@ func (a *API) ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Addre } func (a *API) ClientCalcCommP(ctx context.Context, inpath string) (*api.CommPRet, error) { - - // Hard-code the sector type to 32GiBV1_1, because: - // - ffiwrapper.GeneratePieceCIDFromFile requires a RegisteredSealProof - // - commP itself is sector-size independent, with rather low probability of that changing - // ( note how the final rust call is identical for every RegSP type ) - // https://github.com/filecoin-project/rust-filecoin-proofs-api/blob/v5.0.0/src/seal.rs#L1040-L1050 - // - // IF/WHEN this changes in the future we will have to be able to calculate - // "old style" commP, and thus will need to introduce a version switch or similar - arbitraryProofType := abi.RegisteredSealProof_StackedDrg64GiBV1_1 - rdr, err := os.Open(inpath) if err != nil { return nil, err } defer rdr.Close() //nolint:errcheck - stat, err := rdr.Stat() - if err != nil { - return nil, err - } - // check that the data is a car file; if it's not, retrieval won't work _, err = car.ReadHeader(bufio.NewReader(rdr)) if err != nil { @@ -1295,16 +1278,20 @@ func (a *API) ClientCalcCommP(ctx context.Context, inpath string) (*api.CommPRet return nil, xerrors.Errorf("seek to start: %w", err) } - pieceReader, pieceSize := padreader.New(rdr, uint64(stat.Size())) - commP, err := ffiwrapper.GeneratePieceCIDFromFile(arbitraryProofType, pieceReader, pieceSize) + w := &writer.Writer{} + _, err = io.CopyBuffer(w, rdr, make([]byte, writer.CommPBuf)) + if err != nil { + return nil, xerrors.Errorf("copy inte commp writer: %w", err) + } + commp, err := w.Sum() if err != nil { return nil, xerrors.Errorf("computing commP failed: %w", err) } return &api.CommPRet{ - Root: commP, - Size: pieceSize, + Root: commp.PieceCID, + Size: commp.PieceSize.Unpadded(), }, nil } From 91ccb7fbda9622760b7e762823c309561d08e51b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 10 Mar 2022 14:28:18 +0100 Subject: [PATCH 292/385] fix: piece provider: Don't log CIDs as binary --- extern/sector-storage/piece_provider.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/sector-storage/piece_provider.go b/extern/sector-storage/piece_provider.go index 4622289e8f4..72e09df0672 100644 --- a/extern/sector-storage/piece_provider.go +++ b/extern/sector-storage/piece_provider.go @@ -166,7 +166,7 @@ func (p *pieceProvider) ReadPiece(ctx context.Context, sector storage.SectorRef, r, err := p.tryReadUnsealedPiece(ctx, unsealed, sector, pieceOffset, size) - log.Debugf("result of first tryReadUnsealedPiece: r=%+v, err=%s", r, err) + log.Debugf("result of first tryReadUnsealedPiece: r=%s, err=%s", r, err) if xerrors.Is(err, storiface.ErrSectorNotFound) { log.Debugf("no unsealed sector file with unsealed piece, sector=%+v, pieceOffset=%d, size=%d", sector, pieceOffset, size) From 4421bf2fa10510cb2d1eb26cb15dc71e2a5ed828 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 10 Mar 2022 11:58:31 +0100 Subject: [PATCH 293/385] feat: config: Persistent subsystem log level config --- documentation/en/default-lotus-config.toml | 6 ++++++ .../en/default-lotus-miner-config.toml | 6 ++++++ lib/lotuslog/config.go | 11 +++++++++++ node/builder.go | 4 ++++ node/config/def.go | 5 +++++ node/config/def_test.go | 18 ++++++++++++++++++ node/config/doc_gen.go | 14 ++++++++++++++ node/config/doc_util.go | 2 +- node/config/load.go | 2 +- node/config/types.go | 15 +++++++++++---- 10 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 lib/lotuslog/config.go diff --git a/documentation/en/default-lotus-config.toml b/documentation/en/default-lotus-config.toml index ad917814b0d..1c9caf3a018 100644 --- a/documentation/en/default-lotus-config.toml +++ b/documentation/en/default-lotus-config.toml @@ -23,6 +23,12 @@ #DisableMetadataLog = false +[Logging] + [Logging.SubsystemLevels] + # env var: LOTUS_LOGGING_SUBSYSTEMLEVELS_EXAMPLE-SUBSYSTEM + #example-subsystem = "INFO" + + [Libp2p] # Binding address for the libp2p host - 0 means random port. # Format: multiaddress; see https://multiformats.io/multiaddr/ diff --git a/documentation/en/default-lotus-miner-config.toml b/documentation/en/default-lotus-miner-config.toml index 00370a9cc9d..a6a36f74253 100644 --- a/documentation/en/default-lotus-miner-config.toml +++ b/documentation/en/default-lotus-miner-config.toml @@ -23,6 +23,12 @@ #DisableMetadataLog = false +[Logging] + [Logging.SubsystemLevels] + # env var: LOTUS_LOGGING_SUBSYSTEMLEVELS_EXAMPLE-SUBSYSTEM + #example-subsystem = "INFO" + + [Libp2p] # Binding address for the libp2p host - 0 means random port. # Format: multiaddress; see https://multiformats.io/multiaddr/ diff --git a/lib/lotuslog/config.go b/lib/lotuslog/config.go new file mode 100644 index 00000000000..bf6ceb63f66 --- /dev/null +++ b/lib/lotuslog/config.go @@ -0,0 +1,11 @@ +package lotuslog + +import logging "github.com/ipfs/go-log/v2" + +func SetLevelsFromConfig(l map[string]string) { + for sys, level := range l { + if err := logging.SetLogLevel(sys, level); err != nil { + continue + } + } +} diff --git a/node/builder.go b/node/builder.go index 81de3890dda..acda5a07a80 100644 --- a/node/builder.go +++ b/node/builder.go @@ -33,6 +33,7 @@ import ( "github.com/filecoin-project/lotus/extern/sector-storage/stores" "github.com/filecoin-project/lotus/journal" "github.com/filecoin-project/lotus/journal/alerting" + "github.com/filecoin-project/lotus/lib/lotuslog" "github.com/filecoin-project/lotus/lib/peermgr" _ "github.com/filecoin-project/lotus/lib/sigs/bls" _ "github.com/filecoin-project/lotus/lib/sigs/secp" @@ -249,6 +250,9 @@ func Base() Option { // Config sets up constructors based on the provided Config func ConfigCommon(cfg *config.Common, enableLibp2pNode bool) Option { + // setup logging early + lotuslog.SetLevelsFromConfig(cfg.Logging.SubsystemLevels) + return Options( func(s *Settings) error { s.Config = true; return nil }, Override(new(dtypes.APIEndpoint), func() (dtypes.APIEndpoint, error) { diff --git a/node/config/def.go b/node/config/def.go index 233eccdd5aa..edc7ffef533 100644 --- a/node/config/def.go +++ b/node/config/def.go @@ -47,6 +47,11 @@ func defCommon() Common { ListenAddress: "/ip4/127.0.0.1/tcp/1234/http", Timeout: Duration(30 * time.Second), }, + Logging: Logging{ + SubsystemLevels: map[string]string{ + "example-subsystem": "INFO", + }, + }, Libp2p: Libp2p{ ListenAddresses: []string{ "/ip4/0.0.0.0/tcp/0", diff --git a/node/config/def_test.go b/node/config/def_test.go index a7a0e77cab1..9601ee95b5e 100644 --- a/node/config/def_test.go +++ b/node/config/def_test.go @@ -32,6 +32,24 @@ func TestDefaultFullNodeRoundtrip(t *testing.T) { require.True(t, reflect.DeepEqual(c, c2)) } +func TestDefaultFullNodeCommentRoundtrip(t *testing.T) { + c := DefaultFullNode() + + var s string + { + c, err := ConfigComment(DefaultFullNode()) + require.NoError(t, err) + s = string(c) + } + + c2, err := FromReader(strings.NewReader(s), DefaultFullNode()) + require.NoError(t, err) + + fmt.Println(s) + + require.True(t, reflect.DeepEqual(c, c2)) +} + func TestDefaultMinerRoundtrip(t *testing.T) { c := DefaultStorageMiner() diff --git a/node/config/doc_gen.go b/node/config/doc_gen.go index ccee363b49d..edb4cf892c3 100644 --- a/node/config/doc_gen.go +++ b/node/config/doc_gen.go @@ -127,6 +127,12 @@ of automatically performing on-chain operations.`, Comment: ``, }, + { + Name: "Logging", + Type: "Logging", + + Comment: ``, + }, { Name: "Libp2p", Type: "Libp2p", @@ -484,6 +490,14 @@ count towards this limit.`, closed by the connection manager.`, }, }, + "Logging": []DocField{ + { + Name: "SubsystemLevels", + Type: "map[string]string", + + Comment: `SubsystemLevels specify per-subsystem log levels`, + }, + }, "MinerAddressConfig": []DocField{ { Name: "PreCommitControl", diff --git a/node/config/doc_util.go b/node/config/doc_util.go index ee70a9cfd9a..b8833323868 100644 --- a/node/config/doc_util.go +++ b/node/config/doc_util.go @@ -16,7 +16,7 @@ func findDoc(root interface{}, section, name string) *DocField { return findDocSect("Common", section, name) } -func findDocSect(root string, section, name string) *DocField { +func findDocSect(root, section, name string) *DocField { path := strings.Split(section, ".") docSection := Doc[root] diff --git a/node/config/load.go b/node/config/load.go index db3914b6b24..a76db7caf7a 100644 --- a/node/config/load.go +++ b/node/config/load.go @@ -69,7 +69,7 @@ func ConfigUpdate(cfgCur, cfgDef interface{}, comment bool) ([]byte, error) { } if comment { - // create a map of default lines so we can comment those out later + // create a map of default lines, so we can comment those out later defLines := strings.Split(defStr, "\n") defaults := map[string]struct{}{} for i := range defLines { diff --git a/node/config/types.go b/node/config/types.go index 55f924f2ae4..8320aea7ebf 100644 --- a/node/config/types.go +++ b/node/config/types.go @@ -13,10 +13,11 @@ import ( // Common is common config between full node and miner type Common struct { - API API - Backup Backup - Libp2p Libp2p - Pubsub Pubsub + API API + Backup Backup + Logging Logging + Libp2p Libp2p + Pubsub Pubsub } // FullNode is a full node config @@ -39,6 +40,12 @@ type Backup struct { DisableMetadataLog bool } +// Logging is the logging system config +type Logging struct { + // SubsystemLevels specify per-subsystem log levels + SubsystemLevels map[string]string +} + // StorageMiner is a miner config type StorageMiner struct { Common From 65e599fb8e3e4008a1307826e283508c60dba947 Mon Sep 17 00:00:00 2001 From: vyzo Date: Thu, 10 Mar 2022 18:20:11 +0200 Subject: [PATCH 294/385] update go-libp2p and go-libp2p-resource-manager - go-libp2p at v0.18.0-rc6, which includes fixes for some severe bugs in mplex - go-libp2p-resource-manager at v0.1.5, which improves debug logging --- go.mod | 4 ++-- go.sum | 17 ++++++++++------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 33099071519..1e87b0292b3 100644 --- a/go.mod +++ b/go.mod @@ -112,7 +112,7 @@ require ( github.com/kelseyhightower/envconfig v1.4.0 github.com/libp2p/go-buffer-pool v0.0.2 github.com/libp2p/go-eventbus v0.2.1 - github.com/libp2p/go-libp2p v0.18.0-rc5 + github.com/libp2p/go-libp2p v0.18.0-rc6 github.com/libp2p/go-libp2p-connmgr v0.3.1 // indirect github.com/libp2p/go-libp2p-core v0.14.0 github.com/libp2p/go-libp2p-discovery v0.6.0 @@ -122,7 +122,7 @@ require ( github.com/libp2p/go-libp2p-pubsub v0.6.1 github.com/libp2p/go-libp2p-quic-transport v0.16.1 github.com/libp2p/go-libp2p-record v0.1.3 - github.com/libp2p/go-libp2p-resource-manager v0.1.4 + github.com/libp2p/go-libp2p-resource-manager v0.1.5 github.com/libp2p/go-libp2p-routing-helpers v0.2.3 github.com/libp2p/go-libp2p-swarm v0.10.2 github.com/libp2p/go-libp2p-tls v0.3.1 diff --git a/go.sum b/go.sum index a874bda2e85..8bbe3340afb 100644 --- a/go.sum +++ b/go.sum @@ -1066,8 +1066,8 @@ github.com/libp2p/go-libp2p v0.16.0/go.mod h1:ump42BsirwAWxKzsCiFnTtN1Yc+DuPu76f github.com/libp2p/go-libp2p v0.17.0/go.mod h1:Fkin50rsGdv5mm5BshBUtPRZknt9esfmYXBOYcwOTgw= github.com/libp2p/go-libp2p v0.18.0-rc1/go.mod h1:RgYlH7IIWHXREimC92bw5Lg1V2R5XmSzuLHb5fTnr+8= github.com/libp2p/go-libp2p v0.18.0-rc3/go.mod h1:WYL+Xw1iuwi6rdfzw5VIEpD+HqzYucHZ6fcUuumbI3M= -github.com/libp2p/go-libp2p v0.18.0-rc5 h1:88wWDHb9nNo0vBNCupLde3OTnFAkugOCNkrDfl3ivK4= -github.com/libp2p/go-libp2p v0.18.0-rc5/go.mod h1:aZPS5l84bDvCvP4jkyEUT/J6YOpUq33Fgqrs3K59mpI= +github.com/libp2p/go-libp2p v0.18.0-rc6 h1:IR6TVPYGo1wDY0tY61gyPQVxK1koOkXh49ejVfAnH7A= +github.com/libp2p/go-libp2p v0.18.0-rc6/go.mod h1:oOUOAlBrm1L0+jxT10h2TMUMTDz6pV3EvmkJ3beDYGQ= github.com/libp2p/go-libp2p-asn-util v0.0.0-20200825225859-85005c6cf052/go.mod h1:nRMRTab+kZuk0LnKZpxhOVH/ndsdr2Nr//Zltc/vwgo= github.com/libp2p/go-libp2p-asn-util v0.1.0 h1:rABPCO77SjdbJ/eJ/ynIo8vWICy1VEnL5JAxJbQLo1E= github.com/libp2p/go-libp2p-asn-util v0.1.0/go.mod h1:wu+AnM9Ii2KgO5jMmS1rz9dvzTdj8BXqsPR9HR0XB7I= @@ -1179,8 +1179,9 @@ github.com/libp2p/go-libp2p-mplex v0.2.3/go.mod h1:CK3p2+9qH9x+7ER/gWWDYJ3QW5ZxW github.com/libp2p/go-libp2p-mplex v0.3.0/go.mod h1:l9QWxRbbb5/hQMECEb908GbS9Sm2UAR2KFZKUJEynEs= github.com/libp2p/go-libp2p-mplex v0.4.0/go.mod h1:yCyWJE2sc6TBTnFpjvLuEJgTSw/u+MamvzILKdX7asw= github.com/libp2p/go-libp2p-mplex v0.4.1/go.mod h1:cmy+3GfqfM1PceHTLL7zQzAAYaryDu6iPSC+CIb094g= -github.com/libp2p/go-libp2p-mplex v0.5.0 h1:vt3k4E4HSND9XH4Z8rUpacPJFSAgLOv6HDvG8W9Ks9E= github.com/libp2p/go-libp2p-mplex v0.5.0/go.mod h1:eLImPJLkj3iG5t5lq68w3Vm5NAQ5BcKwrrb2VmOYb3M= +github.com/libp2p/go-libp2p-mplex v0.6.0 h1:5ubK4/vLE2JkogKlJ2JLeXcSfA6qY6mE2HMJV9ve/Sk= +github.com/libp2p/go-libp2p-mplex v0.6.0/go.mod h1:i3usuPrBbh9FD2fLZjGpotyNkwr42KStYZQY7BeTiu4= github.com/libp2p/go-libp2p-nat v0.0.4/go.mod h1:N9Js/zVtAXqaeT99cXgTV9e75KpnWCvVOiGzlcHmBbY= github.com/libp2p/go-libp2p-nat v0.0.5/go.mod h1:1qubaE5bTZMJE+E/uu2URroMbzdubFz1ChgiN79yKPE= github.com/libp2p/go-libp2p-nat v0.0.6/go.mod h1:iV59LVhB3IkFvS6S6sauVTSOrNEANnINbI/fkaLimiw= @@ -1238,8 +1239,8 @@ github.com/libp2p/go-libp2p-record v0.1.3 h1:R27hoScIhQf/A8XJZ8lYpnqh9LatJ5YbHs2 github.com/libp2p/go-libp2p-record v0.1.3/go.mod h1:yNUff/adKIfPnYQXgp6FQmNu3gLJ6EMg7+/vv2+9pY4= github.com/libp2p/go-libp2p-resource-manager v0.1.0/go.mod h1:wJPNjeE4XQlxeidwqVY5G6DLOKqFK33u2n8blpl0I6Y= github.com/libp2p/go-libp2p-resource-manager v0.1.3/go.mod h1:wJPNjeE4XQlxeidwqVY5G6DLOKqFK33u2n8blpl0I6Y= -github.com/libp2p/go-libp2p-resource-manager v0.1.4 h1:RcxMD0pytOUimx3BqTVs6IqItb3H5Qg44SD7XyT68lw= -github.com/libp2p/go-libp2p-resource-manager v0.1.4/go.mod h1:wJPNjeE4XQlxeidwqVY5G6DLOKqFK33u2n8blpl0I6Y= +github.com/libp2p/go-libp2p-resource-manager v0.1.5 h1:7J6t9KLFS0MxXDTfqA6rwfVCZl/yLQnXW5LpZjHAANI= +github.com/libp2p/go-libp2p-resource-manager v0.1.5/go.mod h1:wJPNjeE4XQlxeidwqVY5G6DLOKqFK33u2n8blpl0I6Y= github.com/libp2p/go-libp2p-routing v0.0.1/go.mod h1:N51q3yTr4Zdr7V8Jt2JIktVU+3xBBylx1MZeVA6t1Ys= github.com/libp2p/go-libp2p-routing v0.1.0/go.mod h1:zfLhI1RI8RLEzmEaaPwzonRvXeeSHddONWkcTcB54nE= github.com/libp2p/go-libp2p-routing-helpers v0.2.3 h1:xY61alxJ6PurSi+MXbywZpelvuU4U4p/gPTxjqCqTzY= @@ -1278,8 +1279,9 @@ github.com/libp2p/go-libp2p-testing v0.4.0/go.mod h1:Q+PFXYoiYFN5CAEG2w3gLPEzotl github.com/libp2p/go-libp2p-testing v0.4.2/go.mod h1:Q+PFXYoiYFN5CAEG2w3gLPEzotlKsNSbKQ/lImlOWF0= github.com/libp2p/go-libp2p-testing v0.5.0/go.mod h1:QBk8fqIL1XNcno/l3/hhaIEn4aLRijpYOR+zVjjlh+A= github.com/libp2p/go-libp2p-testing v0.6.0/go.mod h1:QBk8fqIL1XNcno/l3/hhaIEn4aLRijpYOR+zVjjlh+A= -github.com/libp2p/go-libp2p-testing v0.7.0 h1:9bfyhNINizxuLrKsenzGaZalXRXIaAEmx1BP/PzF1gM= github.com/libp2p/go-libp2p-testing v0.7.0/go.mod h1:OLbdn9DbgdMwv00v+tlp1l3oe2Cl+FAjoWIA2pa0X6E= +github.com/libp2p/go-libp2p-testing v0.8.0 h1:/te8SOIyj5sGH5Jr1Uoo+qYB00aK8O4+yHGzLgfE3kc= +github.com/libp2p/go-libp2p-testing v0.8.0/go.mod h1:gRdsNxQSxAZowTgcLY7CC33xPmleZzoBpqSYbWenqPc= github.com/libp2p/go-libp2p-tls v0.1.3/go.mod h1:wZfuewxOndz5RTnCAxFliGjvYSDA40sKitV4c50uI1M= github.com/libp2p/go-libp2p-tls v0.3.0/go.mod h1:fwF5X6PWGxm6IDRwF3V8AVCCj/hOd5oFlg+wo2FxJDY= github.com/libp2p/go-libp2p-tls v0.3.1 h1:lsE2zYte+rZCEOHF72J1Fg3XK3dGQyKvI6i5ehJfEp0= @@ -1331,8 +1333,9 @@ github.com/libp2p/go-mplex v0.1.1/go.mod h1:Xgz2RDCi3co0LeZfgjm4OgUF15+sVR8SRcu3 github.com/libp2p/go-mplex v0.1.2/go.mod h1:Xgz2RDCi3co0LeZfgjm4OgUF15+sVR8SRcu3SFXI1lk= github.com/libp2p/go-mplex v0.2.0/go.mod h1:0Oy/A9PQlwBytDRp4wSkFnzHYDKcpLot35JQ6msjvYQ= github.com/libp2p/go-mplex v0.3.0/go.mod h1:0Oy/A9PQlwBytDRp4wSkFnzHYDKcpLot35JQ6msjvYQ= -github.com/libp2p/go-mplex v0.4.0 h1:Ukkez9/4EOX5rTw4sHefNJp10dksftAA05ZgyjplUbM= github.com/libp2p/go-mplex v0.4.0/go.mod h1:y26Lx+wNVtMYMaPu300Cbot5LkEZ4tJaNYeHeT9dh6E= +github.com/libp2p/go-mplex v0.6.0 h1:5kKp029zrsLVJT5q6ASt4LwuZFxj3B13wXXaGmFrWg0= +github.com/libp2p/go-mplex v0.6.0/go.mod h1:y26Lx+wNVtMYMaPu300Cbot5LkEZ4tJaNYeHeT9dh6E= github.com/libp2p/go-msgio v0.0.2/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= github.com/libp2p/go-msgio v0.0.3/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= From 231893a794bbf64d15d5f8af100767defe8fb5db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 10 Mar 2022 19:31:36 +0100 Subject: [PATCH 295/385] feat: shed: ItestD --- cmd/lotus-shed/itestd.go | 104 +++++++++++++++++++++++++++++++++++++++ cmd/lotus-shed/main.go | 1 + itests/kit/itestd.go | 36 ++++++++++++++ itests/kit/rpc.go | 2 + 4 files changed, 143 insertions(+) create mode 100644 cmd/lotus-shed/itestd.go create mode 100644 itests/kit/itestd.go diff --git a/cmd/lotus-shed/itestd.go b/cmd/lotus-shed/itestd.go new file mode 100644 index 00000000000..3ac542d2728 --- /dev/null +++ b/cmd/lotus-shed/itestd.go @@ -0,0 +1,104 @@ +package main + +import ( + "bufio" + "encoding/json" + "fmt" + "net" + "net/http" + "net/http/httptest" + "os" + "os/exec" + + "github.com/chzyer/readline" + "github.com/urfave/cli/v2" + "golang.org/x/xerrors" + + "github.com/filecoin-project/lotus/itests/kit" +) + +var itestdCmd = &cli.Command{ + Name: "itestd", + Description: "Integration test debug env", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "listen", + Value: "127.0.0.1:5674", + }, + }, + Action: func(cctx *cli.Context) error { + var nodes []kit.ItestdNotif + + m := http.NewServeMux() + m.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + var notif kit.ItestdNotif + if err := json.NewDecoder(r.Body).Decode(¬if); err != nil { + fmt.Printf("!! Decode itest notif: %s\n", err) + return + } + + fmt.Printf("%d @%s '%s=%s'\n", len(nodes), notif.TestName, notif.NodeType, notif.Api) + nodes = append(nodes, notif) + }) + l, err := net.Listen("tcp", cctx.String("listen")) + if err != nil { + return xerrors.Errorf("net listen: %w", err) + } + s := &httptest.Server{ + Listener: l, + Config: &http.Server{Handler: m}, + } + s.Start() + fmt.Printf("ITest env:\n\nLOTUS_ITESTD=%s\n\nSay 'sh' to spawn a shell connected to test nodes\n--- waiting for clients\n", s.URL) + + cs := readline.NewCancelableStdin(os.Stdin) + go func() { + <-cctx.Done() + cs.Close() // nolint:errcheck + }() + + rl := bufio.NewReader(cs) + + for { + cmd, _, err := rl.ReadLine() + if err != nil { + return xerrors.Errorf("readline: %w", err) + } + + switch string(cmd) { + case "sh": + shell := "/bin/sh" + if os.Getenv("SHELL") != "" { + shell = os.Getenv("SHELL") + } + + p := exec.Command(shell, "-i") + p.Env = append(p.Env, os.Environ()...) + lastNodes := map[string]string{} + for _, node := range nodes { + lastNodes[node.NodeType] = node.Api + } + if _, found := lastNodes["MARKETS_API_INFO"]; !found { + lastNodes["MARKETS_API_INFO"] = lastNodes["MINER_API_INFO"] + } + for typ, api := range lastNodes { + p.Env = append(p.Env, fmt.Sprintf("%s=%s", typ, api)) + } + + p.Stdout = os.Stdout + p.Stderr = os.Stderr + p.Stdin = os.Stdin + if err := p.Start(); err != nil { + return xerrors.Errorf("start shell: %w", err) + } + if err := p.Wait(); err != nil { + fmt.Printf("wait for shell: %s\n", err) + } + fmt.Println("\n--- shell quit") + + default: + fmt.Println("!! Unknown command") + } + } + }, +} diff --git a/cmd/lotus-shed/main.go b/cmd/lotus-shed/main.go index 45fd24e18a6..c1facfe7b94 100644 --- a/cmd/lotus-shed/main.go +++ b/cmd/lotus-shed/main.go @@ -69,6 +69,7 @@ func main() { terminationsCmd, migrationsCmd, diffCmd, + itestdCmd, } app := &cli.App{ diff --git a/itests/kit/itestd.go b/itests/kit/itestd.go new file mode 100644 index 00000000000..5911a20310c --- /dev/null +++ b/itests/kit/itestd.go @@ -0,0 +1,36 @@ +package kit + +import ( + "bytes" + "encoding/json" + "net/http" + "os" +) + +type ItestdNotif struct { + NodeType string // api env var name + TestName string + Api string +} + +func sendItestdNotif(nodeType, testName, apiAddr string) { + td := os.Getenv("LOTUS_ITESTD") + if td == "" { + // not running + return + } + + notif := ItestdNotif{ + NodeType: nodeType, + TestName: testName, + Api: apiAddr, + } + nb, err := json.Marshal(¬if) + if err != nil { + return + } + + if _, err := http.Post(td, "application/json", bytes.NewReader(nb)); err != nil { // nolint:gosec + return + } +} diff --git a/itests/kit/rpc.go b/itests/kit/rpc.go index 61c8a7b2330..1abab8005c6 100644 --- a/itests/kit/rpc.go +++ b/itests/kit/rpc.go @@ -40,6 +40,7 @@ func fullRpc(t *testing.T, f *TestFullNode) *TestFullNode { srv, maddr := CreateRPCServer(t, handler, l) fmt.Printf("FULLNODE RPC ENV FOR CLI DEBUGGING `export FULLNODE_API_INFO=%s`\n", "ws://"+srv.Listener.Addr().String()) + sendItestdNotif("FULLNODE_API_INFO", t.Name(), "ws://"+srv.Listener.Addr().String()) cl, stop, err := client.NewFullNodeRPCV1(context.Background(), "ws://"+srv.Listener.Addr().String()+"/rpc/v1", nil) require.NoError(t, err) @@ -57,6 +58,7 @@ func minerRpc(t *testing.T, m *TestMiner) *TestMiner { fmt.Printf("creating RPC server for %s at %s\n", m.ActorAddr, srv.Listener.Addr().String()) fmt.Printf("SP RPC ENV FOR CLI DEBUGGING `export MINER_API_INFO=%s`\n", "ws://"+srv.Listener.Addr().String()) + sendItestdNotif("MINER_API_INFO", t.Name(), "ws://"+srv.Listener.Addr().String()) url := "ws://" + srv.Listener.Addr().String() + "/rpc/v0" cl, stop, err := client.NewStorageMinerRPCV0(context.Background(), url, nil) From 0d9e34d6516bd97a668b1a873fe5d53a47161f1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 10 Mar 2022 22:41:45 +0100 Subject: [PATCH 296/385] client impl: Fix typo in ClientCalcCommP CopyBuffer error --- node/impl/client/client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/impl/client/client.go b/node/impl/client/client.go index 7ecf6a776b4..f105d315277 100644 --- a/node/impl/client/client.go +++ b/node/impl/client/client.go @@ -1281,7 +1281,7 @@ func (a *API) ClientCalcCommP(ctx context.Context, inpath string) (*api.CommPRet w := &writer.Writer{} _, err = io.CopyBuffer(w, rdr, make([]byte, writer.CommPBuf)) if err != nil { - return nil, xerrors.Errorf("copy inte commp writer: %w", err) + return nil, xerrors.Errorf("copy into commp writer: %w", err) } commp, err := w.Sum() From ad66ad4f7d5fcb1533f5c2a727fe2065ea6196fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 10 Mar 2022 20:24:26 +0100 Subject: [PATCH 297/385] fix: sealing fsm: Handle inputLk correctly --- extern/sector-storage/mock/mock.go | 16 ++++++--- extern/storage-sealing/input.go | 24 ++++++------- itests/batch_deal_test.go | 27 ++++++++------ itests/sector_miner_collateral_test.go | 50 ++++++++++++++------------ 4 files changed, 66 insertions(+), 51 deletions(-) diff --git a/extern/sector-storage/mock/mock.go b/extern/sector-storage/mock/mock.go index 20abad309be..ecaeaa16896 100644 --- a/extern/sector-storage/mock/mock.go +++ b/extern/sector-storage/mock/mock.go @@ -426,11 +426,19 @@ func generateFakePoSt(sectorInfo []proof.SectorInfo, rpt func(abi.RegisteredSeal } func (mgr *SectorMgr) ReadPiece(ctx context.Context, sector storage.SectorRef, offset storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, ticket abi.SealRandomness, unsealed cid.Cid) (mount.Reader, bool, error) { - if uint64(offset) != 0 { - panic("implme") + off := storiface.UnpaddedByteIndex(0) + var piece cid.Cid + for _, c := range mgr.sectors[sector.ID].pieces { + piece = c + if off >= offset { + break + } + off += storiface.UnpaddedByteIndex(len(mgr.pieces[piece])) } - - br := bytes.NewReader(mgr.pieces[mgr.sectors[sector.ID].pieces[0]][:size]) + if off > offset { + panic("non-aligned offset todo") + } + br := bytes.NewReader(mgr.pieces[piece][:size]) return struct { io.ReadCloser diff --git a/extern/storage-sealing/input.go b/extern/storage-sealing/input.go index c999badfde2..e644cd84802 100644 --- a/extern/storage-sealing/input.go +++ b/extern/storage-sealing/input.go @@ -315,25 +315,21 @@ func (m *Sealing) SectorAddPieceToAny(ctx context.Context, size abi.UnpaddedPiec m.inputLk.Unlock() // we already have a pre-existing add piece call for this deal, let's wait for it to finish and see if it's successful - for { - res, err := waitAddPieceResp(ctx, pp) - if err != nil { - return api.SectorOffset{}, err - } - // there was an error waiting for a pre-existing add piece call, let's retry - if res.err != nil { - m.inputLk.Lock() - pp = m.addPendingPiece(ctx, size, data, deal, sp) - m.inputLk.Unlock() - continue - } + res, err := waitAddPieceResp(ctx, pp) + if err != nil { + return api.SectorOffset{}, err + } + if res.err == nil { // all good, return the response return api.SectorOffset{Sector: res.sn, Offset: res.offset.Padded()}, res.err } + // if there was an error waiting for a pre-existing add piece call, let's retry + m.inputLk.Lock() } + // addPendingPiece takes over m.inputLk pp := m.addPendingPiece(ctx, size, data, deal, sp) - m.inputLk.Unlock() + res, err := waitAddPieceResp(ctx, pp) if err != nil { return api.SectorOffset{}, err @@ -341,6 +337,7 @@ func (m *Sealing) SectorAddPieceToAny(ctx context.Context, size abi.UnpaddedPiec return api.SectorOffset{Sector: res.sn, Offset: res.offset.Padded()}, res.err } +// called with m.inputLk; transfers the lock to another goroutine! func (m *Sealing) addPendingPiece(ctx context.Context, size abi.UnpaddedPieceSize, data storage.Data, deal api.PieceDealInfo, sp abi.RegisteredSealProof) *pendingPiece { doneCh := make(chan struct{}) pp := &pendingPiece{ @@ -357,6 +354,7 @@ func (m *Sealing) addPendingPiece(ctx context.Context, size abi.UnpaddedPieceSiz m.pendingPieces[proposalCID(deal)] = pp go func() { + defer m.inputLk.Unlock() if err := m.updateInput(ctx, sp); err != nil { log.Errorf("%+v", err) } diff --git a/itests/batch_deal_test.go b/itests/batch_deal_test.go index 93d338e534b..0db90df2309 100644 --- a/itests/batch_deal_test.go +++ b/itests/batch_deal_test.go @@ -9,16 +9,18 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" + "github.com/stretchr/testify/require" + "github.com/filecoin-project/lotus/extern/storage-sealing/sealiface" "github.com/filecoin-project/lotus/itests/kit" "github.com/filecoin-project/lotus/markets/storageadapter" "github.com/filecoin-project/lotus/node" + "github.com/filecoin-project/lotus/node/config" + "github.com/filecoin-project/lotus/node/modules" "github.com/filecoin-project/lotus/node/modules/dtypes" - "github.com/stretchr/testify/require" ) func TestBatchDealInput(t *testing.T) { - t.Skip("this test is disabled as it's flaky: #4611") kit.QuietMiningLogs() var ( @@ -47,17 +49,20 @@ func TestBatchDealInput(t *testing.T) { })), node.Override(new(dtypes.GetSealingConfigFunc), func() (dtypes.GetSealingConfigFunc, error) { return func() (sealiface.Config, error) { - return sealiface.Config{ - MaxWaitDealsSectors: 2, - MaxSealingSectors: 1, - MaxSealingSectorsForDeals: 3, - AlwaysKeepUnsealedCopy: true, - WaitDealsDelay: time.Hour, - }, nil + sc := modules.ToSealingConfig(config.DefaultStorageMiner()) + sc.MaxWaitDealsSectors = 2 + sc.MaxSealingSectors = 1 + sc.MaxSealingSectorsForDeals = 3 + sc.AlwaysKeepUnsealedCopy = true + sc.WaitDealsDelay = time.Hour + sc.BatchPreCommits = false + sc.AggregateCommits = false + + return sc, nil }, nil }), )) - client, miner, ens := kit.EnsembleMinimal(t, kit.MockProofs(), opts) + client, miner, ens := kit.EnsembleMinimal(t, kit.MockProofs(), opts, kit.ThroughRPC()) ens.InterconnectAll().BeginMining(blockTime) dh := kit.NewDealHarness(t, client, miner, miner) @@ -126,9 +131,9 @@ func TestBatchDealInput(t *testing.T) { t.Run("4-p513B", run(513, 4, 2)) if !testing.Short() { t.Run("32-p257B", run(257, 32, 8)) - t.Run("32-p10B", run(10, 32, 2)) // fixme: this appears to break data-transfer / markets in some really creative ways + //t.Run("32-p10B", run(10, 32, 2)) // t.Run("128-p10B", run(10, 128, 8)) } } diff --git a/itests/sector_miner_collateral_test.go b/itests/sector_miner_collateral_test.go index af67b132b4a..81aefc3add8 100644 --- a/itests/sector_miner_collateral_test.go +++ b/itests/sector_miner_collateral_test.go @@ -17,6 +17,8 @@ import ( "github.com/filecoin-project/lotus/extern/storage-sealing/sealiface" "github.com/filecoin-project/lotus/itests/kit" "github.com/filecoin-project/lotus/node" + "github.com/filecoin-project/lotus/node/config" + "github.com/filecoin-project/lotus/node/modules" "github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/repo" ) @@ -40,29 +42,31 @@ func TestMinerBalanceCollateral(t *testing.T) { opts := kit.ConstructorOpts( node.ApplyIf(node.IsType(repo.StorageMiner), node.Override(new(dtypes.GetSealingConfigFunc), func() (dtypes.GetSealingConfigFunc, error) { return func() (sealiface.Config, error) { - return sealiface.Config{ - MaxWaitDealsSectors: 4, - MaxSealingSectors: 4, - MaxSealingSectorsForDeals: 4, - AlwaysKeepUnsealedCopy: true, - WaitDealsDelay: time.Hour, - - BatchPreCommits: batching, - AggregateCommits: batching, - - PreCommitBatchWait: time.Hour, - CommitBatchWait: time.Hour, - - MinCommitBatch: nSectors, - MaxPreCommitBatch: nSectors, - MaxCommitBatch: nSectors, - - CollateralFromMinerBalance: enabled, - AvailableBalanceBuffer: big.Zero(), - DisableCollateralFallback: false, - AggregateAboveBaseFee: big.Zero(), - BatchPreCommitAboveBaseFee: big.Zero(), - }, nil + sc := modules.ToSealingConfig(config.DefaultStorageMiner()) + + sc.MaxWaitDealsSectors = 4 + sc.MaxSealingSectors = 4 + sc.MaxSealingSectorsForDeals = 4 + sc.AlwaysKeepUnsealedCopy = true + sc.WaitDealsDelay = time.Hour + + sc.BatchPreCommits = batching + sc.AggregateCommits = batching + + sc.PreCommitBatchWait = time.Hour + sc.CommitBatchWait = time.Hour + + sc.MinCommitBatch = nSectors + sc.MaxPreCommitBatch = nSectors + sc.MaxCommitBatch = nSectors + + sc.CollateralFromMinerBalance = enabled + sc.AvailableBalanceBuffer = big.Zero() + sc.DisableCollateralFallback = false + sc.AggregateAboveBaseFee = big.Zero() + sc.BatchPreCommitAboveBaseFee = big.Zero() + + return sc, nil }, nil })), ) From d2054e8653bad72bce6ca429cebcc5908e4afe10 Mon Sep 17 00:00:00 2001 From: Aayush Date: Fri, 4 Mar 2022 13:52:41 -0500 Subject: [PATCH 298/385] FVM: support nv15 --- chain/consensus/filcns/compute_state.go | 12 ++++++------ chain/stmgr/forks_test.go | 6 +++--- chain/vm/fvm.go | 19 ++++++++++++++++++- conformance/driver.go | 2 +- extern/filecoin-ffi | 2 +- 5 files changed, 29 insertions(+), 12 deletions(-) diff --git a/chain/consensus/filcns/compute_state.go b/chain/consensus/filcns/compute_state.go index 929ac9f2fd6..5c22813adac 100644 --- a/chain/consensus/filcns/compute_state.go +++ b/chain/consensus/filcns/compute_state.go @@ -96,11 +96,6 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, sm *stmgr.StateManager ctx = blockstore.WithHotView(ctx) makeVmWithBaseStateAndEpoch := func(base cid.Cid, e abi.ChainEpoch) (vm.VMI, error) { - filVested, err := sm.GetFilVested(ctx, e) - if err != nil { - return nil, err - } - vmopt := &vm.VMOpts{ StateBase: base, Epoch: e, @@ -109,13 +104,18 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, sm *stmgr.StateManager Actors: NewActorRegistry(), Syscalls: sm.Syscalls, CircSupplyCalc: sm.GetVMCirculatingSupply, - FilVested: filVested, NetworkVersion: sm.GetNetworkVersion(ctx, e), BaseFee: baseFee, LookbackState: stmgr.LookbackStateGetterForTipset(sm, ts), } if os.Getenv("LOTUS_USE_FVM_DOESNT_WORK_YET") == "1" { + filVested, err := sm.GetFilVested(ctx, e) + if err != nil { + return nil, err + } + + vmopt.FilVested = filVested return vm.NewFVM(ctx, vmopt) } diff --git a/chain/stmgr/forks_test.go b/chain/stmgr/forks_test.go index fbf7b6785b0..d85aa810f72 100644 --- a/chain/stmgr/forks_test.go +++ b/chain/stmgr/forks_test.go @@ -166,7 +166,7 @@ func TestForkHeightTriggers(t *testing.T) { inv := filcns.NewActorRegistry() inv.Register(nil, testActor{}) - sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (*vm.VM, error) { + sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.VMI, error) { nvm, err := vm.NewLotusVM(ctx, vmopt) if err != nil { return nil, err @@ -281,7 +281,7 @@ func testForkRefuseCall(t *testing.T, nullsBefore, nullsAfter int) { inv := filcns.NewActorRegistry() inv.Register(nil, testActor{}) - sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (*vm.VM, error) { + sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.VMI, error) { nvm, err := vm.NewLotusVM(ctx, vmopt) if err != nil { return nil, err @@ -500,7 +500,7 @@ func TestForkPreMigration(t *testing.T) { inv := filcns.NewActorRegistry() inv.Register(nil, testActor{}) - sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (*vm.VM, error) { + sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.VMI, error) { nvm, err := vm.NewLotusVM(ctx, vmopt) if err != nil { return nil, err diff --git a/chain/vm/fvm.go b/chain/vm/fvm.go index 743e0fdeeb1..c8f8a0d9e19 100644 --- a/chain/vm/fvm.go +++ b/chain/vm/fvm.go @@ -5,6 +5,8 @@ import ( "context" "time" + "github.com/filecoin-project/go-state-types/network" + "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/lotus/build" @@ -215,9 +217,24 @@ type FVM struct { } func NewFVM(ctx context.Context, opts *VMOpts) (*FVM, error) { + circToReport := opts.FilVested + // For v14 (and earlier), we perform the FilVested portion of the calculation, and let the FVM dynamically do the rest + // v15 and after, the circ supply is always constant per epoch, so we calculate the base and report it at creation + if opts.NetworkVersion >= network.Version15 { + state, err := state.LoadStateTree(cbor.NewCborStore(opts.Bstore), opts.StateBase) + if err != nil { + return nil, err + } + + circToReport, err = opts.CircSupplyCalc(ctx, opts.Epoch, state) + if err != nil { + return nil, err + } + } + fvm, err := ffi.CreateFVM(0, &FvmExtern{Rand: opts.Rand, Blockstore: opts.Bstore, lbState: opts.LookbackState, base: opts.StateBase, epoch: opts.Epoch}, - opts.Epoch, opts.BaseFee, opts.FilVested, opts.NetworkVersion, opts.StateBase, + opts.Epoch, opts.BaseFee, circToReport, opts.NetworkVersion, opts.StateBase, ) if err != nil { return nil, err diff --git a/conformance/driver.go b/conformance/driver.go index 6af4372d2ec..0a24f07ef15 100644 --- a/conformance/driver.go +++ b/conformance/driver.go @@ -155,7 +155,7 @@ func (d *Driver) ExecuteTipset(bs blockstore.Blockstore, ds ds.Batching, params results: []*vm.ApplyRet{}, } - sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (*vm.VM, error) { + sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.VMI, error) { vmopt.CircSupplyCalc = func(context.Context, abi.ChainEpoch, *state.StateTree) (abi.TokenAmount, error) { return big.Zero(), nil } diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index 9ff2301105f..084ee8673f6 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit 9ff2301105fcf25101f1fcda52e6417f3e2ca60b +Subproject commit 084ee8673f6487c71b60996e6d8d6c5fa2cf04ab From 05fa9c81deab06d026088d79d4596aec80c8e2d4 Mon Sep 17 00:00:00 2001 From: Aayush Date: Sat, 12 Mar 2022 11:03:43 -0500 Subject: [PATCH 299/385] Rename FVM envvar to LOTUS_USE_FVM_EXPERIMENTAL --- chain/consensus/filcns/compute_state.go | 2 +- chain/vm/vmi.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/chain/consensus/filcns/compute_state.go b/chain/consensus/filcns/compute_state.go index 5c22813adac..addf641ed69 100644 --- a/chain/consensus/filcns/compute_state.go +++ b/chain/consensus/filcns/compute_state.go @@ -109,7 +109,7 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, sm *stmgr.StateManager LookbackState: stmgr.LookbackStateGetterForTipset(sm, ts), } - if os.Getenv("LOTUS_USE_FVM_DOESNT_WORK_YET") == "1" { + if os.Getenv("LOTUS_USE_FVM_EXPERIMENTAL") == "1" { filVested, err := sm.GetFilVested(ctx, e) if err != nil { return nil, err diff --git a/chain/vm/vmi.go b/chain/vm/vmi.go index b180f84f20a..ee7fd046cae 100644 --- a/chain/vm/vmi.go +++ b/chain/vm/vmi.go @@ -15,7 +15,7 @@ type VMI interface { } func NewVM(ctx context.Context, opts *VMOpts) (VMI, error) { - if os.Getenv("LOTUS_USE_FVM_DOESNT_WORK_YET") == "1" { + if os.Getenv("LOTUS_USE_FVM_EXPERIMENTAL") == "1" { return NewFVM(ctx, opts) } From 1bf40ad9df6a2638361d04b9b47c54516e475e29 Mon Sep 17 00:00:00 2001 From: Aayush Date: Sat, 12 Mar 2022 14:31:04 -0500 Subject: [PATCH 300/385] Fix broken go.sum --- go.sum | 1 + 1 file changed, 1 insertion(+) diff --git a/go.sum b/go.sum index a25ddb72d46..79629f1b51e 100644 --- a/go.sum +++ b/go.sum @@ -1942,6 +1942,7 @@ github.com/whyrusleeping/cbor-gen v0.0.0-20200826160007-0b9f6c5fb163/go.mod h1:f github.com/whyrusleeping/cbor-gen v0.0.0-20210118024343-169e9d70c0c2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20210219115102-f37d292932f2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20210303213153-67a261a1d291/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= +github.com/whyrusleeping/cbor-gen v0.0.0-20210713220151-be142a5ae1a8/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20220224212727-7a699437a831/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20220302191723-37c43cae8e14 h1:vo2wkP2ceHyGyZwFFtAabpot03EeSxxwAe57pOI9E/4= github.com/whyrusleeping/cbor-gen v0.0.0-20220302191723-37c43cae8e14/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= From 6240729ee415667a7b1e81209fb85ea5982b69a1 Mon Sep 17 00:00:00 2001 From: Jennifer Wang Date: Mon, 14 Mar 2022 14:56:07 -0400 Subject: [PATCH 301/385] enable indexer providing by default --- documentation/en/default-lotus-miner-config.toml | 2 +- node/config/def.go | 2 +- node/config/def_test.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/documentation/en/default-lotus-miner-config.toml b/documentation/en/default-lotus-miner-config.toml index a6a36f74253..30dfd0268b3 100644 --- a/documentation/en/default-lotus-miner-config.toml +++ b/documentation/en/default-lotus-miner-config.toml @@ -277,7 +277,7 @@ # # type: bool # env var: LOTUS_INDEXPROVIDER_ENABLE - #Enable = false + #Enable = true # EntriesCacheCapacity sets the maximum capacity to use for caching the indexing advertisement # entries. Defaults to 1024 if not specified. The cache is evicted using LRU policy. The diff --git a/node/config/def.go b/node/config/def.go index edc7ffef533..c70ab212900 100644 --- a/node/config/def.go +++ b/node/config/def.go @@ -189,7 +189,7 @@ func DefaultStorageMiner() *StorageMiner { }, IndexProvider: IndexProviderConfig{ - Enable: false, + Enable: true, EntriesCacheCapacity: 1024, EntriesChunkSize: 16384, TopicName: "/indexer/ingest/mainnet", diff --git a/node/config/def_test.go b/node/config/def_test.go index 9601ee95b5e..4a3094e9e74 100644 --- a/node/config/def_test.go +++ b/node/config/def_test.go @@ -73,6 +73,6 @@ func TestDefaultMinerRoundtrip(t *testing.T) { func TestDefaultStorageMiner_SetsIndexIngestTopic(t *testing.T) { subject := DefaultStorageMiner() - require.False(t, subject.IndexProvider.Enable) + require.True(t, subject.IndexProvider.Enable) require.Equal(t, "/indexer/ingest/mainnet", subject.IndexProvider.TopicName) } From 53c525f0edf2eacf0cd796dd794fc4e08adc3a93 Mon Sep 17 00:00:00 2001 From: vyzo Date: Tue, 15 Mar 2022 09:43:18 +0200 Subject: [PATCH 302/385] improve resource manager integration - add opt-in env var to control instantation, until we are comfortable with testing to enble by default. - adjust default limits if the connection manager high mark is higher than the default inbound conn limit. --- node/builder.go | 3 +- node/modules/lp2p/rcmgr.go | 127 ++++++++++++++++++++++++++----------- 2 files changed, 91 insertions(+), 39 deletions(-) diff --git a/node/builder.go b/node/builder.go index acda5a07a80..6386f78a608 100644 --- a/node/builder.go +++ b/node/builder.go @@ -222,7 +222,7 @@ var LibP2P = Options( Override(ConnGaterKey, lp2p.ConnGaterOption), // Services (resource management) - Override(new(network.ResourceManager), lp2p.ResourceManager), + Override(new(network.ResourceManager), lp2p.ResourceManager(200)), Override(ResourceManagerKey, lp2p.ResourceManagerOption), ) @@ -282,6 +282,7 @@ func ConfigCommon(cfg *config.Common, enableLibp2pNode bool) Option { cfg.Libp2p.ConnMgrHigh, time.Duration(cfg.Libp2p.ConnMgrGrace), cfg.Libp2p.ProtectedPeers)), + Override(new(network.ResourceManager), lp2p.ResourceManager(cfg.Libp2p.ConnMgrHigh)), Override(new(*pubsub.PubSub), lp2p.GossipSub), Override(new(*config.Pubsub), &cfg.Pubsub), diff --git a/node/modules/lp2p/rcmgr.go b/node/modules/lp2p/rcmgr.go index 0bc4dd6b215..24bea465ff7 100644 --- a/node/modules/lp2p/rcmgr.go +++ b/node/modules/lp2p/rcmgr.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "math/bits" "os" "path/filepath" @@ -15,6 +16,8 @@ import ( "github.com/libp2p/go-libp2p-core/protocol" rcmgr "github.com/libp2p/go-libp2p-resource-manager" + logging "github.com/ipfs/go-log/v2" + "github.com/filecoin-project/lotus/metrics" "github.com/filecoin-project/lotus/node/repo" @@ -22,55 +25,103 @@ import ( "go.opencensus.io/tag" ) -func ResourceManager(lc fx.Lifecycle, repo repo.LockedRepo) (network.ResourceManager, error) { - var limiter *rcmgr.BasicLimiter - var opts []rcmgr.Option - - repoPath := repo.Path() +func ResourceManager(connMgrHi uint) func(lc fx.Lifecycle, repo repo.LockedRepo) (network.ResourceManager, error) { + return func(lc fx.Lifecycle, repo repo.LockedRepo) (network.ResourceManager, error) { + envvar := os.Getenv("LOTUS_RCMGR") + if envvar == "" || envvar == "0" { + // TODO opt-in for now -- flip this to enabled by default once we are comfortable with testing + log.Info("libp2p resource manager is disabled") + return network.NullResourceManager, nil + } - // create limiter -- parse $repo/limits.json if exists - limitsFile := filepath.Join(repoPath, "limits.json") - limitsIn, err := os.Open(limitsFile) - switch { - case err == nil: - defer limitsIn.Close() //nolint:errcheck - limiter, err = rcmgr.NewDefaultLimiterFromJSON(limitsIn) - if err != nil { - return nil, fmt.Errorf("error parsing limit file: %w", err) + log.Info("libp2p resource manager is enabled") + // enable debug logs for rcmgr + logging.SetLogLevel("rcmgr", "debug") + + // Adjust default limits + // - give it more memory, up to 4G, min of 1G + // - if maxconns are too high, adjust Conn/FD/Stream limits + defaultLimits := rcmgr.DefaultLimits.WithSystemMemory(.125, 1<<30, 4<<30) + maxconns := int(connMgrHi) + if maxconns > defaultLimits.SystemBaseLimit.ConnsInbound { + defaultLimits.SystemBaseLimit.ConnsInbound = logScale(maxconns) + defaultLimits.SystemBaseLimit.ConnsOutbound = logScale(maxconns) + defaultLimits.SystemBaseLimit.Conns = logScale(2 * maxconns) + + defaultLimits.SystemBaseLimit.StreamsInbound = logScale(16 * maxconns) + defaultLimits.SystemBaseLimit.StreamsOutbound = logScale(64 * maxconns) + defaultLimits.SystemBaseLimit.Streams = logScale(64 * maxconns) + + if maxconns > defaultLimits.SystemBaseLimit.FD { + defaultLimits.SystemBaseLimit.FD = logScale(maxconns) + } + + defaultLimits.ServiceBaseLimit.StreamsInbound = logScale(8 * maxconns) + defaultLimits.ServiceBaseLimit.StreamsOutbound = logScale(32 * maxconns) + defaultLimits.ServiceBaseLimit.Streams = logScale(32 * maxconns) + + defaultLimits.ProtocolBaseLimit.StreamsInbound = logScale(8 * maxconns) + defaultLimits.ProtocolBaseLimit.StreamsOutbound = logScale(32 * maxconns) + defaultLimits.ProtocolBaseLimit.Streams = logScale(32 * maxconns) + + log.Info("adjusted default resource manager limits") } - case errors.Is(err, os.ErrNotExist): - limiter = rcmgr.NewDefaultLimiter() + // initialize + var limiter *rcmgr.BasicLimiter + var opts []rcmgr.Option - default: - return nil, err - } + repoPath := repo.Path() - // TODO: also set appropriate default limits for lotus protocols - libp2p.SetDefaultServiceLimits(limiter) + // create limiter -- parse $repo/limits.json if exists + limitsFile := filepath.Join(repoPath, "limits.json") + limitsIn, err := os.Open(limitsFile) + switch { + case err == nil: + defer limitsIn.Close() //nolint:errcheck + limiter, err = rcmgr.NewLimiterFromJSON(limitsIn, defaultLimits) + if err != nil { + return nil, fmt.Errorf("error parsing limit file: %w", err) + } - opts = append(opts, rcmgr.WithMetrics(rcmgrMetrics{})) + case errors.Is(err, os.ErrNotExist): + limiter = rcmgr.NewStaticLimiter(defaultLimits) - if os.Getenv("LOTUS_DEBUG_RCMGR") != "" { - debugPath := filepath.Join(repoPath, "debug") - if err := os.MkdirAll(debugPath, 0755); err != nil { - return nil, fmt.Errorf("error creating debug directory: %w", err) + default: + return nil, err } - traceFile := filepath.Join(debugPath, "rcmgr.json.gz") - opts = append(opts, rcmgr.WithTrace(traceFile)) - } - mgr, err := rcmgr.NewResourceManager(limiter, opts...) - if err != nil { - return nil, fmt.Errorf("error creating resource manager: %w", err) - } + // TODO: also set appropriate default limits for lotus protocols + libp2p.SetDefaultServiceLimits(limiter) + + opts = append(opts, rcmgr.WithMetrics(rcmgrMetrics{})) - lc.Append(fx.Hook{ - OnStop: func(_ context.Context) error { - return mgr.Close() - }}) + if os.Getenv("LOTUS_DEBUG_RCMGR") != "" { + debugPath := filepath.Join(repoPath, "debug") + if err := os.MkdirAll(debugPath, 0755); err != nil { + return nil, fmt.Errorf("error creating debug directory: %w", err) + } + traceFile := filepath.Join(debugPath, "rcmgr.json.gz") + opts = append(opts, rcmgr.WithTrace(traceFile)) + } + + mgr, err := rcmgr.NewResourceManager(limiter, opts...) + if err != nil { + return nil, fmt.Errorf("error creating resource manager: %w", err) + } + + lc.Append(fx.Hook{ + OnStop: func(_ context.Context) error { + return mgr.Close() + }}) + + return mgr, nil + } +} - return mgr, nil +func logScale(val int) int { + bitlen := bits.Len(uint(val)) + return 1 << bitlen } func ResourceManagerOption(mgr network.ResourceManager) Libp2pOpts { From 9fcafff847173961bd294e11670de24b0163f0e6 Mon Sep 17 00:00:00 2001 From: vyzo Date: Tue, 15 Mar 2022 09:59:34 +0200 Subject: [PATCH 303/385] adjust conns to 2x maxconns for duplicate connections --- node/modules/lp2p/rcmgr.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/node/modules/lp2p/rcmgr.go b/node/modules/lp2p/rcmgr.go index 24bea465ff7..d0906fd8fc3 100644 --- a/node/modules/lp2p/rcmgr.go +++ b/node/modules/lp2p/rcmgr.go @@ -43,17 +43,18 @@ func ResourceManager(connMgrHi uint) func(lc fx.Lifecycle, repo repo.LockedRepo) // - if maxconns are too high, adjust Conn/FD/Stream limits defaultLimits := rcmgr.DefaultLimits.WithSystemMemory(.125, 1<<30, 4<<30) maxconns := int(connMgrHi) - if maxconns > defaultLimits.SystemBaseLimit.ConnsInbound { - defaultLimits.SystemBaseLimit.ConnsInbound = logScale(maxconns) - defaultLimits.SystemBaseLimit.ConnsOutbound = logScale(maxconns) - defaultLimits.SystemBaseLimit.Conns = logScale(2 * maxconns) + if 2*maxconns > defaultLimits.SystemBaseLimit.ConnsInbound { + // adjust conns to 2x to allow for two conns per peer (TCP+QUIC) + defaultLimits.SystemBaseLimit.ConnsInbound = logScale(2 * maxconns) + defaultLimits.SystemBaseLimit.ConnsOutbound = logScale(2 * maxconns) + defaultLimits.SystemBaseLimit.Conns = logScale(4 * maxconns) defaultLimits.SystemBaseLimit.StreamsInbound = logScale(16 * maxconns) defaultLimits.SystemBaseLimit.StreamsOutbound = logScale(64 * maxconns) defaultLimits.SystemBaseLimit.Streams = logScale(64 * maxconns) - if maxconns > defaultLimits.SystemBaseLimit.FD { - defaultLimits.SystemBaseLimit.FD = logScale(maxconns) + if 2*maxconns > defaultLimits.SystemBaseLimit.FD { + defaultLimits.SystemBaseLimit.FD = logScale(2 * maxconns) } defaultLimits.ServiceBaseLimit.StreamsInbound = logScale(8 * maxconns) From c6bda0e5d485e6927ea65b0b75c18babb910e5a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 15 Mar 2022 14:29:21 +0100 Subject: [PATCH 304/385] fix: storage cli: Output primary sector status correctly --- cmd/lotus-miner/storage.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/cmd/lotus-miner/storage.go b/cmd/lotus-miner/storage.go index 0fea2a3a578..ba2e6841c0f 100644 --- a/cmd/lotus-miner/storage.go +++ b/cmd/lotus-miner/storage.go @@ -598,7 +598,7 @@ var storageListSectorsCmd = &cli.Command{ ft storiface.SectorFileType urls string - primary, seal, store bool + primary, copy, main, seal, store bool state api.SectorState } @@ -626,8 +626,11 @@ var storageListSectorsCmd = &cli.Command{ urls: strings.Join(info.URLs, ";"), primary: info.Primary, - seal: info.CanSeal, - store: info.CanStore, + copy: !info.Primary && len(si) > 1, + main: !info.Primary && len(si) == 1, // only copy, but not primary + + seal: info.CanSeal, + store: info.CanStore, state: st.State, }) @@ -680,7 +683,7 @@ var storageListSectorsCmd = &cli.Command{ "Sector": e.id, "Type": e.ft.String(), "State": color.New(stateOrder[sealing.SectorState(e.state)].col).Sprint(e.state), - "Primary": maybeStr(e.seal, color.FgGreen, "primary"), + "Primary": maybeStr(e.primary, color.FgGreen, "primary") + maybeStr(e.copy, color.FgBlue, "copy") + maybeStr(e.main, color.FgRed, "main"), "Path use": maybeStr(e.seal, color.FgMagenta, "seal ") + maybeStr(e.store, color.FgCyan, "store"), "URLs": e.urls, } From 6c51adc334336783926dcb764fd6f035413dd257 Mon Sep 17 00:00:00 2001 From: Aayush Date: Tue, 15 Mar 2022 11:07:25 -0400 Subject: [PATCH 305/385] Update FFI: fix cargo.lock --- extern/filecoin-ffi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index 084ee8673f6..5d65755dc49 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit 084ee8673f6487c71b60996e6d8d6c5fa2cf04ab +Subproject commit 5d65755dc49ffb2a5282066bf1e848388dbbaada From 2170b4deb5c4ac3a1967d921ce6d922fbb166808 Mon Sep 17 00:00:00 2001 From: Aayush Date: Tue, 15 Mar 2022 18:40:22 -0400 Subject: [PATCH 306/385] Fixup merge --- chain/sync_test.go | 4 ++-- itests/kit/ensemble.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/chain/sync_test.go b/chain/sync_test.go index 321696d1b2e..96ed1440e92 100644 --- a/chain/sync_test.go +++ b/chain/sync_test.go @@ -104,7 +104,7 @@ func prepSyncTest(t testing.TB, h int) *syncTestUtil { ctx: ctx, cancel: cancel, - mn: mocknet.New(ctx), + mn: mocknet.New(), g: g, us: filcns.DefaultUpgradeSchedule(), } @@ -158,7 +158,7 @@ func prepSyncTestWithV5Height(t testing.TB, h int, v5height abi.ChainEpoch) *syn ctx: ctx, cancel: cancel, - mn: mocknet.New(ctx), + mn: mocknet.New(), g: g, us: sched, } diff --git a/itests/kit/ensemble.go b/itests/kit/ensemble.go index effb5dc2925..7b4a067d9ff 100644 --- a/itests/kit/ensemble.go +++ b/itests/kit/ensemble.go @@ -284,7 +284,7 @@ func (n *Ensemble) Start() *Ensemble { // We haven't been bootstrapped yet, we need to generate genesis and // create the networking backbone. gtempl = n.generateGenesis() - n.mn = mocknet.New(ctx) + n.mn = mocknet.New() } // --------------------- From 673f558ba5dc133ff4915f04d18698310a0fce01 Mon Sep 17 00:00:00 2001 From: Aayush Date: Tue, 15 Mar 2022 18:46:56 -0400 Subject: [PATCH 307/385] Rename vm.VMI to vm.Interface --- chain/consensus/filcns/compute_state.go | 4 ++-- chain/stmgr/forks_test.go | 6 +++--- chain/stmgr/stmgr.go | 8 ++++---- chain/vm/fvm.go | 2 +- chain/vm/vm.go | 2 +- chain/vm/vmi.go | 8 ++++++-- conformance/driver.go | 2 +- 7 files changed, 18 insertions(+), 14 deletions(-) diff --git a/chain/consensus/filcns/compute_state.go b/chain/consensus/filcns/compute_state.go index addf641ed69..687b0341aa3 100644 --- a/chain/consensus/filcns/compute_state.go +++ b/chain/consensus/filcns/compute_state.go @@ -95,7 +95,7 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, sm *stmgr.StateManager }() ctx = blockstore.WithHotView(ctx) - makeVmWithBaseStateAndEpoch := func(base cid.Cid, e abi.ChainEpoch) (vm.VMI, error) { + makeVmWithBaseStateAndEpoch := func(base cid.Cid, e abi.ChainEpoch) (vm.Interface, error) { vmopt := &vm.VMOpts{ StateBase: base, Epoch: e, @@ -122,7 +122,7 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, sm *stmgr.StateManager return sm.VMConstructor()(ctx, vmopt) } - runCron := func(vmCron vm.VMI, epoch abi.ChainEpoch) error { + runCron := func(vmCron vm.Interface, epoch abi.ChainEpoch) error { cronMsg := &types.Message{ To: cron.Address, From: builtin.SystemActorAddr, diff --git a/chain/stmgr/forks_test.go b/chain/stmgr/forks_test.go index d85aa810f72..9ee808999c6 100644 --- a/chain/stmgr/forks_test.go +++ b/chain/stmgr/forks_test.go @@ -166,7 +166,7 @@ func TestForkHeightTriggers(t *testing.T) { inv := filcns.NewActorRegistry() inv.Register(nil, testActor{}) - sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.VMI, error) { + sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.Interface, error) { nvm, err := vm.NewLotusVM(ctx, vmopt) if err != nil { return nil, err @@ -281,7 +281,7 @@ func testForkRefuseCall(t *testing.T, nullsBefore, nullsAfter int) { inv := filcns.NewActorRegistry() inv.Register(nil, testActor{}) - sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.VMI, error) { + sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.Interface, error) { nvm, err := vm.NewLotusVM(ctx, vmopt) if err != nil { return nil, err @@ -500,7 +500,7 @@ func TestForkPreMigration(t *testing.T) { inv := filcns.NewActorRegistry() inv.Register(nil, testActor{}) - sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.VMI, error) { + sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.Interface, error) { nvm, err := vm.NewLotusVM(ctx, vmopt) if err != nil { return nil, err diff --git a/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index fd58af8b269..d0bdd73e916 100644 --- a/chain/stmgr/stmgr.go +++ b/chain/stmgr/stmgr.go @@ -84,7 +84,7 @@ type StateManager struct { compWait map[string]chan struct{} stlk sync.Mutex genesisMsigLk sync.Mutex - newVM func(context.Context, *vm.VMOpts) (vm.VMI, error) + newVM func(context.Context, *vm.VMOpts) (vm.Interface, error) Syscalls vm.SyscallBuilder preIgnitionVesting []msig0.State postIgnitionVesting []msig0.State @@ -347,12 +347,12 @@ func (sm *StateManager) ValidateChain(ctx context.Context, ts *types.TipSet) err return nil } -func (sm *StateManager) SetVMConstructor(nvm func(context.Context, *vm.VMOpts) (vm.VMI, error)) { +func (sm *StateManager) SetVMConstructor(nvm func(context.Context, *vm.VMOpts) (vm.Interface, error)) { sm.newVM = nvm } -func (sm *StateManager) VMConstructor() func(context.Context, *vm.VMOpts) (vm.VMI, error) { - return func(ctx context.Context, opts *vm.VMOpts) (vm.VMI, error) { +func (sm *StateManager) VMConstructor() func(context.Context, *vm.VMOpts) (vm.Interface, error) { + return func(ctx context.Context, opts *vm.VMOpts) (vm.Interface, error) { return sm.newVM(ctx, opts) } } diff --git a/chain/vm/fvm.go b/chain/vm/fvm.go index c8f8a0d9e19..a1359dce299 100644 --- a/chain/vm/fvm.go +++ b/chain/vm/fvm.go @@ -31,7 +31,7 @@ import ( "github.com/ipfs/go-cid" ) -var _ VMI = (*FVM)(nil) +var _ Interface = (*FVM)(nil) var _ ffi_cgo.Externs = (*FvmExtern)(nil) type FvmExtern struct { diff --git a/chain/vm/vm.go b/chain/vm/vm.go index ca9855b104b..823682840fd 100644 --- a/chain/vm/vm.go +++ b/chain/vm/vm.go @@ -201,7 +201,7 @@ type ( LookbackStateGetter func(context.Context, abi.ChainEpoch) (*state.StateTree, error) ) -var _ VMI = (*VM)(nil) +var _ Interface = (*VM)(nil) type VM struct { cstate *state.StateTree diff --git a/chain/vm/vmi.go b/chain/vm/vmi.go index ee7fd046cae..4cac7284d8c 100644 --- a/chain/vm/vmi.go +++ b/chain/vm/vmi.go @@ -8,13 +8,17 @@ import ( "github.com/ipfs/go-cid" ) -type VMI interface { +type Interface interface { + // Applies the given message onto the VM's current state, returning the result of the execution ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, error) + // Same as above but for system messages (the Cron invocation and block reward payments). + // Must NEVER fail. ApplyImplicitMessage(ctx context.Context, msg *types.Message) (*ApplyRet, error) + // Flush all buffered objects into the state store provided to the VM at construction. Flush(ctx context.Context) (cid.Cid, error) } -func NewVM(ctx context.Context, opts *VMOpts) (VMI, error) { +func NewVM(ctx context.Context, opts *VMOpts) (Interface, error) { if os.Getenv("LOTUS_USE_FVM_EXPERIMENTAL") == "1" { return NewFVM(ctx, opts) } diff --git a/conformance/driver.go b/conformance/driver.go index 0a24f07ef15..32ef8bf2109 100644 --- a/conformance/driver.go +++ b/conformance/driver.go @@ -155,7 +155,7 @@ func (d *Driver) ExecuteTipset(bs blockstore.Blockstore, ds ds.Batching, params results: []*vm.ApplyRet{}, } - sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.VMI, error) { + sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.Interface, error) { vmopt.CircSupplyCalc = func(context.Context, abi.ChainEpoch, *state.StateTree) (abi.TokenAmount, error) { return big.Zero(), nil } From e6117c49ef228da43e8652f9f6300c63918fc93a Mon Sep 17 00:00:00 2001 From: Aayush Date: Tue, 15 Mar 2022 19:34:59 -0400 Subject: [PATCH 308/385] Address review --- chain/consensus/filcns/compute_state.go | 3 +++ chain/stmgr/call.go | 6 +++++- chain/vm/fvm.go | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/chain/consensus/filcns/compute_state.go b/chain/consensus/filcns/compute_state.go index 687b0341aa3..05d802948a6 100644 --- a/chain/consensus/filcns/compute_state.go +++ b/chain/consensus/filcns/compute_state.go @@ -110,6 +110,9 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, sm *stmgr.StateManager } if os.Getenv("LOTUS_USE_FVM_EXPERIMENTAL") == "1" { + // This is needed so that the FVM does not have to duplicate the genesis vesting schedule, one + // of the components of the circ supply calc. + // This field is NOT needed by the Lotus VM, and also NOT needed by the FVM from v15 onwards. filVested, err := sm.GetFilVested(ctx, e) if err != nil { return nil, err diff --git a/chain/stmgr/call.go b/chain/stmgr/call.go index fb7f33d0347..5db508008db 100644 --- a/chain/stmgr/call.go +++ b/chain/stmgr/call.go @@ -70,6 +70,7 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types. pheight = ts.Height() - 1 } + // Since we're simulating a future message, pretend we're applying it in the "next" tipset vmHeight := pheight + 1 bstate := ts.ParentState() @@ -127,7 +128,7 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types. stTree, err := sm.StateTree(bstate) if err != nil { - return nil, err + return nil, xerrors.Errorf("failed to load state tree: %w", err) } fromActor, err := stTree.GetActor(msg.From) @@ -193,6 +194,7 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, pri } } + // Since we're simulating a future message, pretend we're applying it in the "next" tipset vmHeight := ts.Height() + 1 stateCid, _, err := sm.TipSetState(ctx, ts) @@ -246,6 +248,8 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, pri } } + // We flush to get the VM's view of the state tree after applying the above messages + // This is needed to get the correct nonce from the actor state to match the VM stateCid, err = vmi.Flush(ctx) if err != nil { return nil, xerrors.Errorf("flushing vm: %w", err) diff --git a/chain/vm/fvm.go b/chain/vm/fvm.go index a1359dce299..b13f9340ab7 100644 --- a/chain/vm/fvm.go +++ b/chain/vm/fvm.go @@ -274,6 +274,7 @@ func (vm *FVM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet GasBurned: 0, }, // TODO: do these eventually, not consensus critical + // https://github.com/filecoin-project/ref-fvm/issues/318 ActorErr: nil, ExecutionTrace: types.ExecutionTrace{}, Duration: time.Since(start), @@ -299,6 +300,7 @@ func (vm *FVM) ApplyImplicitMessage(ctx context.Context, cmsg *types.Message) (* }, GasCosts: nil, // TODO: do these eventually, not consensus critical + // https://github.com/filecoin-project/ref-fvm/issues/318 ActorErr: nil, ExecutionTrace: types.ExecutionTrace{}, Duration: time.Since(start), From 9ea623e1254e61c8287eeb32ace2c64ad1ef8ae3 Mon Sep 17 00:00:00 2001 From: Aayush Date: Tue, 15 Mar 2022 19:40:17 -0400 Subject: [PATCH 309/385] Rename the Lotus VM to LegacyVM --- chain/consensus/filcns/compute_state.go | 2 +- chain/gen/genesis/genesis.go | 4 +- chain/gen/genesis/miners.go | 12 ++--- chain/gen/genesis/util.go | 2 +- chain/stmgr/forks_test.go | 6 +-- chain/vm/fvm.go | 2 +- chain/vm/gas.go | 2 +- chain/vm/gas_v0.go | 6 +-- chain/vm/invoker_test.go | 4 +- chain/vm/runtime.go | 4 +- chain/vm/vm.go | 44 +++++++++---------- chain/vm/vmi.go | 2 +- .../simulation/blockbuilder/blockbuilder.go | 12 ++--- conformance/driver.go | 4 +- node/builder_chain.go | 2 +- 15 files changed, 54 insertions(+), 54 deletions(-) diff --git a/chain/consensus/filcns/compute_state.go b/chain/consensus/filcns/compute_state.go index 05d802948a6..9b2183a5913 100644 --- a/chain/consensus/filcns/compute_state.go +++ b/chain/consensus/filcns/compute_state.go @@ -112,7 +112,7 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, sm *stmgr.StateManager if os.Getenv("LOTUS_USE_FVM_EXPERIMENTAL") == "1" { // This is needed so that the FVM does not have to duplicate the genesis vesting schedule, one // of the components of the circ supply calc. - // This field is NOT needed by the Lotus VM, and also NOT needed by the FVM from v15 onwards. + // This field is NOT needed by the LegacyVM, and also NOT needed by the FVM from v15 onwards. filVested, err := sm.GetFilVested(ctx, e) if err != nil { return nil, err diff --git a/chain/gen/genesis/genesis.go b/chain/gen/genesis/genesis.go index 78b06637ce4..a1d1d01b854 100644 --- a/chain/gen/genesis/genesis.go +++ b/chain/gen/genesis/genesis.go @@ -495,9 +495,9 @@ func VerifyPreSealedData(ctx context.Context, cs *store.ChainStore, sys vm.Sysca NetworkVersion: nv, BaseFee: big.Zero(), } - vm, err := vm.NewLotusVM(ctx, &vmopt) + vm, err := vm.NewLegacyVM(ctx, &vmopt) if err != nil { - return cid.Undef, xerrors.Errorf("failed to create NewLotusVM: %w", err) + return cid.Undef, xerrors.Errorf("failed to create NewLegacyVM: %w", err) } for mi, m := range template.Miners { diff --git a/chain/gen/genesis/miners.go b/chain/gen/genesis/miners.go index 93861e6812b..fd83a7640f3 100644 --- a/chain/gen/genesis/miners.go +++ b/chain/gen/genesis/miners.go @@ -99,9 +99,9 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sys vm.Syscal FilVested: big.Zero(), } - vm, err := vm.NewLotusVM(ctx, vmopt) + vm, err := vm.NewLegacyVM(ctx, vmopt) if err != nil { - return cid.Undef, xerrors.Errorf("failed to create NewLotusVM: %w", err) + return cid.Undef, xerrors.Errorf("failed to create NewLegacyVM: %w", err) } if len(miners) == 0 { @@ -521,7 +521,7 @@ func (fr *fakeRand) GetBeaconRandomness(ctx context.Context, personalization cry return out, nil } -func currentTotalPower(ctx context.Context, vm *vm.VM, maddr address.Address) (*power0.CurrentTotalPowerReturn, error) { +func currentTotalPower(ctx context.Context, vm *vm.LegacyVM, maddr address.Address) (*power0.CurrentTotalPowerReturn, error) { pwret, err := doExecValue(ctx, vm, power.Address, maddr, big.Zero(), builtin0.MethodsPower.CurrentTotalPower, nil) if err != nil { return nil, err @@ -534,7 +534,7 @@ func currentTotalPower(ctx context.Context, vm *vm.VM, maddr address.Address) (* return &pwr, nil } -func dealWeight(ctx context.Context, vm *vm.VM, maddr address.Address, dealIDs []abi.DealID, sectorStart, sectorExpiry abi.ChainEpoch, av actors.Version) (abi.DealWeight, abi.DealWeight, error) { +func dealWeight(ctx context.Context, vm *vm.LegacyVM, maddr address.Address, dealIDs []abi.DealID, sectorStart, sectorExpiry abi.ChainEpoch, av actors.Version) (abi.DealWeight, abi.DealWeight, error) { // TODO: This hack should move to market actor wrapper if av <= actors.Version2 { params := &market0.VerifyDealsForActivationParams{ @@ -594,7 +594,7 @@ func dealWeight(ctx context.Context, vm *vm.VM, maddr address.Address, dealIDs [ return dealWeights.Sectors[0].DealWeight, dealWeights.Sectors[0].VerifiedDealWeight, nil } -func currentEpochBlockReward(ctx context.Context, vm *vm.VM, maddr address.Address, av actors.Version) (abi.StoragePower, builtin.FilterEstimate, error) { +func currentEpochBlockReward(ctx context.Context, vm *vm.LegacyVM, maddr address.Address, av actors.Version) (abi.StoragePower, builtin.FilterEstimate, error) { rwret, err := doExecValue(ctx, vm, reward.Address, maddr, big.Zero(), reward.Methods.ThisEpochReward, nil) if err != nil { return big.Zero(), builtin.FilterEstimate{}, err @@ -629,7 +629,7 @@ func currentEpochBlockReward(ctx context.Context, vm *vm.VM, maddr address.Addre return epochReward.ThisEpochBaselinePower, builtin.FilterEstimate(epochReward.ThisEpochRewardSmoothed), nil } -func circSupply(ctx context.Context, vmi *vm.VM, maddr address.Address) abi.TokenAmount { +func circSupply(ctx context.Context, vmi *vm.LegacyVM, maddr address.Address) abi.TokenAmount { unsafeVM := &vm.UnsafeVM{VM: vmi} rt := unsafeVM.MakeRuntime(ctx, &types.Message{ GasLimit: 1_000_000_000, diff --git a/chain/gen/genesis/util.go b/chain/gen/genesis/util.go index 67a4e9579a7..452bc835b26 100644 --- a/chain/gen/genesis/util.go +++ b/chain/gen/genesis/util.go @@ -21,7 +21,7 @@ func mustEnc(i cbg.CBORMarshaler) []byte { return enc } -func doExecValue(ctx context.Context, vm *vm.VM, to, from address.Address, value types.BigInt, method abi.MethodNum, params []byte) ([]byte, error) { +func doExecValue(ctx context.Context, vm *vm.LegacyVM, to, from address.Address, value types.BigInt, method abi.MethodNum, params []byte) ([]byte, error) { act, err := vm.StateTree().GetActor(from) if err != nil { return nil, xerrors.Errorf("doExec failed to get from actor (%s): %w", from, err) diff --git a/chain/stmgr/forks_test.go b/chain/stmgr/forks_test.go index 9ee808999c6..9389734298c 100644 --- a/chain/stmgr/forks_test.go +++ b/chain/stmgr/forks_test.go @@ -167,7 +167,7 @@ func TestForkHeightTriggers(t *testing.T) { inv.Register(nil, testActor{}) sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.Interface, error) { - nvm, err := vm.NewLotusVM(ctx, vmopt) + nvm, err := vm.NewLegacyVM(ctx, vmopt) if err != nil { return nil, err } @@ -282,7 +282,7 @@ func testForkRefuseCall(t *testing.T, nullsBefore, nullsAfter int) { inv.Register(nil, testActor{}) sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.Interface, error) { - nvm, err := vm.NewLotusVM(ctx, vmopt) + nvm, err := vm.NewLegacyVM(ctx, vmopt) if err != nil { return nil, err } @@ -501,7 +501,7 @@ func TestForkPreMigration(t *testing.T) { inv.Register(nil, testActor{}) sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (vm.Interface, error) { - nvm, err := vm.NewLotusVM(ctx, vmopt) + nvm, err := vm.NewLegacyVM(ctx, vmopt) if err != nil { return nil, err } diff --git a/chain/vm/fvm.go b/chain/vm/fvm.go index b13f9340ab7..922eb77c5ab 100644 --- a/chain/vm/fvm.go +++ b/chain/vm/fvm.go @@ -42,7 +42,7 @@ type FvmExtern struct { base cid.Cid } -// VerifyConsensusFault is similar to the one in syscalls.go used by the Lotus VM, except it never errors +// VerifyConsensusFault is similar to the one in syscalls.go used by the LegacyVM, except it never errors // Errors are logged and "no fault" is returned, which is functionally what go-actors does anyway func (x *FvmExtern) VerifyConsensusFault(ctx context.Context, a, b, extra []byte) (*ffi_cgo.ConsensusFault, int64) { totalGas := int64(0) diff --git a/chain/vm/gas.go b/chain/vm/gas.go index e75c86b9fb4..5beaae40ba5 100644 --- a/chain/vm/gas.go +++ b/chain/vm/gas.go @@ -50,7 +50,7 @@ func newGasCharge(name string, computeGas int64, storageGas int64) GasCharge { } } -// Pricelist provides prices for operations in the VM. +// Pricelist provides prices for operations in the LegacyVM. // // Note: this interface should be APPEND ONLY since last chain checkpoint type Pricelist interface { diff --git a/chain/vm/gas_v0.go b/chain/vm/gas_v0.go index 1bda6dfae21..7e0ece769d4 100644 --- a/chain/vm/gas_v0.go +++ b/chain/vm/gas_v0.go @@ -50,7 +50,7 @@ type pricelistV0 struct { // whether it succeeds or fails in application) is given by: // OnChainMessageBase + len(serialized message)*OnChainMessagePerByte // Together, these account for the cost of message propagation and validation, - // up to but excluding any actual processing by the VM. + // up to but excluding any actual processing by the LegacyVM. // This is the cost a block producer burns when including an invalid message. onChainMessageComputeBase int64 onChainMessageStorageBase int64 @@ -83,11 +83,11 @@ type pricelistV0 struct { sendInvokeMethod int64 // Gas cost for any Get operation to the IPLD store - // in the runtime VM context. + // in the runtime LegacyVM context. ipldGetBase int64 // Gas cost (Base + len*PerByte) for any Put operation to the IPLD store - // in the runtime VM context. + // in the runtime LegacyVM context. // // Note: these costs should be significantly higher than the costs for Get // operations, since they reflect not only serialization/deserialization diff --git a/chain/vm/invoker_test.go b/chain/vm/invoker_test.go index fb9910ecdd0..e75d0c854b3 100644 --- a/chain/vm/invoker_test.go +++ b/chain/vm/invoker_test.go @@ -135,7 +135,7 @@ func TestInvokerBasic(t *testing.T) { { _, aerr := code[1](&Runtime{ - vm: &VM{networkVersion: network.Version0}, + vm: &LegacyVM{networkVersion: network.Version0}, Message: &basicRtMessage{}, }, []byte{99}) if aerrors.IsFatal(aerr) { @@ -146,7 +146,7 @@ func TestInvokerBasic(t *testing.T) { { _, aerr := code[1](&Runtime{ - vm: &VM{networkVersion: network.Version7}, + vm: &LegacyVM{networkVersion: network.Version7}, Message: &basicRtMessage{}, }, []byte{99}) if aerrors.IsFatal(aerr) { diff --git a/chain/vm/runtime.go b/chain/vm/runtime.go index 0e2adc87983..c27c4537131 100644 --- a/chain/vm/runtime.go +++ b/chain/vm/runtime.go @@ -65,7 +65,7 @@ type Runtime struct { ctx context.Context - vm *VM + vm *LegacyVM state *state.StateTree height abi.ChainEpoch cst ipldcbor.IpldStore @@ -158,7 +158,7 @@ func (rt *Runtime) shimCall(f func() interface{}) (rval []byte, aerr aerrors.Act defer func() { if r := recover(); r != nil { if ar, ok := r.(aerrors.ActorError); ok { - log.Warnf("VM.Call failure in call from: %s to %s: %+v", rt.Caller(), rt.Receiver(), ar) + log.Warnf("LegacyVM.Call failure in call from: %s to %s: %+v", rt.Caller(), rt.Receiver(), ar) aerr = ar return } diff --git a/chain/vm/vm.go b/chain/vm/vm.go index 823682840fd..a0ca446a7c0 100644 --- a/chain/vm/vm.go +++ b/chain/vm/vm.go @@ -122,7 +122,7 @@ func (bs *gasChargingBlocks) Put(ctx context.Context, blk block.Block) error { return nil } -func (vm *VM) makeRuntime(ctx context.Context, msg *types.Message, parent *Runtime) *Runtime { +func (vm *LegacyVM) makeRuntime(ctx context.Context, msg *types.Message, parent *Runtime) *Runtime { rt := &Runtime{ ctx: ctx, vm: vm, @@ -188,7 +188,7 @@ func (vm *VM) makeRuntime(ctx context.Context, msg *types.Message, parent *Runti } type UnsafeVM struct { - VM *VM + VM *LegacyVM } func (vm *UnsafeVM) MakeRuntime(ctx context.Context, msg *types.Message) *Runtime { @@ -201,9 +201,9 @@ type ( LookbackStateGetter func(context.Context, abi.ChainEpoch) (*state.StateTree, error) ) -var _ Interface = (*VM)(nil) +var _ Interface = (*LegacyVM)(nil) -type VM struct { +type LegacyVM struct { cstate *state.StateTree cst *cbor.BasicIpldStore buf *blockstore.BufferedBlockstore @@ -234,7 +234,7 @@ type VMOpts struct { LookbackState LookbackStateGetter } -func NewLotusVM(ctx context.Context, opts *VMOpts) (*VM, error) { +func NewLegacyVM(ctx context.Context, opts *VMOpts) (*LegacyVM, error) { buf := blockstore.NewBuffered(opts.Bstore) cst := cbor.NewCborStore(buf) state, err := state.LoadStateTree(cst, opts.StateBase) @@ -247,7 +247,7 @@ func NewLotusVM(ctx context.Context, opts *VMOpts) (*VM, error) { return nil, err } - return &VM{ + return &LegacyVM{ cstate: state, cst: cst, buf: buf, @@ -276,7 +276,7 @@ type ApplyRet struct { GasCosts *GasOutputs } -func (vm *VM) send(ctx context.Context, msg *types.Message, parent *Runtime, +func (vm *LegacyVM) send(ctx context.Context, msg *types.Message, parent *Runtime, gasCharge *GasCharge, start time.Time) ([]byte, aerrors.ActorError, *Runtime) { defer atomic.AddUint64(&StatSends, 1) @@ -395,7 +395,7 @@ func checkMessage(msg *types.Message) error { return nil } -func (vm *VM) ApplyImplicitMessage(ctx context.Context, msg *types.Message) (*ApplyRet, error) { +func (vm *LegacyVM) ApplyImplicitMessage(ctx context.Context, msg *types.Message) (*ApplyRet, error) { start := build.Clock.Now() defer atomic.AddUint64(&StatApplied, 1) ret, actorErr, rt := vm.send(ctx, msg, nil, nil, start) @@ -413,7 +413,7 @@ func (vm *VM) ApplyImplicitMessage(ctx context.Context, msg *types.Message) (*Ap }, actorErr } -func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, error) { +func (vm *LegacyVM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, error) { start := build.Clock.Now() ctx, span := trace.StartSpan(ctx, "vm.ApplyMessage") defer span.End() @@ -620,7 +620,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, }, nil } -func (vm *VM) ShouldBurn(ctx context.Context, st *state.StateTree, msg *types.Message, errcode exitcode.ExitCode) (bool, error) { +func (vm *LegacyVM) ShouldBurn(ctx context.Context, st *state.StateTree, msg *types.Message, errcode exitcode.ExitCode) (bool, error) { if vm.networkVersion <= network.Version12 { // Check to see if we should burn funds. We avoid burning on successful // window post. This won't catch _indirect_ window post calls, but this @@ -650,7 +650,7 @@ func (vm *VM) ShouldBurn(ctx context.Context, st *state.StateTree, msg *types.Me type vmFlushKey struct{} -func (vm *VM) Flush(ctx context.Context) (cid.Cid, error) { +func (vm *LegacyVM) Flush(ctx context.Context) (cid.Cid, error) { _, span := trace.StartSpan(ctx, "vm.Flush") defer span.End() @@ -669,9 +669,9 @@ func (vm *VM) Flush(ctx context.Context) (cid.Cid, error) { return root, nil } -// Get the buffered blockstore associated with the VM. This includes any temporary blocks produced -// during this VM's execution. -func (vm *VM) ActorStore(ctx context.Context) adt.Store { +// Get the buffered blockstore associated with the LegacyVM. This includes any temporary blocks produced +// during this LegacyVM's execution. +func (vm *LegacyVM) ActorStore(ctx context.Context) adt.Store { return adt.WrapStore(ctx, vm.cst) } @@ -824,11 +824,11 @@ func copyRec(ctx context.Context, from, to blockstore.Blockstore, root cid.Cid, return nil } -func (vm *VM) StateTree() types.StateTree { +func (vm *LegacyVM) StateTree() types.StateTree { return vm.cstate } -func (vm *VM) Invoke(act *types.Actor, rt *Runtime, method abi.MethodNum, params []byte) ([]byte, aerrors.ActorError) { +func (vm *LegacyVM) Invoke(act *types.Actor, rt *Runtime, method abi.MethodNum, params []byte) ([]byte, aerrors.ActorError) { ctx, span := trace.StartSpan(rt.ctx, "vm.Invoke") defer span.End() if span.IsRecordingEvents() { @@ -851,11 +851,11 @@ func (vm *VM) Invoke(act *types.Actor, rt *Runtime, method abi.MethodNum, params return ret, nil } -func (vm *VM) SetInvoker(i *ActorRegistry) { +func (vm *LegacyVM) SetInvoker(i *ActorRegistry) { vm.areg = i } -func (vm *VM) GetCircSupply(ctx context.Context) (abi.TokenAmount, error) { +func (vm *LegacyVM) GetCircSupply(ctx context.Context) (abi.TokenAmount, error) { // Before v15, this was recalculated on each invocation as the state tree was mutated if vm.networkVersion <= network.Version14 { return vm.circSupplyCalc(ctx, vm.blockHeight, vm.cstate) @@ -864,14 +864,14 @@ func (vm *VM) GetCircSupply(ctx context.Context) (abi.TokenAmount, error) { return vm.baseCircSupply, nil } -func (vm *VM) incrementNonce(addr address.Address) error { +func (vm *LegacyVM) incrementNonce(addr address.Address) error { return vm.cstate.MutateActor(addr, func(a *types.Actor) error { a.Nonce++ return nil }) } -func (vm *VM) transfer(from, to address.Address, amt types.BigInt, networkVersion network.Version) aerrors.ActorError { +func (vm *LegacyVM) transfer(from, to address.Address, amt types.BigInt, networkVersion network.Version) aerrors.ActorError { var f *types.Actor var fromID, toID address.Address var err error @@ -959,7 +959,7 @@ func (vm *VM) transfer(from, to address.Address, amt types.BigInt, networkVersio return nil } -func (vm *VM) transferToGasHolder(addr address.Address, gasHolder *types.Actor, amt types.BigInt) error { +func (vm *LegacyVM) transferToGasHolder(addr address.Address, gasHolder *types.Actor, amt types.BigInt) error { if amt.LessThan(types.NewInt(0)) { return xerrors.Errorf("attempted to transfer negative value to gas holder") } @@ -973,7 +973,7 @@ func (vm *VM) transferToGasHolder(addr address.Address, gasHolder *types.Actor, }) } -func (vm *VM) transferFromGasHolder(addr address.Address, gasHolder *types.Actor, amt types.BigInt) error { +func (vm *LegacyVM) transferFromGasHolder(addr address.Address, gasHolder *types.Actor, amt types.BigInt) error { if amt.LessThan(types.NewInt(0)) { return xerrors.Errorf("attempted to transfer negative value from gas holder") } diff --git a/chain/vm/vmi.go b/chain/vm/vmi.go index 4cac7284d8c..9ffd8d830f9 100644 --- a/chain/vm/vmi.go +++ b/chain/vm/vmi.go @@ -23,5 +23,5 @@ func NewVM(ctx context.Context, opts *VMOpts) (Interface, error) { return NewFVM(ctx, opts) } - return NewLotusVM(ctx, opts) + return NewLegacyVM(ctx, opts) } diff --git a/cmd/lotus-sim/simulation/blockbuilder/blockbuilder.go b/cmd/lotus-sim/simulation/blockbuilder/blockbuilder.go index 7aaaf0ec7c6..392eaa7c815 100644 --- a/cmd/lotus-sim/simulation/blockbuilder/blockbuilder.go +++ b/cmd/lotus-sim/simulation/blockbuilder/blockbuilder.go @@ -44,7 +44,7 @@ type BlockBuilder struct { parentTs *types.TipSet parentSt *state.StateTree - vm *vm.VM + vm *vm.LegacyVM sm *stmgr.StateManager gasTotal int64 @@ -73,9 +73,9 @@ func NewBlockBuilder(ctx context.Context, logger *zap.SugaredLogger, sm *stmgr.S parentSt: parentSt, } - // Then we construct a VM to execute messages for gas estimation. + // Then we construct a LegacyVM to execute messages for gas estimation. // - // Most parts of this VM are "real" except: + // Most parts of this LegacyVM are "real" except: // 1. We don't charge a fee. // 2. The runtime has "fake" proof logic. // 3. We don't actually save any of the results. @@ -92,7 +92,7 @@ func NewBlockBuilder(ctx context.Context, logger *zap.SugaredLogger, sm *stmgr.S BaseFee: abi.NewTokenAmount(0), LookbackState: stmgr.LookbackStateGetterForTipset(sm, parentTs), } - bb.vm, err = vm.NewLotusVM(bb.ctx, vmopt) + bb.vm, err = vm.NewLegacyVM(bb.ctx, vmopt) if err != nil { return nil, err } @@ -190,12 +190,12 @@ func (bb *BlockBuilder) PushMessage(msg *types.Message) (*types.MessageReceipt, return &ret.MessageReceipt, nil } -// ActorStore returns the VM's current (pending) blockstore. +// ActorStore returns the LegacyVM's current (pending) blockstore. func (bb *BlockBuilder) ActorStore() adt.Store { return bb.vm.ActorStore(bb.ctx) } -// StateTree returns the VM's current (pending) state-tree. This includes any changes made by +// StateTree returns the LegacyVM's current (pending) state-tree. This includes any changes made by // successfully pushed messages. // // You probably want ParentStateTree diff --git a/conformance/driver.go b/conformance/driver.go index 32ef8bf2109..f6ca9f9db76 100644 --- a/conformance/driver.go +++ b/conformance/driver.go @@ -160,7 +160,7 @@ func (d *Driver) ExecuteTipset(bs blockstore.Blockstore, ds ds.Batching, params return big.Zero(), nil } - return vm.NewLotusVM(ctx, vmopt) + return vm.NewLegacyVM(ctx, vmopt) }) postcid, receiptsroot, err := tse.ApplyBlocks(context.Background(), @@ -226,7 +226,7 @@ func (d *Driver) ExecuteMessage(bs blockstore.Blockstore, params ExecuteMessageP NetworkVersion: params.NetworkVersion, } - lvm, err := vm.NewLotusVM(context.TODO(), vmOpts) + lvm, err := vm.NewLegacyVM(context.TODO(), vmOpts) if err != nil { return nil, cid.Undef, err } diff --git a/node/builder_chain.go b/node/builder_chain.go index afee868fd15..226ecac687e 100644 --- a/node/builder_chain.go +++ b/node/builder_chain.go @@ -65,7 +65,7 @@ var ChainNode = Options( Override(new(ffiwrapper.Verifier), ffiwrapper.ProofVerifier), Override(new(ffiwrapper.Prover), ffiwrapper.ProofProver), - // Consensus: VM + // Consensus: LegacyVM Override(new(vm.SyscallBuilder), vm.Syscalls), // Consensus: Chain storage/access From 668c33fdcd17a3d96efb8d480ce1e3963a502829 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 16 Mar 2022 10:35:26 +0100 Subject: [PATCH 310/385] stores: http: Support multiple storage IDs in ?keep --- api/version.go | 4 ++-- extern/sector-storage/stores/http_handler.go | 2 +- extern/sector-storage/stores/index.go | 22 ++++++++++++++++++++ extern/sector-storage/stores/remote.go | 8 +++---- extern/sector-storage/worker_local.go | 6 +++++- 5 files changed, 34 insertions(+), 8 deletions(-) diff --git a/api/version.go b/api/version.go index 9f4f7351361..cc0c7b270c1 100644 --- a/api/version.go +++ b/api/version.go @@ -57,8 +57,8 @@ var ( FullAPIVersion0 = newVer(1, 5, 0) FullAPIVersion1 = newVer(2, 2, 0) - MinerAPIVersion0 = newVer(1, 4, 0) - WorkerAPIVersion0 = newVer(1, 5, 0) + MinerAPIVersion0 = newVer(1, 5, 0) + WorkerAPIVersion0 = newVer(1, 6, 0) ) //nolint:varcheck,deadcode diff --git a/extern/sector-storage/stores/http_handler.go b/extern/sector-storage/stores/http_handler.go index 80fa8740834..6b7d249040f 100644 --- a/extern/sector-storage/stores/http_handler.go +++ b/extern/sector-storage/stores/http_handler.go @@ -172,7 +172,7 @@ func (handler *FetchHandler) remoteDeleteSector(w http.ResponseWriter, r *http.R return } - if err := handler.Local.Remove(r.Context(), id, ft, false, []ID{ID(r.FormValue("keep"))}); err != nil { + if err := handler.Local.Remove(r.Context(), id, ft, false, ParseIDList(r.FormValue("keep"))); err != nil { log.Errorf("%+v", err) w.WriteHeader(500) return diff --git a/extern/sector-storage/stores/index.go b/extern/sector-storage/stores/index.go index a90cdf0b969..35a1da693e9 100644 --- a/extern/sector-storage/stores/index.go +++ b/extern/sector-storage/stores/index.go @@ -7,6 +7,7 @@ import ( "net/url" gopath "path" "sort" + "strings" "sync" "time" @@ -29,6 +30,27 @@ var SkippedHeartbeatThresh = HeartbeatInterval * 5 // filesystem, local or networked / shared by multiple machines type ID string +const IDSep = "." + +type IDList []ID + +func (il IDList) String() string { + l := make([]string, len(il)) + for i, id := range il { + l[i] = string(id) + } + return strings.Join(l, IDSep) +} + +func ParseIDList(s string) IDList { + strs := strings.Split(s, IDSep) + out := make([]ID, len(strs)) + for i, str := range strs { + out[i] = ID(str) + } + return out +} + type Group = string type StorageInfo struct { diff --git a/extern/sector-storage/stores/remote.go b/extern/sector-storage/stores/remote.go index bd6b34be334..8581e47720d 100644 --- a/extern/sector-storage/stores/remote.go +++ b/extern/sector-storage/stores/remote.go @@ -156,7 +156,7 @@ func (r *Remote) AcquireSector(ctx context.Context, s storage.SectorRef, existin if op == storiface.AcquireMove { id := ID(storageID) - if err := r.deleteFromRemote(ctx, url, &id); err != nil { + if err := r.deleteFromRemote(ctx, url, []ID{id}); err != nil { log.Warnf("deleting sector %v from %s (delete %s): %+v", s, storageID, url, err) } } @@ -355,7 +355,7 @@ storeLoop: } } for _, url := range info.URLs { - if err := r.deleteFromRemote(ctx, url, nil); err != nil { + if err := r.deleteFromRemote(ctx, url, keepIn); err != nil { log.Warnf("remove %s: %+v", url, err) continue } @@ -366,9 +366,9 @@ storeLoop: return nil } -func (r *Remote) deleteFromRemote(ctx context.Context, url string, keepIn *ID) error { +func (r *Remote) deleteFromRemote(ctx context.Context, url string, keepIn IDList) error { if keepIn != nil { - url = url + "?keep=" + string(*keepIn) + url = url + "?keep=" + keepIn.String() } log.Infof("Delete %s", url) diff --git a/extern/sector-storage/worker_local.go b/extern/sector-storage/worker_local.go index 2ca86f5465a..22270c2f4e9 100644 --- a/extern/sector-storage/worker_local.go +++ b/extern/sector-storage/worker_local.go @@ -516,7 +516,11 @@ func (l *LocalWorker) Remove(ctx context.Context, sector abi.SectorID) error { func (l *LocalWorker) MoveStorage(ctx context.Context, sector storage.SectorRef, types storiface.SectorFileType) (storiface.CallID, error) { return l.asyncCall(ctx, sector, MoveStorage, func(ctx context.Context, ci storiface.CallID) (interface{}, error) { - return nil, l.storage.MoveStorage(ctx, sector, types) + if err := l.storage.MoveStorage(ctx, sector, types); err != nil { + return nil, xerrors.Errorf("move to storage: %w", err) + } + + return nil, l.storage.RemoveCopies(ctx, sector.ID, types) }) } From d249eb3f9395d442696889b0f52cd2483d2b220a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 16 Mar 2022 11:23:10 +0100 Subject: [PATCH 311/385] stores: Support RemoveCopies on remote store --- extern/sector-storage/stores/remote.go | 34 ++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/extern/sector-storage/stores/remote.go b/extern/sector-storage/stores/remote.go index 8581e47720d..d33c01603d8 100644 --- a/extern/sector-storage/stores/remote.go +++ b/extern/sector-storage/stores/remote.go @@ -44,12 +44,36 @@ type Remote struct { pfHandler PartialFileHandler } -func (r *Remote) RemoveCopies(ctx context.Context, s abi.SectorID, types storiface.SectorFileType) error { - // TODO: do this on remotes too - // (not that we really need to do that since it's always called by the - // worker which pulled the copy) +func (r *Remote) RemoveCopies(ctx context.Context, s abi.SectorID, typ storiface.SectorFileType) error { + if bits.OnesCount(uint(typ)) != 1 { + return xerrors.New("delete expects one file type") + } + + if err := r.local.RemoveCopies(ctx, s, typ); err != nil { + return xerrors.Errorf("removing local copies: %w", err) + } + + si, err := r.index.StorageFindSector(ctx, s, typ, 0, false) + if err != nil { + return xerrors.Errorf("finding existing sector %d(t:%d) failed: %w", s, typ, err) + } + + var hasPrimary bool + var keep []ID + for _, info := range si { + if info.Primary { + hasPrimary = true + keep = append(keep, info.ID) + break + } + } + + if !hasPrimary { + log.Warnf("remote RemoveCopies: no primary copies of sector %v (%s), not removing anything", s, typ) + return nil + } - return r.local.RemoveCopies(ctx, s, types) + return r.Remove(ctx, s, typ, true, keep) } func NewRemote(local Store, index SectorIndex, auth http.Header, fetchLimit int, pfHandler PartialFileHandler) *Remote { From defdea7b493b2354e4cb20e3e496eff21ab2f459 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 16 Mar 2022 11:23:31 +0100 Subject: [PATCH 312/385] worker: Call RemoveCopies in MoveStorage --- extern/sector-storage/worker_local.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/extern/sector-storage/worker_local.go b/extern/sector-storage/worker_local.go index 22270c2f4e9..e86709d725e 100644 --- a/extern/sector-storage/worker_local.go +++ b/extern/sector-storage/worker_local.go @@ -520,7 +520,16 @@ func (l *LocalWorker) MoveStorage(ctx context.Context, sector storage.SectorRef, return nil, xerrors.Errorf("move to storage: %w", err) } - return nil, l.storage.RemoveCopies(ctx, sector.ID, types) + for _, fileType := range storiface.PathTypes { + if fileType&types == 0 { + continue + } + + if err := l.storage.RemoveCopies(ctx, sector.ID, types); err != nil { + return nil, xerrors.Errorf("rm copies (t:%s, s:%v): %w", fileType, sector, err) + } + } + return nil, nil }) } From 39e3ddb0ed1ea15b83b3c6d325cd3524376c85c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 16 Mar 2022 11:49:48 +0100 Subject: [PATCH 313/385] storagemgr: MoveStorage in separate steps --- extern/sector-storage/manager.go | 43 +++++++++++++++++++------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index 28e0715591c..595f6419ee7 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -12,6 +12,7 @@ import ( "github.com/ipfs/go-cid" logging "github.com/ipfs/go-log/v2" "github.com/mitchellh/go-homedir" + "go.uber.org/multierr" "golang.org/x/xerrors" "github.com/filecoin-project/go-state-types/abi" @@ -589,7 +590,7 @@ func (m *Manager) FinalizeReplicaUpdate(ctx context.Context, sector storage.Sect return xerrors.Errorf("acquiring sector lock: %w", err) } - fts := storiface.FTUnsealed + moveUnsealed := storiface.FTUnsealed { unsealedStores, err := m.index.StorageFindSector(ctx, sector.ID, storiface.FTUnsealed, 0, false) if err != nil { @@ -597,7 +598,7 @@ func (m *Manager) FinalizeReplicaUpdate(ctx context.Context, sector storage.Sect } if len(unsealedStores) == 0 { // Is some edge-cases unsealed sector may not exist already, that's fine - fts = storiface.FTNone + moveUnsealed = storiface.FTNone } } @@ -616,10 +617,10 @@ func (m *Manager) FinalizeReplicaUpdate(ctx context.Context, sector storage.Sect } } - selector := newExistingSelector(m.index, sector.ID, storiface.FTCache|storiface.FTSealed|storiface.FTUpdate|storiface.FTUpdateCache, false) + selector := newExistingSelector(m.index, sector.ID, storiface.FTCache|storiface.FTUpdateCache, false) err := m.sched.Schedule(ctx, sector, sealtasks.TTFinalizeReplicaUpdate, selector, - m.schedFetch(sector, storiface.FTCache|storiface.FTSealed|storiface.FTUpdate|storiface.FTUpdateCache|fts, pathType, storiface.AcquireMove), + m.schedFetch(sector, storiface.FTCache|storiface.FTUpdateCache|moveUnsealed, pathType, storiface.AcquireMove), func(ctx context.Context, w Worker) error { _, err := m.waitSimpleCall(ctx)(w.FinalizeReplicaUpdate(ctx, sector, keepUnsealed)) return err @@ -628,22 +629,30 @@ func (m *Manager) FinalizeReplicaUpdate(ctx context.Context, sector storage.Sect return err } - fetchSel := newAllocSelector(m.index, storiface.FTCache|storiface.FTSealed|storiface.FTUpdate|storiface.FTUpdateCache, storiface.PathStorage) - moveUnsealed := fts - { - if len(keepUnsealed) == 0 { - moveUnsealed = storiface.FTNone + move := func(types storiface.SectorFileType) error { + fetchSel := newAllocSelector(m.index, types, storiface.PathStorage) + { + if len(keepUnsealed) == 0 { + moveUnsealed = storiface.FTNone + } + } + + err = m.sched.Schedule(ctx, sector, sealtasks.TTFetch, fetchSel, + m.schedFetch(sector, types, storiface.PathStorage, storiface.AcquireMove), + func(ctx context.Context, w Worker) error { + _, err := m.waitSimpleCall(ctx)(w.MoveStorage(ctx, sector, types)) + return err + }) + if err != nil { + return xerrors.Errorf("moving sector to storage: %w", err) } + return nil } - err = m.sched.Schedule(ctx, sector, sealtasks.TTFetch, fetchSel, - m.schedFetch(sector, storiface.FTCache|storiface.FTSealed|storiface.FTUpdate|storiface.FTUpdateCache|moveUnsealed, storiface.PathStorage, storiface.AcquireMove), - func(ctx context.Context, w Worker) error { - _, err := m.waitSimpleCall(ctx)(w.MoveStorage(ctx, sector, storiface.FTCache|storiface.FTSealed|storiface.FTUpdate|storiface.FTUpdateCache|moveUnsealed)) - return err - }) - if err != nil { - return xerrors.Errorf("moving sector to storage: %w", err) + err = multierr.Append(move(storiface.FTUpdate|storiface.FTUpdateCache), move(storiface.FTCache)) + err = multierr.Append(err, move(storiface.FTSealed)) // Sealed separate from cache just in case ReleaseSectorKey was already called + if moveUnsealed != storiface.FTNone { + err = multierr.Append(err, move(moveUnsealed)) } return nil From 99c6ef564e8fafa3015dbf13c769eefa941a8b7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 16 Mar 2022 12:03:44 +0100 Subject: [PATCH 314/385] worker: RemoveCopies expects one type at a time --- extern/sector-storage/stores/remote.go | 2 +- extern/sector-storage/worker_local.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extern/sector-storage/stores/remote.go b/extern/sector-storage/stores/remote.go index d33c01603d8..42a41f78823 100644 --- a/extern/sector-storage/stores/remote.go +++ b/extern/sector-storage/stores/remote.go @@ -46,7 +46,7 @@ type Remote struct { func (r *Remote) RemoveCopies(ctx context.Context, s abi.SectorID, typ storiface.SectorFileType) error { if bits.OnesCount(uint(typ)) != 1 { - return xerrors.New("delete expects one file type") + return xerrors.New("RemoveCopies expects one file type") } if err := r.local.RemoveCopies(ctx, s, typ); err != nil { diff --git a/extern/sector-storage/worker_local.go b/extern/sector-storage/worker_local.go index e86709d725e..4f7ae767dfe 100644 --- a/extern/sector-storage/worker_local.go +++ b/extern/sector-storage/worker_local.go @@ -525,7 +525,7 @@ func (l *LocalWorker) MoveStorage(ctx context.Context, sector storage.SectorRef, continue } - if err := l.storage.RemoveCopies(ctx, sector.ID, types); err != nil { + if err := l.storage.RemoveCopies(ctx, sector.ID, fileType); err != nil { return nil, xerrors.Errorf("rm copies (t:%s, s:%v): %w", fileType, sector, err) } } From 2cef55a4f64175eb2729696ca96e2a687355a4e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 16 Mar 2022 17:33:05 +0100 Subject: [PATCH 315/385] feat: sealing: Sector upgrade queue --- cmd/lotus-miner/info.go | 1 + extern/storage-sealing/fsm.go | 5 + extern/storage-sealing/fsm_events.go | 4 + extern/storage-sealing/input.go | 141 ++++++++++++++++++++--- extern/storage-sealing/sealing.go | 7 +- extern/storage-sealing/sector_state.go | 4 +- extern/storage-sealing/states_proving.go | 15 +++ extern/storage-sealing/upgrade_queue.go | 13 +-- itests/kit/log.go | 1 + 9 files changed, 157 insertions(+), 34 deletions(-) diff --git a/cmd/lotus-miner/info.go b/cmd/lotus-miner/info.go index 32219e73b4a..f6629fcf4c2 100644 --- a/cmd/lotus-miner/info.go +++ b/cmd/lotus-miner/info.go @@ -466,6 +466,7 @@ var stateOrder = map[sealing.SectorState]stateMeta{} var stateList = []stateMeta{ {col: 39, state: "Total"}, {col: color.FgGreen, state: sealing.Proving}, + {col: color.FgGreen, state: sealing.Available}, {col: color.FgGreen, state: sealing.UpdateActivating}, {col: color.FgBlue, state: sealing.Empty}, diff --git a/extern/storage-sealing/fsm.go b/extern/storage-sealing/fsm.go index 2c50d188560..2088131f00b 100644 --- a/extern/storage-sealing/fsm.go +++ b/extern/storage-sealing/fsm.go @@ -283,6 +283,9 @@ var fsmPlanners = map[SectorState]func(events []statemachine.Event, state *Secto Proving: planOne( on(SectorFaultReported{}, FaultReported), on(SectorFaulty{}, Faulty), + on(SectorMarkForUpdate{}, Available), + ), + Available: planOne( on(SectorStartCCUpdate{}, SnapDealsWaitDeals), ), Terminating: planOne( @@ -558,6 +561,8 @@ func (m *Sealing) plan(events []statemachine.Event, state *SectorInfo) (func(sta // Post-seal case Proving: return m.handleProvingSector, processed, nil + case Available: + return m.handleAvailableSector, processed, nil case Terminating: return m.handleTerminating, processed, nil case TerminateWait: diff --git a/extern/storage-sealing/fsm_events.go b/extern/storage-sealing/fsm_events.go index fc3b774f963..4789c9bee2e 100644 --- a/extern/storage-sealing/fsm_events.go +++ b/extern/storage-sealing/fsm_events.go @@ -297,6 +297,10 @@ func (evt SectorFinalizeFailed) apply(*SectorInfo) {} // Snap deals // CC update path +type SectorMarkForUpdate struct{} + +func (evt SectorMarkForUpdate) apply(state *SectorInfo) {} + type SectorStartCCUpdate struct{} func (evt SectorStartCCUpdate) apply(state *SectorInfo) { diff --git a/extern/storage-sealing/input.go b/extern/storage-sealing/input.go index e644cd84802..41f713c1cd2 100644 --- a/extern/storage-sealing/input.go +++ b/extern/storage-sealing/input.go @@ -12,11 +12,14 @@ import ( "github.com/filecoin-project/go-commp-utils/zerocomm" "github.com/filecoin-project/go-padreader" "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-statemachine" "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/policy" + "github.com/filecoin-project/lotus/chain/types" sectorstorage "github.com/filecoin-project/lotus/extern/sector-storage" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" "github.com/filecoin-project/lotus/extern/storage-sealing/sealiface" @@ -384,8 +387,29 @@ func (m *Sealing) MatchPendingPiecesToOpenSectors(ctx context.Context) error { return m.updateInput(ctx, sp) } +type expFn func(sn abi.SectorNumber) (abi.ChainEpoch, abi.TokenAmount, error) + // called with m.inputLk func (m *Sealing) updateInput(ctx context.Context, sp abi.RegisteredSealProof) error { + memo := make(map[abi.SectorNumber]struct { + e abi.ChainEpoch + p abi.TokenAmount + }) + expF := func(sn abi.SectorNumber) (abi.ChainEpoch, abi.TokenAmount, error) { + if e, ok := memo[sn]; ok { + return e.e, e.p, nil + } + onChainInfo, err := m.Api.StateSectorGetInfo(ctx, m.maddr, sn, TipSetToken{}) + if err != nil { + return 0, big.Zero(), err + } + memo[sn] = struct { + e abi.ChainEpoch + p abi.TokenAmount + }{e: onChainInfo.Expiration, p: onChainInfo.InitialPledge} + return onChainInfo.Expiration, onChainInfo.InitialPledge, nil + } + ssize, err := sp.SectorSize() if err != nil { return err @@ -411,19 +435,6 @@ func (m *Sealing) updateInput(ctx context.Context, sp abi.RegisteredSealProof) e toAssign[proposalCid] = struct{}{} - memo := make(map[abi.SectorNumber]abi.ChainEpoch) - expF := func(sn abi.SectorNumber) (abi.ChainEpoch, error) { - if exp, ok := memo[sn]; ok { - return exp, nil - } - onChainInfo, err := m.Api.StateSectorGetInfo(ctx, m.maddr, sn, TipSetToken{}) - if err != nil { - return 0, err - } - memo[sn] = onChainInfo.Expiration - return onChainInfo.Expiration, nil - } - for id, sector := range m.openSectors { avail := abi.PaddedPieceSize(ssize).Unpadded() - sector.used // check that sector lifetime is long enough to fit deal using latest expiration from on chain @@ -434,7 +445,7 @@ func (m *Sealing) updateInput(ctx context.Context, sp abi.RegisteredSealProof) e continue } if !ok { - exp, _ := expF(sector.number) + exp, _, _ := expF(sector.number) log.Infof("CC update sector %d cannot fit deal, expiration %d before deal end epoch %d", id, exp, piece.deal.DealProposal.EndEpoch) continue } @@ -497,7 +508,7 @@ func (m *Sealing) updateInput(ctx context.Context, sp abi.RegisteredSealProof) e if len(toAssign) > 0 { log.Errorf("we are trying to create a new sector with open sectors %v", m.openSectors) - if err := m.tryCreateDealSector(ctx, sp); err != nil { + if err := m.tryGetDealSector(ctx, sp, expF); err != nil { log.Errorw("Failed to create a new sector for deals", "error", err) } } @@ -505,7 +516,91 @@ func (m *Sealing) updateInput(ctx context.Context, sp abi.RegisteredSealProof) e return nil } -func (m *Sealing) tryCreateDealSector(ctx context.Context, sp abi.RegisteredSealProof) error { +func (m *Sealing) calcTargetExpiration(ctx context.Context, ssize abi.SectorSize) (target abi.ChainEpoch) { + var candidates []*pendingPiece + + for _, piece := range m.pendingPieces { + if piece.assigned { + continue // already assigned to a sector, skip + } + candidates = append(candidates, piece) + } + + // earliest expiration first + sort.Slice(candidates, func(i, j int) bool { + return candidates[i].deal.DealProposal.EndEpoch < candidates[i].deal.DealProposal.EndEpoch + }) + + var totalBytes uint64 + for _, candidate := range candidates { + totalBytes += uint64(candidate.size) + + if totalBytes >= uint64(abi.PaddedPieceSize(ssize).Unpadded()) { + return candidate.deal.DealProposal.EndEpoch + } + } + + _, curEpoch, err := m.Api.ChainHead(ctx) + if err != nil { + log.Errorf("getting current epoch: %s", err) + return 0 + } + + _, maxDur := policy.DealDurationBounds(0) + + return curEpoch + maxDur +} + +func (m *Sealing) tryGetUpgradeSector(ctx context.Context, sp abi.RegisteredSealProof, ef expFn) (bool, error) { + if len(m.available) == 0 { + return false, nil + } + + ssize, _ := sp.SectorSize() // error already checked in the caller + targetExpiration := m.calcTargetExpiration(ctx, ssize) + + var candidate abi.SectorID + var bestExpiration abi.ChainEpoch + bestPledge := types.TotalFilecoinInt + + for s := range m.available { + expiration, pledge, err := ef(s.Number) + if err != nil { + log.Errorw("checking sector expiration", "error", err) + continue + } + + // if best is below target, we want larger expirations + // if best is above target, we want lower pledge, but only if still above target + + if bestExpiration < targetExpiration { + if expiration > bestExpiration { + bestExpiration = expiration + bestPledge = pledge + candidate = s + } + continue + } + + if expiration > targetExpiration && pledge.LessThan(bestPledge) { + bestExpiration = expiration + bestPledge = pledge + candidate = s + } + } + + if bestExpiration == 0 { + // didn't find a good sector + return false, nil + } + + log.Infow("Upgrading sector", "number", candidate.Number, "type", "deal", "proofType", sp, "expiration", bestExpiration, "pledge", types.FIL(bestPledge)) + delete(m.available, candidate) + m.creating = &candidate.Number + return true, m.sectors.Send(uint64(candidate.Number), SectorStartCCUpdate{}) +} + +func (m *Sealing) tryGetDealSector(ctx context.Context, sp abi.RegisteredSealProof, ef expFn) error { m.startupWait.Wait() if m.creating != nil { @@ -517,15 +612,23 @@ func (m *Sealing) tryCreateDealSector(ctx context.Context, sp abi.RegisteredSeal return xerrors.Errorf("getting storage config: %w", err) } - if !cfg.MakeNewSectorForDeals { + if cfg.MaxSealingSectorsForDeals > 0 && m.stats.curSealing() >= cfg.MaxSealingSectorsForDeals { return nil } - if cfg.MaxSealingSectorsForDeals > 0 && m.stats.curSealing() >= cfg.MaxSealingSectorsForDeals { + if cfg.MaxWaitDealsSectors > 0 && m.stats.curStaging() >= cfg.MaxWaitDealsSectors { return nil } - if cfg.MaxWaitDealsSectors > 0 && m.stats.curStaging() >= cfg.MaxWaitDealsSectors { + got, err := m.tryGetUpgradeSector(ctx, sp, ef) + if err != nil { + return err + } + if got { + return nil + } + + if !cfg.MakeNewSectorForDeals { return nil } diff --git a/extern/storage-sealing/sealing.go b/extern/storage-sealing/sealing.go index 907d7cdfdd0..642fbb1db97 100644 --- a/extern/storage-sealing/sealing.go +++ b/extern/storage-sealing/sealing.go @@ -108,6 +108,7 @@ type Sealing struct { upgradeLk sync.Mutex toUpgrade map[abi.SectorNumber]struct{} + available map[abi.SectorID]struct{} notifee SectorStateNotifee addrSel AddrSel @@ -129,11 +130,11 @@ type openSector struct { maybeAccept func(cid.Cid) error // called with inputLk } -func (o *openSector) dealFitsInLifetime(dealEnd abi.ChainEpoch, expF func(sn abi.SectorNumber) (abi.ChainEpoch, error)) (bool, error) { +func (o *openSector) dealFitsInLifetime(dealEnd abi.ChainEpoch, expF expFn) (bool, error) { if !o.ccUpdate { return true, nil } - expiration, err := expF(o.number) + expiration, _, err := expF(o.number) if err != nil { return false, err } @@ -179,6 +180,8 @@ func New(mctx context.Context, api SealingAPI, fc config.MinerFeeConfig, events assignedPieces: map[abi.SectorID][]cid.Cid{}, toUpgrade: map[abi.SectorNumber]struct{}{}, + available: map[abi.SectorID]struct{}{}, + notifee: notifee, addrSel: as, diff --git a/extern/storage-sealing/sector_state.go b/extern/storage-sealing/sector_state.go index 0f8228d027f..7547f00a078 100644 --- a/extern/storage-sealing/sector_state.go +++ b/extern/storage-sealing/sector_state.go @@ -25,6 +25,7 @@ var ExistSectorStateList = map[SectorState]struct{}{ CommitAggregateWait: {}, FinalizeSector: {}, Proving: {}, + Available: {}, FailedUnrecoverable: {}, SealPreCommit1Failed: {}, SealPreCommit2Failed: {}, @@ -98,6 +99,7 @@ const ( FinalizeSector SectorState = "FinalizeSector" Proving SectorState = "Proving" + Available SectorState = "Available" // proving CC available for SnapDeals // snap deals / cc update SnapDealsWaitDeals SectorState = "SnapDealsWaitDeals" @@ -161,7 +163,7 @@ func toStatState(st SectorState, finEarly bool) statSectorState { return sstProving } return sstSealing - case Proving, UpdateActivating, ReleaseSectorKey, Removed, Removing, Terminating, TerminateWait, TerminateFinality, TerminateFailed: + case Proving, Available, UpdateActivating, ReleaseSectorKey, Removed, Removing, Terminating, TerminateWait, TerminateFinality, TerminateFailed: return sstProving } diff --git a/extern/storage-sealing/states_proving.go b/extern/storage-sealing/states_proving.go index e741199760b..afb5c54bfec 100644 --- a/extern/storage-sealing/states_proving.go +++ b/extern/storage-sealing/states_proving.go @@ -130,6 +130,11 @@ func (m *Sealing) handleRemoving(ctx statemachine.Context, sector SectorInfo) er func (m *Sealing) handleProvingSector(ctx statemachine.Context, sector SectorInfo) error { // TODO: track sector health / expiration + m.inputLk.Lock() + // in case we revert into Proving without going into Available + delete(m.available, m.minerSectorID(sector.SectorNumber)) + m.inputLk.Unlock() + cfg, err := m.getConfig() if err != nil { return xerrors.Errorf("getting sealing config: %w", err) @@ -144,3 +149,13 @@ func (m *Sealing) handleProvingSector(ctx statemachine.Context, sector SectorInf return nil } + +func (m *Sealing) handleAvailableSector(ctx statemachine.Context, sector SectorInfo) error { + m.inputLk.Lock() + m.available[m.minerSectorID(sector.SectorNumber)] = struct{}{} + m.inputLk.Unlock() + // TODO: Watch termination + // TODO: Auto-extend if set + + return nil +} diff --git a/extern/storage-sealing/upgrade_queue.go b/extern/storage-sealing/upgrade_queue.go index 1e5bef67c80..7f8bc9c039c 100644 --- a/extern/storage-sealing/upgrade_queue.go +++ b/extern/storage-sealing/upgrade_queue.go @@ -50,17 +50,6 @@ func (m *Sealing) MarkForUpgrade(ctx context.Context, id abi.SectorNumber) error } func (m *Sealing) MarkForSnapUpgrade(ctx context.Context, id abi.SectorNumber) error { - cfg, err := m.getConfig() - if err != nil { - return xerrors.Errorf("getting storage config: %w", err) - } - - curStaging := m.stats.curStaging() - if cfg.MaxWaitDealsSectors > 0 && curStaging >= cfg.MaxWaitDealsSectors { - return xerrors.Errorf("already waiting for deals in %d >= %d (cfg.MaxWaitDealsSectors) sectors, no free resources to wait for deals in another", - curStaging, cfg.MaxWaitDealsSectors) - } - si, err := m.GetSectorInfo(id) if err != nil { return xerrors.Errorf("getting sector info: %w", err) @@ -100,7 +89,7 @@ func (m *Sealing) MarkForSnapUpgrade(ctx context.Context, id abi.SectorNumber) e "Upgrade expiration before marking for upgrade", id, onChainInfo.Expiration) } - return m.sectors.Send(uint64(id), SectorStartCCUpdate{}) + return m.sectors.Send(uint64(id), SectorMarkForUpdate{}) } func sectorActive(ctx context.Context, api SealingAPI, maddr address.Address, tok TipSetToken, sector abi.SectorNumber) (bool, error) { diff --git a/itests/kit/log.go b/itests/kit/log.go index 3dce3af9d0c..4ec610baff1 100644 --- a/itests/kit/log.go +++ b/itests/kit/log.go @@ -15,5 +15,6 @@ func QuietMiningLogs() { _ = logging.SetLogLevel("storageminer", "ERROR") _ = logging.SetLogLevel("pubsub", "ERROR") _ = logging.SetLogLevel("gen", "ERROR") + _ = logging.SetLogLevel("rpc", "ERROR") _ = logging.SetLogLevel("dht/RtRefreshManager", "ERROR") } From 9a854e9ab70e731c03723066c23fbfde6016cf79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 16 Mar 2022 17:45:22 +0100 Subject: [PATCH 316/385] feat: sealing: Linter did have a good point --- extern/storage-sealing/input.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/storage-sealing/input.go b/extern/storage-sealing/input.go index 41f713c1cd2..05d3f137409 100644 --- a/extern/storage-sealing/input.go +++ b/extern/storage-sealing/input.go @@ -528,7 +528,7 @@ func (m *Sealing) calcTargetExpiration(ctx context.Context, ssize abi.SectorSize // earliest expiration first sort.Slice(candidates, func(i, j int) bool { - return candidates[i].deal.DealProposal.EndEpoch < candidates[i].deal.DealProposal.EndEpoch + return candidates[i].deal.DealProposal.EndEpoch < candidates[j].deal.DealProposal.EndEpoch }) var totalBytes uint64 From a9d757f3a04b7bcd6fa047602fa0cc8829e86fe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 16 Mar 2022 17:48:02 +0100 Subject: [PATCH 317/385] itests: TestTooManyMarkedForUpgrade is not applicable anymore --- itests/ccupgrade_test.go | 70 ---------------------------------------- 1 file changed, 70 deletions(-) diff --git a/itests/ccupgrade_test.go b/itests/ccupgrade_test.go index 6e7a5d09077..b8e58643ff6 100644 --- a/itests/ccupgrade_test.go +++ b/itests/ccupgrade_test.go @@ -10,7 +10,6 @@ import ( "github.com/filecoin-project/go-address" "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/chain/types" "github.com/filecoin-project/lotus/itests/kit" @@ -89,18 +88,6 @@ func runTestCCUpgrade(t *testing.T) *kit.TestFullNode { return client } -func waitForDeadline(ctx context.Context, t *testing.T, waitIdx uint64, node *kit.TestFullNode, maddr address.Address) { - for { - ts, err := node.ChainHead(ctx) - require.NoError(t, err) - dl, err := node.StateMinerProvingDeadline(ctx, maddr, ts.Key()) - require.NoError(t, err) - if dl.Index == waitIdx { - return - } - } -} - func waitForSectorActive(ctx context.Context, t *testing.T, sn abi.SectorNumber, node *kit.TestFullNode, maddr address.Address) { for { active, err := node.StateMinerActiveSectors(ctx, maddr, types.EmptyTSK) @@ -116,18 +103,6 @@ func waitForSectorActive(ctx context.Context, t *testing.T, sn abi.SectorNumber, } } -func waitForSectorStartUpgrade(ctx context.Context, t *testing.T, sn abi.SectorNumber, miner *kit.TestMiner) { - for { - si, err := miner.StorageMiner.SectorsStatus(ctx, sn, false) - require.NoError(t, err) - if si.State != api.SectorState("Proving") { - t.Logf("Done proving sector in state: %s", si.State) - return - } - - } -} - func TestCCUpgradeAndPoSt(t *testing.T) { kit.QuietMiningLogs() t.Run("upgrade and then post", func(t *testing.T) { @@ -147,48 +122,3 @@ func TestCCUpgradeAndPoSt(t *testing.T) { }) }) } - -func TestTooManyMarkedForUpgrade(t *testing.T) { - kit.QuietMiningLogs() - - ctx := context.Background() - blockTime := 1 * time.Millisecond - - client, miner, ens := kit.EnsembleMinimal(t, kit.GenesisNetworkVersion(network.Version15)) - ens.InterconnectAll().BeginMiningMustPost(blockTime) - - maddr, err := miner.ActorAddress(ctx) - if err != nil { - t.Fatal(err) - } - - CCUpgrade := abi.SectorNumber(kit.DefaultPresealsPerBootstrapMiner + 1) - waitForDeadline(ctx, t, 1, client, maddr) - miner.PledgeSectors(ctx, 3, 0, nil) - - sl, err := miner.SectorsList(ctx) - require.NoError(t, err) - require.Len(t, sl, 3, "expected 3 sectors") - - { - si, err := client.StateSectorGetInfo(ctx, maddr, CCUpgrade, types.EmptyTSK) - require.NoError(t, err) - require.Less(t, 50000, int(si.Expiration)) - } - - waitForSectorActive(ctx, t, CCUpgrade, client, maddr) - waitForSectorActive(ctx, t, CCUpgrade+1, client, maddr) - waitForSectorActive(ctx, t, CCUpgrade+2, client, maddr) - - err = miner.SectorMarkForUpgrade(ctx, CCUpgrade, true) - require.NoError(t, err) - err = miner.SectorMarkForUpgrade(ctx, CCUpgrade+1, true) - require.NoError(t, err) - - waitForSectorStartUpgrade(ctx, t, CCUpgrade, miner) - waitForSectorStartUpgrade(ctx, t, CCUpgrade+1, miner) - - err = miner.SectorMarkForUpgrade(ctx, CCUpgrade+2, true) - require.Error(t, err) - assert.Contains(t, err.Error(), "no free resources to wait for deals") -} From 1bd2cbbef6d7960b17027e27e2a109fbde3109da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 16 Mar 2022 18:53:54 +0100 Subject: [PATCH 318/385] sealing: Support abort uprade for Available sectors --- extern/storage-sealing/fsm.go | 1 + 1 file changed, 1 insertion(+) diff --git a/extern/storage-sealing/fsm.go b/extern/storage-sealing/fsm.go index 2088131f00b..3fc0f15696a 100644 --- a/extern/storage-sealing/fsm.go +++ b/extern/storage-sealing/fsm.go @@ -287,6 +287,7 @@ var fsmPlanners = map[SectorState]func(events []statemachine.Event, state *Secto ), Available: planOne( on(SectorStartCCUpdate{}, SnapDealsWaitDeals), + on(SectorAbortUpgrade{}, Proving), ), Terminating: planOne( on(SectorTerminating{}, TerminateWait), From 1158a928ecb1528598f99ac6bde5818773085f22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 16 Mar 2022 19:05:53 +0100 Subject: [PATCH 319/385] itests: Test reverting Available sectors to Proving --- itests/ccupgrade_test.go | 71 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/itests/ccupgrade_test.go b/itests/ccupgrade_test.go index b8e58643ff6..78a03ba02b4 100644 --- a/itests/ccupgrade_test.go +++ b/itests/ccupgrade_test.go @@ -4,6 +4,8 @@ package itests import ( "context" "fmt" + "github.com/filecoin-project/lotus/api" + sealing "github.com/filecoin-project/lotus/extern/storage-sealing" "testing" "time" @@ -122,3 +124,72 @@ func TestCCUpgradeAndPoSt(t *testing.T) { }) }) } + +func TestAbortUpgradeAvailable(t *testing.T) { + kit.QuietMiningLogs() + + ctx := context.Background() + blockTime := 1 * time.Millisecond + + client, miner, ens := kit.EnsembleMinimal(t, kit.GenesisNetworkVersion(network.Version15), kit.ThroughRPC()) + ens.InterconnectAll().BeginMiningMustPost(blockTime) + + maddr, err := miner.ActorAddress(ctx) + if err != nil { + t.Fatal(err) + } + + CCUpgrade := abi.SectorNumber(kit.DefaultPresealsPerBootstrapMiner + 1) + fmt.Printf("CCUpgrade: %d\n", CCUpgrade) + + // wait for deadline 0 to pass so that committing starts after post on preseals + // this gives max time for post to complete minimizing chances of timeout + // waitForDeadline(ctx, t, 1, client, maddr) + miner.PledgeSectors(ctx, 1, 0, nil) + sl, err := miner.SectorsList(ctx) + require.NoError(t, err) + require.Len(t, sl, 1, "expected 1 sector") + require.Equal(t, CCUpgrade, sl[0], "unexpected sector number") + { + si, err := client.StateSectorGetInfo(ctx, maddr, CCUpgrade, types.EmptyTSK) + require.NoError(t, err) + require.Less(t, 50000, int(si.Expiration)) + } + waitForSectorActive(ctx, t, CCUpgrade, client, maddr) + + err = miner.SectorMarkForUpgrade(ctx, sl[0], true) + require.NoError(t, err) + + sl, err = miner.SectorsList(ctx) + require.NoError(t, err) + require.Len(t, sl, 1, "expected 1 sector") + + ss, err := miner.SectorsStatus(ctx, sl[0], false) + require.NoError(t, err) + + for i := 0; i < 100; i++ { + ss, err = miner.SectorsStatus(ctx, sl[0], false) + require.NoError(t, err) + if ss.State == api.SectorState(sealing.Proving) { + time.Sleep(50 * time.Millisecond) + continue + } + + require.Equal(t, api.SectorState(sealing.Available), ss.State) + break + } + + require.NoError(t, miner.SectorAbortUpgrade(ctx, sl[0])) + + for i := 0; i < 100; i++ { + ss, err = miner.SectorsStatus(ctx, sl[0], false) + require.NoError(t, err) + if ss.State == api.SectorState(sealing.Available) { + time.Sleep(50 * time.Millisecond) + continue + } + + require.Equal(t, api.SectorState(sealing.Proving), ss.State) + break + } +} From d3cec2f0d1cfa8f721fa31e4c87c295b80018454 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 16 Mar 2022 19:29:47 +0100 Subject: [PATCH 320/385] sealing: Add MakeCCSectorsAvailable config --- documentation/en/default-lotus-miner-config.toml | 6 ++++++ extern/storage-sealing/fsm.go | 2 ++ extern/storage-sealing/fsm_events.go | 4 ++++ extern/storage-sealing/sealiface/config.go | 2 ++ extern/storage-sealing/states_sealing.go | 3 +++ node/config/doc_gen.go | 6 ++++++ node/config/types.go | 3 +++ node/modules/storageminer.go | 2 ++ 8 files changed, 28 insertions(+) diff --git a/documentation/en/default-lotus-miner-config.toml b/documentation/en/default-lotus-miner-config.toml index 30dfd0268b3..d00d790c5f1 100644 --- a/documentation/en/default-lotus-miner-config.toml +++ b/documentation/en/default-lotus-miner-config.toml @@ -365,6 +365,12 @@ # env var: LOTUS_SEALING_FINALIZEEARLY #FinalizeEarly = false + # After sealing CC sectors, make them available for upgrading with deals + # + # type: bool + # env var: LOTUS_SEALING_MAKECCSECTORSAVAILABLE + #MakeCCSectorsAvailable = false + # Whether to use available miner balance for sector collateral instead of sending it with each message # # type: bool diff --git a/extern/storage-sealing/fsm.go b/extern/storage-sealing/fsm.go index 3fc0f15696a..b85290f0464 100644 --- a/extern/storage-sealing/fsm.go +++ b/extern/storage-sealing/fsm.go @@ -111,6 +111,7 @@ var fsmPlanners = map[SectorState]func(events []statemachine.Event, state *Secto Committing: planCommitting, CommitFinalize: planOne( on(SectorFinalized{}, SubmitCommit), + on(SectorFinalizedAvailable{}, SubmitCommit), on(SectorFinalizeFailed{}, CommitFinalizeFailed), ), SubmitCommit: planOne( @@ -136,6 +137,7 @@ var fsmPlanners = map[SectorState]func(events []statemachine.Event, state *Secto FinalizeSector: planOne( on(SectorFinalized{}, Proving), + on(SectorFinalizedAvailable{}, Available), on(SectorFinalizeFailed{}, FinalizeFailed), ), diff --git a/extern/storage-sealing/fsm_events.go b/extern/storage-sealing/fsm_events.go index 4789c9bee2e..66497473f7f 100644 --- a/extern/storage-sealing/fsm_events.go +++ b/extern/storage-sealing/fsm_events.go @@ -286,6 +286,10 @@ type SectorFinalized struct{} func (evt SectorFinalized) apply(*SectorInfo) {} +type SectorFinalizedAvailable struct{} + +func (evt SectorFinalizedAvailable) apply(*SectorInfo) {} + type SectorRetryFinalize struct{} func (evt SectorRetryFinalize) apply(*SectorInfo) {} diff --git a/extern/storage-sealing/sealiface/config.go b/extern/storage-sealing/sealiface/config.go index 852034aa7fb..20bd2b56436 100644 --- a/extern/storage-sealing/sealiface/config.go +++ b/extern/storage-sealing/sealiface/config.go @@ -20,6 +20,8 @@ type Config struct { MakeNewSectorForDeals bool + MakeCCSectorsAvailable bool + WaitDealsDelay time.Duration CommittedCapacitySectorLifetime time.Duration diff --git a/extern/storage-sealing/states_sealing.go b/extern/storage-sealing/states_sealing.go index 3dba325ee42..f508717f76e 100644 --- a/extern/storage-sealing/states_sealing.go +++ b/extern/storage-sealing/states_sealing.go @@ -782,5 +782,8 @@ func (m *Sealing) handleFinalizeSector(ctx statemachine.Context, sector SectorIn return ctx.Send(SectorFinalizeFailed{xerrors.Errorf("finalize sector: %w", err)}) } + if cfg.MakeCCSectorsAvailable && !sector.hasDeals() { + return ctx.Send(SectorFinalizedAvailable{}) + } return ctx.Send(SectorFinalized{}) } diff --git a/node/config/doc_gen.go b/node/config/doc_gen.go index edb4cf892c3..972c196f792 100644 --- a/node/config/doc_gen.go +++ b/node/config/doc_gen.go @@ -750,6 +750,12 @@ avoid the relatively high cost of unsealing the data later, at the cost of more Comment: `Run sector finalization before submitting sector proof to the chain`, }, + { + Name: "MakeCCSectorsAvailable", + Type: "bool", + + Comment: `After sealing CC sectors, make them available for upgrading with deals`, + }, { Name: "CollateralFromMinerBalance", Type: "bool", diff --git a/node/config/types.go b/node/config/types.go index 8320aea7ebf..2e9357993e1 100644 --- a/node/config/types.go +++ b/node/config/types.go @@ -250,6 +250,9 @@ type SealingConfig struct { // Run sector finalization before submitting sector proof to the chain FinalizeEarly bool + // After sealing CC sectors, make them available for upgrading with deals + MakeCCSectorsAvailable bool + // Whether to use available miner balance for sector collateral instead of sending it with each message CollateralFromMinerBalance bool // Minimum available balance to keep in the miner actor before sending it with messages diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index bd21ee746ab..05d41a42742 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -897,6 +897,7 @@ func NewSetSealConfigFunc(r repo.LockedRepo) (dtypes.SetSealingConfigFunc, error MaxSealingSectorsForDeals: cfg.MaxSealingSectorsForDeals, CommittedCapacitySectorLifetime: config.Duration(cfg.CommittedCapacitySectorLifetime), WaitDealsDelay: config.Duration(cfg.WaitDealsDelay), + MakeCCSectorsAvailable: cfg.MakeCCSectorsAvailable, AlwaysKeepUnsealedCopy: cfg.AlwaysKeepUnsealedCopy, FinalizeEarly: cfg.FinalizeEarly, @@ -935,6 +936,7 @@ func ToSealingConfig(cfg *config.StorageMiner) sealiface.Config { MakeNewSectorForDeals: cfg.Dealmaking.MakeNewSectorForDeals, CommittedCapacitySectorLifetime: time.Duration(cfg.Sealing.CommittedCapacitySectorLifetime), WaitDealsDelay: time.Duration(cfg.Sealing.WaitDealsDelay), + MakeCCSectorsAvailable: cfg.Sealing.MakeCCSectorsAvailable, AlwaysKeepUnsealedCopy: cfg.Sealing.AlwaysKeepUnsealedCopy, FinalizeEarly: cfg.Sealing.FinalizeEarly, From 3c15314ed54de5e30511813d43296305fa0781b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 16 Mar 2022 19:53:00 +0100 Subject: [PATCH 321/385] sealing: Use bitfields in sectorActive --- extern/storage-sealing/sealing.go | 3 ++- extern/storage-sealing/upgrade_queue.go | 16 ++-------------- storage/adapter_storage_miner.go | 19 ++++++++++++++++--- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/extern/storage-sealing/sealing.go b/extern/storage-sealing/sealing.go index 642fbb1db97..e9dc7d0ce23 100644 --- a/extern/storage-sealing/sealing.go +++ b/extern/storage-sealing/sealing.go @@ -13,6 +13,7 @@ import ( "golang.org/x/xerrors" "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/crypto" @@ -63,7 +64,7 @@ type SealingAPI interface { StateMinerInfo(context.Context, address.Address, TipSetToken) (miner.MinerInfo, error) StateMinerAvailableBalance(context.Context, address.Address, TipSetToken) (big.Int, error) StateMinerSectorAllocated(context.Context, address.Address, abi.SectorNumber, TipSetToken) (bool, error) - StateMinerActiveSectors(context.Context, address.Address, TipSetToken) ([]*miner.SectorOnChainInfo, error) + StateMinerActiveSectors(context.Context, address.Address, TipSetToken) (bitfield.BitField, error) StateMarketStorageDeal(context.Context, abi.DealID, TipSetToken) (*api.MarketDeal, error) StateMarketStorageDealProposal(context.Context, abi.DealID, TipSetToken) (market.DealProposal, error) StateNetworkVersion(ctx context.Context, tok TipSetToken) (network.Version, error) diff --git a/extern/storage-sealing/upgrade_queue.go b/extern/storage-sealing/upgrade_queue.go index 7f8bc9c039c..5b37df9805e 100644 --- a/extern/storage-sealing/upgrade_queue.go +++ b/extern/storage-sealing/upgrade_queue.go @@ -59,11 +59,7 @@ func (m *Sealing) MarkForSnapUpgrade(ctx context.Context, id abi.SectorNumber) e return xerrors.Errorf("can't mark sectors not in the 'Proving' state for upgrade") } - if len(si.Pieces) != 1 { - return xerrors.Errorf("not a committed-capacity sector, expected 1 piece") - } - - if si.Pieces[0].DealInfo != nil { + if si.hasDeals() { return xerrors.Errorf("not a committed-capacity sector, has deals") } @@ -98,15 +94,7 @@ func sectorActive(ctx context.Context, api SealingAPI, maddr address.Address, to return false, xerrors.Errorf("failed to check active sectors: %w", err) } - // Ensure the upgraded sector is active - var found bool - for _, si := range active { - if si.SectorNumber == sector { - found = true - break - } - } - return found, nil + return active.IsSet(uint64(sector)) } func (m *Sealing) tryUpgradeSector(ctx context.Context, params *miner.SectorPreCommitInfo) big.Int { diff --git a/storage/adapter_storage_miner.go b/storage/adapter_storage_miner.go index 01ff9d8d3a4..d976d9aa21f 100644 --- a/storage/adapter_storage_miner.go +++ b/storage/adapter_storage_miner.go @@ -9,6 +9,7 @@ import ( "golang.org/x/xerrors" "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/crypto" @@ -112,13 +113,25 @@ func (s SealingAPIAdapter) StateMinerSectorAllocated(ctx context.Context, maddr return s.delegate.StateMinerSectorAllocated(ctx, maddr, sid, tsk) } -func (s SealingAPIAdapter) StateMinerActiveSectors(ctx context.Context, maddr address.Address, tok sealing.TipSetToken) ([]*miner.SectorOnChainInfo, error) { +func (s SealingAPIAdapter) StateMinerActiveSectors(ctx context.Context, maddr address.Address, tok sealing.TipSetToken) (bitfield.BitField, error) { tsk, err := types.TipSetKeyFromBytes(tok) if err != nil { - return nil, xerrors.Errorf("faile dto unmarshal TipSetToken to TipSetKey: %w", err) + return bitfield.BitField{}, xerrors.Errorf("failed to unmarshal TipSetToken to TipSetKey: %w", err) } - return s.delegate.StateMinerActiveSectors(ctx, maddr, tsk) + act, err := s.delegate.StateGetActor(ctx, maddr, tsk) + if err != nil { + return bitfield.BitField{}, xerrors.Errorf("getting miner actor: temp error: %+v", err) + } + + stor := store.ActorStore(ctx, blockstore.NewAPIBlockstore(s.delegate)) + + state, err := miner.Load(stor, act) + if err != nil { + return bitfield.BitField{}, xerrors.Errorf("loading miner state: %+v", err) + } + + return miner.AllPartSectors(state, miner.Partition.ActiveSectors) } func (s SealingAPIAdapter) StateWaitMsg(ctx context.Context, mcid cid.Cid) (sealing.MsgLookup, error) { From a44033954895f4895793a2c249b25816696c8522 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 16 Mar 2022 19:57:37 +0100 Subject: [PATCH 322/385] sealing: Run more checks when considering Available sectors --- extern/storage-sealing/input.go | 10 ++++++++++ extern/storage-sealing/upgrade_queue.go | 7 +++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/extern/storage-sealing/input.go b/extern/storage-sealing/input.go index 05d3f137409..cd5e5a509e0 100644 --- a/extern/storage-sealing/input.go +++ b/extern/storage-sealing/input.go @@ -570,6 +570,16 @@ func (m *Sealing) tryGetUpgradeSector(ctx context.Context, sp abi.RegisteredSeal continue } + active, err := m.sectorActive(ctx, TipSetToken{}, s.Number) + if err != nil { + log.Errorw("checking sector active", "error", err) + continue + } + if !active { + log.Debugw("skipping available sector", "reason", "not active") + continue + } + // if best is below target, we want larger expirations // if best is above target, we want lower pledge, but only if still above target diff --git a/extern/storage-sealing/upgrade_queue.go b/extern/storage-sealing/upgrade_queue.go index 5b37df9805e..165f13722ba 100644 --- a/extern/storage-sealing/upgrade_queue.go +++ b/extern/storage-sealing/upgrade_queue.go @@ -3,7 +3,6 @@ package sealing import ( "context" - "github.com/filecoin-project/go-address" "github.com/filecoin-project/lotus/chain/actors/builtin/miner" market7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/market" @@ -72,7 +71,7 @@ func (m *Sealing) MarkForSnapUpgrade(ctx context.Context, id abi.SectorNumber) e return xerrors.Errorf("failed to read sector on chain info: %w", err) } - active, err := sectorActive(ctx, m.Api, m.maddr, tok, id) + active, err := m.sectorActive(ctx, tok, id) if err != nil { return xerrors.Errorf("failed to check if sector is active") } @@ -88,8 +87,8 @@ func (m *Sealing) MarkForSnapUpgrade(ctx context.Context, id abi.SectorNumber) e return m.sectors.Send(uint64(id), SectorMarkForUpdate{}) } -func sectorActive(ctx context.Context, api SealingAPI, maddr address.Address, tok TipSetToken, sector abi.SectorNumber) (bool, error) { - active, err := api.StateMinerActiveSectors(ctx, maddr, tok) +func (m *Sealing) sectorActive(ctx context.Context, tok TipSetToken, sector abi.SectorNumber) (bool, error) { + active, err := m.Api.StateMinerActiveSectors(ctx, m.maddr, tok) if err != nil { return false, xerrors.Errorf("failed to check active sectors: %w", err) } From 62a393bf12e26f1fa355d8ff4fa882e5f3e97bd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 16 Mar 2022 20:04:48 +0100 Subject: [PATCH 323/385] sealing: Address snap queue review --- extern/storage-sealing/input.go | 14 +++++++++++--- itests/ccupgrade_test.go | 6 ------ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/extern/storage-sealing/input.go b/extern/storage-sealing/input.go index cd5e5a509e0..c683a465f75 100644 --- a/extern/storage-sealing/input.go +++ b/extern/storage-sealing/input.go @@ -556,7 +556,10 @@ func (m *Sealing) tryGetUpgradeSector(ctx context.Context, sp abi.RegisteredSeal return false, nil } - ssize, _ := sp.SectorSize() // error already checked in the caller + ssize, err := sp.SectorSize() + if err != nil { + return false, xerrors.Errorf("getting sector size: %w", err) + } targetExpiration := m.calcTargetExpiration(ctx, ssize) var candidate abi.SectorID @@ -592,7 +595,7 @@ func (m *Sealing) tryGetUpgradeSector(ctx context.Context, sp abi.RegisteredSeal continue } - if expiration > targetExpiration && pledge.LessThan(bestPledge) { + if expiration >= targetExpiration && pledge.LessThan(bestPledge) { bestExpiration = expiration bestPledge = pledge candidate = s @@ -600,7 +603,7 @@ func (m *Sealing) tryGetUpgradeSector(ctx context.Context, sp abi.RegisteredSeal } if bestExpiration == 0 { - // didn't find a good sector + // didn't find a good sector / no sectors were available return false, nil } @@ -686,6 +689,11 @@ func (m *Sealing) StartPacking(sid abi.SectorNumber) error { func (m *Sealing) AbortUpgrade(sid abi.SectorNumber) error { m.startupWait.Wait() + m.inputLk.Lock() + // always do this early + delete(m.available, m.minerSectorID(sid)) + m.inputLk.Unlock() + log.Infow("aborting upgrade of sector", "sector", sid, "trigger", "user") return m.sectors.Send(uint64(sid), SectorAbortUpgrade{xerrors.New("triggered by user")}) } diff --git a/itests/ccupgrade_test.go b/itests/ccupgrade_test.go index 78a03ba02b4..44c2143e6c1 100644 --- a/itests/ccupgrade_test.go +++ b/itests/ccupgrade_test.go @@ -49,9 +49,6 @@ func runTestCCUpgrade(t *testing.T) *kit.TestFullNode { CCUpgrade := abi.SectorNumber(kit.DefaultPresealsPerBootstrapMiner + 1) fmt.Printf("CCUpgrade: %d\n", CCUpgrade) - // wait for deadline 0 to pass so that committing starts after post on preseals - // this gives max time for post to complete minimizing chances of timeout - // waitForDeadline(ctx, t, 1, client, maddr) miner.PledgeSectors(ctx, 1, 0, nil) sl, err := miner.SectorsList(ctx) require.NoError(t, err) @@ -142,9 +139,6 @@ func TestAbortUpgradeAvailable(t *testing.T) { CCUpgrade := abi.SectorNumber(kit.DefaultPresealsPerBootstrapMiner + 1) fmt.Printf("CCUpgrade: %d\n", CCUpgrade) - // wait for deadline 0 to pass so that committing starts after post on preseals - // this gives max time for post to complete minimizing chances of timeout - // waitForDeadline(ctx, t, 1, client, maddr) miner.PledgeSectors(ctx, 1, 0, nil) sl, err := miner.SectorsList(ctx) require.NoError(t, err) From aa4adb0dfd38bd800c954cfea453a9e7d67f50ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 16 Mar 2022 20:09:18 +0100 Subject: [PATCH 324/385] sealing: Fix build --- extern/storage-sealing/input.go | 23 +++++++++++-------- extern/storage-sealing/states_failed.go | 2 +- .../storage-sealing/states_replica_update.go | 2 +- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/extern/storage-sealing/input.go b/extern/storage-sealing/input.go index c683a465f75..64efb4944f3 100644 --- a/extern/storage-sealing/input.go +++ b/extern/storage-sealing/input.go @@ -573,21 +573,24 @@ func (m *Sealing) tryGetUpgradeSector(ctx context.Context, sp abi.RegisteredSeal continue } - active, err := m.sectorActive(ctx, TipSetToken{}, s.Number) - if err != nil { - log.Errorw("checking sector active", "error", err) - continue - } - if !active { - log.Debugw("skipping available sector", "reason", "not active") - continue + slowChecks := func() bool { + active, err := m.sectorActive(ctx, TipSetToken{}, s.Number) + if err != nil { + log.Errorw("checking sector active", "error", err) + return false + } + if !active { + log.Debugw("skipping available sector", "reason", "not active") + return false + } + return true } // if best is below target, we want larger expirations // if best is above target, we want lower pledge, but only if still above target if bestExpiration < targetExpiration { - if expiration > bestExpiration { + if expiration > bestExpiration && slowChecks() { bestExpiration = expiration bestPledge = pledge candidate = s @@ -595,7 +598,7 @@ func (m *Sealing) tryGetUpgradeSector(ctx context.Context, sp abi.RegisteredSeal continue } - if expiration >= targetExpiration && pledge.LessThan(bestPledge) { + if expiration >= targetExpiration && pledge.LessThan(bestPledge) && slowChecks() { bestExpiration = expiration bestPledge = pledge candidate = s diff --git a/extern/storage-sealing/states_failed.go b/extern/storage-sealing/states_failed.go index a1c3be4609c..90fa5090a3a 100644 --- a/extern/storage-sealing/states_failed.go +++ b/extern/storage-sealing/states_failed.go @@ -238,7 +238,7 @@ func (m *Sealing) handleSubmitReplicaUpdateFailed(ctx statemachine.Context, sect } // Abort upgrade for sectors that went faulty since being marked for upgrade - active, err := sectorActive(ctx.Context(), m.Api, m.maddr, tok, sector.SectorNumber) + active, err := m.sectorActive(ctx.Context(), tok, sector.SectorNumber) if err != nil { log.Errorf("sector active check: api error, not proceeding: %+v", err) return nil diff --git a/extern/storage-sealing/states_replica_update.go b/extern/storage-sealing/states_replica_update.go index bede7a5fa81..8a4f05dc4a5 100644 --- a/extern/storage-sealing/states_replica_update.go +++ b/extern/storage-sealing/states_replica_update.go @@ -41,7 +41,7 @@ func (m *Sealing) handleProveReplicaUpdate(ctx statemachine.Context, sector Sect log.Errorf("handleProveReplicaUpdate: api error, not proceeding: %+v", err) return nil } - active, err := sectorActive(ctx.Context(), m.Api, m.maddr, tok, sector.SectorNumber) + active, err := m.sectorActive(ctx.Context(), tok, sector.SectorNumber) if err != nil { log.Errorf("sector active check: api error, not proceeding: %+v", err) return nil From b8ba5274e27f227ade054d60df56ecb3b6ca6192 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 16 Mar 2022 20:17:20 +0100 Subject: [PATCH 325/385] sealing: Enforce minimum expiration in tryGetUpgradeSector --- extern/storage-sealing/input.go | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/extern/storage-sealing/input.go b/extern/storage-sealing/input.go index 64efb4944f3..4c9c2127388 100644 --- a/extern/storage-sealing/input.go +++ b/extern/storage-sealing/input.go @@ -516,7 +516,7 @@ func (m *Sealing) updateInput(ctx context.Context, sp abi.RegisteredSealProof) e return nil } -func (m *Sealing) calcTargetExpiration(ctx context.Context, ssize abi.SectorSize) (target abi.ChainEpoch) { +func (m *Sealing) calcTargetExpiration(ctx context.Context, ssize abi.SectorSize) (minTarget, target abi.ChainEpoch, err error) { var candidates []*pendingPiece for _, piece := range m.pendingPieces { @@ -536,19 +536,18 @@ func (m *Sealing) calcTargetExpiration(ctx context.Context, ssize abi.SectorSize totalBytes += uint64(candidate.size) if totalBytes >= uint64(abi.PaddedPieceSize(ssize).Unpadded()) { - return candidate.deal.DealProposal.EndEpoch + return candidates[0].deal.DealProposal.EndEpoch, candidate.deal.DealProposal.EndEpoch, nil } } _, curEpoch, err := m.Api.ChainHead(ctx) if err != nil { - log.Errorf("getting current epoch: %s", err) - return 0 + return 0, 0, xerrors.Errorf("getting current epoch: %w", err) } - _, maxDur := policy.DealDurationBounds(0) + minDur, maxDur := policy.DealDurationBounds(0) - return curEpoch + maxDur + return curEpoch + minDur, curEpoch + maxDur, nil } func (m *Sealing) tryGetUpgradeSector(ctx context.Context, sp abi.RegisteredSealProof, ef expFn) (bool, error) { @@ -560,7 +559,10 @@ func (m *Sealing) tryGetUpgradeSector(ctx context.Context, sp abi.RegisteredSeal if err != nil { return false, xerrors.Errorf("getting sector size: %w", err) } - targetExpiration := m.calcTargetExpiration(ctx, ssize) + minExpiration, targetExpiration, err := m.calcTargetExpiration(ctx, ssize) + if err != nil { + return false, xerrors.Errorf("calculating min target expiration: %w", err) + } var candidate abi.SectorID var bestExpiration abi.ChainEpoch @@ -605,7 +607,8 @@ func (m *Sealing) tryGetUpgradeSector(ctx context.Context, sp abi.RegisteredSeal } } - if bestExpiration == 0 { + if bestExpiration < minExpiration { + log.Infow("Not upgrading any sectors", "available", len(m.available), "bestExp", bestExpiration, "target", targetExpiration, "min", minExpiration, "candidate", candidate) // didn't find a good sector / no sectors were available return false, nil } From 9e4c8881b6085cccbff36ce036a9e8caf0a1170b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 16 Mar 2022 20:20:07 +0100 Subject: [PATCH 326/385] sealing: regenerate mocks --- extern/storage-sealing/mocks/api.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/extern/storage-sealing/mocks/api.go b/extern/storage-sealing/mocks/api.go index 95c222ecdc4..efe89ff0b08 100644 --- a/extern/storage-sealing/mocks/api.go +++ b/extern/storage-sealing/mocks/api.go @@ -9,6 +9,7 @@ import ( reflect "reflect" address "github.com/filecoin-project/go-address" + bitfield "github.com/filecoin-project/go-bitfield" abi "github.com/filecoin-project/go-state-types/abi" big "github.com/filecoin-project/go-state-types/big" crypto "github.com/filecoin-project/go-state-types/crypto" @@ -214,10 +215,10 @@ func (mr *MockSealingAPIMockRecorder) StateMarketStorageDealProposal(arg0, arg1, } // StateMinerActiveSectors mocks base method. -func (m *MockSealingAPI) StateMinerActiveSectors(arg0 context.Context, arg1 address.Address, arg2 sealing.TipSetToken) ([]*miner.SectorOnChainInfo, error) { +func (m *MockSealingAPI) StateMinerActiveSectors(arg0 context.Context, arg1 address.Address, arg2 sealing.TipSetToken) (bitfield.BitField, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "StateMinerActiveSectors", arg0, arg1, arg2) - ret0, _ := ret[0].([]*miner.SectorOnChainInfo) + ret0, _ := ret[0].(bitfield.BitField) ret1, _ := ret[1].(error) return ret0, ret1 } From 5e14892ef8383314c5a508a50c652ae063afa476 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 16 Mar 2022 20:28:15 +0100 Subject: [PATCH 327/385] sealing: fix lint issues --- extern/storage-sealing/input.go | 8 ++++---- extern/storage-sealing/upgrade_queue.go | 6 +++--- itests/ccupgrade_test.go | 9 +++++---- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/extern/storage-sealing/input.go b/extern/storage-sealing/input.go index 4c9c2127388..b2fdeeaa37e 100644 --- a/extern/storage-sealing/input.go +++ b/extern/storage-sealing/input.go @@ -575,8 +575,8 @@ func (m *Sealing) tryGetUpgradeSector(ctx context.Context, sp abi.RegisteredSeal continue } - slowChecks := func() bool { - active, err := m.sectorActive(ctx, TipSetToken{}, s.Number) + slowChecks := func(sid abi.SectorNumber) bool { + active, err := m.sectorActive(ctx, TipSetToken{}, sid) if err != nil { log.Errorw("checking sector active", "error", err) return false @@ -592,7 +592,7 @@ func (m *Sealing) tryGetUpgradeSector(ctx context.Context, sp abi.RegisteredSeal // if best is above target, we want lower pledge, but only if still above target if bestExpiration < targetExpiration { - if expiration > bestExpiration && slowChecks() { + if expiration > bestExpiration && slowChecks(s.Number) { bestExpiration = expiration bestPledge = pledge candidate = s @@ -600,7 +600,7 @@ func (m *Sealing) tryGetUpgradeSector(ctx context.Context, sp abi.RegisteredSeal continue } - if expiration >= targetExpiration && pledge.LessThan(bestPledge) && slowChecks() { + if expiration >= targetExpiration && pledge.LessThan(bestPledge) && slowChecks(s.Number) { bestExpiration = expiration bestPledge = pledge candidate = s diff --git a/extern/storage-sealing/upgrade_queue.go b/extern/storage-sealing/upgrade_queue.go index 165f13722ba..fe95a6aa8c3 100644 --- a/extern/storage-sealing/upgrade_queue.go +++ b/extern/storage-sealing/upgrade_queue.go @@ -3,13 +3,13 @@ package sealing import ( "context" - "github.com/filecoin-project/lotus/chain/actors/builtin/miner" - market7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/market" - "golang.org/x/xerrors" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" + + "github.com/filecoin-project/lotus/chain/actors/builtin/miner" + market7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/market" ) func (m *Sealing) IsMarkedForUpgrade(id abi.SectorNumber) bool { diff --git a/itests/ccupgrade_test.go b/itests/ccupgrade_test.go index 44c2143e6c1..53e1ac703bf 100644 --- a/itests/ccupgrade_test.go +++ b/itests/ccupgrade_test.go @@ -4,19 +4,20 @@ package itests import ( "context" "fmt" - "github.com/filecoin-project/lotus/api" - sealing "github.com/filecoin-project/lotus/extern/storage-sealing" "testing" "time" "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/network" - "github.com/filecoin-project/lotus/chain/types" - "github.com/filecoin-project/lotus/itests/kit" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/types" + sealing "github.com/filecoin-project/lotus/extern/storage-sealing" + "github.com/filecoin-project/lotus/itests/kit" ) func TestCCUpgrade(t *testing.T) { From d78f1e4eee7e9f895d74089a2992f0ac7e23f250 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 16 Mar 2022 21:29:57 +0100 Subject: [PATCH 328/385] sealing: Rename Sealing.creating to a less confusing name --- extern/storage-sealing/input.go | 10 +++++----- extern/storage-sealing/sealing.go | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/extern/storage-sealing/input.go b/extern/storage-sealing/input.go index b2fdeeaa37e..723bd354570 100644 --- a/extern/storage-sealing/input.go +++ b/extern/storage-sealing/input.go @@ -33,8 +33,8 @@ func (m *Sealing) handleWaitDeals(ctx statemachine.Context, sector SectorInfo) e m.inputLk.Lock() - if m.creating != nil && *m.creating == sector.SectorNumber { - m.creating = nil + if m.nextDealSector != nil && *m.nextDealSector == sector.SectorNumber { + m.nextDealSector = nil } sid := m.minerSectorID(sector.SectorNumber) @@ -615,14 +615,14 @@ func (m *Sealing) tryGetUpgradeSector(ctx context.Context, sp abi.RegisteredSeal log.Infow("Upgrading sector", "number", candidate.Number, "type", "deal", "proofType", sp, "expiration", bestExpiration, "pledge", types.FIL(bestPledge)) delete(m.available, candidate) - m.creating = &candidate.Number + m.nextDealSector = &candidate.Number return true, m.sectors.Send(uint64(candidate.Number), SectorStartCCUpdate{}) } func (m *Sealing) tryGetDealSector(ctx context.Context, sp abi.RegisteredSealProof, ef expFn) error { m.startupWait.Wait() - if m.creating != nil { + if m.nextDealSector != nil { return nil // new sector is being created right now } @@ -656,7 +656,7 @@ func (m *Sealing) tryGetDealSector(ctx context.Context, sp abi.RegisteredSealPro return err } - m.creating = &sid + m.nextDealSector = &sid log.Infow("Creating sector", "number", sid, "type", "deal", "proofType", sp) return m.sectors.Send(uint64(sid), SectorStart{ diff --git a/extern/storage-sealing/sealing.go b/extern/storage-sealing/sealing.go index e9dc7d0ce23..8f6cf3226ea 100644 --- a/extern/storage-sealing/sealing.go +++ b/extern/storage-sealing/sealing.go @@ -105,7 +105,7 @@ type Sealing struct { sectorTimers map[abi.SectorID]*time.Timer pendingPieces map[cid.Cid]*pendingPiece assignedPieces map[abi.SectorID][]cid.Cid - creating *abi.SectorNumber // used to prevent a race where we could create a new sector more than once + nextDealSector *abi.SectorNumber // used to prevent a race where we could create a new sector more than once upgradeLk sync.Mutex toUpgrade map[abi.SectorNumber]struct{} From 4a1b211876cc6d553db3b1c1a9602368973e57e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 16 Mar 2022 22:16:39 +0100 Subject: [PATCH 329/385] miner cli: Treat Activating sectors like Proving in sectors list --- cmd/lotus-miner/sectors.go | 2 +- extern/storage-sealing/input.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/lotus-miner/sectors.go b/cmd/lotus-miner/sectors.go index 24098b5581e..150c0f2c670 100644 --- a/cmd/lotus-miner/sectors.go +++ b/cmd/lotus-miner/sectors.go @@ -351,7 +351,7 @@ var sectorsListCmd = &cli.Command{ if cctx.Bool("unproven") { for state := range sealing.ExistSectorStateList { - if state == sealing.Proving { + if state == sealing.Proving || state == sealing.Available { continue } states = append(states, api.SectorState(state)) diff --git a/extern/storage-sealing/input.go b/extern/storage-sealing/input.go index 723bd354570..d2b51edc984 100644 --- a/extern/storage-sealing/input.go +++ b/extern/storage-sealing/input.go @@ -608,7 +608,7 @@ func (m *Sealing) tryGetUpgradeSector(ctx context.Context, sp abi.RegisteredSeal } if bestExpiration < minExpiration { - log.Infow("Not upgrading any sectors", "available", len(m.available), "bestExp", bestExpiration, "target", targetExpiration, "min", minExpiration, "candidate", candidate) + log.Infow("Not upgrading any sectors", "available", len(m.available), "pieces", len(m.pendingPieces), "bestExp", bestExpiration, "target", targetExpiration, "min", minExpiration, "candidate", candidate) // didn't find a good sector / no sectors were available return false, nil } From 77b123b02f244719bb35ee97e8a721adb9a8e121 Mon Sep 17 00:00:00 2001 From: Aayush Date: Wed, 16 Mar 2022 11:58:23 -0400 Subject: [PATCH 330/385] CircSupply: Remove unused method --- chain/stmgr/supply.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/chain/stmgr/supply.go b/chain/stmgr/supply.go index 7e239d2dba3..7c55a1a0dc1 100644 --- a/chain/stmgr/supply.go +++ b/chain/stmgr/supply.go @@ -339,10 +339,6 @@ func (sm *StateManager) GetVMCirculatingSupply(ctx context.Context, height abi.C return cs.FilCirculating, err } -func (sm *StateManager) loadGenesisMsigs(ctx context.Context) error { - return nil -} - func (sm *StateManager) GetVMCirculatingSupplyDetailed(ctx context.Context, height abi.ChainEpoch, st *state.StateTree) (api.CirculatingSupply, error) { filVested, err := sm.GetFilVested(ctx, height) if err != nil { From 58876aefa3d878ea58fee13e55cbc53a10142f42 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Wed, 16 Mar 2022 17:29:58 -0400 Subject: [PATCH 331/385] Update FFI --- extern/filecoin-ffi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index 5d65755dc49..c2668aa67ec 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit 5d65755dc49ffb2a5282066bf1e848388dbbaada +Subproject commit c2668aa67ec589a773153022348b9c0ed6ed4d5d From 361dc55dfddd30e2bcf1962e792653df192e82c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 17 Mar 2022 15:40:11 +0100 Subject: [PATCH 332/385] fix: storagefsm: Fix error loop on bad event --- extern/storage-sealing/fsm.go | 2 +- extern/storage-sealing/fsm_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/extern/storage-sealing/fsm.go b/extern/storage-sealing/fsm.go index b85290f0464..a026661359f 100644 --- a/extern/storage-sealing/fsm.go +++ b/extern/storage-sealing/fsm.go @@ -399,7 +399,7 @@ func (m *Sealing) plan(events []statemachine.Event, state *SectorInfo) (func(sta processed, err := p(events, state) if err != nil { - return nil, 0, xerrors.Errorf("running planner for state %s failed: %w", state.State, err) + return nil, processed, xerrors.Errorf("running planner for state %s failed: %w", state.State, err) } ///// diff --git a/extern/storage-sealing/fsm_test.go b/extern/storage-sealing/fsm_test.go index 10ee17c6b8b..f3012a400f7 100644 --- a/extern/storage-sealing/fsm_test.go +++ b/extern/storage-sealing/fsm_test.go @@ -323,6 +323,33 @@ func TestBrokenState(t *testing.T) { } } +func TestBadEvent(t *testing.T) { + var notif []struct{ before, after SectorInfo } + ma, _ := address.NewIDAddress(55151) + m := test{ + s: &Sealing{ + maddr: ma, + stats: SectorStats{ + bySector: map[abi.SectorID]SectorState{}, + byState: map[SectorState]int64{}, + }, + notifee: func(before, after SectorInfo) { + notif = append(notif, struct{ before, after SectorInfo }{before, after}) + }, + }, + t: t, + state: &SectorInfo{State: Proving}, + } + + _, processed, err := m.s.Plan([]statemachine.Event{{User: SectorPacked{}}}, m.state) + require.NoError(t, err) + require.Equal(t, uint64(1), processed) + require.Equal(m.t, m.state.State, Proving) + + require.Len(t, m.state.Log, 2) + require.Contains(t, m.state.Log[1].Message, "received unexpected event") +} + func TestTicketExpired(t *testing.T) { var notif []struct{ before, after SectorInfo } ma, _ := address.NewIDAddress(55151) From 49a4c06a88fa3a3f408f3eae9977395b66691814 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 17 Mar 2022 15:15:54 +0100 Subject: [PATCH 333/385] fix: sealing: FinalizeSector doesn't need sealed replica access --- extern/sector-storage/manager.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index 595f6419ee7..70195d333d4 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -549,10 +549,10 @@ func (m *Manager) FinalizeSector(ctx context.Context, sector storage.SectorRef, } } - selector := newExistingSelector(m.index, sector.ID, storiface.FTCache|storiface.FTSealed, false) + selector := newExistingSelector(m.index, sector.ID, storiface.FTCache, false) err := m.sched.Schedule(ctx, sector, sealtasks.TTFinalize, selector, - m.schedFetch(sector, storiface.FTCache|storiface.FTSealed|unsealed, pathType, storiface.AcquireMove), + m.schedFetch(sector, storiface.FTCache|unsealed, pathType, storiface.AcquireMove), func(ctx context.Context, w Worker) error { _, err := m.waitSimpleCall(ctx)(w.FinalizeSector(ctx, sector, keepUnsealed)) return err From 84896f4790301b1786983bc4312d973414f5c8bc Mon Sep 17 00:00:00 2001 From: Jennifer Wang Date: Thu, 17 Mar 2022 15:13:01 -0400 Subject: [PATCH 334/385] update the change log for v1.15.1 --- CHANGELOG.md | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 330a14d8500..54b30b09494 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,113 @@ # Lotus changelog +# 1.15.1-rc1 / 2022-03-16 + +This is the first release candidate of the next *highly recommended* feature release v1.15.1. This feature release introduces Index Provider, GraphSync v2, and many other latest functionalities, improvements and bug fixes. +More importantly, node operator can now enable the FVM(experimental) to sync miannet!! + +## Highlights + +### 🔥🔥🔥 FVM (Experimental) 🔥🔥🔥 +- feat: fvm: FVM integration ([filecoin-project/lotus#8332](https://github.com/filecoin-project/lotus/pull/8332)) +The lotus team is excited to announce the launch of experimental non-programmable FVM on mainnet. By enabling `"LOTUS_USE_FVM_EXPERIMENTAL=1` envvar, the lotus daemon will be running the [WASM-compiled built-in actors](https://github.com/filecoin-project/builtin-actors) that is compatible with the existing chain(Network v15 OhSnap). If you are trying it out and having any questions or feedbacks, please leave a comment [here](https://github.com/filecoin-project/lotus/discussions/8334)! + + +### 🌟🌟🌟 Index Provider (Production Ready!) 🌟🌟🌟 +- feat: markets: Integrate index ingest protocol and retrieve by any CID ([filecoin-project/lotus#7313](https://github.com/filecoin-project/lotus/pull/7313)) + +More and more useful data is being stored in Filecoin via deals made by clients to Storage Providers. It is the goal that these content is discoverable when people needs them. To archive that goal, one of the projects [the Bedrock team](https://www.notion.so/pl-strflt/Bedrock-2e956d5d8143432080a1d84435ccf0ff) is working on is building an Indexer Ecosystem, a project that's focus on content addressing on Filecoin, then potentially have interoperability with IPFS in the future and eventually serve the retrieval market. The Indexer Ecosystem high level architecture overview diagram can be found [here](https://github.com/filecoin-project/storetheindex/blob/main/doc/indexer_ecosys.png) and a detailed write up about can be found [here](https://www.notion.so/pl-strflt/Introducing-Indexer-to-SP-90bf296794174a8281c121d4ce6747a0). + +That being said, with this release, lotus Storage Providers can easily become an Index Provider and serve the Indexer Content Addressing System. Index Providers generate advertisements from the deals made by a storage provider and announces the data to the indexer nodes for further processing: +- To learn more about *what is an Index Provider and how to be an Index Provider*, read it [here](https://lotus.filecoin.io/storage-providers/operate/index-provider/) in lotus docuementation. +- An [one-off migration](https://lotus.filecoin.io/storage-providers/operate/index-provider/#first-time-migration) is needed in order for a Storage Provider to become an Index Provider and announce the proper formatted index. It's *highly recommended* for all Index Provider to do a [force bulk initialization](https://lotus.filecoin.io/storage-providers/configure/dagstore/#forcing-bulk-initialization) to enable index announcement on all existing deals. + - Note that the Initialization places IO workload on your storage system. SP should set a proper `concurrency` based on your hardware or can stop/start initialization at their wish/convenience as proving deadlines approach and elapse, to avoid IOPS starvation or competition with window PoSt. +- After the first one-time migration, being an Index Provider barely puts any extra usage on SP's market system. + - You can find the testing result by SPX fellows [here](https://github.com/filecoin-project/lotus/discussions/8087). + +We recommend all Storage Providers that are serving deals in the Filecoin network to become a Index Provider, make the data you are storing discoverable for the retrieval market and retrieval clients! + - If you have any questions about becoming an index provider, or the indexer system in general, leave a comment [here](https://github.com/filecoin-project/lotus/discussions/8341). + - Follow the indexer project at https://github.com/filecoin-project/go-indexer-core. + - If you have any feature request or bug reports of running an index provider, create an issue in https://github.com/filecoin-project/index-provider. + - You may also join the #storetheindex channel in the Filecoin Slack to engage with the team & the community! + +### ❗️❗️❗️ Dag Migration For New CAR index format in DagStore ❗️❗️❗️ +The index provider leverages the latest CARv2 indexing format `MultihashIndexSorted`, which stores the multihash code as well as the digest of all CIDs in a CAR file. Thus, all Storage Providers SHOULD perform an one-off DAG mirgation to regenerate DagStore CARv2 indices. You have to do it to become an index provider, failing to do so may also impact your future deal making. + +## New Features +- feat: market utils: Support unixfsnode in TraverseDag ([filecoin-project/lotus#8168](https://github.com/filecoin-project/lotus/pull/8168)) +- feat: config: enable indexer providing by default ([filecoin-project/lotus#8314](https://github.com/filecoin-project/lotus/pull/8314)) +- feat: api: Make ClientCalcCommP multithreaded ([filecoin-project/lotus#8276](https://github.com/filecoin-project/lotus/pull/8276)) +- feat: config: Persistent subsystem log level config ([filecoin-project/lotus#8283](https://github.com/filecoin-project/lotus/pull/8283)) +- feat: shed: blockstore/vlog to car export cmds ([filecoin-project/lotus#8265](https://github.com/filecoin-project/lotus/pull/8265)) +- feat: shed: ItestD ([filecoin-project/lotus#8290](https://github.com/filecoin-project/lotus/pull/8290)) +- feat: Make add piece idempotent ([filecoin-project/lotus#8160](https://github.com/filecoin-project/lotus/pull/8160)) +- feat: paychmgr: Support paych funding (a.k.a. fast paid retrieval) ([filecoin-project/lotus#7883](https://github.com/filecoin-project/lotus/pull/7883)) +- feat: ci: packer snap ([filecoin-project/lotus#7819](https://github.com/filecoin-project/lotus/pull/7819)) +- feat: #6147: Include worker name in sealing errors ([filecoin-project/lotus#7844](https://github.com/filecoin-project/lotus/pull/7844)) +- Feat: cli: Remove verified data cap ([filecoin-project/lotus#8175](https://github.com/filecoin-project/lotus/pull/8175)) +- feat: gateway: add MsigGetVestingSchedule to gateway api ([filecoin-project/lotus#8104](https://github.com/filecoin-project/lotus/pull/8104)) +- feat: itests: add itests ensemble mocknet getter ([filecoin-project/lotus#8157](https://github.com/filecoin-project/lotus/pull/8157)) +- feat: lotus-miner sectors list --initial-pledge ([filecoin-project/lotus#8098](https://github.com/filecoin-project/lotus/pull/8098)) +- Resource Manager Metrics ([filecoin-project/lotus#8089](https://github.com/filecoin-project/lotus/pull/8089)) +- feat: cli: set current network version from params ([filecoin-project/lotus#8111](https://github.com/filecoin-project/lotus/pull/8111)) +- feat: Snapdeals support in `storage find` CLI ([filecoin-project/lotus#8130](https://github.com/filecoin-project/lotus/pull/8130)) + +## Improvements +- improve resource manager integration ([filecoin-project/lotus#8318](https://github.com/filecoin-project/lotus/pull/8318)) +- add check manual-stateless-deal with interactive deal making ([filecoin-project/lotus#7560](https://github.com/filecoin-project/lotus/pull/7560)) +- test: cli: adding wallet tests ([filecoin-project/lotus#8079](https://github.com/filecoin-project/lotus/pull/8079)) +- test: chain: unit tests for the syncer & sync manager ([filecoin-project/lotus#8072](https://github.com/filecoin-project/lotus/pull/8072)) +- test: cli: unit tests for sync related commands ([filecoin-project/lotus#8080](https://github.com/filecoin-project/lotus/pull/8080)) +- misc: wallet: wallet tests with annotations for system test matrix ([filecoin-project/lotus#7928](https://github.com/filecoin-project/lotus/pull/7928)) +- test: Cli: add mempool tests ([filecoin-project/lotus#8162](https://github.com/filecoin-project/lotus/pull/8162)) +- add a state-tree diff command to lotus shed ([filecoin-project/lotus#8081](https://github.com/filecoin-project/lotus/pull/8081)) +- test: mempool: Add unit and integration tests ([filecoin-project/lotus#8017](https://github.com/filecoin-project/lotus/pull/8017)) +- splistore cold object reification redux ([filecoin-project/lotus#8029](https://github.com/filecoin-project/lotus/pull/8029)) +- test: cli: chain category unit tests ([filecoin-project/lotus#8048](https://github.com/filecoin-project/lotus/pull/8048)) + +## Bug Fixes +- fix: storage cli: Output primary sector status correctly ([filecoin-project/lotus#8320](https://github.com/filecoin-project/lotus/pull/8320)) +- fix: sealing fsm: Handle inputLk correctly ([filecoin-project/lotus#8291](https://github.com/filecoin-project/lotus/pull/8291)) +- fix: piece provider: Don't log CIDs as binary ([filecoin-project/lotus#8287](https://github.com/filecoin-project/lotus/pull/8287)) +- fix:sealing:Log instead of error normal shutdown of state machine ([filecoin-project/lotus#8232](https://github.com/filecoin-project/lotus/pull/8232)) +- fix:sealing:Handle finalize replica update failures in fsm ([filecoin-project/lotus#8229](https://github.com/filecoin-project/lotus/pull/8229)) +- ci: appimage: re-install appimage CI ([filecoin-project/lotus#7943](https://github.com/filecoin-project/lotus/pull/7943)) +- fix: sealing: PRU insufficient collateral ([filecoin-project/lotus#8219](https://github.com/filecoin-project/lotus/pull/8219)) +- fix: shed: diff command ([filecoin-project/lotus#8202](https://github.com/filecoin-project/lotus/pull/8202)) +- Make `--lite` option visible in the lotus daemon help text ([filecoin-project/lotus#8207](https://github.com/filecoin-project/lotus/pull/8207)) +- fix:sealing:Less verbose sector manager logging ([filecoin-project/lotus#8213](https://github.com/filecoin-project/lotus/pull/8213)) +- avoid panic ([filecoin-project/lotus#8205](https://github.com/filecoin-project/lotus/pull/8205)) +- A package is vulnerable to Exposure of Sensitive Information ([filecoin-project/lotus#8204](https://github.com/filecoin-project/lotus/pull/8204)) +- fix: sealing: add flag usage ([filecoin-project/lotus#8190](https://github.com/filecoin-project/lotus/pull/8190)) +- Fix the epoch used for gas in the message pool & validation ([filecoin-project/lotus#8163](https://github.com/filecoin-project/lotus/pull/8163)) +- fix:sealing:really-do-it flag for abort upgrade ([filecoin-project/lotus#8181](https://github.com/filecoin-project/lotus/pull/8181)) +- fix:proving:post check sector handles snap deals replica faults ([filecoin-project/lotus#8177](https://github.com/filecoin-project/lotus/pull/8177)) +- fix: client: calculate commps for pieces bigger than 32GB ([filecoin-project/lotus#8179](https://github.com/filecoin-project/lotus/pull/8179)) +- fix:cli:Continue instead of return error if no valid value is filled ([filecoin-project/lotus#8131](https://github.com/filecoin-project/lotus/pull/8131)) +- fix: limit reification sizes ([filecoin-project/lotus#8149](https://github.com/filecoin-project/lotus/pull/8149)) +- fix: state: Allow lotus-miner info to complete without admin permission ([filecoin-project/lotus#8057](https://github.com/filecoin-project/lotus/pull/8057)) +- fix:paychan:deflake integration test ([filecoin-project/lotus#8088](https://github.com/filecoin-project/lotus/pull/8088)) +- fix: worker: allow enable/disabling ReplicaUpdate tasks ([filecoin-project/lotus#8090](https://github.com/filecoin-project/lotus/pull/8090)) +- don't fail reification on missing references ([filecoin-project/lotus#8128](https://github.com/filecoin-project/lotus/pull/8128)) +- sealer: fix error message ([filecoin-project/lotus#8121](https://github.com/filecoin-project/lotus/pull/8121)) +- don't track peer ids in rcmgr metrics ([filecoin-project/lotus#8099](https://github.com/filecoin-project/lotus/pull/8099)) +- temporarily disable reification ([filecoin-project/lotus#8132](https://github.com/filecoin-project/lotus/pull/8132)) +- [Describe]: when excute cmd "lotus-bench sealing" without "benchmark-… ([filecoin-project/lotus#8173](https://github.com/filecoin-project/lotus/pull/8173)) + +## Dependency Updates +- deps: update go-libp2p and go-libp2p-resource-manager ([filecoin-project/lotus#8289](https://github.com/filecoin-project/lotus/pull/8289)) +- feat(deps): update to graphsync v0.13.0 with 2.0 protocol ([filecoin-project/lotus#8273](https://github.com/filecoin-project/lotus/pull/8273)) +- dep: actor: get v7 ([filecoin-project/lotus#8194](https://github.com/filecoin-project/lotus/pull/8194)) +- github.com/filecoin-project/go-data-transfer (v1.14.1 -> v1.15.0): +- github.com/filecoin-project/go-fil-markets (v1.19.2 -> v1.20.1): +- deps: update go-libp2p to v0.18.0-rc5 ([filecoin-project/lotus#8169](https://github.com/filecoin-project/lotus/pull/8169)) + +## Others +- chore: build: backport releases ([filecoin-project/lotus#8192](https://github.com/filecoin-project/lotus/pull/8192)) +- feat: build: bump the version to v1.15.1-dev ([filecoin-project/lotus#8073](https://github.com/filecoin-project/lotus/pull/8073)) +- makefile: add make jen ([filecoin-project/lotus#8122](https://github.com/filecoin-project/lotus/pull/8122)) +- chore: Merge releases into master ([filecoin-project/lotus#8156](https://github.com/filecoin-project/lotus/pull/8156)) + # 1.15.0 / 2022-03-09 This is an optional release with retrieval improvements(client side), SP ux with unsealing, snap deals and regular deal making and many other new features, improvements and bug fixes. From 3c252e1d87be73c3c715a996a2c915e3295d97f8 Mon Sep 17 00:00:00 2001 From: Jennifer Wang Date: Thu, 17 Mar 2022 15:30:02 -0400 Subject: [PATCH 335/385] bump the version to v1.15.1-rc1 --- build/openrpc/full.json.gz | Bin 27023 -> 27023 bytes build/openrpc/miner.json.gz | Bin 13154 -> 13154 bytes build/openrpc/worker.json.gz | Bin 3961 -> 3961 bytes build/version.go | 2 +- documentation/en/cli-lotus-miner.md | 2 +- documentation/en/cli-lotus-worker.md | 2 +- documentation/en/cli-lotus.md | 2 +- go.mod | 2 +- go.sum | 3 ++- 9 files changed, 7 insertions(+), 6 deletions(-) diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 2261c102e43d406b7c5ee9f32fe6e6669891ea72..16040bf9c8ceb98dd04952becea566f5dcbf39f5 100644 GIT binary patch delta 26981 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 delta 26942 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 E0HkXo;s5{u diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 2ef745e363f046bd79be12f9150368b0af11e933..83c477de7de10df83eb4a5a8547ff4e60d3fdd9b 100644 GIT binary patch delta 23 fcmaEq_9$&a2lI|J|Bc<}jX0c+i(U|IV`2aRiiHX3 delta 23 ecmaEq_9$&a2Xn*=$Bo_RjW~F^EUiV`m>2+s^9dOM diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index 465501bc648c999ee83526a899f95e4e142a1eb1..74c8e394b6487c15670c107748f14c49f7c68a34 100644 GIT binary patch delta 23 fcmew<_fu{{GqeBuLmS&(^Kop57T?15jDZ0FihK$` delta 23 fcmew<_fu{{Gc)u3!yDUP^KsNLGzqaiV_*OPfE5WI diff --git a/build/version.go b/build/version.go index c80c1df4086..965ebb66218 100644 --- a/build/version.go +++ b/build/version.go @@ -37,7 +37,7 @@ func BuildTypeString() string { } // BuildVersion is the local build version -const BuildVersion = "1.15.1-dev" +const BuildVersion = "1.15.1-rc1" func UserVersion() string { if os.Getenv("LOTUS_VERSION_IGNORE_COMMIT") == "1" { diff --git a/documentation/en/cli-lotus-miner.md b/documentation/en/cli-lotus-miner.md index 382fe426546..688964f87b9 100644 --- a/documentation/en/cli-lotus-miner.md +++ b/documentation/en/cli-lotus-miner.md @@ -7,7 +7,7 @@ USAGE: lotus-miner [global options] command [command options] [arguments...] VERSION: - 1.15.1-dev + 1.15.1-rc1 COMMANDS: init Initialize a lotus miner repo diff --git a/documentation/en/cli-lotus-worker.md b/documentation/en/cli-lotus-worker.md index f9ca241235b..26f8f2420ee 100644 --- a/documentation/en/cli-lotus-worker.md +++ b/documentation/en/cli-lotus-worker.md @@ -7,7 +7,7 @@ USAGE: lotus-worker [global options] command [command options] [arguments...] VERSION: - 1.15.1-dev + 1.15.1-rc1 COMMANDS: run Start lotus worker diff --git a/documentation/en/cli-lotus.md b/documentation/en/cli-lotus.md index a9697f3aff0..5f50d6d4f2c 100644 --- a/documentation/en/cli-lotus.md +++ b/documentation/en/cli-lotus.md @@ -7,7 +7,7 @@ USAGE: lotus [global options] command [command options] [arguments...] VERSION: - 1.15.1-dev + 1.15.1-rc1 COMMANDS: daemon Start a lotus daemon process diff --git a/go.mod b/go.mod index 03450afdba7..3cf616d8966 100644 --- a/go.mod +++ b/go.mod @@ -105,7 +105,7 @@ require ( github.com/ipfs/interface-go-ipfs-core v0.5.2 github.com/ipld/go-car v0.3.3 github.com/ipld/go-car/v2 v2.1.1 - github.com/ipld/go-codec-dagpb v1.3.0 + github.com/ipld/go-codec-dagpb v1.3.2 github.com/ipld/go-ipld-prime v0.16.0 github.com/ipld/go-ipld-selector-text-lite v0.0.1 github.com/jonboulle/clockwork v0.2.2 // indirect diff --git a/go.sum b/go.sum index 8bbe3340afb..73ed47440c5 100644 --- a/go.sum +++ b/go.sum @@ -911,8 +911,9 @@ github.com/ipld/go-car v0.3.3/go.mod h1:/wkKF4908ULT4dFIFIUZYcfjAnj+KFnJvlh8Hsz1 github.com/ipld/go-car/v2 v2.1.1 h1:saaKz4nC0AdfCGHLYKeXLGn8ivoPC54fyS55uyOLKwA= github.com/ipld/go-car/v2 v2.1.1/go.mod h1:+2Yvf0Z3wzkv7NeI69i8tuZ+ft7jyjPYIWZzeVNeFcI= github.com/ipld/go-codec-dagpb v1.2.0/go.mod h1:6nBN7X7h8EOsEejZGqC7tej5drsdBAXbMHyBT+Fne5s= -github.com/ipld/go-codec-dagpb v1.3.0 h1:czTcaoAuNNyIYWs6Qe01DJ+sEX7B+1Z0LcXjSatMGe8= github.com/ipld/go-codec-dagpb v1.3.0/go.mod h1:ga4JTU3abYApDC3pZ00BC2RSvC3qfBb9MSJkMLSwnhA= +github.com/ipld/go-codec-dagpb v1.3.2 h1:MZQUIjanHXXfDuYmtWYT8nFbqfFsZuyHClj6VDmSXr4= +github.com/ipld/go-codec-dagpb v1.3.2/go.mod h1:ga4JTU3abYApDC3pZ00BC2RSvC3qfBb9MSJkMLSwnhA= github.com/ipld/go-ipld-prime v0.0.2-0.20191108012745-28a82f04c785/go.mod h1:bDDSvVz7vaK12FNvMeRYnpRFkSUPNQOiCYQezMD/P3w= github.com/ipld/go-ipld-prime v0.9.0/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= github.com/ipld/go-ipld-prime v0.9.1-0.20210324083106-dc342a9917db/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= From 7244ff9e1495fef16cb3d9ab95f574dfedfe48e4 Mon Sep 17 00:00:00 2001 From: Jiaying Wang <42981373+jennijuju@users.noreply.github.com> Date: Thu, 17 Mar 2022 17:37:13 -0400 Subject: [PATCH 336/385] Update CHANGELOG.md --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54b30b09494..7dac5d3ac1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ # 1.15.1-rc1 / 2022-03-16 This is the first release candidate of the next *highly recommended* feature release v1.15.1. This feature release introduces Index Provider, GraphSync v2, and many other latest functionalities, improvements and bug fixes. -More importantly, node operator can now enable the FVM(experimental) to sync miannet!! +More importantly, node operator can now enable the FVM(experimental) to sync mainnet!! ## Highlights @@ -15,7 +15,7 @@ The lotus team is excited to announce the launch of experimental non-programmabl ### 🌟🌟🌟 Index Provider (Production Ready!) 🌟🌟🌟 - feat: markets: Integrate index ingest protocol and retrieve by any CID ([filecoin-project/lotus#7313](https://github.com/filecoin-project/lotus/pull/7313)) -More and more useful data is being stored in Filecoin via deals made by clients to Storage Providers. It is the goal that these content is discoverable when people needs them. To archive that goal, one of the projects [the Bedrock team](https://www.notion.so/pl-strflt/Bedrock-2e956d5d8143432080a1d84435ccf0ff) is working on is building an Indexer Ecosystem, a project that's focus on content addressing on Filecoin, then potentially have interoperability with IPFS in the future and eventually serve the retrieval market. The Indexer Ecosystem high level architecture overview diagram can be found [here](https://github.com/filecoin-project/storetheindex/blob/main/doc/indexer_ecosys.png) and a detailed write up about can be found [here](https://www.notion.so/pl-strflt/Introducing-Indexer-to-SP-90bf296794174a8281c121d4ce6747a0). +More and more useful data is being stored on Filecoin via deals made by clients to Storage Providers. The goal is that this content is discoverable when people need them. To achieve that goal, one of the projects [the Bedrock team](https://www.notion.so/pl-strflt/Bedrock-2e956d5d8143432080a1d84435ccf0ff) is working on is building an Indexer Ecosystem, a project that's focus on content addressing on Filecoin, then potentially have interoperability with IPFS in the future and eventually serve the retrieval market. The Indexer Ecosystem high level architecture overview diagram can be found [here](https://github.com/filecoin-project/storetheindex/blob/main/doc/indexer_ecosys.png) and a detailed write up about can be found [here](https://www.notion.so/pl-strflt/Introducing-Indexer-to-SP-90bf296794174a8281c121d4ce6747a0). That being said, with this release, lotus Storage Providers can easily become an Index Provider and serve the Indexer Content Addressing System. Index Providers generate advertisements from the deals made by a storage provider and announces the data to the indexer nodes for further processing: - To learn more about *what is an Index Provider and how to be an Index Provider*, read it [here](https://lotus.filecoin.io/storage-providers/operate/index-provider/) in lotus docuementation. @@ -32,6 +32,7 @@ We recommend all Storage Providers that are serving deals in the Filecoin networ ### ❗️❗️❗️ Dag Migration For New CAR index format in DagStore ❗️❗️❗️ The index provider leverages the latest CARv2 indexing format `MultihashIndexSorted`, which stores the multihash code as well as the digest of all CIDs in a CAR file. Thus, all Storage Providers SHOULD perform an one-off DAG mirgation to regenerate DagStore CARv2 indices. You have to do it to become an index provider, failing to do so may also impact your future deal making. +Follow the instruction [here](https://lotus.filecoin.io/storage-providers/operate/index-provider/) to perform the migration. ## New Features - feat: market utils: Support unixfsnode in TraverseDag ([filecoin-project/lotus#8168](https://github.com/filecoin-project/lotus/pull/8168)) From 7d0f5dd4f9a603216b028d9e5ba9b80ebb44ded8 Mon Sep 17 00:00:00 2001 From: Aayush Date: Tue, 22 Mar 2022 20:44:51 -0400 Subject: [PATCH 337/385] FFI: Bump v7 actors to v7.0.6 --- extern/filecoin-ffi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index c2668aa67ec..e81d302831f 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit c2668aa67ec589a773153022348b9c0ed6ed4d5d +Subproject commit e81d302831f5dcd0c5b7b9415c353f8b43291b8c From 46447ef55c7aa264f86427f60074854611314236 Mon Sep 17 00:00:00 2001 From: Aayush Date: Mon, 21 Mar 2022 19:32:18 -0400 Subject: [PATCH 338/385] stmgr: call: use a buffered concurrent-access blockstore --- chain/stmgr/call.go | 6 +++--- testplans/lotus-soup/go.mod | 4 ++-- testplans/lotus-soup/go.sum | 43 ++++++++++++++++++++++--------------- 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/chain/stmgr/call.go b/chain/stmgr/call.go index 5db508008db..888ca0254b1 100644 --- a/chain/stmgr/call.go +++ b/chain/stmgr/call.go @@ -5,12 +5,12 @@ import ( "errors" "fmt" + "github.com/filecoin-project/lotus/blockstore" + cbor "github.com/ipfs/go-ipld-cbor" "github.com/filecoin-project/lotus/chain/state" - "github.com/filecoin-project/lotus/blockstore" - "github.com/filecoin-project/lotus/chain/rand" "github.com/filecoin-project/go-address" @@ -223,7 +223,7 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, pri return nil, err } - buffStore := blockstore.NewBuffered(sm.cs.StateBlockstore()) + buffStore := blockstore.NewTieredBstore(sm.cs.StateBlockstore(), blockstore.NewMemorySync()) vmopt := &vm.VMOpts{ StateBase: stateCid, Epoch: vmHeight, diff --git a/testplans/lotus-soup/go.mod b/testplans/lotus-soup/go.mod index 41847e082f9..4a54a5132e4 100644 --- a/testplans/lotus-soup/go.mod +++ b/testplans/lotus-soup/go.mod @@ -8,7 +8,7 @@ require ( github.com/davecgh/go-spew v1.1.1 github.com/drand/drand v1.3.0 github.com/filecoin-project/go-address v0.0.6 - github.com/filecoin-project/go-data-transfer v1.14.0 + github.com/filecoin-project/go-data-transfer v1.15.0 github.com/filecoin-project/go-fil-markets v1.20.1 github.com/filecoin-project/go-jsonrpc v0.1.5 github.com/filecoin-project/go-state-types v0.1.3 @@ -28,7 +28,7 @@ require ( github.com/ipfs/go-unixfs v0.3.1 github.com/ipld/go-car v0.3.3 github.com/kpacha/opencensus-influxdb v0.0.0-20181102202715-663e2683a27c - github.com/libp2p/go-libp2p v0.18.0-rc5 + github.com/libp2p/go-libp2p v0.18.0-rc6 github.com/libp2p/go-libp2p-core v0.14.0 github.com/libp2p/go-libp2p-pubsub-tracer v0.0.0-20200626141350-e730b32bf1e6 github.com/multiformats/go-multiaddr v0.5.0 diff --git a/testplans/lotus-soup/go.sum b/testplans/lotus-soup/go.sum index 51e5172a59a..bfc249e4e89 100644 --- a/testplans/lotus-soup/go.sum +++ b/testplans/lotus-soup/go.sum @@ -415,12 +415,12 @@ github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod github.com/filecoin-project/go-crypto v0.0.1 h1:AcvpSGGCgjaY8y1az6AMfKQWreF/pWO2JJGLl6gCq6o= github.com/filecoin-project/go-crypto v0.0.1/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= github.com/filecoin-project/go-dagaggregator-unixfs v0.2.0/go.mod h1:WTuJWgBQY0omnQqa8kRPT9O0Uj5wQOgslVMUuTeHdJ8= -github.com/filecoin-project/go-data-transfer v1.14.0 h1:4pnfJk8FYtqcdAg+QRGzaz57seUC/Tz+HJgPuGB7zdg= github.com/filecoin-project/go-data-transfer v1.14.0/go.mod h1:wNJKhaLLYBJDM3VFvgvYi4iUjPa69pz/1Q5Q4HzX2wE= +github.com/filecoin-project/go-data-transfer v1.15.0 h1:gVH7MxEgoj/qXPz+S6ggFlHlDv1mLlRZuJtTvcq8r1o= +github.com/filecoin-project/go-data-transfer v1.15.0/go.mod h1:RaJIYjh6x6z+FXKNvUULOdUZdN+JutKigfcMMbfykWA= github.com/filecoin-project/go-ds-versioning v0.0.0-20211206185234-508abd7c2aff/go.mod h1:C9/l9PnB1+mwPa26BBVpCjG/XQCB0yj/q5CK2J8X1I4= github.com/filecoin-project/go-ds-versioning v0.1.1 h1:JiyBqaQlwC+UM0WhcBtVEeT3XrX59mQhT8U3p7nu86o= github.com/filecoin-project/go-ds-versioning v0.1.1/go.mod h1:C9/l9PnB1+mwPa26BBVpCjG/XQCB0yj/q5CK2J8X1I4= -github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commcid v0.1.0 h1:3R4ds1A9r6cr8mvZBfMYxTS88OqLYEo6roi+GiIeOh8= github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= @@ -480,8 +480,8 @@ github.com/filecoin-project/specs-actors/v5 v5.0.4/go.mod h1:5BAKRAMsOOlD8+qCw4U github.com/filecoin-project/specs-actors/v6 v6.0.0/go.mod h1:V1AYfi5GkHXipx1mnVivoICZh3wtwPxDVuds+fbfQtk= github.com/filecoin-project/specs-actors/v6 v6.0.1 h1:laxvHNsvrq83Y9n+W7znVCePi3oLyRf0Rkl4jFO8Wew= github.com/filecoin-project/specs-actors/v6 v6.0.1/go.mod h1:V1AYfi5GkHXipx1mnVivoICZh3wtwPxDVuds+fbfQtk= -github.com/filecoin-project/specs-actors/v7 v7.0.0-20211117170924-fd07a4c7dff9/go.mod h1:p6LIOFezA1rgRLMewbvdi3Pp6SAu+q9FtJ9CAleSjrE= github.com/filecoin-project/specs-actors/v7 v7.0.0-20211222192039-c83bea50c402/go.mod h1:p6LIOFezA1rgRLMewbvdi3Pp6SAu+q9FtJ9CAleSjrE= +github.com/filecoin-project/specs-actors/v7 v7.0.0-rc1.0.20220118005651-2470cb39827e/go.mod h1:TA5FwCna+Yi36POaT7SLKXsgEDvJwc0V/L6ZsO19B9M= github.com/filecoin-project/specs-actors/v7 v7.0.0 h1:FQN7tjt3o68hfb3qLFSJBoLMuOFY0REkFVLO/zXj8RU= github.com/filecoin-project/specs-actors/v7 v7.0.0/go.mod h1:TA5FwCna+Yi36POaT7SLKXsgEDvJwc0V/L6ZsO19B9M= github.com/filecoin-project/specs-storage v0.2.0 h1:Y4UDv0apRQ3zI2GiPPubi8JblpUZZphEdaJUxCutfyg= @@ -502,8 +502,9 @@ github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVB github.com/franela/goblin v0.0.0-20210519012713-85d372ac71e2/go.mod h1:VzmDKDJVZI3aJmnRI9VjAn9nJ8qPPsN1fqzr9dqInIo= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= -github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss= github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= +github.com/frankban/quicktest v1.14.2 h1:SPb1KFFmM+ybpEjPUhCCkZOM5xlovT5UbrMvWnXyBns= +github.com/frankban/quicktest v1.14.2/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= @@ -737,8 +738,9 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -975,8 +977,9 @@ github.com/ipfs/go-fs-lock v0.0.6/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28 github.com/ipfs/go-fs-lock v0.0.7 h1:6BR3dajORFrFTkb5EpCUFIAypsoxpGpDSVUdFwzgL9U= github.com/ipfs/go-fs-lock v0.0.7/go.mod h1:Js8ka+FNYmgQRLrRXzU3CB/+Csr1BwrRilEcvYrHhhc= github.com/ipfs/go-graphsync v0.11.0/go.mod h1:wC+c8vGVjAHthsVIl8LKr37cUra2GOaMYcQNNmMxDqE= -github.com/ipfs/go-graphsync v0.12.0 h1:QCsVHVzb9FTkcm3NEa8GjXnUeGit1L9s08HcSVQ4m/g= github.com/ipfs/go-graphsync v0.12.0/go.mod h1:nASYWYETgsnMbQ3+DirNImOHQ8TY0a5AhAqyOY55tUg= +github.com/ipfs/go-graphsync v0.13.0 h1:8reYjVKxKocJ9jD471xs9XNuegquPrnBFuGZmCqT8zU= +github.com/ipfs/go-graphsync v0.13.0/go.mod h1:oPBU9JGNlyWHyH9lWYmyl19M++5yiXjBnNC4boh5nVU= github.com/ipfs/go-ipfs v0.11.0/go.mod h1:g68Thu2Ho11AWoHsN34P5fSK7iA6OWWRy3T/g8HLixc= github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08= github.com/ipfs/go-ipfs-blockstore v0.1.0/go.mod h1:5aD0AvHPi7mZc6Ci1WCAhiBQu2IsfTduLl+422H6Rqw= @@ -1106,8 +1109,9 @@ github.com/ipfs/go-unixfs v0.3.1 h1:LrfED0OGfG98ZEegO4/xiprx2O+yS+krCMQSp7zLVv8= github.com/ipfs/go-unixfs v0.3.1/go.mod h1:h4qfQYzghiIc8ZNFKiLMFWOTzrWIAtzYQ59W/pCFf1o= github.com/ipfs/go-unixfsnode v1.1.2/go.mod h1:5dcE2x03pyjHk4JjamXmunTMzz+VUtqvPwZjIEkfV6s= github.com/ipfs/go-unixfsnode v1.1.3/go.mod h1:ZZxUM5wXBC+G0Co9FjrYTOm+UlhZTjxLfRYdWY9veZ4= -github.com/ipfs/go-unixfsnode v1.2.0 h1:tHHBJftsJyHGa8bS62PpkYNqHy/Sug3c/vxxC8NaGQY= github.com/ipfs/go-unixfsnode v1.2.0/go.mod h1:mQEgLjxkV/1mohkC4p7taRRBYPBeXu97SA3YaerT2q0= +github.com/ipfs/go-unixfsnode v1.4.0 h1:9BUxHBXrbNi8mWHc6j+5C580WJqtVw9uoeEKn4tMhwA= +github.com/ipfs/go-unixfsnode v1.4.0/go.mod h1:qc7YFFZ8tABc58p62HnIYbUMwj9chhUuFWmxSokfePo= github.com/ipfs/go-verifcid v0.0.1 h1:m2HI7zIuR5TFyQ1b79Da5N9dnnCP1vcu2QqawmWlK2E= github.com/ipfs/go-verifcid v0.0.1/go.mod h1:5Hrva5KBeIog4A+UpqlaIU+DEstipcJYQQZc0g37pY0= github.com/ipfs/interface-go-ipfs-core v0.4.0/go.mod h1:UJBcU6iNennuI05amq3FQ7g0JHUkibHFAfhfUIy927o= @@ -1126,8 +1130,9 @@ github.com/ipld/go-car v0.3.3/go.mod h1:/wkKF4908ULT4dFIFIUZYcfjAnj+KFnJvlh8Hsz1 github.com/ipld/go-car/v2 v2.1.1 h1:saaKz4nC0AdfCGHLYKeXLGn8ivoPC54fyS55uyOLKwA= github.com/ipld/go-car/v2 v2.1.1/go.mod h1:+2Yvf0Z3wzkv7NeI69i8tuZ+ft7jyjPYIWZzeVNeFcI= github.com/ipld/go-codec-dagpb v1.2.0/go.mod h1:6nBN7X7h8EOsEejZGqC7tej5drsdBAXbMHyBT+Fne5s= -github.com/ipld/go-codec-dagpb v1.3.0 h1:czTcaoAuNNyIYWs6Qe01DJ+sEX7B+1Z0LcXjSatMGe8= github.com/ipld/go-codec-dagpb v1.3.0/go.mod h1:ga4JTU3abYApDC3pZ00BC2RSvC3qfBb9MSJkMLSwnhA= +github.com/ipld/go-codec-dagpb v1.3.2 h1:MZQUIjanHXXfDuYmtWYT8nFbqfFsZuyHClj6VDmSXr4= +github.com/ipld/go-codec-dagpb v1.3.2/go.mod h1:ga4JTU3abYApDC3pZ00BC2RSvC3qfBb9MSJkMLSwnhA= github.com/ipld/go-ipld-prime v0.0.2-0.20191108012745-28a82f04c785/go.mod h1:bDDSvVz7vaK12FNvMeRYnpRFkSUPNQOiCYQezMD/P3w= github.com/ipld/go-ipld-prime v0.9.0/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= github.com/ipld/go-ipld-prime v0.9.1-0.20210324083106-dc342a9917db/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= @@ -1138,8 +1143,9 @@ github.com/ipld/go-ipld-prime v0.14.0/go.mod h1:9ASQLwUFLptCov6lIYc70GRB4V7UTyLD github.com/ipld/go-ipld-prime v0.14.1/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= github.com/ipld/go-ipld-prime v0.14.2/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= github.com/ipld/go-ipld-prime v0.14.3-0.20211207234443-319145880958/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= -github.com/ipld/go-ipld-prime v0.14.4 h1:bqhmume8+nbNsX4/+J6eohktfZHAI8GKrF3rQ0xgOyc= github.com/ipld/go-ipld-prime v0.14.4/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= +github.com/ipld/go-ipld-prime v0.16.0 h1:RS5hhjB/mcpeEPJvfyj0qbOj/QL+/j05heZ0qa97dVo= +github.com/ipld/go-ipld-prime v0.16.0/go.mod h1:axSCuOCBPqrH+gvXr2w9uAOulJqBPhHPT2PjoiiU1qA= github.com/ipld/go-ipld-prime-proto v0.0.0-20191113031812-e32bd156a1e5/go.mod h1:gcvzoEDBjwycpXt3LBE061wT9f46szXGHAmj9uoP6fU= github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20211210234204-ce2a1c70cd73 h1:TsyATB2ZRRQGTwafJdgEUQkmjOExRV0DNokcihZxbnQ= github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20211210234204-ce2a1c70cd73/go.mod h1:2PJ0JgxyB08t0b2WKrcuqI3di0V+5n6RS/LTUJhkoxY= @@ -1302,8 +1308,8 @@ github.com/libp2p/go-libp2p v0.16.0/go.mod h1:ump42BsirwAWxKzsCiFnTtN1Yc+DuPu76f github.com/libp2p/go-libp2p v0.17.0/go.mod h1:Fkin50rsGdv5mm5BshBUtPRZknt9esfmYXBOYcwOTgw= github.com/libp2p/go-libp2p v0.18.0-rc1/go.mod h1:RgYlH7IIWHXREimC92bw5Lg1V2R5XmSzuLHb5fTnr+8= github.com/libp2p/go-libp2p v0.18.0-rc3/go.mod h1:WYL+Xw1iuwi6rdfzw5VIEpD+HqzYucHZ6fcUuumbI3M= -github.com/libp2p/go-libp2p v0.18.0-rc5 h1:88wWDHb9nNo0vBNCupLde3OTnFAkugOCNkrDfl3ivK4= -github.com/libp2p/go-libp2p v0.18.0-rc5/go.mod h1:aZPS5l84bDvCvP4jkyEUT/J6YOpUq33Fgqrs3K59mpI= +github.com/libp2p/go-libp2p v0.18.0-rc6 h1:IR6TVPYGo1wDY0tY61gyPQVxK1koOkXh49ejVfAnH7A= +github.com/libp2p/go-libp2p v0.18.0-rc6/go.mod h1:oOUOAlBrm1L0+jxT10h2TMUMTDz6pV3EvmkJ3beDYGQ= github.com/libp2p/go-libp2p-asn-util v0.0.0-20200825225859-85005c6cf052/go.mod h1:nRMRTab+kZuk0LnKZpxhOVH/ndsdr2Nr//Zltc/vwgo= github.com/libp2p/go-libp2p-asn-util v0.1.0 h1:rABPCO77SjdbJ/eJ/ynIo8vWICy1VEnL5JAxJbQLo1E= github.com/libp2p/go-libp2p-asn-util v0.1.0/go.mod h1:wu+AnM9Ii2KgO5jMmS1rz9dvzTdj8BXqsPR9HR0XB7I= @@ -1420,8 +1426,9 @@ github.com/libp2p/go-libp2p-mplex v0.2.3/go.mod h1:CK3p2+9qH9x+7ER/gWWDYJ3QW5ZxW github.com/libp2p/go-libp2p-mplex v0.3.0/go.mod h1:l9QWxRbbb5/hQMECEb908GbS9Sm2UAR2KFZKUJEynEs= github.com/libp2p/go-libp2p-mplex v0.4.0/go.mod h1:yCyWJE2sc6TBTnFpjvLuEJgTSw/u+MamvzILKdX7asw= github.com/libp2p/go-libp2p-mplex v0.4.1/go.mod h1:cmy+3GfqfM1PceHTLL7zQzAAYaryDu6iPSC+CIb094g= -github.com/libp2p/go-libp2p-mplex v0.5.0 h1:vt3k4E4HSND9XH4Z8rUpacPJFSAgLOv6HDvG8W9Ks9E= github.com/libp2p/go-libp2p-mplex v0.5.0/go.mod h1:eLImPJLkj3iG5t5lq68w3Vm5NAQ5BcKwrrb2VmOYb3M= +github.com/libp2p/go-libp2p-mplex v0.6.0 h1:5ubK4/vLE2JkogKlJ2JLeXcSfA6qY6mE2HMJV9ve/Sk= +github.com/libp2p/go-libp2p-mplex v0.6.0/go.mod h1:i3usuPrBbh9FD2fLZjGpotyNkwr42KStYZQY7BeTiu4= github.com/libp2p/go-libp2p-nat v0.0.4/go.mod h1:N9Js/zVtAXqaeT99cXgTV9e75KpnWCvVOiGzlcHmBbY= github.com/libp2p/go-libp2p-nat v0.0.5/go.mod h1:1qubaE5bTZMJE+E/uu2URroMbzdubFz1ChgiN79yKPE= github.com/libp2p/go-libp2p-nat v0.0.6/go.mod h1:iV59LVhB3IkFvS6S6sauVTSOrNEANnINbI/fkaLimiw= @@ -1485,8 +1492,8 @@ github.com/libp2p/go-libp2p-record v0.1.3 h1:R27hoScIhQf/A8XJZ8lYpnqh9LatJ5YbHs2 github.com/libp2p/go-libp2p-record v0.1.3/go.mod h1:yNUff/adKIfPnYQXgp6FQmNu3gLJ6EMg7+/vv2+9pY4= github.com/libp2p/go-libp2p-resource-manager v0.1.0/go.mod h1:wJPNjeE4XQlxeidwqVY5G6DLOKqFK33u2n8blpl0I6Y= github.com/libp2p/go-libp2p-resource-manager v0.1.3/go.mod h1:wJPNjeE4XQlxeidwqVY5G6DLOKqFK33u2n8blpl0I6Y= -github.com/libp2p/go-libp2p-resource-manager v0.1.4 h1:RcxMD0pytOUimx3BqTVs6IqItb3H5Qg44SD7XyT68lw= -github.com/libp2p/go-libp2p-resource-manager v0.1.4/go.mod h1:wJPNjeE4XQlxeidwqVY5G6DLOKqFK33u2n8blpl0I6Y= +github.com/libp2p/go-libp2p-resource-manager v0.1.5 h1:7J6t9KLFS0MxXDTfqA6rwfVCZl/yLQnXW5LpZjHAANI= +github.com/libp2p/go-libp2p-resource-manager v0.1.5/go.mod h1:wJPNjeE4XQlxeidwqVY5G6DLOKqFK33u2n8blpl0I6Y= github.com/libp2p/go-libp2p-routing v0.0.1/go.mod h1:N51q3yTr4Zdr7V8Jt2JIktVU+3xBBylx1MZeVA6t1Ys= github.com/libp2p/go-libp2p-routing v0.1.0/go.mod h1:zfLhI1RI8RLEzmEaaPwzonRvXeeSHddONWkcTcB54nE= github.com/libp2p/go-libp2p-routing-helpers v0.2.3 h1:xY61alxJ6PurSi+MXbywZpelvuU4U4p/gPTxjqCqTzY= @@ -1527,8 +1534,9 @@ github.com/libp2p/go-libp2p-testing v0.4.0/go.mod h1:Q+PFXYoiYFN5CAEG2w3gLPEzotl github.com/libp2p/go-libp2p-testing v0.4.2/go.mod h1:Q+PFXYoiYFN5CAEG2w3gLPEzotlKsNSbKQ/lImlOWF0= github.com/libp2p/go-libp2p-testing v0.5.0/go.mod h1:QBk8fqIL1XNcno/l3/hhaIEn4aLRijpYOR+zVjjlh+A= github.com/libp2p/go-libp2p-testing v0.6.0/go.mod h1:QBk8fqIL1XNcno/l3/hhaIEn4aLRijpYOR+zVjjlh+A= -github.com/libp2p/go-libp2p-testing v0.7.0 h1:9bfyhNINizxuLrKsenzGaZalXRXIaAEmx1BP/PzF1gM= github.com/libp2p/go-libp2p-testing v0.7.0/go.mod h1:OLbdn9DbgdMwv00v+tlp1l3oe2Cl+FAjoWIA2pa0X6E= +github.com/libp2p/go-libp2p-testing v0.8.0 h1:/te8SOIyj5sGH5Jr1Uoo+qYB00aK8O4+yHGzLgfE3kc= +github.com/libp2p/go-libp2p-testing v0.8.0/go.mod h1:gRdsNxQSxAZowTgcLY7CC33xPmleZzoBpqSYbWenqPc= github.com/libp2p/go-libp2p-tls v0.1.3/go.mod h1:wZfuewxOndz5RTnCAxFliGjvYSDA40sKitV4c50uI1M= github.com/libp2p/go-libp2p-tls v0.3.0/go.mod h1:fwF5X6PWGxm6IDRwF3V8AVCCj/hOd5oFlg+wo2FxJDY= github.com/libp2p/go-libp2p-tls v0.3.1 h1:lsE2zYte+rZCEOHF72J1Fg3XK3dGQyKvI6i5ehJfEp0= @@ -1580,8 +1588,9 @@ github.com/libp2p/go-mplex v0.1.1/go.mod h1:Xgz2RDCi3co0LeZfgjm4OgUF15+sVR8SRcu3 github.com/libp2p/go-mplex v0.1.2/go.mod h1:Xgz2RDCi3co0LeZfgjm4OgUF15+sVR8SRcu3SFXI1lk= github.com/libp2p/go-mplex v0.2.0/go.mod h1:0Oy/A9PQlwBytDRp4wSkFnzHYDKcpLot35JQ6msjvYQ= github.com/libp2p/go-mplex v0.3.0/go.mod h1:0Oy/A9PQlwBytDRp4wSkFnzHYDKcpLot35JQ6msjvYQ= -github.com/libp2p/go-mplex v0.4.0 h1:Ukkez9/4EOX5rTw4sHefNJp10dksftAA05ZgyjplUbM= github.com/libp2p/go-mplex v0.4.0/go.mod h1:y26Lx+wNVtMYMaPu300Cbot5LkEZ4tJaNYeHeT9dh6E= +github.com/libp2p/go-mplex v0.6.0 h1:5kKp029zrsLVJT5q6ASt4LwuZFxj3B13wXXaGmFrWg0= +github.com/libp2p/go-mplex v0.6.0/go.mod h1:y26Lx+wNVtMYMaPu300Cbot5LkEZ4tJaNYeHeT9dh6E= github.com/libp2p/go-msgio v0.0.2/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= github.com/libp2p/go-msgio v0.0.3/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= @@ -2261,6 +2270,7 @@ github.com/whyrusleeping/cbor-gen v0.0.0-20200826160007-0b9f6c5fb163/go.mod h1:f github.com/whyrusleeping/cbor-gen v0.0.0-20210118024343-169e9d70c0c2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20210219115102-f37d292932f2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20210303213153-67a261a1d291/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= +github.com/whyrusleeping/cbor-gen v0.0.0-20210713220151-be142a5ae1a8/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20220224212727-7a699437a831/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20220302191723-37c43cae8e14 h1:vo2wkP2ceHyGyZwFFtAabpot03EeSxxwAe57pOI9E/4= github.com/whyrusleeping/cbor-gen v0.0.0-20220302191723-37c43cae8e14/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= @@ -2825,7 +2835,6 @@ golang.org/x/tools v0.0.0-20200721032237-77f530d86f9a/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20201112185108-eeaa07dd7696/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= From 595e29186e572764ff38ff329ec51b7483e60d58 Mon Sep 17 00:00:00 2001 From: Aayush Date: Mon, 21 Mar 2022 19:32:18 -0400 Subject: [PATCH 339/385] stmgr: call: use a buffered concurrent-access blockstore --- chain/stmgr/call.go | 6 +++--- testplans/lotus-soup/go.mod | 4 ++-- testplans/lotus-soup/go.sum | 43 ++++++++++++++++++++++--------------- 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/chain/stmgr/call.go b/chain/stmgr/call.go index 5db508008db..888ca0254b1 100644 --- a/chain/stmgr/call.go +++ b/chain/stmgr/call.go @@ -5,12 +5,12 @@ import ( "errors" "fmt" + "github.com/filecoin-project/lotus/blockstore" + cbor "github.com/ipfs/go-ipld-cbor" "github.com/filecoin-project/lotus/chain/state" - "github.com/filecoin-project/lotus/blockstore" - "github.com/filecoin-project/lotus/chain/rand" "github.com/filecoin-project/go-address" @@ -223,7 +223,7 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, pri return nil, err } - buffStore := blockstore.NewBuffered(sm.cs.StateBlockstore()) + buffStore := blockstore.NewTieredBstore(sm.cs.StateBlockstore(), blockstore.NewMemorySync()) vmopt := &vm.VMOpts{ StateBase: stateCid, Epoch: vmHeight, diff --git a/testplans/lotus-soup/go.mod b/testplans/lotus-soup/go.mod index 41847e082f9..4a54a5132e4 100644 --- a/testplans/lotus-soup/go.mod +++ b/testplans/lotus-soup/go.mod @@ -8,7 +8,7 @@ require ( github.com/davecgh/go-spew v1.1.1 github.com/drand/drand v1.3.0 github.com/filecoin-project/go-address v0.0.6 - github.com/filecoin-project/go-data-transfer v1.14.0 + github.com/filecoin-project/go-data-transfer v1.15.0 github.com/filecoin-project/go-fil-markets v1.20.1 github.com/filecoin-project/go-jsonrpc v0.1.5 github.com/filecoin-project/go-state-types v0.1.3 @@ -28,7 +28,7 @@ require ( github.com/ipfs/go-unixfs v0.3.1 github.com/ipld/go-car v0.3.3 github.com/kpacha/opencensus-influxdb v0.0.0-20181102202715-663e2683a27c - github.com/libp2p/go-libp2p v0.18.0-rc5 + github.com/libp2p/go-libp2p v0.18.0-rc6 github.com/libp2p/go-libp2p-core v0.14.0 github.com/libp2p/go-libp2p-pubsub-tracer v0.0.0-20200626141350-e730b32bf1e6 github.com/multiformats/go-multiaddr v0.5.0 diff --git a/testplans/lotus-soup/go.sum b/testplans/lotus-soup/go.sum index 51e5172a59a..bfc249e4e89 100644 --- a/testplans/lotus-soup/go.sum +++ b/testplans/lotus-soup/go.sum @@ -415,12 +415,12 @@ github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod github.com/filecoin-project/go-crypto v0.0.1 h1:AcvpSGGCgjaY8y1az6AMfKQWreF/pWO2JJGLl6gCq6o= github.com/filecoin-project/go-crypto v0.0.1/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= github.com/filecoin-project/go-dagaggregator-unixfs v0.2.0/go.mod h1:WTuJWgBQY0omnQqa8kRPT9O0Uj5wQOgslVMUuTeHdJ8= -github.com/filecoin-project/go-data-transfer v1.14.0 h1:4pnfJk8FYtqcdAg+QRGzaz57seUC/Tz+HJgPuGB7zdg= github.com/filecoin-project/go-data-transfer v1.14.0/go.mod h1:wNJKhaLLYBJDM3VFvgvYi4iUjPa69pz/1Q5Q4HzX2wE= +github.com/filecoin-project/go-data-transfer v1.15.0 h1:gVH7MxEgoj/qXPz+S6ggFlHlDv1mLlRZuJtTvcq8r1o= +github.com/filecoin-project/go-data-transfer v1.15.0/go.mod h1:RaJIYjh6x6z+FXKNvUULOdUZdN+JutKigfcMMbfykWA= github.com/filecoin-project/go-ds-versioning v0.0.0-20211206185234-508abd7c2aff/go.mod h1:C9/l9PnB1+mwPa26BBVpCjG/XQCB0yj/q5CK2J8X1I4= github.com/filecoin-project/go-ds-versioning v0.1.1 h1:JiyBqaQlwC+UM0WhcBtVEeT3XrX59mQhT8U3p7nu86o= github.com/filecoin-project/go-ds-versioning v0.1.1/go.mod h1:C9/l9PnB1+mwPa26BBVpCjG/XQCB0yj/q5CK2J8X1I4= -github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commcid v0.1.0 h1:3R4ds1A9r6cr8mvZBfMYxTS88OqLYEo6roi+GiIeOh8= github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= @@ -480,8 +480,8 @@ github.com/filecoin-project/specs-actors/v5 v5.0.4/go.mod h1:5BAKRAMsOOlD8+qCw4U github.com/filecoin-project/specs-actors/v6 v6.0.0/go.mod h1:V1AYfi5GkHXipx1mnVivoICZh3wtwPxDVuds+fbfQtk= github.com/filecoin-project/specs-actors/v6 v6.0.1 h1:laxvHNsvrq83Y9n+W7znVCePi3oLyRf0Rkl4jFO8Wew= github.com/filecoin-project/specs-actors/v6 v6.0.1/go.mod h1:V1AYfi5GkHXipx1mnVivoICZh3wtwPxDVuds+fbfQtk= -github.com/filecoin-project/specs-actors/v7 v7.0.0-20211117170924-fd07a4c7dff9/go.mod h1:p6LIOFezA1rgRLMewbvdi3Pp6SAu+q9FtJ9CAleSjrE= github.com/filecoin-project/specs-actors/v7 v7.0.0-20211222192039-c83bea50c402/go.mod h1:p6LIOFezA1rgRLMewbvdi3Pp6SAu+q9FtJ9CAleSjrE= +github.com/filecoin-project/specs-actors/v7 v7.0.0-rc1.0.20220118005651-2470cb39827e/go.mod h1:TA5FwCna+Yi36POaT7SLKXsgEDvJwc0V/L6ZsO19B9M= github.com/filecoin-project/specs-actors/v7 v7.0.0 h1:FQN7tjt3o68hfb3qLFSJBoLMuOFY0REkFVLO/zXj8RU= github.com/filecoin-project/specs-actors/v7 v7.0.0/go.mod h1:TA5FwCna+Yi36POaT7SLKXsgEDvJwc0V/L6ZsO19B9M= github.com/filecoin-project/specs-storage v0.2.0 h1:Y4UDv0apRQ3zI2GiPPubi8JblpUZZphEdaJUxCutfyg= @@ -502,8 +502,9 @@ github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVB github.com/franela/goblin v0.0.0-20210519012713-85d372ac71e2/go.mod h1:VzmDKDJVZI3aJmnRI9VjAn9nJ8qPPsN1fqzr9dqInIo= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= -github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss= github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= +github.com/frankban/quicktest v1.14.2 h1:SPb1KFFmM+ybpEjPUhCCkZOM5xlovT5UbrMvWnXyBns= +github.com/frankban/quicktest v1.14.2/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= @@ -737,8 +738,9 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -975,8 +977,9 @@ github.com/ipfs/go-fs-lock v0.0.6/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28 github.com/ipfs/go-fs-lock v0.0.7 h1:6BR3dajORFrFTkb5EpCUFIAypsoxpGpDSVUdFwzgL9U= github.com/ipfs/go-fs-lock v0.0.7/go.mod h1:Js8ka+FNYmgQRLrRXzU3CB/+Csr1BwrRilEcvYrHhhc= github.com/ipfs/go-graphsync v0.11.0/go.mod h1:wC+c8vGVjAHthsVIl8LKr37cUra2GOaMYcQNNmMxDqE= -github.com/ipfs/go-graphsync v0.12.0 h1:QCsVHVzb9FTkcm3NEa8GjXnUeGit1L9s08HcSVQ4m/g= github.com/ipfs/go-graphsync v0.12.0/go.mod h1:nASYWYETgsnMbQ3+DirNImOHQ8TY0a5AhAqyOY55tUg= +github.com/ipfs/go-graphsync v0.13.0 h1:8reYjVKxKocJ9jD471xs9XNuegquPrnBFuGZmCqT8zU= +github.com/ipfs/go-graphsync v0.13.0/go.mod h1:oPBU9JGNlyWHyH9lWYmyl19M++5yiXjBnNC4boh5nVU= github.com/ipfs/go-ipfs v0.11.0/go.mod h1:g68Thu2Ho11AWoHsN34P5fSK7iA6OWWRy3T/g8HLixc= github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08= github.com/ipfs/go-ipfs-blockstore v0.1.0/go.mod h1:5aD0AvHPi7mZc6Ci1WCAhiBQu2IsfTduLl+422H6Rqw= @@ -1106,8 +1109,9 @@ github.com/ipfs/go-unixfs v0.3.1 h1:LrfED0OGfG98ZEegO4/xiprx2O+yS+krCMQSp7zLVv8= github.com/ipfs/go-unixfs v0.3.1/go.mod h1:h4qfQYzghiIc8ZNFKiLMFWOTzrWIAtzYQ59W/pCFf1o= github.com/ipfs/go-unixfsnode v1.1.2/go.mod h1:5dcE2x03pyjHk4JjamXmunTMzz+VUtqvPwZjIEkfV6s= github.com/ipfs/go-unixfsnode v1.1.3/go.mod h1:ZZxUM5wXBC+G0Co9FjrYTOm+UlhZTjxLfRYdWY9veZ4= -github.com/ipfs/go-unixfsnode v1.2.0 h1:tHHBJftsJyHGa8bS62PpkYNqHy/Sug3c/vxxC8NaGQY= github.com/ipfs/go-unixfsnode v1.2.0/go.mod h1:mQEgLjxkV/1mohkC4p7taRRBYPBeXu97SA3YaerT2q0= +github.com/ipfs/go-unixfsnode v1.4.0 h1:9BUxHBXrbNi8mWHc6j+5C580WJqtVw9uoeEKn4tMhwA= +github.com/ipfs/go-unixfsnode v1.4.0/go.mod h1:qc7YFFZ8tABc58p62HnIYbUMwj9chhUuFWmxSokfePo= github.com/ipfs/go-verifcid v0.0.1 h1:m2HI7zIuR5TFyQ1b79Da5N9dnnCP1vcu2QqawmWlK2E= github.com/ipfs/go-verifcid v0.0.1/go.mod h1:5Hrva5KBeIog4A+UpqlaIU+DEstipcJYQQZc0g37pY0= github.com/ipfs/interface-go-ipfs-core v0.4.0/go.mod h1:UJBcU6iNennuI05amq3FQ7g0JHUkibHFAfhfUIy927o= @@ -1126,8 +1130,9 @@ github.com/ipld/go-car v0.3.3/go.mod h1:/wkKF4908ULT4dFIFIUZYcfjAnj+KFnJvlh8Hsz1 github.com/ipld/go-car/v2 v2.1.1 h1:saaKz4nC0AdfCGHLYKeXLGn8ivoPC54fyS55uyOLKwA= github.com/ipld/go-car/v2 v2.1.1/go.mod h1:+2Yvf0Z3wzkv7NeI69i8tuZ+ft7jyjPYIWZzeVNeFcI= github.com/ipld/go-codec-dagpb v1.2.0/go.mod h1:6nBN7X7h8EOsEejZGqC7tej5drsdBAXbMHyBT+Fne5s= -github.com/ipld/go-codec-dagpb v1.3.0 h1:czTcaoAuNNyIYWs6Qe01DJ+sEX7B+1Z0LcXjSatMGe8= github.com/ipld/go-codec-dagpb v1.3.0/go.mod h1:ga4JTU3abYApDC3pZ00BC2RSvC3qfBb9MSJkMLSwnhA= +github.com/ipld/go-codec-dagpb v1.3.2 h1:MZQUIjanHXXfDuYmtWYT8nFbqfFsZuyHClj6VDmSXr4= +github.com/ipld/go-codec-dagpb v1.3.2/go.mod h1:ga4JTU3abYApDC3pZ00BC2RSvC3qfBb9MSJkMLSwnhA= github.com/ipld/go-ipld-prime v0.0.2-0.20191108012745-28a82f04c785/go.mod h1:bDDSvVz7vaK12FNvMeRYnpRFkSUPNQOiCYQezMD/P3w= github.com/ipld/go-ipld-prime v0.9.0/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= github.com/ipld/go-ipld-prime v0.9.1-0.20210324083106-dc342a9917db/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= @@ -1138,8 +1143,9 @@ github.com/ipld/go-ipld-prime v0.14.0/go.mod h1:9ASQLwUFLptCov6lIYc70GRB4V7UTyLD github.com/ipld/go-ipld-prime v0.14.1/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= github.com/ipld/go-ipld-prime v0.14.2/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= github.com/ipld/go-ipld-prime v0.14.3-0.20211207234443-319145880958/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= -github.com/ipld/go-ipld-prime v0.14.4 h1:bqhmume8+nbNsX4/+J6eohktfZHAI8GKrF3rQ0xgOyc= github.com/ipld/go-ipld-prime v0.14.4/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= +github.com/ipld/go-ipld-prime v0.16.0 h1:RS5hhjB/mcpeEPJvfyj0qbOj/QL+/j05heZ0qa97dVo= +github.com/ipld/go-ipld-prime v0.16.0/go.mod h1:axSCuOCBPqrH+gvXr2w9uAOulJqBPhHPT2PjoiiU1qA= github.com/ipld/go-ipld-prime-proto v0.0.0-20191113031812-e32bd156a1e5/go.mod h1:gcvzoEDBjwycpXt3LBE061wT9f46szXGHAmj9uoP6fU= github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20211210234204-ce2a1c70cd73 h1:TsyATB2ZRRQGTwafJdgEUQkmjOExRV0DNokcihZxbnQ= github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20211210234204-ce2a1c70cd73/go.mod h1:2PJ0JgxyB08t0b2WKrcuqI3di0V+5n6RS/LTUJhkoxY= @@ -1302,8 +1308,8 @@ github.com/libp2p/go-libp2p v0.16.0/go.mod h1:ump42BsirwAWxKzsCiFnTtN1Yc+DuPu76f github.com/libp2p/go-libp2p v0.17.0/go.mod h1:Fkin50rsGdv5mm5BshBUtPRZknt9esfmYXBOYcwOTgw= github.com/libp2p/go-libp2p v0.18.0-rc1/go.mod h1:RgYlH7IIWHXREimC92bw5Lg1V2R5XmSzuLHb5fTnr+8= github.com/libp2p/go-libp2p v0.18.0-rc3/go.mod h1:WYL+Xw1iuwi6rdfzw5VIEpD+HqzYucHZ6fcUuumbI3M= -github.com/libp2p/go-libp2p v0.18.0-rc5 h1:88wWDHb9nNo0vBNCupLde3OTnFAkugOCNkrDfl3ivK4= -github.com/libp2p/go-libp2p v0.18.0-rc5/go.mod h1:aZPS5l84bDvCvP4jkyEUT/J6YOpUq33Fgqrs3K59mpI= +github.com/libp2p/go-libp2p v0.18.0-rc6 h1:IR6TVPYGo1wDY0tY61gyPQVxK1koOkXh49ejVfAnH7A= +github.com/libp2p/go-libp2p v0.18.0-rc6/go.mod h1:oOUOAlBrm1L0+jxT10h2TMUMTDz6pV3EvmkJ3beDYGQ= github.com/libp2p/go-libp2p-asn-util v0.0.0-20200825225859-85005c6cf052/go.mod h1:nRMRTab+kZuk0LnKZpxhOVH/ndsdr2Nr//Zltc/vwgo= github.com/libp2p/go-libp2p-asn-util v0.1.0 h1:rABPCO77SjdbJ/eJ/ynIo8vWICy1VEnL5JAxJbQLo1E= github.com/libp2p/go-libp2p-asn-util v0.1.0/go.mod h1:wu+AnM9Ii2KgO5jMmS1rz9dvzTdj8BXqsPR9HR0XB7I= @@ -1420,8 +1426,9 @@ github.com/libp2p/go-libp2p-mplex v0.2.3/go.mod h1:CK3p2+9qH9x+7ER/gWWDYJ3QW5ZxW github.com/libp2p/go-libp2p-mplex v0.3.0/go.mod h1:l9QWxRbbb5/hQMECEb908GbS9Sm2UAR2KFZKUJEynEs= github.com/libp2p/go-libp2p-mplex v0.4.0/go.mod h1:yCyWJE2sc6TBTnFpjvLuEJgTSw/u+MamvzILKdX7asw= github.com/libp2p/go-libp2p-mplex v0.4.1/go.mod h1:cmy+3GfqfM1PceHTLL7zQzAAYaryDu6iPSC+CIb094g= -github.com/libp2p/go-libp2p-mplex v0.5.0 h1:vt3k4E4HSND9XH4Z8rUpacPJFSAgLOv6HDvG8W9Ks9E= github.com/libp2p/go-libp2p-mplex v0.5.0/go.mod h1:eLImPJLkj3iG5t5lq68w3Vm5NAQ5BcKwrrb2VmOYb3M= +github.com/libp2p/go-libp2p-mplex v0.6.0 h1:5ubK4/vLE2JkogKlJ2JLeXcSfA6qY6mE2HMJV9ve/Sk= +github.com/libp2p/go-libp2p-mplex v0.6.0/go.mod h1:i3usuPrBbh9FD2fLZjGpotyNkwr42KStYZQY7BeTiu4= github.com/libp2p/go-libp2p-nat v0.0.4/go.mod h1:N9Js/zVtAXqaeT99cXgTV9e75KpnWCvVOiGzlcHmBbY= github.com/libp2p/go-libp2p-nat v0.0.5/go.mod h1:1qubaE5bTZMJE+E/uu2URroMbzdubFz1ChgiN79yKPE= github.com/libp2p/go-libp2p-nat v0.0.6/go.mod h1:iV59LVhB3IkFvS6S6sauVTSOrNEANnINbI/fkaLimiw= @@ -1485,8 +1492,8 @@ github.com/libp2p/go-libp2p-record v0.1.3 h1:R27hoScIhQf/A8XJZ8lYpnqh9LatJ5YbHs2 github.com/libp2p/go-libp2p-record v0.1.3/go.mod h1:yNUff/adKIfPnYQXgp6FQmNu3gLJ6EMg7+/vv2+9pY4= github.com/libp2p/go-libp2p-resource-manager v0.1.0/go.mod h1:wJPNjeE4XQlxeidwqVY5G6DLOKqFK33u2n8blpl0I6Y= github.com/libp2p/go-libp2p-resource-manager v0.1.3/go.mod h1:wJPNjeE4XQlxeidwqVY5G6DLOKqFK33u2n8blpl0I6Y= -github.com/libp2p/go-libp2p-resource-manager v0.1.4 h1:RcxMD0pytOUimx3BqTVs6IqItb3H5Qg44SD7XyT68lw= -github.com/libp2p/go-libp2p-resource-manager v0.1.4/go.mod h1:wJPNjeE4XQlxeidwqVY5G6DLOKqFK33u2n8blpl0I6Y= +github.com/libp2p/go-libp2p-resource-manager v0.1.5 h1:7J6t9KLFS0MxXDTfqA6rwfVCZl/yLQnXW5LpZjHAANI= +github.com/libp2p/go-libp2p-resource-manager v0.1.5/go.mod h1:wJPNjeE4XQlxeidwqVY5G6DLOKqFK33u2n8blpl0I6Y= github.com/libp2p/go-libp2p-routing v0.0.1/go.mod h1:N51q3yTr4Zdr7V8Jt2JIktVU+3xBBylx1MZeVA6t1Ys= github.com/libp2p/go-libp2p-routing v0.1.0/go.mod h1:zfLhI1RI8RLEzmEaaPwzonRvXeeSHddONWkcTcB54nE= github.com/libp2p/go-libp2p-routing-helpers v0.2.3 h1:xY61alxJ6PurSi+MXbywZpelvuU4U4p/gPTxjqCqTzY= @@ -1527,8 +1534,9 @@ github.com/libp2p/go-libp2p-testing v0.4.0/go.mod h1:Q+PFXYoiYFN5CAEG2w3gLPEzotl github.com/libp2p/go-libp2p-testing v0.4.2/go.mod h1:Q+PFXYoiYFN5CAEG2w3gLPEzotlKsNSbKQ/lImlOWF0= github.com/libp2p/go-libp2p-testing v0.5.0/go.mod h1:QBk8fqIL1XNcno/l3/hhaIEn4aLRijpYOR+zVjjlh+A= github.com/libp2p/go-libp2p-testing v0.6.0/go.mod h1:QBk8fqIL1XNcno/l3/hhaIEn4aLRijpYOR+zVjjlh+A= -github.com/libp2p/go-libp2p-testing v0.7.0 h1:9bfyhNINizxuLrKsenzGaZalXRXIaAEmx1BP/PzF1gM= github.com/libp2p/go-libp2p-testing v0.7.0/go.mod h1:OLbdn9DbgdMwv00v+tlp1l3oe2Cl+FAjoWIA2pa0X6E= +github.com/libp2p/go-libp2p-testing v0.8.0 h1:/te8SOIyj5sGH5Jr1Uoo+qYB00aK8O4+yHGzLgfE3kc= +github.com/libp2p/go-libp2p-testing v0.8.0/go.mod h1:gRdsNxQSxAZowTgcLY7CC33xPmleZzoBpqSYbWenqPc= github.com/libp2p/go-libp2p-tls v0.1.3/go.mod h1:wZfuewxOndz5RTnCAxFliGjvYSDA40sKitV4c50uI1M= github.com/libp2p/go-libp2p-tls v0.3.0/go.mod h1:fwF5X6PWGxm6IDRwF3V8AVCCj/hOd5oFlg+wo2FxJDY= github.com/libp2p/go-libp2p-tls v0.3.1 h1:lsE2zYte+rZCEOHF72J1Fg3XK3dGQyKvI6i5ehJfEp0= @@ -1580,8 +1588,9 @@ github.com/libp2p/go-mplex v0.1.1/go.mod h1:Xgz2RDCi3co0LeZfgjm4OgUF15+sVR8SRcu3 github.com/libp2p/go-mplex v0.1.2/go.mod h1:Xgz2RDCi3co0LeZfgjm4OgUF15+sVR8SRcu3SFXI1lk= github.com/libp2p/go-mplex v0.2.0/go.mod h1:0Oy/A9PQlwBytDRp4wSkFnzHYDKcpLot35JQ6msjvYQ= github.com/libp2p/go-mplex v0.3.0/go.mod h1:0Oy/A9PQlwBytDRp4wSkFnzHYDKcpLot35JQ6msjvYQ= -github.com/libp2p/go-mplex v0.4.0 h1:Ukkez9/4EOX5rTw4sHefNJp10dksftAA05ZgyjplUbM= github.com/libp2p/go-mplex v0.4.0/go.mod h1:y26Lx+wNVtMYMaPu300Cbot5LkEZ4tJaNYeHeT9dh6E= +github.com/libp2p/go-mplex v0.6.0 h1:5kKp029zrsLVJT5q6ASt4LwuZFxj3B13wXXaGmFrWg0= +github.com/libp2p/go-mplex v0.6.0/go.mod h1:y26Lx+wNVtMYMaPu300Cbot5LkEZ4tJaNYeHeT9dh6E= github.com/libp2p/go-msgio v0.0.2/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= github.com/libp2p/go-msgio v0.0.3/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= @@ -2261,6 +2270,7 @@ github.com/whyrusleeping/cbor-gen v0.0.0-20200826160007-0b9f6c5fb163/go.mod h1:f github.com/whyrusleeping/cbor-gen v0.0.0-20210118024343-169e9d70c0c2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20210219115102-f37d292932f2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20210303213153-67a261a1d291/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= +github.com/whyrusleeping/cbor-gen v0.0.0-20210713220151-be142a5ae1a8/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20220224212727-7a699437a831/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20220302191723-37c43cae8e14 h1:vo2wkP2ceHyGyZwFFtAabpot03EeSxxwAe57pOI9E/4= github.com/whyrusleeping/cbor-gen v0.0.0-20220302191723-37c43cae8e14/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= @@ -2825,7 +2835,6 @@ golang.org/x/tools v0.0.0-20200721032237-77f530d86f9a/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20201112185108-eeaa07dd7696/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= From 450d4b256a499ac5c5ef5086964229c962036beb Mon Sep 17 00:00:00 2001 From: vyzo Date: Mon, 21 Mar 2022 12:33:07 +0200 Subject: [PATCH 340/385] update go-libp2p to v0.18 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3cf616d8966..6db254da458 100644 --- a/go.mod +++ b/go.mod @@ -112,7 +112,7 @@ require ( github.com/kelseyhightower/envconfig v1.4.0 github.com/libp2p/go-buffer-pool v0.0.2 github.com/libp2p/go-eventbus v0.2.1 - github.com/libp2p/go-libp2p v0.18.0-rc6 + github.com/libp2p/go-libp2p v0.18.0 github.com/libp2p/go-libp2p-connmgr v0.3.1 github.com/libp2p/go-libp2p-core v0.14.0 github.com/libp2p/go-libp2p-discovery v0.6.0 diff --git a/go.sum b/go.sum index 99983c499f1..ff427a32d97 100644 --- a/go.sum +++ b/go.sum @@ -1066,8 +1066,8 @@ github.com/libp2p/go-libp2p v0.16.0/go.mod h1:ump42BsirwAWxKzsCiFnTtN1Yc+DuPu76f github.com/libp2p/go-libp2p v0.17.0/go.mod h1:Fkin50rsGdv5mm5BshBUtPRZknt9esfmYXBOYcwOTgw= github.com/libp2p/go-libp2p v0.18.0-rc1/go.mod h1:RgYlH7IIWHXREimC92bw5Lg1V2R5XmSzuLHb5fTnr+8= github.com/libp2p/go-libp2p v0.18.0-rc3/go.mod h1:WYL+Xw1iuwi6rdfzw5VIEpD+HqzYucHZ6fcUuumbI3M= -github.com/libp2p/go-libp2p v0.18.0-rc6 h1:IR6TVPYGo1wDY0tY61gyPQVxK1koOkXh49ejVfAnH7A= -github.com/libp2p/go-libp2p v0.18.0-rc6/go.mod h1:oOUOAlBrm1L0+jxT10h2TMUMTDz6pV3EvmkJ3beDYGQ= +github.com/libp2p/go-libp2p v0.18.0 h1:moKKKG875KNGsCjZxTIFB75ihHiVjFeWg5I4aR1pDLk= +github.com/libp2p/go-libp2p v0.18.0/go.mod h1:+veaZ9z1SZQhmc5PW78jvnnxZ89Mgvmh4cggO11ETmw= github.com/libp2p/go-libp2p-asn-util v0.0.0-20200825225859-85005c6cf052/go.mod h1:nRMRTab+kZuk0LnKZpxhOVH/ndsdr2Nr//Zltc/vwgo= github.com/libp2p/go-libp2p-asn-util v0.1.0 h1:rABPCO77SjdbJ/eJ/ynIo8vWICy1VEnL5JAxJbQLo1E= github.com/libp2p/go-libp2p-asn-util v0.1.0/go.mod h1:wu+AnM9Ii2KgO5jMmS1rz9dvzTdj8BXqsPR9HR0XB7I= From 8e75a8d12dc3a45b55a3b3180b444941d1e5da69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 21 Mar 2022 10:32:03 +0100 Subject: [PATCH 341/385] fix: sealing: always do cooldown in handleSubmitReplicaUpdateFailed --- extern/storage-sealing/input.go | 4 ++++ extern/storage-sealing/states_failed.go | 12 ++++-------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/extern/storage-sealing/input.go b/extern/storage-sealing/input.go index d2b51edc984..b70bd809b09 100644 --- a/extern/storage-sealing/input.go +++ b/extern/storage-sealing/input.go @@ -473,6 +473,8 @@ func (m *Sealing) updateInput(ctx context.Context, sp abi.RegisteredSealProof) e return matches[i].sector.Number < matches[j].sector.Number // prefer older sectors }) + log.Debugw("updateInput matching", "matches", len(matches), "toAssign", len(toAssign), "openSectors", len(m.openSectors), "pieces", len(m.pendingPieces)) + var assigned int for _, mt := range matches { if m.pendingPieces[mt.deal].assigned { @@ -506,6 +508,8 @@ func (m *Sealing) updateInput(ctx context.Context, sp abi.RegisteredSealProof) e } } + log.Debugw("updateInput matching done", "matches", len(matches), "toAssign", len(toAssign), "assigned", assigned, "openSectors", len(m.openSectors), "pieces", len(m.pendingPieces)) + if len(toAssign) > 0 { log.Errorf("we are trying to create a new sector with open sectors %v", m.openSectors) if err := m.tryGetDealSector(ctx, sp, expF); err != nil { diff --git a/extern/storage-sealing/states_failed.go b/extern/storage-sealing/states_failed.go index 90fa5090a3a..dedba2fc6c6 100644 --- a/extern/storage-sealing/states_failed.go +++ b/extern/storage-sealing/states_failed.go @@ -184,14 +184,14 @@ func (m *Sealing) handleComputeProofFailed(ctx statemachine.Context, sector Sect } func (m *Sealing) handleSubmitReplicaUpdateFailed(ctx statemachine.Context, sector SectorInfo) error { + if err := failedCooldown(ctx, sector); err != nil { + return err + } + if sector.ReplicaUpdateMessage != nil { mw, err := m.Api.StateSearchMsg(ctx.Context(), *sector.ReplicaUpdateMessage) if err != nil { // API error - if err := failedCooldown(ctx, sector); err != nil { - return err - } - return ctx.Send(SectorRetrySubmitReplicaUpdateWait{}) } @@ -248,10 +248,6 @@ func (m *Sealing) handleSubmitReplicaUpdateFailed(ctx statemachine.Context, sect return ctx.Send(SectorAbortUpgrade{}) } - if err := failedCooldown(ctx, sector); err != nil { - return err - } - return ctx.Send(SectorRetrySubmitReplicaUpdate{}) } From 3fbf7656057d739389278e62a1e2cc6acf3f9c6e Mon Sep 17 00:00:00 2001 From: Aayush Date: Wed, 23 Mar 2022 13:17:32 -0400 Subject: [PATCH 342/385] FVM: log when fvm is used --- chain/vm/fvm.go | 1 + 1 file changed, 1 insertion(+) diff --git a/chain/vm/fvm.go b/chain/vm/fvm.go index 922eb77c5ab..72c84f966ec 100644 --- a/chain/vm/fvm.go +++ b/chain/vm/fvm.go @@ -217,6 +217,7 @@ type FVM struct { } func NewFVM(ctx context.Context, opts *VMOpts) (*FVM, error) { + log.Info("using the FVM, this is experimental!") circToReport := opts.FilVested // For v14 (and earlier), we perform the FilVested portion of the calculation, and let the FVM dynamically do the rest // v15 and after, the circ supply is always constant per epoch, so we calculate the base and report it at creation From 9436b15528b77253e580fbd2360261696b586fce Mon Sep 17 00:00:00 2001 From: Jennifer Wang Date: Wed, 23 Mar 2022 15:00:22 -0400 Subject: [PATCH 343/385] chore: release: v1.15.1-rc2 --- CHANGELOG.md | 11 +++++++++-- build/openrpc/full.json.gz | Bin 27023 -> 27023 bytes build/openrpc/miner.json.gz | Bin 13154 -> 13154 bytes build/openrpc/worker.json.gz | Bin 3961 -> 3961 bytes build/version.go | 2 +- documentation/en/cli-lotus-miner.md | 2 +- documentation/en/cli-lotus-worker.md | 2 +- documentation/en/cli-lotus.md | 2 +- 8 files changed, 13 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7dac5d3ac1d..d0f40743fa1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,8 @@ # Lotus changelog -# 1.15.1-rc1 / 2022-03-16 +# 1.15.1-rc2 / 2022-03-23 -This is the first release candidate of the next *highly recommended* feature release v1.15.1. This feature release introduces Index Provider, GraphSync v2, and many other latest functionalities, improvements and bug fixes. +This is the second release candidate of the next *highly recommended* feature release v1.15.1. This feature release introduces Index Provider, GraphSync v2, and many other latest functionalities, improvements and bug fixes. More importantly, node operator can now enable the FVM(experimental) to sync mainnet!! ## Highlights @@ -10,6 +10,7 @@ More importantly, node operator can now enable the FVM(experimental) to sync mai ### 🔥🔥🔥 FVM (Experimental) 🔥🔥🔥 - feat: fvm: FVM integration ([filecoin-project/lotus#8332](https://github.com/filecoin-project/lotus/pull/8332)) The lotus team is excited to announce the launch of experimental non-programmable FVM on mainnet. By enabling `"LOTUS_USE_FVM_EXPERIMENTAL=1` envvar, the lotus daemon will be running the [WASM-compiled built-in actors](https://github.com/filecoin-project/builtin-actors) that is compatible with the existing chain(Network v15 OhSnap). If you are trying it out and having any questions or feedbacks, please leave a comment [here](https://github.com/filecoin-project/lotus/discussions/8334)! + - chore: FVM: log when fvm is used([filecoin-project/lotus#8363](https://github.com/filecoin-project/lotus/pull/8363)) ### 🌟🌟🌟 Index Provider (Production Ready!) 🌟🌟🌟 @@ -35,6 +36,7 @@ The index provider leverages the latest CARv2 indexing format `MultihashIndexSor Follow the instruction [here](https://lotus.filecoin.io/storage-providers/operate/index-provider/) to perform the migration. ## New Features +- feat: sealing: Sector upgrade queue ([filecoin-project/lotus#8333](https://github.com/filecoin-project/lotus/pull/8333)) - feat: market utils: Support unixfsnode in TraverseDag ([filecoin-project/lotus#8168](https://github.com/filecoin-project/lotus/pull/8168)) - feat: config: enable indexer providing by default ([filecoin-project/lotus#8314](https://github.com/filecoin-project/lotus/pull/8314)) - feat: api: Make ClientCalcCommP multithreaded ([filecoin-project/lotus#8276](https://github.com/filecoin-project/lotus/pull/8276)) @@ -67,6 +69,10 @@ Follow the instruction [here](https://lotus.filecoin.io/storage-providers/operat - test: cli: chain category unit tests ([filecoin-project/lotus#8048](https://github.com/filecoin-project/lotus/pull/8048)) ## Bug Fixes +- fix: sealing: Remove sector copies from workers after snapdeals ([filecoin-project/lotus#8331](https://github.com/filecoin-project/lotus/pull/8331)) +- fix: storagefsm: Fix error loop on bad event ([filecoin-project/lotus#8339](https://github.com/filecoin-project/lotus/pull/8339)) +- fix: sealing: FinalizeSector doesn't need sealed replica access ([filecoin-project/lotus#8339](https://github.com/filecoin-project/lotus/pull/8339)) +- fix: sealing: always do cooldown in handleSubmitReplicaUpdateFailed ([filecoin-project/lotus#8353](https://github.com/filecoin-project/lotus/pull/8353)) - fix: storage cli: Output primary sector status correctly ([filecoin-project/lotus#8320](https://github.com/filecoin-project/lotus/pull/8320)) - fix: sealing fsm: Handle inputLk correctly ([filecoin-project/lotus#8291](https://github.com/filecoin-project/lotus/pull/8291)) - fix: piece provider: Don't log CIDs as binary ([filecoin-project/lotus#8287](https://github.com/filecoin-project/lotus/pull/8287)) @@ -99,6 +105,7 @@ Follow the instruction [here](https://lotus.filecoin.io/storage-providers/operat - deps: update go-libp2p and go-libp2p-resource-manager ([filecoin-project/lotus#8289](https://github.com/filecoin-project/lotus/pull/8289)) - feat(deps): update to graphsync v0.13.0 with 2.0 protocol ([filecoin-project/lotus#8273](https://github.com/filecoin-project/lotus/pull/8273)) - dep: actor: get v7 ([filecoin-project/lotus#8194](https://github.com/filecoin-project/lotus/pull/8194)) +- deps: update go-libp2p to v0.18 release ([filecoin-project/lotus#8355](https://github.com/filecoin-project/lotus/pull/8355)) - github.com/filecoin-project/go-data-transfer (v1.14.1 -> v1.15.0): - github.com/filecoin-project/go-fil-markets (v1.19.2 -> v1.20.1): - deps: update go-libp2p to v0.18.0-rc5 ([filecoin-project/lotus#8169](https://github.com/filecoin-project/lotus/pull/8169)) diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 16040bf9c8ceb98dd04952becea566f5dcbf39f5..0b2e8f6604a366859b16cdfb2e86001ee5414f66 100644 GIT binary patch delta 23 ecmeCb%-DaKaY7$s^~U}m85}|%RP)(`SQ!9)JqY~( delta 23 ecmeCb%-DaKaY7$s_Qw7n85{;;W-07JtPB8mh6pzR diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 83c477de7de10df83eb4a5a8547ff4e60d3fdd9b..497ff02b69988a107ff840ed64a80d148b589217 100644 GIT binary patch delta 21 dcmaEq_9$&a7i0X!?(;?*OW&V*B-+Nr004Vk3M~Kt delta 21 dcmaEq_9$&a7o-2i?(;?*PRB(rh_*2?0042d2+IHf diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index 74c8e394b6487c15670c107748f14c49f7c68a34..c4c2c353928a92680aeba75898ea618fc8c30fe4 100644 GIT binary patch delta 3866 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 delta 3866 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 c+j5j9_Y>f9dAt1o00030|FByZv Date: Sat, 26 Mar 2022 22:36:32 -0400 Subject: [PATCH 344/385] chore: ffi: the latest fvm release --- chain/vm/fvm.go | 15 +++++++++++---- extern/filecoin-ffi | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/chain/vm/fvm.go b/chain/vm/fvm.go index 72c84f966ec..ab32247e003 100644 --- a/chain/vm/fvm.go +++ b/chain/vm/fvm.go @@ -233,10 +233,17 @@ func NewFVM(ctx context.Context, opts *VMOpts) (*FVM, error) { } } - fvm, err := ffi.CreateFVM(0, - &FvmExtern{Rand: opts.Rand, Blockstore: opts.Bstore, lbState: opts.LookbackState, base: opts.StateBase, epoch: opts.Epoch}, - opts.Epoch, opts.BaseFee, circToReport, opts.NetworkVersion, opts.StateBase, - ) + fvmOpts := ffi.FVMOpts{ + FVMVersion: 0, + Externs: &FvmExtern{Rand: opts.Rand, Blockstore: opts.Bstore, lbState: opts.LookbackState, base: opts.StateBase, epoch: opts.Epoch}, + Epoch: opts.Epoch, + BaseFee: opts.BaseFee, + BaseCircSupply: circToReport, + NetworkVersion: opts.NetworkVersion, + StateBase: opts.StateBase, + } + + fvm, err := ffi.CreateFVM(&fvmOpts) if err != nil { return nil, err } diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index e81d302831f..7f93fe5cf63 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit e81d302831f5dcd0c5b7b9415c353f8b43291b8c +Subproject commit 7f93fe5cf63aee1c6c21986903e870b02e337a16 From c951e348b46b7738fdddc32ba16fb5d789e8a209 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sat, 26 Mar 2022 15:50:21 -0400 Subject: [PATCH 345/385] feat: config: Move MakeNewSectorForDeals config into the Sealing sectoin --- documentation/en/default-lotus-miner-config.toml | 16 ++++++++-------- node/config/def.go | 2 +- node/config/doc_gen.go | 16 ++++++++-------- node/config/types.go | 9 +++++---- node/modules/storageminer.go | 3 ++- 5 files changed, 24 insertions(+), 22 deletions(-) diff --git a/documentation/en/default-lotus-miner-config.toml b/documentation/en/default-lotus-miner-config.toml index d00d790c5f1..8e1d4ce0b95 100644 --- a/documentation/en/default-lotus-miner-config.toml +++ b/documentation/en/default-lotus-miner-config.toml @@ -173,14 +173,6 @@ # env var: LOTUS_DEALMAKING_EXPECTEDSEALDURATION #ExpectedSealDuration = "24h0m0s" - # Whether new sectors are created to pack incoming deals - # When this is set to false no new sectors will be created for sealing incoming deals - # This is useful for forcing all deals to be assigned as snap deals to sectors marked for upgrade - # - # type: bool - # env var: LOTUS_DEALMAKING_MAKENEWSECTORFORDEALS - #MakeNewSectorForDeals = true - # Maximum amount of time proposed deal StartEpoch can be in future # # type: Duration @@ -365,6 +357,14 @@ # env var: LOTUS_SEALING_FINALIZEEARLY #FinalizeEarly = false + # Whether new sectors are created to pack incoming deals + # When this is set to false no new sectors will be created for sealing incoming deals + # This is useful for forcing all deals to be assigned as snap deals to sectors marked for upgrade + # + # type: bool + # env var: LOTUS_SEALING_MAKENEWSECTORFORDEALS + #MakeNewSectorForDeals = true + # After sealing CC sectors, make them available for upgrading with deals # # type: bool diff --git a/node/config/def.go b/node/config/def.go index c70ab212900..86f655e3750 100644 --- a/node/config/def.go +++ b/node/config/def.go @@ -110,6 +110,7 @@ func DefaultStorageMiner() *StorageMiner { WaitDealsDelay: Duration(time.Hour * 6), AlwaysKeepUnsealedCopy: true, FinalizeEarly: false, + MakeNewSectorForDeals: true, CollateralFromMinerBalance: false, AvailableBalanceBuffer: types.FIL(big.Zero()), @@ -163,7 +164,6 @@ func DefaultStorageMiner() *StorageMiner { ConsiderVerifiedStorageDeals: true, ConsiderUnverifiedStorageDeals: true, PieceCidBlocklist: []cid.Cid{}, - MakeNewSectorForDeals: true, // TODO: It'd be nice to set this based on sector size MaxDealStartDelay: Duration(time.Hour * 24 * 14), ExpectedSealDuration: Duration(time.Hour * 24), diff --git a/node/config/doc_gen.go b/node/config/doc_gen.go index 972c196f792..d1aa69ff7dc 100644 --- a/node/config/doc_gen.go +++ b/node/config/doc_gen.go @@ -253,14 +253,6 @@ Default value: 1 minute.`, Comment: `Maximum expected amount of time getting the deal into a sealed sector will take This includes the time the deal will need to get transferred and published before being assigned to a sector`, - }, - { - Name: "MakeNewSectorForDeals", - Type: "bool", - - Comment: `Whether new sectors are created to pack incoming deals -When this is set to false no new sectors will be created for sealing incoming deals -This is useful for forcing all deals to be assigned as snap deals to sectors marked for upgrade`, }, { Name: "MaxDealStartDelay", @@ -750,6 +742,14 @@ avoid the relatively high cost of unsealing the data later, at the cost of more Comment: `Run sector finalization before submitting sector proof to the chain`, }, + { + Name: "MakeNewSectorForDeals", + Type: "bool", + + Comment: `Whether new sectors are created to pack incoming deals +When this is set to false no new sectors will be created for sealing incoming deals +This is useful for forcing all deals to be assigned as snap deals to sectors marked for upgrade`, + }, { Name: "MakeCCSectorsAvailable", Type: "bool", diff --git a/node/config/types.go b/node/config/types.go index 2e9357993e1..d8c01e85ba4 100644 --- a/node/config/types.go +++ b/node/config/types.go @@ -128,10 +128,6 @@ type DealmakingConfig struct { // This includes the time the deal will need to get transferred and published // before being assigned to a sector ExpectedSealDuration Duration - // Whether new sectors are created to pack incoming deals - // When this is set to false no new sectors will be created for sealing incoming deals - // This is useful for forcing all deals to be assigned as snap deals to sectors marked for upgrade - MakeNewSectorForDeals bool // Maximum amount of time proposed deal StartEpoch can be in future MaxDealStartDelay Duration // When a deal is ready to publish, the amount of time to wait for more @@ -250,6 +246,11 @@ type SealingConfig struct { // Run sector finalization before submitting sector proof to the chain FinalizeEarly bool + // Whether new sectors are created to pack incoming deals + // When this is set to false no new sectors will be created for sealing incoming deals + // This is useful for forcing all deals to be assigned as snap deals to sectors marked for upgrade + MakeNewSectorForDeals bool + // After sealing CC sectors, make them available for upgrading with deals MakeCCSectorsAvailable bool diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index 05d41a42742..a1986c44e8f 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -897,6 +897,7 @@ func NewSetSealConfigFunc(r repo.LockedRepo) (dtypes.SetSealingConfigFunc, error MaxSealingSectorsForDeals: cfg.MaxSealingSectorsForDeals, CommittedCapacitySectorLifetime: config.Duration(cfg.CommittedCapacitySectorLifetime), WaitDealsDelay: config.Duration(cfg.WaitDealsDelay), + MakeNewSectorForDeals: cfg.MakeNewSectorForDeals, MakeCCSectorsAvailable: cfg.MakeCCSectorsAvailable, AlwaysKeepUnsealedCopy: cfg.AlwaysKeepUnsealedCopy, FinalizeEarly: cfg.FinalizeEarly, @@ -933,7 +934,7 @@ func ToSealingConfig(cfg *config.StorageMiner) sealiface.Config { MaxSealingSectors: cfg.Sealing.MaxSealingSectors, MaxSealingSectorsForDeals: cfg.Sealing.MaxSealingSectorsForDeals, StartEpochSealingBuffer: abi.ChainEpoch(cfg.Dealmaking.StartEpochSealingBuffer), - MakeNewSectorForDeals: cfg.Dealmaking.MakeNewSectorForDeals, + MakeNewSectorForDeals: cfg.Sealing.MakeNewSectorForDeals, CommittedCapacitySectorLifetime: time.Duration(cfg.Sealing.CommittedCapacitySectorLifetime), WaitDealsDelay: time.Duration(cfg.Sealing.WaitDealsDelay), MakeCCSectorsAvailable: cfg.Sealing.MakeCCSectorsAvailable, From eeab118a05ab6db7d90c2f1f650cd6ace79103d9 Mon Sep 17 00:00:00 2001 From: jennijuju Date: Sun, 27 Mar 2022 19:36:10 -0400 Subject: [PATCH 346/385] chore: build: v1.15.1-rc3 --- CHANGELOG.md | 7 ++++--- build/openrpc/full.json.gz | Bin 27023 -> 27023 bytes build/openrpc/miner.json.gz | Bin 13154 -> 13154 bytes build/openrpc/worker.json.gz | Bin 3961 -> 3961 bytes build/version.go | 2 +- documentation/en/cli-lotus-miner.md | 2 +- documentation/en/cli-lotus-worker.md | 2 +- documentation/en/cli-lotus.md | 2 +- 8 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d0f40743fa1..8fb5b619ee1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Lotus changelog -# 1.15.1-rc2 / 2022-03-23 +# 1.15.1-rc3 / 2022-03-27 This is the second release candidate of the next *highly recommended* feature release v1.15.1. This feature release introduces Index Provider, GraphSync v2, and many other latest functionalities, improvements and bug fixes. More importantly, node operator can now enable the FVM(experimental) to sync mainnet!! @@ -10,8 +10,8 @@ More importantly, node operator can now enable the FVM(experimental) to sync mai ### 🔥🔥🔥 FVM (Experimental) 🔥🔥🔥 - feat: fvm: FVM integration ([filecoin-project/lotus#8332](https://github.com/filecoin-project/lotus/pull/8332)) The lotus team is excited to announce the launch of experimental non-programmable FVM on mainnet. By enabling `"LOTUS_USE_FVM_EXPERIMENTAL=1` envvar, the lotus daemon will be running the [WASM-compiled built-in actors](https://github.com/filecoin-project/builtin-actors) that is compatible with the existing chain(Network v15 OhSnap). If you are trying it out and having any questions or feedbacks, please leave a comment [here](https://github.com/filecoin-project/lotus/discussions/8334)! - - chore: FVM: log when fvm is used([filecoin-project/lotus#8363](https://github.com/filecoin-project/lotus/pull/8363)) - + - chore: FVM: log when fvm is used([filecoin-project/lotus#8363](https://github.com/filecoin-project/lotus/pull/8363)) + - chore: ffi: the latest fvm release([filecoin-project/lotus#8382](https://github.com/filecoin-project/lotus/pull/8382)) ### 🌟🌟🌟 Index Provider (Production Ready!) 🌟🌟🌟 - feat: markets: Integrate index ingest protocol and retrieve by any CID ([filecoin-project/lotus#7313](https://github.com/filecoin-project/lotus/pull/7313)) @@ -67,6 +67,7 @@ Follow the instruction [here](https://lotus.filecoin.io/storage-providers/operat - test: mempool: Add unit and integration tests ([filecoin-project/lotus#8017](https://github.com/filecoin-project/lotus/pull/8017)) - splistore cold object reification redux ([filecoin-project/lotus#8029](https://github.com/filecoin-project/lotus/pull/8029)) - test: cli: chain category unit tests ([filecoin-project/lotus#8048](https://github.com/filecoin-project/lotus/pull/8048)) +- feat: config: Move MakeNewSectorForDeals config into the Sealing section([filecoin-project/lotus#8382](https://github.com/filecoin-project/lotus/pull/8382)) ## Bug Fixes - fix: sealing: Remove sector copies from workers after snapdeals ([filecoin-project/lotus#8331](https://github.com/filecoin-project/lotus/pull/8331)) diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 0b2e8f6604a366859b16cdfb2e86001ee5414f66..5d25cd308896e38fe561896df5b66bb7cb462b9b 100644 GIT binary patch delta 26940 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 z zG_$`k^00ZE88h^?eA*s*&$PG2knZ7lu>=QNYHES;R(2sgwu#Uo(^$Cm;GFDfGz{lR zf4hE4JH@#f&=_SsSpcj$SqFUD84;%a)i6@CE|84PLn#Yq4YFGc(JmO`_}bgCmv6bAJ%wp(r^^ z|6mvM>VV`wN#hK|6PkEmi*gOsdDfhohf#8GfMnE9EZ;=CqskBz8rs6?Egv;x@Sy?x zVA|rV`Cv{c!?)X~iu>Y^5r&dF{4y%y%BleFOasX94W`$BnOlp@ z30|5BuOb~c;o5b$(K%#4ViL_4xdEZhHh3olGtsH}wx%;Av={#7O+z*{3OSlJ(7lPj zl>rM(Ue&R3ar2i*QBGV|&x9FWLP5IuZ5iNT!SV0+@;cLe{0H|ge&L!Srq&I0ftp)D zSg~Vq$4@Y?HYbyAUyCr1(e3u?ifP8(iDnM*QDg6Ki`9J1| BA;ACu delta 26979 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 F{Xaz8O(_5X diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 497ff02b69988a107ff840ed64a80d148b589217..20d435804537dd8146c15bcf8adb9544c41bf424 100644 GIT binary patch delta 22 ecmaEq_9$&aC(|>Bjos&sIDUMu|18?Z!~g({GYb^} delta 22 ecmaEq_9$&aCsSJd#_sb*982GydL-J$!~g(=0t%A= diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index c4c2c353928a92680aeba75898ea618fc8c30fe4..364e4e75a2ea192d6900bc1e31c28431c56280d9 100644 GIT binary patch delta 21 dcmew<_fu{{E91kBZLj$_!lZxgXM4uL0048Y33LDe delta 21 dcmew<_fu{{E8~NWZLj$_RCn|2VtdBG003~y2=4#@ diff --git a/build/version.go b/build/version.go index 84e06c5b389..a0b8e1cfb61 100644 --- a/build/version.go +++ b/build/version.go @@ -37,7 +37,7 @@ func BuildTypeString() string { } // BuildVersion is the local build version -const BuildVersion = "1.15.1-rc2" +const BuildVersion = "1.15.1-rc3" func UserVersion() string { if os.Getenv("LOTUS_VERSION_IGNORE_COMMIT") == "1" { diff --git a/documentation/en/cli-lotus-miner.md b/documentation/en/cli-lotus-miner.md index e27c35c92c0..8ba2b75b769 100644 --- a/documentation/en/cli-lotus-miner.md +++ b/documentation/en/cli-lotus-miner.md @@ -7,7 +7,7 @@ USAGE: lotus-miner [global options] command [command options] [arguments...] VERSION: - 1.15.1-rc2 + 1.15.1-rc3 COMMANDS: init Initialize a lotus miner repo diff --git a/documentation/en/cli-lotus-worker.md b/documentation/en/cli-lotus-worker.md index 9acc6a2aeed..778b1cb9b7d 100644 --- a/documentation/en/cli-lotus-worker.md +++ b/documentation/en/cli-lotus-worker.md @@ -7,7 +7,7 @@ USAGE: lotus-worker [global options] command [command options] [arguments...] VERSION: - 1.15.1-rc2 + 1.15.1-rc3 COMMANDS: run Start lotus worker diff --git a/documentation/en/cli-lotus.md b/documentation/en/cli-lotus.md index 6595a777a1c..178d7c52074 100644 --- a/documentation/en/cli-lotus.md +++ b/documentation/en/cli-lotus.md @@ -7,7 +7,7 @@ USAGE: lotus [global options] command [command options] [arguments...] VERSION: - 1.15.1-rc2 + 1.15.1-rc3 COMMANDS: daemon Start a lotus daemon process From 21a1f3a34d3dfab36b6743fa84275812c59b4756 Mon Sep 17 00:00:00 2001 From: Jennifer Wang Date: Tue, 29 Mar 2022 12:02:41 -0400 Subject: [PATCH 347/385] deps: update ffi --- extern/filecoin-ffi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index 7f93fe5cf63..dd1c85ababb 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit 7f93fe5cf63aee1c6c21986903e870b02e337a16 +Subproject commit dd1c85ababbbc48d6a0458d8378c16a5d30fddb7 From 4d2691a2e19ce21ec37926910c6f954f7dfaff8b Mon Sep 17 00:00:00 2001 From: Jennifer Wang Date: Tue, 29 Mar 2022 20:36:39 -0400 Subject: [PATCH 348/385] build: release: v1.15.1-rc4 --- CHANGELOG.md | 4 ++-- build/openrpc/full.json.gz | Bin 27023 -> 27022 bytes build/openrpc/miner.json.gz | Bin 13154 -> 13154 bytes build/openrpc/worker.json.gz | Bin 3961 -> 3961 bytes build/version.go | 2 +- documentation/en/cli-lotus-miner.md | 2 +- documentation/en/cli-lotus-worker.md | 2 +- documentation/en/cli-lotus.md | 2 +- 8 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8fb5b619ee1..a4c2349fce9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,8 @@ # Lotus changelog -# 1.15.1-rc3 / 2022-03-27 +# 1.15.1-rc4 / 2022-03-29 -This is the second release candidate of the next *highly recommended* feature release v1.15.1. This feature release introduces Index Provider, GraphSync v2, and many other latest functionalities, improvements and bug fixes. +This is the forth release candidate of the next *highly recommended* feature release v1.15.1. This feature release introduces Index Provider, GraphSync v2, and many other latest functionalities, improvements and bug fixes. More importantly, node operator can now enable the FVM(experimental) to sync mainnet!! ## Highlights diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 5d25cd308896e38fe561896df5b66bb7cb462b9b..71922543bc236acfe2cd5e2e8b788c3a20f23743 100644 GIT binary patch delta 26978 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

yGqxe;g1Og)=jss?0e!k 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 z zG_$`k^00ZE88h^?eA*s*&$PG2knZ7lu>=QNYHES;R(2sgwu#Uo(^$Cm;GFDfGz{lR zf4hE4JH@#f&=_SsSpcj$SqFUD84;%a)i6@CE|84PLn#Yq4YFGc(JmO`_}bgCmv6bAJ%wp(r^^ z|6mvM>VV`wN#hK|6PkEmi*gOsdDfhohf#8GfMnE9EZ;=CqskBz8rs6?Egv;x@Sy?x zVA|rV`Cv{c!?)X~iu>Y^5r&dF{4y%y%BleFOasX94W`$BnOlp@ z30|5BuOb~c;o5b$(K%#4ViL_4xdEZhHh3olGtsH}wx%;Av={#7O+z*{3OSlJ(7lPj zl>rM(Ue&R3ar2i*QBGV|&x9FWLP5IuZ5iNT!SV0+@;cLe{0H|ge&L!Srq&I0ftp)D zSg~Vq$4@Y?HYbyAUyCr1(e3u?ifP8(iDnM*QDg6Ki`9G5q BA-n(p diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 20d435804537dd8146c15bcf8adb9544c41bf424..3c9cb8ec0c468b888c5736f52587351eb7c1efd8 100644 GIT binary patch delta 21 ccmaEq_9$&a7h}N2?(;?*+51Y`McbGd0CSlM0ssI2 delta 21 dcmaEq_9$&a7o)?*?(;?*Kfc$07Hwl<004Uq3NHWv diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index 364e4e75a2ea192d6900bc1e31c28431c56280d9..bf803844c2b9dd4829e6a8e6d0e631e93a13d7d1 100644 GIT binary patch delta 22 ecmew<_fu{{3)A%n8{1y_IKrfV?Pq(&zyJVz3kk~r diff --git a/build/version.go b/build/version.go index a0b8e1cfb61..9942c10bde7 100644 --- a/build/version.go +++ b/build/version.go @@ -37,7 +37,7 @@ func BuildTypeString() string { } // BuildVersion is the local build version -const BuildVersion = "1.15.1-rc3" +const BuildVersion = "1.15.1-rc4" func UserVersion() string { if os.Getenv("LOTUS_VERSION_IGNORE_COMMIT") == "1" { diff --git a/documentation/en/cli-lotus-miner.md b/documentation/en/cli-lotus-miner.md index 8ba2b75b769..16fd041b459 100644 --- a/documentation/en/cli-lotus-miner.md +++ b/documentation/en/cli-lotus-miner.md @@ -7,7 +7,7 @@ USAGE: lotus-miner [global options] command [command options] [arguments...] VERSION: - 1.15.1-rc3 + 1.15.1-rc4 COMMANDS: init Initialize a lotus miner repo diff --git a/documentation/en/cli-lotus-worker.md b/documentation/en/cli-lotus-worker.md index 778b1cb9b7d..b7266ccfc4a 100644 --- a/documentation/en/cli-lotus-worker.md +++ b/documentation/en/cli-lotus-worker.md @@ -7,7 +7,7 @@ USAGE: lotus-worker [global options] command [command options] [arguments...] VERSION: - 1.15.1-rc3 + 1.15.1-rc4 COMMANDS: run Start lotus worker diff --git a/documentation/en/cli-lotus.md b/documentation/en/cli-lotus.md index 178d7c52074..369121fc87e 100644 --- a/documentation/en/cli-lotus.md +++ b/documentation/en/cli-lotus.md @@ -7,7 +7,7 @@ USAGE: lotus [global options] command [command options] [arguments...] VERSION: - 1.15.1-rc3 + 1.15.1-rc4 COMMANDS: daemon Start a lotus daemon process From eeeb33c9ac4c2527e92a468c1bda25e339e2be28 Mon Sep 17 00:00:00 2001 From: Jiaying Wang <42981373+jennijuju@users.noreply.github.com> Date: Tue, 29 Mar 2022 20:59:16 -0400 Subject: [PATCH 349/385] Update CHANGELOG.md Co-authored-by: Aayush Rajasekaran --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4c2349fce9..4180aab28db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ # 1.15.1-rc4 / 2022-03-29 -This is the forth release candidate of the next *highly recommended* feature release v1.15.1. This feature release introduces Index Provider, GraphSync v2, and many other latest functionalities, improvements and bug fixes. +This is the fourth release candidate of the next *highly recommended* feature release v1.15.1. This feature release introduces Index Provider, GraphSync v2, and many other latest functionalities, improvements and bug fixes. More importantly, node operator can now enable the FVM(experimental) to sync mainnet!! ## Highlights From 7e86f7196e51f56304d15e6e02047de036e20506 Mon Sep 17 00:00:00 2001 From: hannahhoward Date: Tue, 29 Mar 2022 17:53:59 -0700 Subject: [PATCH 350/385] chore(deps): update go-data-transfer with fixes --- go.mod | 6 +++--- go.sum | 13 ++++++++----- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 6db254da458..33857abcd7f 100644 --- a/go.mod +++ b/go.mod @@ -35,7 +35,7 @@ require ( github.com/filecoin-project/go-cbor-util v0.0.1 github.com/filecoin-project/go-commp-utils v0.1.3 github.com/filecoin-project/go-crypto v0.0.1 - github.com/filecoin-project/go-data-transfer v1.15.0 + github.com/filecoin-project/go-data-transfer v1.15.1 github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 github.com/filecoin-project/go-fil-markets v1.20.1 @@ -44,7 +44,7 @@ require ( github.com/filecoin-project/go-padreader v0.0.1 github.com/filecoin-project/go-paramfetch v0.0.4 github.com/filecoin-project/go-state-types v0.1.3 - github.com/filecoin-project/go-statemachine v1.0.1 + github.com/filecoin-project/go-statemachine v1.0.2 github.com/filecoin-project/go-statestore v0.2.0 github.com/filecoin-project/go-storedcounter v0.1.0 github.com/filecoin-project/index-provider v0.5.0 @@ -82,7 +82,7 @@ require ( github.com/ipfs/go-ds-leveldb v0.5.0 github.com/ipfs/go-ds-measure v0.2.0 github.com/ipfs/go-fs-lock v0.0.7 - github.com/ipfs/go-graphsync v0.13.0 + github.com/ipfs/go-graphsync v0.13.1 github.com/ipfs/go-ipfs-blockstore v1.1.2 github.com/ipfs/go-ipfs-blocksutil v0.0.1 github.com/ipfs/go-ipfs-chunker v0.0.5 diff --git a/go.sum b/go.sum index ff427a32d97..49dddb84cde 100644 --- a/go.sum +++ b/go.sum @@ -325,8 +325,8 @@ github.com/filecoin-project/go-crypto v0.0.1 h1:AcvpSGGCgjaY8y1az6AMfKQWreF/pWO2 github.com/filecoin-project/go-crypto v0.0.1/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= github.com/filecoin-project/go-dagaggregator-unixfs v0.2.0/go.mod h1:WTuJWgBQY0omnQqa8kRPT9O0Uj5wQOgslVMUuTeHdJ8= github.com/filecoin-project/go-data-transfer v1.14.0/go.mod h1:wNJKhaLLYBJDM3VFvgvYi4iUjPa69pz/1Q5Q4HzX2wE= -github.com/filecoin-project/go-data-transfer v1.15.0 h1:gVH7MxEgoj/qXPz+S6ggFlHlDv1mLlRZuJtTvcq8r1o= -github.com/filecoin-project/go-data-transfer v1.15.0/go.mod h1:RaJIYjh6x6z+FXKNvUULOdUZdN+JutKigfcMMbfykWA= +github.com/filecoin-project/go-data-transfer v1.15.1 h1:IbC5u2Do5EsEBB6jtHBDplPxTDc+mFm6mB0bbT08vIo= +github.com/filecoin-project/go-data-transfer v1.15.1/go.mod h1:dXsUoDjR9tKN7aV6R0BBDNNBPzbNvrrNuWt9MUn3yYc= github.com/filecoin-project/go-ds-versioning v0.0.0-20211206185234-508abd7c2aff/go.mod h1:C9/l9PnB1+mwPa26BBVpCjG/XQCB0yj/q5CK2J8X1I4= github.com/filecoin-project/go-ds-versioning v0.1.1 h1:JiyBqaQlwC+UM0WhcBtVEeT3XrX59mQhT8U3p7nu86o= github.com/filecoin-project/go-ds-versioning v0.1.1/go.mod h1:C9/l9PnB1+mwPa26BBVpCjG/XQCB0yj/q5CK2J8X1I4= @@ -363,8 +363,10 @@ github.com/filecoin-project/go-state-types v0.1.1/go.mod h1:ezYnPf0bNkTsDibL/psS github.com/filecoin-project/go-state-types v0.1.3 h1:rzIJyQo5HO2ptc8Jcu8P0qTutnI7NWwTle54eAHoNO0= github.com/filecoin-project/go-state-types v0.1.3/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= -github.com/filecoin-project/go-statemachine v1.0.1 h1:LQ60+JDVjMdLxXmVFM2jjontzOYnfVE7u02CXV3WKSw= github.com/filecoin-project/go-statemachine v1.0.1/go.mod h1:jZdXXiHa61n4NmgWFG4w8tnqgvZVHYbJ3yW7+y8bF54= +github.com/filecoin-project/go-statemachine v1.0.2-0.20220322104818-27f8fbb86dfd/go.mod h1:jZdXXiHa61n4NmgWFG4w8tnqgvZVHYbJ3yW7+y8bF54= +github.com/filecoin-project/go-statemachine v1.0.2 h1:421SSWBk8GIoCoWYYTE/d+qCWccgmRH0uXotXRDjUbc= +github.com/filecoin-project/go-statemachine v1.0.2/go.mod h1:jZdXXiHa61n4NmgWFG4w8tnqgvZVHYbJ3yW7+y8bF54= github.com/filecoin-project/go-statestore v0.1.0/go.mod h1:LFc9hD+fRxPqiHiaqUEZOinUJB4WARkRfNl10O7kTnI= github.com/filecoin-project/go-statestore v0.2.0 h1:cRRO0aPLrxKQCZ2UOQbzFGn4WDNdofHZoGPjfNaAo5Q= github.com/filecoin-project/go-statestore v0.2.0/go.mod h1:8sjBYbS35HwPzct7iT4lIXjLlYyPor80aU7t7a/Kspo= @@ -757,8 +759,8 @@ github.com/ipfs/go-fs-lock v0.0.7 h1:6BR3dajORFrFTkb5EpCUFIAypsoxpGpDSVUdFwzgL9U github.com/ipfs/go-fs-lock v0.0.7/go.mod h1:Js8ka+FNYmgQRLrRXzU3CB/+Csr1BwrRilEcvYrHhhc= github.com/ipfs/go-graphsync v0.11.0/go.mod h1:wC+c8vGVjAHthsVIl8LKr37cUra2GOaMYcQNNmMxDqE= github.com/ipfs/go-graphsync v0.12.0/go.mod h1:nASYWYETgsnMbQ3+DirNImOHQ8TY0a5AhAqyOY55tUg= -github.com/ipfs/go-graphsync v0.13.0 h1:8reYjVKxKocJ9jD471xs9XNuegquPrnBFuGZmCqT8zU= -github.com/ipfs/go-graphsync v0.13.0/go.mod h1:oPBU9JGNlyWHyH9lWYmyl19M++5yiXjBnNC4boh5nVU= +github.com/ipfs/go-graphsync v0.13.1 h1:lWiP/WLycoPUYyj3IDEi1GJNP30kFuYOvimcfeuZyQs= +github.com/ipfs/go-graphsync v0.13.1/go.mod h1:y8e8G6CmZeL9Srvx1l15CtGiRdf3h5JdQuqPz/iYL0A= github.com/ipfs/go-ipfs v0.11.0/go.mod h1:g68Thu2Ho11AWoHsN34P5fSK7iA6OWWRy3T/g8HLixc= github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08= github.com/ipfs/go-ipfs-blockstore v0.1.0/go.mod h1:5aD0AvHPi7mZc6Ci1WCAhiBQu2IsfTduLl+422H6Rqw= @@ -911,6 +913,7 @@ github.com/ipld/go-car/v2 v2.1.1 h1:saaKz4nC0AdfCGHLYKeXLGn8ivoPC54fyS55uyOLKwA= github.com/ipld/go-car/v2 v2.1.1/go.mod h1:+2Yvf0Z3wzkv7NeI69i8tuZ+ft7jyjPYIWZzeVNeFcI= github.com/ipld/go-codec-dagpb v1.2.0/go.mod h1:6nBN7X7h8EOsEejZGqC7tej5drsdBAXbMHyBT+Fne5s= github.com/ipld/go-codec-dagpb v1.3.0/go.mod h1:ga4JTU3abYApDC3pZ00BC2RSvC3qfBb9MSJkMLSwnhA= +github.com/ipld/go-codec-dagpb v1.3.1/go.mod h1:ErNNglIi5KMur/MfFE/svtgQthzVvf+43MrzLbpcIZY= github.com/ipld/go-codec-dagpb v1.3.2 h1:MZQUIjanHXXfDuYmtWYT8nFbqfFsZuyHClj6VDmSXr4= github.com/ipld/go-codec-dagpb v1.3.2/go.mod h1:ga4JTU3abYApDC3pZ00BC2RSvC3qfBb9MSJkMLSwnhA= github.com/ipld/go-ipld-prime v0.0.2-0.20191108012745-28a82f04c785/go.mod h1:bDDSvVz7vaK12FNvMeRYnpRFkSUPNQOiCYQezMD/P3w= From 2ad3a117f133e236dc8687b053c6c21d85ec70b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 31 Mar 2022 17:01:33 -0400 Subject: [PATCH 351/385] fix: sealing: Fix PR1 worker selection --- extern/sector-storage/manager.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index 70195d333d4..1cf9f60bdda 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -851,7 +851,7 @@ func (m *Manager) ProveReplicaUpdate1(ctx context.Context, sector storage.Sector // NOTE: We set allowFetch to false in so that we always execute on a worker // with direct access to the data. We want to do that because this step is // generally very cheap / fast, and transferring data is not worth the effort - selector := newExistingSelector(m.index, sector.ID, storiface.FTUpdate|storiface.FTUpdateCache|storiface.FTSealed|storiface.FTCache, false) + selector := newExistingSelector(m.index, sector.ID, storiface.FTUpdate|storiface.FTUpdateCache, false) err = m.sched.Schedule(ctx, sector, sealtasks.TTProveReplicaUpdate1, selector, m.schedFetch(sector, storiface.FTSealed|storiface.FTCache|storiface.FTUpdate|storiface.FTUpdateCache, storiface.PathSealing, storiface.AcquireCopy), func(ctx context.Context, w Worker) error { From 01efb3b1a74f591850cb48c67dbfd8678b60345a Mon Sep 17 00:00:00 2001 From: zl Date: Mon, 28 Mar 2022 19:07:12 +0800 Subject: [PATCH 352/385] fix: dead loop on removing a sector --- extern/storage-sealing/fsm.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/extern/storage-sealing/fsm.go b/extern/storage-sealing/fsm.go index a026661359f..034433a59c6 100644 --- a/extern/storage-sealing/fsm.go +++ b/extern/storage-sealing/fsm.go @@ -320,7 +320,7 @@ var fsmPlanners = map[SectorState]func(events []statemachine.Event, state *Secto FaultReported: final, // not really supported right now FaultedFinal: final, - Removed: final, + Removed: finalRemoved, FailedUnrecoverable: final, } @@ -694,6 +694,12 @@ func (m *Sealing) ForceSectorState(ctx context.Context, id abi.SectorNumber, sta return m.sectors.Send(id, SectorForceState{state}) } +// as sector has been removed, it's no needs to care about later events, +// just returns length of events as `processed` is ok. +func finalRemoved(events []statemachine.Event, state *SectorInfo) (uint64, error) { + return uint64(len(events)), nil +} + func final(events []statemachine.Event, state *SectorInfo) (uint64, error) { if len(events) > 0 { if gm, ok := events[0].User.(globalMutator); ok { From 6c1651cb3d4ef6f986d677c1ff2fa978a3f037cd Mon Sep 17 00:00:00 2001 From: koalacxr Date: Wed, 16 Mar 2022 13:10:03 +0800 Subject: [PATCH 353/385] modify quantile imports error --- cmd/lotus-sim/info_commit.go | 8 +++----- cmd/lotus-sim/info_message.go | 7 ++++--- go.mod | 2 +- go.sum | 4 ++-- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/cmd/lotus-sim/info_commit.go b/cmd/lotus-sim/info_commit.go index 738fcde95e5..1b574fbf882 100644 --- a/cmd/lotus-sim/info_commit.go +++ b/cmd/lotus-sim/info_commit.go @@ -6,17 +6,15 @@ import ( "os" "syscall" - "github.com/streadway/quantile" - "github.com/urfave/cli/v2" - "github.com/filecoin-project/go-state-types/exitcode" - "github.com/ipfs/go-cid" - "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/cmd/lotus-sim/simulation" "github.com/filecoin-project/lotus/lib/stati" + "github.com/ipfs/go-cid" + "github.com/koalacxr/quantile" + "github.com/urfave/cli/v2" ) var infoCommitGasSimCommand = &cli.Command{ diff --git a/cmd/lotus-sim/info_message.go b/cmd/lotus-sim/info_message.go index 33c45e7280f..76de5eb72aa 100644 --- a/cmd/lotus-sim/info_message.go +++ b/cmd/lotus-sim/info_message.go @@ -4,13 +4,14 @@ import ( "fmt" "syscall" + "github.com/filecoin-project/lotus/cli" + "github.com/ipfs/go-cid" + "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/cmd/lotus-sim/simulation" "github.com/filecoin-project/lotus/lib/stati" - "github.com/ipfs/go-cid" - "github.com/streadway/quantile" - "github.com/urfave/cli/v2" + "github.com/koalacxr/quantile" ) var infoMessageSizeSimCommand = &cli.Command{ diff --git a/go.mod b/go.mod index 33857abcd7f..a665fd4c100 100644 --- a/go.mod +++ b/go.mod @@ -110,6 +110,7 @@ require ( github.com/ipld/go-ipld-selector-text-lite v0.0.1 github.com/jonboulle/clockwork v0.2.2 // indirect github.com/kelseyhightower/envconfig v1.4.0 + github.com/koalacxr/quantile v0.0.1 github.com/libp2p/go-buffer-pool v0.0.2 github.com/libp2p/go-eventbus v0.2.1 github.com/libp2p/go-libp2p v0.18.0 @@ -143,7 +144,6 @@ require ( github.com/prometheus/client_golang v1.11.0 github.com/raulk/clock v1.1.0 github.com/raulk/go-watchdog v1.2.0 - github.com/streadway/quantile v0.0.0-20150917103942-b0c588724d25 github.com/stretchr/testify v1.7.0 github.com/syndtr/goleveldb v1.0.0 github.com/uber/jaeger-client-go v2.25.0+incompatible // indirect diff --git a/go.sum b/go.sum index 49dddb84cde..993cdc58240 100644 --- a/go.sum +++ b/go.sum @@ -1010,6 +1010,8 @@ github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02 github.com/klauspost/cpuid/v2 v2.0.6/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/koalacxr/quantile v0.0.1 h1:wAW+SQ286Erny9wOjVww96t8ws+x5Zj6AKHDULUK+o0= +github.com/koalacxr/quantile v0.0.1/go.mod h1:bGN/mCZLZ4lrSDHRQ6Lglj9chowGux8sGUIND+DQeD0= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= @@ -1865,8 +1867,6 @@ github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3 github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/streadway/handy v0.0.0-20200128134331-0f66f006fb2e/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= -github.com/streadway/quantile v0.0.0-20150917103942-b0c588724d25 h1:7z3LSn867ex6VSaahyKadf4WtSsJIgne6A1WLOAGM8A= -github.com/streadway/quantile v0.0.0-20150917103942-b0c588724d25/go.mod h1:lbP8tGiBjZ5YWIc2fzuRpTaz0b/53vT6PEs3QuAWzuU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= From 257bc70c2e79f199b56f27d5a1e9cb1512efb573 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 30 Mar 2022 14:34:20 -0400 Subject: [PATCH 354/385] fix lotus-sim build --- cmd/lotus-sim/info_commit.go | 7 ++++--- cmd/lotus-sim/info_message.go | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/cmd/lotus-sim/info_commit.go b/cmd/lotus-sim/info_commit.go index 1b574fbf882..7a0daa3327e 100644 --- a/cmd/lotus-sim/info_commit.go +++ b/cmd/lotus-sim/info_commit.go @@ -6,15 +6,16 @@ import ( "os" "syscall" + "github.com/ipfs/go-cid" + "github.com/koalacxr/quantile" + "github.com/urfave/cli/v2" + "github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/cmd/lotus-sim/simulation" "github.com/filecoin-project/lotus/lib/stati" - "github.com/ipfs/go-cid" - "github.com/koalacxr/quantile" - "github.com/urfave/cli/v2" ) var infoCommitGasSimCommand = &cli.Command{ diff --git a/cmd/lotus-sim/info_message.go b/cmd/lotus-sim/info_message.go index 76de5eb72aa..afdd20c4e61 100644 --- a/cmd/lotus-sim/info_message.go +++ b/cmd/lotus-sim/info_message.go @@ -4,14 +4,14 @@ import ( "fmt" "syscall" - "github.com/filecoin-project/lotus/cli" "github.com/ipfs/go-cid" + "github.com/koalacxr/quantile" + "github.com/urfave/cli/v2" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/cmd/lotus-sim/simulation" "github.com/filecoin-project/lotus/lib/stati" - "github.com/koalacxr/quantile" ) var infoMessageSizeSimCommand = &cli.Command{ From 0bc3e26090c143dca3be4e759d1fc068f8268d4c Mon Sep 17 00:00:00 2001 From: Jennifer Wang Date: Thu, 31 Mar 2022 23:13:35 -0400 Subject: [PATCH 355/385] bump the version to v1.15.1-rc5 --- build/openrpc/full.json.gz | Bin 27022 -> 27023 bytes build/openrpc/miner.json.gz | Bin 13154 -> 13154 bytes build/openrpc/worker.json.gz | Bin 3961 -> 3961 bytes build/version.go | 2 +- documentation/en/cli-lotus-miner.md | 2 +- documentation/en/cli-lotus-worker.md | 2 +- documentation/en/cli-lotus.md | 2 +- 7 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 71922543bc236acfe2cd5e2e8b788c3a20f23743..8a83321a53f46b7f52edbc58df6dc45461b4a080 100644 GIT binary patch delta 26979 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 z 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 diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 3c9cb8ec0c468b888c5736f52587351eb7c1efd8..7499e1f206de27dc6c376d57347908afbe2a2182 100644 GIT binary patch delta 13125 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 delta 3866 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 diff --git a/build/version.go b/build/version.go index 9942c10bde7..1c08a7e6a54 100644 --- a/build/version.go +++ b/build/version.go @@ -37,7 +37,7 @@ func BuildTypeString() string { } // BuildVersion is the local build version -const BuildVersion = "1.15.1-rc4" +const BuildVersion = "1.15.1-rc5" func UserVersion() string { if os.Getenv("LOTUS_VERSION_IGNORE_COMMIT") == "1" { diff --git a/documentation/en/cli-lotus-miner.md b/documentation/en/cli-lotus-miner.md index 16fd041b459..aad43070341 100644 --- a/documentation/en/cli-lotus-miner.md +++ b/documentation/en/cli-lotus-miner.md @@ -7,7 +7,7 @@ USAGE: lotus-miner [global options] command [command options] [arguments...] VERSION: - 1.15.1-rc4 + 1.15.1-rc5 COMMANDS: init Initialize a lotus miner repo diff --git a/documentation/en/cli-lotus-worker.md b/documentation/en/cli-lotus-worker.md index b7266ccfc4a..0e3f8b58e7c 100644 --- a/documentation/en/cli-lotus-worker.md +++ b/documentation/en/cli-lotus-worker.md @@ -7,7 +7,7 @@ USAGE: lotus-worker [global options] command [command options] [arguments...] VERSION: - 1.15.1-rc4 + 1.15.1-rc5 COMMANDS: run Start lotus worker diff --git a/documentation/en/cli-lotus.md b/documentation/en/cli-lotus.md index 369121fc87e..ec41ed92c2a 100644 --- a/documentation/en/cli-lotus.md +++ b/documentation/en/cli-lotus.md @@ -7,7 +7,7 @@ USAGE: lotus [global options] command [command options] [arguments...] VERSION: - 1.15.1-rc4 + 1.15.1-rc5 COMMANDS: daemon Start a lotus daemon process From 0a220a3efbf791c2a239f4170c6ed3fa04ed7d08 Mon Sep 17 00:00:00 2001 From: Jennifer Wang Date: Thu, 31 Mar 2022 23:51:57 -0400 Subject: [PATCH 356/385] update the changelog --- CHANGELOG.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4180aab28db..78eccc510c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,8 @@ # Lotus changelog -# 1.15.1-rc4 / 2022-03-29 +# 1.15.1-rc5 / 2022-03-31 -This is the fourth release candidate of the next *highly recommended* feature release v1.15.1. This feature release introduces Index Provider, GraphSync v2, and many other latest functionalities, improvements and bug fixes. +This is the fifth release candidate of the next *highly recommended* feature release v1.15.1. This feature release introduces Index Provider, GraphSync v2, and many other latest functionalities, improvements and bug fixes. More importantly, node operator can now enable the FVM(experimental) to sync mainnet!! ## Highlights @@ -70,6 +70,8 @@ Follow the instruction [here](https://lotus.filecoin.io/storage-providers/operat - feat: config: Move MakeNewSectorForDeals config into the Sealing section([filecoin-project/lotus#8382](https://github.com/filecoin-project/lotus/pull/8382)) ## Bug Fixes +- fix: sealing: Fix PR1 worker selection (#8421) +- fix: miner: dead loop on removing sector (#8421) - fix: sealing: Remove sector copies from workers after snapdeals ([filecoin-project/lotus#8331](https://github.com/filecoin-project/lotus/pull/8331)) - fix: storagefsm: Fix error loop on bad event ([filecoin-project/lotus#8339](https://github.com/filecoin-project/lotus/pull/8339)) - fix: sealing: FinalizeSector doesn't need sealed replica access ([filecoin-project/lotus#8339](https://github.com/filecoin-project/lotus/pull/8339)) From 6ff99568cf6a160e243b7fe82499d6a25bf806a0 Mon Sep 17 00:00:00 2001 From: Jennifer Wang Date: Thu, 31 Mar 2022 23:52:08 -0400 Subject: [PATCH 357/385] pull the latest ffi --- extern/filecoin-ffi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index dd1c85ababb..4b939fe1942 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit dd1c85ababbbc48d6a0458d8378c16a5d30fddb7 +Subproject commit 4b939fe19424ecc7f621cc1959ac4ba6bd422065 From f04b5f2963ae19df16f4e9edf4c089e43592c5e5 Mon Sep 17 00:00:00 2001 From: Cory Schwartz Date: Wed, 30 Mar 2022 22:02:43 -0700 Subject: [PATCH 358/385] add debug --- .circleci/config.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 478c84500a9..d046bd288c0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -690,7 +690,7 @@ jobs: at: "." - packer/build: template: tools/packer/lotus.pkr.hcl - args: "-var ci_workspace_bins=./linux -var lotus_network=mainnet -var git_tag=$CIRCLE_TAG" + args: "-debug -var ci_workspace_bins=./linux -var lotus_network=mainnet -var git_tag=$CIRCLE_TAG" publish-packer-calibrationnet: description: build and push AWS IAM and DigitalOcean droplet. executor: @@ -702,7 +702,7 @@ jobs: at: "." - packer/build: template: tools/packer/lotus.pkr.hcl - args: "-var ci_workspace_bins=./linux-calibrationnet -var lotus_network=calibrationnet -var git_tag=$CIRCLE_TAG" + args: "-debug -var ci_workspace_bins=./linux-calibrationnet -var lotus_network=calibrationnet -var git_tag=$CIRCLE_TAG" publish-packer-butterflynet: description: build and push AWS IAM and DigitalOcean droplet. executor: @@ -714,7 +714,7 @@ jobs: at: "." - packer/build: template: tools/packer/lotus.pkr.hcl - args: "-var ci_workspace_bins=./linux-butterflynet -var lotus_network=butterflynet -var git_tag=$CIRCLE_TAG" + args: "-debug -var ci_workspace_bins=./linux-butterflynet -var lotus_network=butterflynet -var git_tag=$CIRCLE_TAG" publish-packer-snap: description: build packer image with snap. mainnet only. executor: @@ -726,6 +726,7 @@ jobs: at: "." - packer/build: template: tools/packer/lotus-snap.pkr.hcl + args: "-debug" publish-dockerhub: description: publish to dockerhub machine: From 17bcf919102de08ca2e972862f1caef717f40b24 Mon Sep 17 00:00:00 2001 From: Cory Schwartz Date: Wed, 30 Mar 2022 22:03:41 -0700 Subject: [PATCH 359/385] tmp: remove filters --- .circleci/config.yml | 56 ++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d046bd288c0..4e853af7a37 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1041,43 +1041,43 @@ workflows: - publish-packer-mainnet: requires: - build-all - filters: - branches: - ignore: - - /.*/ - tags: - only: - - /^v\d+\.\d+\.\d+(-rc\d+)?$/ + # filters: + # branches: + # ignore: + # - /.*/ + # tags: + # only: + # - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - publish-packer-calibrationnet: requires: - build-ntwk-calibration - filters: - branches: - ignore: - - /.*/ - tags: - only: - - /^v\d+\.\d+\.\d+(-rc\d+)?$/ + # filters: + # branches: + # ignore: + # - /.*/ + # tags: + # only: + # - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - publish-packer-butterflynet: requires: - build-ntwk-butterfly - filters: - branches: - ignore: - - /.*/ - tags: - only: - - /^v\d+\.\d+\.\d+(-rc\d+)?$/ + # filters: + # branches: + # ignore: + # - /.*/ + # tags: + # only: + # - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - publish-snapcraft: name: publish-snapcraft-stable channel: stable - filters: - branches: - ignore: - - /.*/ - tags: - only: - - /^v\d+\.\d+\.\d+(-rc\d+)?$/ + # filters: + # branches: + # ignore: + # - /.*/ + # tags: + # only: + # - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - publish-dockerhub: name: publish-dockerhub tag: stable From b40b7cc40e84d60be5fca045a4e9f785740312f3 Mon Sep 17 00:00:00 2001 From: Cory Schwartz Date: Wed, 30 Mar 2022 22:27:18 -0700 Subject: [PATCH 360/385] copy packer_build source --- .circleci/config.yml | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4e853af7a37..ca10f6b1dfd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,7 +2,6 @@ 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: @@ -75,6 +74,26 @@ commands: command: | git fetch --all + packer_build: + description: "Run a packer build" + parameters: + template: + description: | + The name of the packer template file + type: string + default: packer.json + args: + description: | + Arguments to pass to the packer build command + type: string + default: "" + + steps: + - run: + name: "Run a packer build" + command: packer build << parameters.args >> << parameters.template >> + no_output_timeout: 30m + jobs: mod-tidy-check: executor: golang @@ -688,9 +707,9 @@ jobs: - checkout - attach_workspace: at: "." - - packer/build: + - packer_build: template: tools/packer/lotus.pkr.hcl - args: "-debug -var ci_workspace_bins=./linux -var lotus_network=mainnet -var git_tag=$CIRCLE_TAG" + args: "-var ci_workspace_bins=./linux -var lotus_network=mainnet -var git_tag=$CIRCLE_TAG" publish-packer-calibrationnet: description: build and push AWS IAM and DigitalOcean droplet. executor: @@ -700,9 +719,9 @@ jobs: - checkout - attach_workspace: at: "." - - packer/build: + - packer_build: template: tools/packer/lotus.pkr.hcl - args: "-debug -var ci_workspace_bins=./linux-calibrationnet -var lotus_network=calibrationnet -var git_tag=$CIRCLE_TAG" + args: "-var ci_workspace_bins=./linux-calibrationnet -var lotus_network=calibrationnet -var git_tag=$CIRCLE_TAG" publish-packer-butterflynet: description: build and push AWS IAM and DigitalOcean droplet. executor: @@ -712,9 +731,9 @@ jobs: - checkout - attach_workspace: at: "." - - packer/build: + - packer_build: template: tools/packer/lotus.pkr.hcl - args: "-debug -var ci_workspace_bins=./linux-butterflynet -var lotus_network=butterflynet -var git_tag=$CIRCLE_TAG" + args: "-var ci_workspace_bins=./linux-butterflynet -var lotus_network=butterflynet -var git_tag=$CIRCLE_TAG" publish-packer-snap: description: build packer image with snap. mainnet only. executor: @@ -724,9 +743,8 @@ jobs: - checkout - attach_workspace: at: "." - - packer/build: + - packer_build: template: tools/packer/lotus-snap.pkr.hcl - args: "-debug" publish-dockerhub: description: publish to dockerhub machine: From 33019ee4967fc1d4327abcb6168251b24ac4f03f Mon Sep 17 00:00:00 2001 From: Cory Schwartz Date: Wed, 30 Mar 2022 22:30:17 -0700 Subject: [PATCH 361/385] add packer executor --- .circleci/config.yml | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ca10f6b1dfd..92f4eef63cd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -11,6 +11,16 @@ executors: ubuntu: docker: - image: ubuntu:20.04 + packer: + description: | + The HashiCorp provided Packer container + parameters: + packer-version: + type: string + default: 1.8.1 + docker: + - image: hashicorp/packer:<< parameters.packer-version >> + commands: install-deps: @@ -701,8 +711,7 @@ jobs: publish-packer-mainnet: description: build and push AWS IAM and DigitalOcean droplet. executor: - name: packer/default - packer-version: 1.6.6 + name: packer steps: - checkout - attach_workspace: @@ -713,8 +722,7 @@ jobs: publish-packer-calibrationnet: description: build and push AWS IAM and DigitalOcean droplet. executor: - name: packer/default - packer-version: 1.6.6 + name: packer steps: - checkout - attach_workspace: @@ -725,8 +733,7 @@ jobs: publish-packer-butterflynet: description: build and push AWS IAM and DigitalOcean droplet. executor: - name: packer/default - packer-version: 1.6.6 + name: packer steps: - checkout - attach_workspace: @@ -737,8 +744,7 @@ jobs: publish-packer-snap: description: build packer image with snap. mainnet only. executor: - name: packer/default - packer-version: 1.6.6 + name: packer steps: - checkout - attach_workspace: From c330641866e716b5ac1f98ba0f1961aab9521b52 Mon Sep 17 00:00:00 2001 From: Cory Schwartz Date: Wed, 30 Mar 2022 22:35:20 -0700 Subject: [PATCH 362/385] use 1.8 --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 92f4eef63cd..c82898390d2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -17,7 +17,7 @@ executors: parameters: packer-version: type: string - default: 1.8.1 + default: "1.8" docker: - image: hashicorp/packer:<< parameters.packer-version >> From 61742f5d5ac9556d99d11f7fdd6d9d46001488a0 Mon Sep 17 00:00:00 2001 From: Cory Schwartz Date: Wed, 30 Mar 2022 22:53:57 -0700 Subject: [PATCH 363/385] restore filters --- .circleci/config.yml | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c82898390d2..5c8b40cd54d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1075,33 +1075,33 @@ workflows: - publish-packer-calibrationnet: requires: - build-ntwk-calibration - # filters: - # branches: - # ignore: - # - /.*/ - # tags: - # only: - # - /^v\d+\.\d+\.\d+(-rc\d+)?$/ + filters: + branches: + ignore: + - /.*/ + tags: + only: + - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - publish-packer-butterflynet: requires: - build-ntwk-butterfly - # filters: - # branches: - # ignore: - # - /.*/ - # tags: - # only: - # - /^v\d+\.\d+\.\d+(-rc\d+)?$/ + filters: + branches: + ignore: + - /.*/ + tags: + only: + - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - publish-snapcraft: name: publish-snapcraft-stable channel: stable - # filters: - # branches: - # ignore: - # - /.*/ - # tags: - # only: - # - /^v\d+\.\d+\.\d+(-rc\d+)?$/ + filters: + branches: + ignore: + - /.*/ + tags: + only: + - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - publish-dockerhub: name: publish-dockerhub tag: stable From 6b4cc440600139de4cf32a9597732d1b5f0d5031 Mon Sep 17 00:00:00 2001 From: Cory Schwartz Date: Wed, 30 Mar 2022 22:57:02 -0700 Subject: [PATCH 364/385] fix template --- .circleci/template.yml | 50 ++++++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/.circleci/template.yml b/.circleci/template.yml index c8643e3ac5e..166020bae95 100644 --- a/.circleci/template.yml +++ b/.circleci/template.yml @@ -12,6 +12,16 @@ executors: ubuntu: docker: - image: ubuntu:20.04 + packer: + description: | + The HashiCorp provided Packer container + parameters: + packer-version: + type: string + default: "1.8" + docker: + - image: hashicorp/packer:<< parameters.packer-version >> + commands: install-deps: @@ -75,6 +85,26 @@ commands: command: | git fetch --all + packer_build: + description: "Run a packer build" + parameters: + template: + description: | + The name of the packer template file + type: string + default: packer.json + args: + description: | + Arguments to pass to the packer build command + type: string + default: "" + + steps: + - run: + name: "Run a packer build" + command: packer build << parameters.args >> << parameters.template >> + no_output_timeout: 30m + jobs: mod-tidy-check: executor: golang @@ -682,49 +712,45 @@ jobs: publish-packer-mainnet: description: build and push AWS IAM and DigitalOcean droplet. executor: - name: packer/default - packer-version: 1.6.6 + name: packer steps: - checkout - attach_workspace: at: "." - - packer/build: + - packer_build: template: tools/packer/lotus.pkr.hcl args: "-var ci_workspace_bins=./linux -var lotus_network=mainnet -var git_tag=$CIRCLE_TAG" publish-packer-calibrationnet: description: build and push AWS IAM and DigitalOcean droplet. executor: - name: packer/default - packer-version: 1.6.6 + name: packer steps: - checkout - attach_workspace: at: "." - - packer/build: + - packer_build: template: tools/packer/lotus.pkr.hcl args: "-var ci_workspace_bins=./linux-calibrationnet -var lotus_network=calibrationnet -var git_tag=$CIRCLE_TAG" publish-packer-butterflynet: description: build and push AWS IAM and DigitalOcean droplet. executor: - name: packer/default - packer-version: 1.6.6 + name: packer steps: - checkout - attach_workspace: at: "." - - packer/build: + - packer_build: template: tools/packer/lotus.pkr.hcl args: "-var ci_workspace_bins=./linux-butterflynet -var lotus_network=butterflynet -var git_tag=$CIRCLE_TAG" publish-packer-snap: description: build packer image with snap. mainnet only. executor: - name: packer/default - packer-version: 1.6.6 + name: packer steps: - checkout - attach_workspace: at: "." - - packer/build: + - packer_build: template: tools/packer/lotus-snap.pkr.hcl publish-dockerhub: description: publish to dockerhub From 78187ab8d14c1f6ab3d3abaf09ec341f5b1d47c1 Mon Sep 17 00:00:00 2001 From: Cory Schwartz Date: Wed, 30 Mar 2022 23:10:17 -0700 Subject: [PATCH 365/385] fix template --- .circleci/config.yml | 14 +++++++------- .circleci/template.yml | 1 - 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5c8b40cd54d..6117582b4ec 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1065,13 +1065,13 @@ workflows: - publish-packer-mainnet: requires: - build-all - # filters: - # branches: - # ignore: - # - /.*/ - # tags: - # only: - # - /^v\d+\.\d+\.\d+(-rc\d+)?$/ + filters: + branches: + ignore: + - /.*/ + tags: + only: + - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - publish-packer-calibrationnet: requires: - build-ntwk-calibration diff --git a/.circleci/template.yml b/.circleci/template.yml index 166020bae95..30e4acec938 100644 --- a/.circleci/template.yml +++ b/.circleci/template.yml @@ -2,7 +2,6 @@ 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: From 71614bd639e6d938f56cae859d57e2dca2bb3691 Mon Sep 17 00:00:00 2001 From: Cory Schwartz Date: Wed, 30 Mar 2022 22:02:43 -0700 Subject: [PATCH 366/385] add debug --- .circleci/config.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6117582b4ec..936039e425a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -718,7 +718,7 @@ jobs: at: "." - packer_build: template: tools/packer/lotus.pkr.hcl - args: "-var ci_workspace_bins=./linux -var lotus_network=mainnet -var git_tag=$CIRCLE_TAG" + args: "-debug -var ci_workspace_bins=./linux -var lotus_network=mainnet -var git_tag=$CIRCLE_TAG" publish-packer-calibrationnet: description: build and push AWS IAM and DigitalOcean droplet. executor: @@ -729,7 +729,7 @@ jobs: at: "." - packer_build: template: tools/packer/lotus.pkr.hcl - args: "-var ci_workspace_bins=./linux-calibrationnet -var lotus_network=calibrationnet -var git_tag=$CIRCLE_TAG" + args: "-debug -var ci_workspace_bins=./linux-calibrationnet -var lotus_network=calibrationnet -var git_tag=$CIRCLE_TAG" publish-packer-butterflynet: description: build and push AWS IAM and DigitalOcean droplet. executor: @@ -740,7 +740,7 @@ jobs: at: "." - packer_build: template: tools/packer/lotus.pkr.hcl - args: "-var ci_workspace_bins=./linux-butterflynet -var lotus_network=butterflynet -var git_tag=$CIRCLE_TAG" + args: "-debug -var ci_workspace_bins=./linux-butterflynet -var lotus_network=butterflynet -var git_tag=$CIRCLE_TAG" publish-packer-snap: description: build packer image with snap. mainnet only. executor: @@ -751,6 +751,7 @@ jobs: at: "." - packer_build: template: tools/packer/lotus-snap.pkr.hcl + args: "-debug" publish-dockerhub: description: publish to dockerhub machine: From 2804c2ca99b2b64d5760f322c447a3da2bcdc91d Mon Sep 17 00:00:00 2001 From: Cory Schwartz Date: Wed, 30 Mar 2022 22:03:41 -0700 Subject: [PATCH 367/385] tmp: remove filters --- .circleci/config.yml | 56 ++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 936039e425a..61a5248a227 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1066,43 +1066,43 @@ workflows: - publish-packer-mainnet: requires: - build-all - filters: - branches: - ignore: - - /.*/ - tags: - only: - - /^v\d+\.\d+\.\d+(-rc\d+)?$/ + # filters: + # branches: + # ignore: + # - /.*/ + # tags: + # only: + # - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - publish-packer-calibrationnet: requires: - build-ntwk-calibration - filters: - branches: - ignore: - - /.*/ - tags: - only: - - /^v\d+\.\d+\.\d+(-rc\d+)?$/ + # filters: + # branches: + # ignore: + # - /.*/ + # tags: + # only: + # - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - publish-packer-butterflynet: requires: - build-ntwk-butterfly - filters: - branches: - ignore: - - /.*/ - tags: - only: - - /^v\d+\.\d+\.\d+(-rc\d+)?$/ + # filters: + # branches: + # ignore: + # - /.*/ + # tags: + # only: + # - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - publish-snapcraft: name: publish-snapcraft-stable channel: stable - filters: - branches: - ignore: - - /.*/ - tags: - only: - - /^v\d+\.\d+\.\d+(-rc\d+)?$/ + # filters: + # branches: + # ignore: + # - /.*/ + # tags: + # only: + # - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - publish-dockerhub: name: publish-dockerhub tag: stable From eb0d52a2491469db3c6fd0018958a504065b3a09 Mon Sep 17 00:00:00 2001 From: Cory Schwartz Date: Wed, 30 Mar 2022 22:27:18 -0700 Subject: [PATCH 368/385] copy packer_build source --- .circleci/config.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 61a5248a227..c82898390d2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -718,7 +718,7 @@ jobs: at: "." - packer_build: template: tools/packer/lotus.pkr.hcl - args: "-debug -var ci_workspace_bins=./linux -var lotus_network=mainnet -var git_tag=$CIRCLE_TAG" + args: "-var ci_workspace_bins=./linux -var lotus_network=mainnet -var git_tag=$CIRCLE_TAG" publish-packer-calibrationnet: description: build and push AWS IAM and DigitalOcean droplet. executor: @@ -729,7 +729,7 @@ jobs: at: "." - packer_build: template: tools/packer/lotus.pkr.hcl - args: "-debug -var ci_workspace_bins=./linux-calibrationnet -var lotus_network=calibrationnet -var git_tag=$CIRCLE_TAG" + args: "-var ci_workspace_bins=./linux-calibrationnet -var lotus_network=calibrationnet -var git_tag=$CIRCLE_TAG" publish-packer-butterflynet: description: build and push AWS IAM and DigitalOcean droplet. executor: @@ -740,7 +740,7 @@ jobs: at: "." - packer_build: template: tools/packer/lotus.pkr.hcl - args: "-debug -var ci_workspace_bins=./linux-butterflynet -var lotus_network=butterflynet -var git_tag=$CIRCLE_TAG" + args: "-var ci_workspace_bins=./linux-butterflynet -var lotus_network=butterflynet -var git_tag=$CIRCLE_TAG" publish-packer-snap: description: build packer image with snap. mainnet only. executor: @@ -751,7 +751,6 @@ jobs: at: "." - packer_build: template: tools/packer/lotus-snap.pkr.hcl - args: "-debug" publish-dockerhub: description: publish to dockerhub machine: From cb39ce66bcf63731d2181695a74228b8bcd0d107 Mon Sep 17 00:00:00 2001 From: Cory Schwartz Date: Wed, 30 Mar 2022 22:30:17 -0700 Subject: [PATCH 369/385] add packer executor --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c82898390d2..ee9710e627b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,4 +1,4 @@ -version: 2.1 + version: 2.1 orbs: go: gotest/tools@0.0.13 aws-cli: circleci/aws-cli@1.3.2 From f410da2a0a97e464823652c3e1d18065ac3ddc77 Mon Sep 17 00:00:00 2001 From: Cory Schwartz Date: Wed, 30 Mar 2022 22:53:57 -0700 Subject: [PATCH 370/385] restore filters --- .circleci/config.yml | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ee9710e627b..129bf44267d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1075,33 +1075,33 @@ workflows: - publish-packer-calibrationnet: requires: - build-ntwk-calibration - # filters: - # branches: - # ignore: - # - /.*/ - # tags: - # only: - # - /^v\d+\.\d+\.\d+(-rc\d+)?$/ + filters: + branches: + ignore: + - /.*/ + tags: + only: + - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - publish-packer-butterflynet: requires: - build-ntwk-butterfly - # filters: - # branches: - # ignore: - # - /.*/ - # tags: - # only: - # - /^v\d+\.\d+\.\d+(-rc\d+)?$/ + filters: + branches: + ignore: + - /.*/ + tags: + only: + - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - publish-snapcraft: name: publish-snapcraft-stable channel: stable - # filters: - # branches: - # ignore: - # - /.*/ - # tags: - # only: - # - /^v\d+\.\d+\.\d+(-rc\d+)?$/ + filters: + branches: + ignore: + - /.*/ + tags: + only: + - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - publish-dockerhub: name: publish-dockerhub tag: stable From cc57f732d27e0d98bc73b41eb2298df95744eb43 Mon Sep 17 00:00:00 2001 From: Cory Schwartz Date: Wed, 30 Mar 2022 23:10:17 -0700 Subject: [PATCH 371/385] fix template --- .circleci/config.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 129bf44267d..350ae297072 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1065,13 +1065,13 @@ workflows: - publish-packer-mainnet: requires: - build-all - # filters: - # branches: - # ignore: - # - /.*/ - # tags: - # only: - # - /^v\d+\.\d+\.\d+(-rc\d+)?$/ + filters: + branches: + ignore: + - /.*/ + tags: + only: + - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - publish-packer-calibrationnet: requires: - build-ntwk-calibration From 5915d4ac6a7f93a807bbbedd05e86c4d4f41e6b2 Mon Sep 17 00:00:00 2001 From: Jennifer Wang Date: Fri, 1 Apr 2022 00:10:06 -0400 Subject: [PATCH 372/385] fix ci --- .circleci/config.yml | 17 +++++++++++++++-- .circleci/template.yml | 15 ++++++++++++++- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 350ae297072..a3d9e793da4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,4 +1,4 @@ - version: 2.1 +version: 2.1 orbs: go: gotest/tools@0.0.13 aws-cli: circleci/aws-cli@1.3.2 @@ -657,6 +657,11 @@ jobs: default: "latest" description: A comma-separated string containing docker image tags to build and push (default = latest) + target: + type: string + default: "lotus-all-in-one" + description: Docker target to build + steps: - run: name: Confirm that environment variables are set @@ -696,6 +701,7 @@ jobs: docker build \ <<#parameters.extra-build-args>><><> \ + --target <> \ -f <>/<> \ $docker_tag_args \ <> @@ -1062,6 +1068,13 @@ workflows: path: . repo: lotus-dev tag: '${CIRCLE_SHA1:0:8}' + target: lotus-all-in-one + - build-and-push-image: + dockerfile: Dockerfile.lotus + path: . + repo: lotus-test + tag: '${CIRCLE_SHA1:0:8}' + target: lotus-test - publish-packer-mainnet: requires: - build-all @@ -1137,4 +1150,4 @@ workflows: only: - master jobs: - - publish-packer-snap + - publish-packer-snap \ No newline at end of file diff --git a/.circleci/template.yml b/.circleci/template.yml index 30e4acec938..f2cb2ccf57b 100644 --- a/.circleci/template.yml +++ b/.circleci/template.yml @@ -657,6 +657,11 @@ jobs: default: "latest" description: A comma-separated string containing docker image tags to build and push (default = latest) + target: + type: string + default: "lotus-all-in-one" + description: Docker target to build + steps: - run: name: Confirm that environment variables are set @@ -696,6 +701,7 @@ jobs: docker build \ <<#parameters.extra-build-args>><><> \ + --target <> \ -f <>/<> \ $docker_tag_args \ <> @@ -887,6 +893,13 @@ workflows: path: . repo: lotus-dev tag: '${CIRCLE_SHA1:0:8}' + target: lotus-all-in-one + - build-and-push-image: + dockerfile: Dockerfile.lotus + path: . + repo: lotus-test + tag: '${CIRCLE_SHA1:0:8}' + target: lotus-test - publish-packer-mainnet: requires: - build-all @@ -962,4 +975,4 @@ workflows: only: - master jobs: - - publish-packer-snap + - publish-packer-snap \ No newline at end of file From c4aece4ab4bf105ffb30c76eb92e3d1ddcce8bb1 Mon Sep 17 00:00:00 2001 From: Jennifer Wang Date: Fri, 1 Apr 2022 15:58:15 -0400 Subject: [PATCH 373/385] pull ffi that includes the latest fvm --- extern/filecoin-ffi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index 4b939fe1942..5d00bb4365a 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit 4b939fe19424ecc7f621cc1959ac4ba6bd422065 +Subproject commit 5d00bb4365a97890bd038edfceecaa63ebbb3e2d From bba2ee92bd59e3d74b46d5537560896ce41912d0 Mon Sep 17 00:00:00 2001 From: Jennifer Wang Date: Fri, 1 Apr 2022 17:08:27 -0400 Subject: [PATCH 374/385] update dockerfile --- Dockerfile.lotus | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/Dockerfile.lotus b/Dockerfile.lotus index 812ad9f6191..ba32668243b 100644 --- a/Dockerfile.lotus +++ b/Dockerfile.lotus @@ -28,6 +28,14 @@ WORKDIR /opt/filecoin RUN make clean deps +FROM builder-local AS builder-test +MAINTAINER Lotus Development Team + +WORKDIR /opt/filecoin + +RUN make debug + + FROM builder-local AS builder MAINTAINER Lotus Development Team @@ -207,3 +215,40 @@ EXPOSE 1234 EXPOSE 2345 EXPOSE 3456 EXPOSE 1777 + +### +from base as lotus-test + +ENV FILECOIN_PARAMETER_CACHE /var/tmp/filecoin-proof-parameters +ENV LOTUS_MINER_PATH /var/lib/lotus-miner +ENV LOTUS_PATH /var/lib/lotus +ENV LOTUS_WORKER_PATH /var/lib/lotus-worker +ENV WALLET_PATH /var/lib/lotus-wallet + +COPY --from=builder-test /opt/filecoin/lotus /usr/local/bin/ +COPY --from=builder-test /opt/filecoin/lotus-miner /usr/local/bin/ +COPY --from=builder-test /opt/filecoin/lotus-worker /usr/local/bin/ +COPY --from=builder-test /opt/filecoin/lotus-seed /usr/local/bin/ + +RUN mkdir /var/tmp/filecoin-proof-parameters +RUN mkdir /var/lib/lotus +RUN mkdir /var/lib/lotus-miner +RUN mkdir /var/lib/lotus-worker +RUN mkdir /var/lib/lotus-wallet +RUN chown fc: /var/tmp/filecoin-proof-parameters +RUN chown fc: /var/lib/lotus +RUN chown fc: /var/lib/lotus-miner +RUN chown fc: /var/lib/lotus-worker +RUN chown fc: /var/lib/lotus-wallet + + +VOLUME /var/tmp/filecoin-proof-parameters +VOLUME /var/lib/lotus +VOLUME /var/lib/lotus-miner +VOLUME /var/lib/lotus-worker +VOLUME /var/lib/lotus-wallet + +EXPOSE 1234 +EXPOSE 2345 +EXPOSE 3456 +EXPOSE 1777 \ No newline at end of file From e69cc545b3ab0bf1e0928b2e996aac8b95a33718 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 5 Apr 2022 17:59:30 -0400 Subject: [PATCH 375/385] chore: ffi: update to fix build on aarch64 --- extern/filecoin-ffi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index 5d00bb4365a..145f6258251 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit 5d00bb4365a97890bd038edfceecaa63ebbb3e2d +Subproject commit 145f6258251d257749d5aa953c98dd0364231f48 From 76c10807d6cc67566c97845f704cce3c51c33c88 Mon Sep 17 00:00:00 2001 From: Cory Schwartz Date: Wed, 6 Apr 2022 11:11:49 -0700 Subject: [PATCH 376/385] disable publish-packer --- .circleci/config.yml | 63 ------------------------------------------ .circleci/template.yml | 63 ------------------------------------------ 2 files changed, 126 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a3d9e793da4..a3c85fc29ca 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -714,39 +714,6 @@ jobs: docker push $<>/<>:${tag} done - publish-packer-mainnet: - description: build and push AWS IAM and DigitalOcean droplet. - executor: - name: packer - 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" - publish-packer-calibrationnet: - description: build and push AWS IAM and DigitalOcean droplet. - executor: - name: packer - steps: - - checkout - - attach_workspace: - at: "." - - packer_build: - template: tools/packer/lotus.pkr.hcl - args: "-var ci_workspace_bins=./linux-calibrationnet -var lotus_network=calibrationnet -var git_tag=$CIRCLE_TAG" - publish-packer-butterflynet: - description: build and push AWS IAM and DigitalOcean droplet. - executor: - name: packer - steps: - - checkout - - attach_workspace: - at: "." - - packer_build: - template: tools/packer/lotus.pkr.hcl - args: "-var ci_workspace_bins=./linux-butterflynet -var lotus_network=butterflynet -var git_tag=$CIRCLE_TAG" publish-packer-snap: description: build packer image with snap. mainnet only. executor: @@ -1075,36 +1042,6 @@ workflows: repo: lotus-test tag: '${CIRCLE_SHA1:0:8}' target: lotus-test - - publish-packer-mainnet: - requires: - - build-all - filters: - branches: - ignore: - - /.*/ - tags: - only: - - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - - publish-packer-calibrationnet: - requires: - - build-ntwk-calibration - filters: - branches: - ignore: - - /.*/ - tags: - only: - - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - - publish-packer-butterflynet: - requires: - - build-ntwk-butterfly - filters: - branches: - ignore: - - /.*/ - tags: - only: - - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - publish-snapcraft: name: publish-snapcraft-stable channel: stable diff --git a/.circleci/template.yml b/.circleci/template.yml index f2cb2ccf57b..82e5bb8f6f6 100644 --- a/.circleci/template.yml +++ b/.circleci/template.yml @@ -714,39 +714,6 @@ jobs: docker push $<>/<>:${tag} done - publish-packer-mainnet: - description: build and push AWS IAM and DigitalOcean droplet. - executor: - name: packer - 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" - publish-packer-calibrationnet: - description: build and push AWS IAM and DigitalOcean droplet. - executor: - name: packer - steps: - - checkout - - attach_workspace: - at: "." - - packer_build: - template: tools/packer/lotus.pkr.hcl - args: "-var ci_workspace_bins=./linux-calibrationnet -var lotus_network=calibrationnet -var git_tag=$CIRCLE_TAG" - publish-packer-butterflynet: - description: build and push AWS IAM and DigitalOcean droplet. - executor: - name: packer - steps: - - checkout - - attach_workspace: - at: "." - - packer_build: - template: tools/packer/lotus.pkr.hcl - args: "-var ci_workspace_bins=./linux-butterflynet -var lotus_network=butterflynet -var git_tag=$CIRCLE_TAG" publish-packer-snap: description: build packer image with snap. mainnet only. executor: @@ -900,36 +867,6 @@ workflows: repo: lotus-test tag: '${CIRCLE_SHA1:0:8}' target: lotus-test - - publish-packer-mainnet: - requires: - - build-all - filters: - branches: - ignore: - - /.*/ - tags: - only: - - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - - publish-packer-calibrationnet: - requires: - - build-ntwk-calibration - filters: - branches: - ignore: - - /.*/ - tags: - only: - - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - - publish-packer-butterflynet: - requires: - - build-ntwk-butterfly - filters: - branches: - ignore: - - /.*/ - tags: - only: - - /^v\d+\.\d+\.\d+(-rc\d+)?$/ - publish-snapcraft: name: publish-snapcraft-stable channel: stable From 4043923e56fdf5fcb9804b64601b06fb7e988c53 Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Wed, 6 Apr 2022 14:05:02 +0100 Subject: [PATCH 377/385] Set index provider options based on lotus config Always set index provider options based on the lotus configuration. Otherwise, they will have no effect. --- node/modules/storageminer_idxprov.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/node/modules/storageminer_idxprov.go b/node/modules/storageminer_idxprov.go index 23c718048ed..2c656193df0 100644 --- a/node/modules/storageminer_idxprov.go +++ b/node/modules/storageminer_idxprov.go @@ -30,6 +30,10 @@ func IndexProvider(cfg config.IndexProviderConfig) func(params IdxProv, marketHo engine.WithDatastore(ipds), engine.WithHost(marketHost), engine.WithRetrievalAddrs(marketHost.Addrs()...), + engine.WithEntriesCacheCapacity(cfg.EntriesCacheCapacity), + engine.WithEntriesChunkSize(cfg.EntriesChunkSize), + engine.WithTopicName(cfg.TopicName), + engine.WithPurgeCacheOnStart(cfg.PurgeCacheOnStart), } llog := log.With("idxProvEnabled", cfg.Enable, "pid", marketHost.ID(), "retAddrs", marketHost.Addrs()) From e37c54f38eca20ba429636080e1a34e1bdbbe872 Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Wed, 6 Apr 2022 13:51:34 +0100 Subject: [PATCH 378/385] Reuse the market process `PubSub` instance in index provider engine The markets process instantiates its own `PubSub` instance with all validators, peer scoring, etc. set up. Use that instane to join the indexing topic, otherwise the default topic instantiated by index-provider internally (via go-legs) has no validators. --- node/modules/storageminer_idxprov.go | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/node/modules/storageminer_idxprov.go b/node/modules/storageminer_idxprov.go index 2c656193df0..365648691d5 100644 --- a/node/modules/storageminer_idxprov.go +++ b/node/modules/storageminer_idxprov.go @@ -9,6 +9,7 @@ import ( "github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore/namespace" "github.com/libp2p/go-libp2p-core/host" + pubsub "github.com/libp2p/go-libp2p-pubsub" "go.uber.org/fx" "golang.org/x/xerrors" @@ -23,8 +24,8 @@ type IdxProv struct { Datastore dtypes.MetadataDS } -func IndexProvider(cfg config.IndexProviderConfig) func(params IdxProv, marketHost host.Host, dt dtypes.ProviderDataTransfer, maddr dtypes.MinerAddress) (provider.Interface, error) { - return func(args IdxProv, marketHost host.Host, dt dtypes.ProviderDataTransfer, maddr dtypes.MinerAddress) (provider.Interface, error) { +func IndexProvider(cfg config.IndexProviderConfig) func(params IdxProv, marketHost host.Host, dt dtypes.ProviderDataTransfer, maddr dtypes.MinerAddress, ps *pubsub.PubSub) (provider.Interface, error) { + return func(args IdxProv, marketHost host.Host, dt dtypes.ProviderDataTransfer, maddr dtypes.MinerAddress, ps *pubsub.PubSub) (provider.Interface, error) { ipds := namespace.Wrap(args.Datastore, datastore.NewKey("/index-provider")) var opts = []engine.Option{ engine.WithDatastore(ipds), @@ -36,16 +37,31 @@ func IndexProvider(cfg config.IndexProviderConfig) func(params IdxProv, marketHo engine.WithPurgeCacheOnStart(cfg.PurgeCacheOnStart), } - llog := log.With("idxProvEnabled", cfg.Enable, "pid", marketHost.ID(), "retAddrs", marketHost.Addrs()) + llog := log.With( + "idxProvEnabled", cfg.Enable, + "pid", marketHost.ID(), + "topic", cfg.TopicName, + "retAddrs", marketHost.Addrs()) // If announcements to the network are enabled, then set options for datatransfer publisher. if cfg.Enable { + // Join the indexer topic using the market's pubsub instance. Otherwise, the provider + // engine would create its own instance of pubsub down the line in go-legs, which has + // no validators by default. + t, err := ps.Join(cfg.TopicName) + if err != nil { + llog.Errorw("Failed to join indexer topic", "err", err) + return nil, xerrors.Errorf("joining indexer topic %s: %w", cfg.TopicName, err) + } + // Get the miner ID and set as extra gossip data. // The extra data is required by the lotus-specific index-provider gossip message validators. ma := address.Address(maddr) opts = append(opts, engine.WithPublisherKind(engine.DataTransferPublisher), engine.WithDataTransfer(dt), - engine.WithExtraGossipData(ma.Bytes())) + engine.WithExtraGossipData(ma.Bytes()), + engine.WithTopic(t), + ) llog = llog.With("extraGossipData", ma) } else { opts = append(opts, engine.WithPublisherKind(engine.NoPublisher)) From 0a2429b467f3b0a7e6b395ef9ddde386c45bdc74 Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Wed, 6 Apr 2022 20:04:39 +0100 Subject: [PATCH 379/385] Fix DI of `PubSub` in markets by binding dependencies it needs Bind drand and bootstrap peers config so that `PubSub` instantiated by `ConfigCommon` has all the dependencies it needs when `PubSub` instance is needed in markets. In ths case, the instance is needed by the index provider engine to announce new indexing advertisements. --- node/builder_miner.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/node/builder_miner.go b/node/builder_miner.go index d24beff80ec..ad2b74f3ee3 100644 --- a/node/builder_miner.go +++ b/node/builder_miner.go @@ -75,6 +75,11 @@ func ConfigStorageMiner(c interface{}) Option { enableLibp2pNode := cfg.Subsystems.EnableMarkets // we enable libp2p nodes if the storage market subsystem is enabled, otherwise we don't return Options( + + // Needed to instantiate pubsub used by index provider via ConfigCommon + Override(new(dtypes.DrandSchedule), modules.BuiltinDrandConfig), + Override(new(dtypes.BootstrapPeers), modules.BuiltinBootstrap), + Override(new(dtypes.DrandBootstrap), modules.DrandBootstrap), ConfigCommon(&cfg.Common, enableLibp2pNode), Override(CheckFDLimit, modules.CheckFdLimit(build.MinerFDLimit)), // recommend at least 100k FD limit to miners From 75188546254351efc6ce933d8bbb7209f8bb9c19 Mon Sep 17 00:00:00 2001 From: Aayush Date: Thu, 7 Apr 2022 12:22:07 -0400 Subject: [PATCH 380/385] fix: FVM: add finality check for consensus faults --- chain/vm/fvm.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/chain/vm/fvm.go b/chain/vm/fvm.go index ab32247e003..20e0e817d1e 100644 --- a/chain/vm/fvm.go +++ b/chain/vm/fvm.go @@ -5,6 +5,8 @@ import ( "context" "time" + "github.com/filecoin-project/lotus/chain/actors/policy" + "github.com/filecoin-project/go-state-types/network" "github.com/filecoin-project/go-state-types/big" @@ -168,6 +170,10 @@ func (x *FvmExtern) VerifyBlockSig(ctx context.Context, blk *types.BlockHeader) } func (x *FvmExtern) workerKeyAtLookback(ctx context.Context, minerId address.Address, height abi.ChainEpoch) (address.Address, int64, error) { + if height < x.epoch-policy.ChainFinality { + return address.Undef, 0, xerrors.Errorf("cannot get worker key (currEpoch %d, height %d)", x.epoch, height) + } + gasUsed := int64(0) gasAdder := func(gc GasCharge) { // technically not overflow safe, but that's fine From fd402803003df56a8b70c419a1b36d92ab4d6cb3 Mon Sep 17 00:00:00 2001 From: Jennifer Wang Date: Thu, 7 Apr 2022 14:08:36 -0400 Subject: [PATCH 381/385] update changelog --- CHANGELOG.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78eccc510c6..99c04080e44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,8 @@ # Lotus changelog -# 1.15.1-rc5 / 2022-03-31 +# 1.15.1-rc6 / 2022-04-07 -This is the fifth release candidate of the next *highly recommended* feature release v1.15.1. This feature release introduces Index Provider, GraphSync v2, and many other latest functionalities, improvements and bug fixes. +This is the sixth release candidate of the next *highly recommended* feature release v1.15.1. This feature release introduces Index Provider, GraphSync v2, and many other latest functionalities, improvements and bug fixes. More importantly, node operator can now enable the FVM(experimental) to sync mainnet!! ## Highlights @@ -70,6 +70,8 @@ Follow the instruction [here](https://lotus.filecoin.io/storage-providers/operat - feat: config: Move MakeNewSectorForDeals config into the Sealing section([filecoin-project/lotus#8382](https://github.com/filecoin-project/lotus/pull/8382)) ## Bug Fixes +- fix: market: Reuse the market PubSub in index provider #8451 +- fix: market: set all index provider options based on lotus config #8444 - fix: sealing: Fix PR1 worker selection (#8421) - fix: miner: dead loop on removing sector (#8421) - fix: sealing: Remove sector copies from workers after snapdeals ([filecoin-project/lotus#8331](https://github.com/filecoin-project/lotus/pull/8331)) @@ -118,6 +120,7 @@ Follow the instruction [here](https://lotus.filecoin.io/storage-providers/operat - feat: build: bump the version to v1.15.1-dev ([filecoin-project/lotus#8073](https://github.com/filecoin-project/lotus/pull/8073)) - makefile: add make jen ([filecoin-project/lotus#8122](https://github.com/filecoin-project/lotus/pull/8122)) - chore: Merge releases into master ([filecoin-project/lotus#8156](https://github.com/filecoin-project/lotus/pull/8156)) +- chore: ci: disable publish-packer #8451 # 1.15.0 / 2022-03-09 From 0c099dfbd02eaa25af0f66bde70089d9c22c5cef Mon Sep 17 00:00:00 2001 From: Jennifer Wang Date: Thu, 7 Apr 2022 14:10:01 -0400 Subject: [PATCH 382/385] bump the version to v1.15.1-rc6 --- build/openrpc/full.json.gz | Bin 27023 -> 27023 bytes build/openrpc/miner.json.gz | Bin 13154 -> 13154 bytes build/openrpc/worker.json.gz | Bin 3961 -> 3961 bytes build/version.go | 2 +- documentation/en/cli-lotus-miner.md | 2 +- documentation/en/cli-lotus-worker.md | 2 +- documentation/en/cli-lotus.md | 2 +- 7 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 8a83321a53f46b7f52edbc58df6dc45461b4a080..4e312d3f7e8f3942e28c84a9dd777086bd8f081b 100644 GIT binary patch delta 26940 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%0DA|x|Z5z4^=aRA8zcyvBTgeOU_(!2dPdO}1$ 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

RpkdQr?BGi~kqO_YU^~%lSYY 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 J)!?C_{tt7qIVk`D delta 26979 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 z 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 TyZrwE00960eA>;U2Ic?&;6~Mm diff --git a/build/version.go b/build/version.go index 1c08a7e6a54..a2ea837ed40 100644 --- a/build/version.go +++ b/build/version.go @@ -37,7 +37,7 @@ func BuildTypeString() string { } // BuildVersion is the local build version -const BuildVersion = "1.15.1-rc5" +const BuildVersion = "1.15.1-rc6" func UserVersion() string { if os.Getenv("LOTUS_VERSION_IGNORE_COMMIT") == "1" { diff --git a/documentation/en/cli-lotus-miner.md b/documentation/en/cli-lotus-miner.md index aad43070341..4b7aa7aa856 100644 --- a/documentation/en/cli-lotus-miner.md +++ b/documentation/en/cli-lotus-miner.md @@ -7,7 +7,7 @@ USAGE: lotus-miner [global options] command [command options] [arguments...] VERSION: - 1.15.1-rc5 + 1.15.1-rc6 COMMANDS: init Initialize a lotus miner repo diff --git a/documentation/en/cli-lotus-worker.md b/documentation/en/cli-lotus-worker.md index 0e3f8b58e7c..c5e328d8491 100644 --- a/documentation/en/cli-lotus-worker.md +++ b/documentation/en/cli-lotus-worker.md @@ -7,7 +7,7 @@ USAGE: lotus-worker [global options] command [command options] [arguments...] VERSION: - 1.15.1-rc5 + 1.15.1-rc6 COMMANDS: run Start lotus worker diff --git a/documentation/en/cli-lotus.md b/documentation/en/cli-lotus.md index ec41ed92c2a..2465708f9a1 100644 --- a/documentation/en/cli-lotus.md +++ b/documentation/en/cli-lotus.md @@ -7,7 +7,7 @@ USAGE: lotus [global options] command [command options] [arguments...] VERSION: - 1.15.1-rc5 + 1.15.1-rc6 COMMANDS: daemon Start a lotus daemon process From fa6389a7e7dd7c6d34445e1e9071330838f3579a Mon Sep 17 00:00:00 2001 From: Jennifer Wang Date: Thu, 7 Apr 2022 14:43:38 -0400 Subject: [PATCH 383/385] add missing item to changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99c04080e44..5eaaeff39e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -70,6 +70,7 @@ Follow the instruction [here](https://lotus.filecoin.io/storage-providers/operat - feat: config: Move MakeNewSectorForDeals config into the Sealing section([filecoin-project/lotus#8382](https://github.com/filecoin-project/lotus/pull/8382)) ## Bug Fixes +- fix: FVM: add finality check for consensus faults #8452 - fix: market: Reuse the market PubSub in index provider #8451 - fix: market: set all index provider options based on lotus config #8444 - fix: sealing: Fix PR1 worker selection (#8421) From 681c255bc5ec2a6ab35939b9a83f7c0a2b7d2422 Mon Sep 17 00:00:00 2001 From: Jennifer Wang Date: Thu, 7 Apr 2022 17:39:04 -0400 Subject: [PATCH 384/385] update changelog --- CHANGELOG.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5eaaeff39e8..5eef6bb9995 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,9 @@ # Lotus changelog -# 1.15.1-rc6 / 2022-04-07 +# 1.15.1 / 2022-04-07 -This is the sixth release candidate of the next *highly recommended* feature release v1.15.1. This feature release introduces Index Provider, GraphSync v2, and many other latest functionalities, improvements and bug fixes. -More importantly, node operator can now enable the FVM(experimental) to sync mainnet!! +This is a *HIGHLY recommended* feature release v1.15.1, especially for node operators and storage providers who want to be a part of the content addressing network of Filecoin and IPFS. +This feature release introduces Index Provider, GraphSync v2, and many other latest functionalities, improvements and bug fixes. More importantly, node operator can now enable the FVM(experimental) to sync mainnet!! ## Highlights @@ -37,6 +37,7 @@ Follow the instruction [here](https://lotus.filecoin.io/storage-providers/operat ## New Features - feat: sealing: Sector upgrade queue ([filecoin-project/lotus#8333](https://github.com/filecoin-project/lotus/pull/8333)) + - see more details in docs: [here](https://lotus.filecoin.io/storage-providers/operate/snap-deals/#snap-deal-queue) - feat: market utils: Support unixfsnode in TraverseDag ([filecoin-project/lotus#8168](https://github.com/filecoin-project/lotus/pull/8168)) - feat: config: enable indexer providing by default ([filecoin-project/lotus#8314](https://github.com/filecoin-project/lotus/pull/8314)) - feat: api: Make ClientCalcCommP multithreaded ([filecoin-project/lotus#8276](https://github.com/filecoin-project/lotus/pull/8276)) From af7e30186736370bfde4145cb9477e8b31aeec62 Mon Sep 17 00:00:00 2001 From: Jennifer Wang Date: Thu, 7 Apr 2022 17:40:58 -0400 Subject: [PATCH 385/385] bump the version to v1.15.1 --- build/openrpc/full.json.gz | Bin 27023 -> 27020 bytes build/openrpc/miner.json.gz | Bin 13154 -> 13150 bytes build/openrpc/worker.json.gz | Bin 3961 -> 3957 bytes build/version.go | 2 +- documentation/en/cli-lotus-miner.md | 2 +- documentation/en/cli-lotus-worker.md | 2 +- documentation/en/cli-lotus.md | 2 +- 7 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 4e312d3f7e8f3942e28c84a9dd777086bd8f081b..d37075e3fafb33db59ac3fdaa05ffbdc1f3d9915 100644 GIT binary patch literal 27020 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 H3-SK|r1)*I diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 069cb99ceb8844d517241bb66da097ecfd8f11da..687d2667e2c76e11ecd69046fabf23275b9a8147 100644 GIT binary patch delta 13124 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 delta 13128 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 P00960j)EkZ0_Fe!9{9hh literal 3961 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 TH;exd00960={nY}2Ic?&-O

|FasKQQqbu%Jv2)#7J1l7BR1ksh7-JcVU|K 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 TFUa-PnIkp5HUSJ{>aIW3%Q+58a$(# zKFj0ZlIljomYY~ZS7Q`g{d!wLle*Blle^}_e%Ywdrddt39-R=$|6e_>=;@lasZD_H}UKd)|k6p;uSP9Vg@lvNnZtXvhlQR0SL)2VpmH9~5RuNv> z);@!C{|b1cLE9_&5!huj9XYU%Cqj5s<3Z&U=5mC}wp2u!oLWHyoq-`H zj%>mySGMnq^!YUX$N#*+p$-bH;ziPlFo6Oqc>rrH7UM38)HRD`WnX&zPAm zi|yBA3cQiUwaOnasdOtS=t9r_KEHh`u6Cw-h2DG=>wwsW_E(h%)L^)4765z!CG;F*f8=_X2vdIu8Yh3xPo9HPi5W`>wP6%p#T2p3DM*6m zMcMzi|8`cPnd?-uWaFk`Zo2y~fmpPr_ zgjpK5(E#dMK2NFM5MeXiXDH0BNVqvaYpLD3Hj2V&q0FkosQZISlL6Y=c0*Ty1N}$ptKkLw# zT3r?PfnUJ_G3C)jPE*pIq$NSsX>w%GkRJ$+OwuGC;8~!{#4&+4fI5ilQBpl1fO7Ya zJK1398JD6l02zFsNW`B=Ua?q!&w8ksHdqX!)eW4s_wLNiY? zT`HX!#ZQ>-S)b{8OUA4Z)r${2KJVor=lDQw9|L6CBy~gKE!lk;{>j4=V-_4wgY4%c z5BKJqb@IiQ{_+AR8R;w#Q9)j4IRQGp8GxfV@rG!Q@%|7TH<$qYCndpQi!T4R9I~G6c|ar?jj_JqC(I{Y@A}+WiWM%vQ*Yj zZQ;ap8-Yyf0mr24MhXP|^zTKxQEhaV6pE^)W_ISPR|?`a7`@jphao9-JqOtbZsDmx zTM^+8ggV1~e3~&3hidC8hGJZu?7fX?H8pJTYA$5fTyC^ay1Hc2TCCbTpN+fQW~Hf( zxeHvDuf0H)3N#QgqC+9bBb1GybqBK|{JnCVa!EU%%pr6wIAqEne@QefYvbp)gvjnH z2{qerjp8guujD2CPl&dYeFW7_TlJm)4If(sS=7``>n+l*5c|&+&Q~cl@J+4iHniKe zZg8$Y#d{iYAH3-C4y8$YFn6pQZ5RknB>T9pRM_M+Pwb0%TbiOVKv+OA$j%g?ZHY(a zEUPH(VkujbxJ$ao*f8ClL}E+G)GO%5UE%Rn9@K^H^F*F>IDIkjJ*z(yUDco zW6Dxg%_9*{SABA zMrj_yXihe6mGr3-5C+*MVosKul}6{#c~mTyn;nUGpzLe1&Sy=P_!;5QpsD}C)KPP1 z+=DFM^1@IVee!4@fvcbbiTpHKJ)(PUyqiiCFn|5BrK zv)Ze<6s#jaUkoyE;0Sb8c*11X1V#+5Vt-%|Vi2MsEdfphq*XrX8Max(xYLIjbRb9- zXvBqhuKlf>C3I*1A;1HT$SGH;IRMAib!opOHsQ5z4i87cLZsoP*3FVPSjZ3h?#Eo- z)Kw0m@(oajcA3n%F5q+9Y~UG`Hib4>g+qM4eiJ*!0Vr>48ZD31olK|NuTQT2+6^0S zId(V*br@jsA05rMPtTX|ROeVU)iu2yPc&<~AA5F-e(FxNw*fzNv58;2T|T~OOn9=u zl=n67iur5)rNdwGsMcGC_nnxnf2(|=s<`d|oq~vNO&}G*c%j?MuLmks`~3moV4g^u z^hFA*7UX@iFMJlbgH3Hn(g}Tn@|!;~Ac16~&j{X^@Z7y_sc*BU&a;IHp$N*{>f4^% zP*?kFMQ_WyofURtW!ov{r6nQb?uJxVmQ!H?1*RZ&zNU1SwCqnUDE%w+1Do$i>1Qfc z;(u(X?D4wz1dgxs2SQL#`2?1+Q7;#YFR%lD`~uNLJd&c6cQn92@b7eY4`9=oW8=>n zsXO&gOs1uav<#N>7(oz;_UBVe5o80Of+6Q0zcv0SfT5-XWLADju&#+;9|%I69|nS< zl~8zix9@R-<}2IXdNVG2I?0Jm(mH!7F+O_BR&y+{%>yD!sY54N=3EN2@ivyW&suJR zi$K^a8JAjH+YAKN?Otkgm~&ypt&BT$lzs%6*7s&qCadYUx{w|xdxPwABD?XJYEaHt ztiPI+d7)|}Z4lrHw*R*N4O8MUS8>P=VO4A5fsL%=5i=1r{{^k$xgDL)e|%#?s?WZH zPWgfawtc~got5f|Y-rR+vD-By-`_za7y)(O)gDkL7k1QBga2t}JhSLa9i5sUV0p0s zFqrNBAi{ngm_+j3T2v=wR`OC@B;E^pi!NoX-4b<|+nwudydyw1p9z%I67AFZ8ah`P z^a45x7aycZW)m>T#3DY z*G6=Y)OwzMhl&!hQ900lNt1b}&5!n?GTeGzYb1?&Ev^i>K|8cxal8=do$hspi)VMr z4w?rCHE5=}8bTZcL^l~T^);*6twCz@<^+BpTHd*ivE1>NXy6vo2g^sUINdTZFZs&l zOuVdAfqygKR221>EHe=8`v@Zv)F9(U%6*-o$EOk=3aqU-Z2KrU>@_)5EGQl3Uk6+O zaO`&`!oD^$Yaeg`BG#1T9JMkVuL49V{^J`Sfc*TyUPAz;Rh^4Tu5y4W1mqJ===#Lv$=C@xe1OKD1y+^lV*Xi*cTm5LQs2e387CsDIKGcw7#xxcF zRx6RWsftj;t$&44mf>IHf%avuKN%0%g@apQW&w3*=${fBSL=o(KaefI$=E8IF1JU| zs)~nyJw@h~)BkIiQ!@1D40?H3L;TO+u;$)~meqc6Sb6%*qGNQjDnhG}&6GYVaSYpi zIJKg^L@9Ebwp(;iCiu4>1;KVhV%9HC)6iZDl=?fRPZbrtKz$%gAV>vGg-vn}JIFNB z1jbS(*VTn>acud=(;oJs+`@*}0hty#9a25FB<5TrG$SLwzr`H4mFAQ0Hk(bCVNnso z%)z1@0r_!(4p+jb-k*!9oDC_>SNKy8=5AeISV=lh60K$_EP|(>A-_KwW8`LZ*z8gM zGZiOk_jdF1YJMM%qvH#UYC9nTdDHBoVWJfR)O+&OdtwJ7p|R8)Q$azIjzS(4OXWsu z_Hf)kr>WjqqwQLDlmLuQtQkgL;3HN_NGUKf8zBf2n=a{j<=2V_sYv1~=2lwP(m>x8 z+vcuLg#PgeUyC|^c2i4# zTVgkR*;1*pF_E0+bU}b{snF$th&1n6JOA9yZEY>36i5Isf=H~+gg0?KC(cP!o$2Q| ztRiY#etGWfdu6!B)6q{Q$3$=|8?j_i(Cz8*Z!U1;wCfUSx!|{BZ<>9EC#k?~-cG4g zmVTsUTBsBxMUHG!XQkT6z@zA3C1pB%^@9d8lPWy%Pn9FPh048XFp!;?zYy?Z(g~50 zPY(r67il6i!C5Q4U;f&-n6VZS0I_D6wO{vpAQ?rTk6{H{zT08+6Xc9Ipjo5DcDi*3 z_FyN5Bm$?hlcPY7%3rB;i@%^8@TYtMz$5IOdZ>7H{D5SRfvOLdfTKe9a2h;-G^}0|#+XgA5rWOX<%+#K!}bVv2-?cvRib`Z747g;gof zLrf>S0w^q5{ub(7%Ui2N$cW4+|GD8SwZD+y*%I8P#JdE<=O|I|c1sg)s;3lHz05hP zeBMwnaZS2aBtNao!@pIxlV0!O*Ozpk4Q|NE23yBeK)ie7yj^+-%>Y2j<$8{b+u|)O zHMlYIb6nVPnoxNqr|VH$p;gtM1i_7;w1<2IO#`@5U&PuV=>;&nK||=2n82wd5X;f( zT0Z7@Dv@7Mx-m)rAG?@AQ5N94cC1;$B{9dNB@LhSsPt(5Dp6B8QBxD^-G;S(N7hpx zur}WPPCQH2lok>IPu=as+efuIX6Lm>-e}(geldQC(^lSiN&GeFpqM)i`Zng(iq>$R z{8+$%p+|pyb6+fjp>-)=fNN+!?fIzlYhqya(Wzp#T&(n4ULoCj<=8##k5_bLsJS7f zc4h76mPCPbN1!RFoN7LlV0}4Ljh@&e$jS-@q5DB3HGL+R`9@wNI!K_J{5(X)X<(lT z0tN{doK`W33og$T)P3Xy?L%j)twB%&P1-zJv@aXXIqM*d?&ZQxey$gj9gsLg*a{nI$3lQUYNh)SV96FjAn+9cOU zH~U5O7h;y$LM-iD)>E0(tXtn`1@pw+>Q{DLeG^y)6;WI`)-GHTBxB4FspnT~+${b; ztHazsD71f+Aa+<(c(Y_d~O~xOS^C>zqs? zmnDtEklvNnyhyl`cB$!L7~BxP7`s-_nUZDJoYn{&rQc|5`NWu+qkX6mHcK{QOco09 zJZVTsHy~k}O9;4qjF(P+4H~hwSf!C#{$$;+qx<=lhwT6c{X1`I5>g9TYbk7AniKh?r^I(pORvni4bSwk!T5yJoF5{Go@22HtCfyUcr$Tv~! z9n=Z9X#niB33#cwOIS7y@c~E6R1=AV{h_DlOviHFg{tT|OYnk`?9 zu98ne9+T?v8{uthEXL|M7wyqWs#683O?B-#_?)MpW}YmQe|k*v_$Wyp&R04>puZf( zzU2H8b7x~cGVKmJqptM`k63Qu>f`GIaAge>3+e2e=>Gam_JLB}$EyV}pheO3jsI3bDdt$Zwta(ry=YgML(z(Mtt8W}* zyya*|Hvs)+r?pbNDp_OeS?l8kC_tc&zf86&AiuD!HYNil73>iBdhKCSIO0LzDHy6_&qRrPQtt-?;{Y6YS9H zM~Gs?=XJ7O9Fm4&B!us!n~}?lGCnIS%mL-<<|@(YwcLBGsa}%?^GyP9i=E@1EI}ZW zvZbn2>*9x!+ci2Tkd`;QDo%ZNk5i_0p35Jtfsnd5;`vE(MO_t(P@x0+BT)}zI12Zh zD$!$WXCc+gou@T@E>hV9&28+vmByvlco8F-d*lkKWkh-&nOQ&;EmDgy_W|L&S-o!! zASBRVvno0Bs)9wQEeNOt4aM{^p zBq#?S*@MXOdjYp1-g9yz-HjJ0UVDH)daz4!b%n@a%Gs6pNIPc3UDU$?=l+PCs0H!V zBtC=}<*=2cqX|&&s!M2~1+O0{v|2T$>)S^v4WCP$^59tJAABzM@%VO@#?vWMXw&g; zCCuZB*4d-YbILhVvIa{M?ineFg$RBbdg*6UEL=Y3i)FMU8YK0|*d0CSmLkc|RA~8? z(RYkghk_kN+HRPSa>~pJ@%G1K?^=e~olz1)&{VT>UVvVP>BTJHd^BfNO zxAOIfSEwP=Rqp<-hvKVwQ*y{QITei${9a(ojE}l#k(N;WO?c-IqfHefa-yC9U(#}h zw3s%oEN**?3>2|H%Zvn|zH}>k^mrBkM8Q5~JK_)!>XkE36s7EF2)%X4FB}0t(?ukH zg-^mN1A8-eQ2p`|HN6hs))EP{uJY`@Se2dMd|cZ9UAd|%Z=@5Ko4r|*COt)T06yvd z@w;3{_dPmfp%&H80OfS9jEc7qOF_Dh>~K-8Jtotg?ITPtm>3;o?i6if@fw5aBHndC z`rF#JOCmnAQy<{4;(%pKQn`O&;4Y7E9z`*tRuNMplcZ?wE~!IfCo~*J$Q@!4y*!NF zMuztTHylzb+Dj}|{Y72&!59}{N`WLoMQ0y4f!9tZt2((KW)U5YO5;6d{j5e0Zx{)w zfb}h+U&cRb3|ke{$nB$!_i|-VuwQm=dXPJ1OsU`bbMYGD3o-=P8vfdMROtqI*Y`>A zviJXl8@zX!rq`#f+SN4!&i=FOi_!`|c>!O4`e4Rg$4le2A2h&bU2Ym~g@F`DA1?;q zd>sQC1heLC1Na}WYIZhIY%jPkJ*=wcu23{V56>&3+O8sN%@$V=_6IWx-R9b9W@+@c z3-7juj2Y*`gBiyxb8>jZ$U_?6-CxqUf-lLlh)jDJG}@^?zD7%emoXFb>T8d3-+3Ib zScD6O@XsAl;E&WUwAinS>bEkU`yEqe`3e;M#Q&fqIYb;avJTlroxn) z-+pJDLOPNA3Il;7=o+?uj_eHp>-a?$Gwzr_uLGKm-#yC67Fq_av&^O1@jt@ zh5CZci}$a9CfaP8QzdBQg+7IyA7XWlWfgSzTH-MUW4aK8sfuiB_S&L0i;ZniWk16j z9k@7kRu`+-VpjjkoEJ4eAgNdE35f=L@R**5Iy?63@JH#@?2a%F60fW*&nZn|i`&S{ zT%y0QF?5(uO2$iUJR0~cldmg*J_As4r%azU{UaU6^%mz==Wb=n;vThDQ7dWF7~TGoQ)5u12QVAvuz4M>iB1?W?XCh ze*ZVK#+``c{37VU>?cw;qDVea?F)dW0sS`sMDBpL#5yb9*t(m-rkA3zW}zny5i*Zn zYP?*JCM}+tyXE{*hp7WAxgWcuG0>x|8Q-RWZb%8tN#!9F*yuO^iB+<-=&BWV=(-m8QnGLk)~m>!^i*H+=9Mf}Ik+dqClsD~ZHP#D9B7)8IXx00nnxgX2q>y$yt zd~adLD&V-LF3k4ffJjFqWJ^&4vWv*pq2WVOfK~nQzRw)sTr%^Fh7mOa9A=a!$CuaN zeLb<2RBJ9448n@ENOK~bBm6Qg556az8~6MYBbC-HNX)FaJ8%U}4lIjpmeUEsNtSf! z=gP2;1R>qz!W^R{K*I>|IY zh_zc=<4WDby^X@Nds}M3=>%kuLJ8o)j1nIT5w;GA)`29Ag4Mr$`1ubFpv}res=iFe zkmLEDMAd$?1iXSElz-J$LvB-gNtOMk;*Z2L z0fy1RxyMp*h;3WeywXV7Ii7&qx9kRbL^g4I6gwYYTxBrYnOk z<7Z7(D2*!#b|Kzk#n|az28mpVfB?On?^4|*xTFu}q(_qd!2xs`)mLG&Nr!HUVllfkfSZ>DAL_^da|_qYO3V% zWdCIW%n*t}n3M+*&%Gfqu}Na+*-+s}P;t1BBf5+VfeF-@6de+1J;igJt*TU1Yh}b4 z^ki$5_#_X(-)*VR)FzkTAqfW4n2~z6iWD z&$H%q2YN6Lq&o^AN>)Yz@o%yv;VbDZ2YLA9vhnlu^=_R%W`q}6em$5Fv7=aCOHIiC z7ogh<1klHn^KyorN00Vm!1*Bafv%5IqPKg$;|T|u)Jz|Rt)pbEnV#`p>8Qt}Sgkb! zDwzpDya&gx<7`|;%dT?XpiMPG+vDIT!|QIuP2*D98#lAY|N1Okf4Hj_q%Gxp>yC>i zjS}}LUeEt1q9{mDv)&wBC#rkBjM>Y-LL%}PcgMPfLUMeV#3BG(1P4{X2ssE&5i3i~d^-P%{0oU3)o{B%`(SX5CV z_GgJqfVGMOrX%uApr(Bj>Nf*6mQ+>FI71e3xTEw@39-bsTa0Q8kh9 z2)(gGGQ(l6Ue)3*elXCz*IRUHE6CCRP+0a7N03BP?eFUYp6n4_cZj$hrE{1A?AJjZ z*qBQ;R$?mLJZKMS6b@G>BbS1jjMsky7qRN)ZbIiTAib6jc6I&PMQtTE@O}wlY&^9e zesgD(6FenH2JoM@$BJdaT!{_S`n}QS{+~k5Dk#oy?XtKNywTw9?vN1NU4lCS8XA{C zXxyE~LU4C?cMUGVT^bD@d^o43YW|vvVZ?kQ%z88OUr-ys%x+QI zy*2ek_RP_U`TBjPf2}r1_i!aG4yVBsPKE8o9y0-sj1QA!jpH75YNwU$&~kLaZUkPa zBUc(F{-w7{%22*9X7N#jU~L2NiUrPYi>T5RcGJK%xpXJmd99?Ea`4KUnO67`E z+@Nb7k`(+QE$=^9U7&U*YLi}b)jWtGJi7)fiw>~jo&7S4<4qdatpR#8{XEz7jr%7= zE1ror@TWa|5)0?10ROZoyexcSMP!D0&uuqtl8T;CF5HM15v8~k6(W+=Il#m)X7hWs zq=wl#)iQUatf3il99A6iR2AzmQD>2(@sE*5zVjD~a{A)2D(WJ**9RVYUoUpkGf58? zZeHIFB=a8C5E5~%W)r{Ku6(RHG2^Q$cO>ImFa3(!nEIz(#t5`jk$?BOA^+e`wrm*a zuQL;ey1Rg;VTI=WI0Ka}rpWYjd#uf&@cemBEjAcko%keJ4$8Lrd(zw_aA8x)>*!bM zd+%2zpy+~5BAWhT!jeO7gD}QXtzjCB14v724K&Q^&UQMxsLImT^L&6zdG zi{?ufYFB1j8XS|aBXds`Mh#hcigyo)i`O-A=D74A$CuxRIBpxD6!L!6Owv=B?exTz zl@VZT-gosygc$QsR@VwttAt9#TXnY$`XW)LMFk|vuQ28$tfiprLEeJ~(_n|nj}r-Rx@ zp&qV0>gH?t_`RBmqg9JBEk_%Op#9e6fUq$3vWj90Vg(}np2HWuAA+Kt_jTQX*wFKhIgt>hQl)CDMi zonqao)`+G4507*6Fp#u+!x^rkSzgoScNAFt>zCmH)QFmH>0-RP6x(;*ZRD9Ix(Y|N zuSr-Y5u(|GI?`m{TC`~WNQY>#>rIX^Nnp>1eY4}&5s(jI5E6i8f zb<7ngAxpYSX$rC=)%|OA%NEiM96LXrsraIclXYVs(dyum@@F+o>03df9;{#y*Ah~* zQonOI^$KdIN~(;tNi7&UIbz7v&O+0CFXKaVY3LTrO*GQYb){ydzg~6u?`vrCOXcsG zrU@ZB*A6-B+Y&NFA{@taL)r(M37cZ4=s=gIW%Lg;RicYevyGx;9dv%L0a}+n1jt8(Rioj40#gO7b2wNB&*pa&)-_#K3^-(jShp$wA$`-4;=H zqko#kp=u;qP55=ymPrMQ;Fm~@s)GUt&%nO4Upf)%v+~PL<=ROVY?!Wj%T5Mjhav^x zJSq0VkMe-rW3rS{G+Qprar>dNxI(&b+T(hmEbIM`dfUtA)|%%qg}_PEf!Z)hxwav! zRA>dv;tKJqbw1d^bTx9wGq+j?hJCoK6*LPBU@;`LPX5?oVB)1~v%!xKM7^?$*?9ds ztjZluQHil(Cu~w(6l6S}yeNT=1B|y-$Y$EeCR_U01ajaZt-SL*>ME05j8#d>{~jd- z<}}fp?4&Q!%J&8J3bc#dL*izc`~k>Uq!o{Zl@8uEJ>WMb_^!;QKg7^UIZv5KEWTL^ zRI)Wkh3{1T#~(yvLGdJKRrKBwlXj%rCf%L!wZ5d0D>l^qQK}=s?8p&xIwUm2Co53X zGToQ}%urSyV4z$KdAc865NYlPt?p$kT>a>A?-wgHTFun;(SXtYfHZg4?&GeD$2=XH z3T9>+Nw6`IS1vnxPEzly{Vn=K=Z>ls7I9IOq4{HI2Lk&>h~U^K+=Z?Ycp(zZpTgYt zJ5ol)U;rgJ@}|DoGq*$djfj16hAsNJ?^?hQkYfn6`tB)-KTL2OW=6Wo2PIM*KlL6Y%Fx^3qMy zIj`i?VBxkquS5ZG()p{vXdRsrrU0uMj}9c@hUBsUw=`agFflObIL=%#A8Oeofd>QC z_{1YOg@Xc{z8cP3?d{6MqI~F>$LOHROIhN8h2UqRYgCzlZs+g^k)#YI zaRhm)UEQR0rBC24x(AqF9K3ClpB{o8$FT zeKq}m5QYC=pzz%!G(szBp14F``4SkR3Yt1XOf`MdhlDHxRz=IXHDF|xG4;e9X!eUKP#3l$w!=b~G_w(QY z#s$A~ZRR(YjY1IL3r#wFD-$X)I}zeFQ;1!G5{yx zbuLB@@D&)Z6UwWcKEDk6HdGvgr&d>g?t5C>Z{BkmJNEPY_>^oRrXD$$t zBS;+cO&d(izSJ{{i^-CAO2FaaZ~h_)<4?4C$R|67M$Qb3{B>+_6;1mAG-&1|s+iRS7RJOoBVf_I8i`6OhKOYm-h1TQk8J^}do zT!QS4a?L4EUBX6)O*OTCW0&U#9ca~~30FSMo}JKZj%9ftf2RX=lTHZlh(oA)DLjlujztQ*S8@^?pk1h&QD3%%ihDy=dkBKZevBX;uV;4j~wT+DrZ28`1eyS6su_`opl zP1M)}S1+t=!Zx3oT^t&cMA;Y9U>JI1?57cMS%&bwtxYit|HWvL=g~$X)YJCS=%-(5 z(PkkOJTIGTEMPVD6#S1Zrs`9KXQo<-L=IfAIP#Qlp;C;C;!M7J6RcnaDxT<4w#C#7mi2|x&CIVz0w1U;4SiH)u8pxtYs*?Xdjp&IETcU9y zH^&zmdo5D3iNXo zz)MIk#bZUwH(Vwt$JLyRX4d{~!= zLq=bpH{mkp&H#tc;JAf#q|umQKEe4uzwBs)d}Tr-@HIo4HsQjMvViWZm}kA0t-F!F zy}m_FKAdxqA;=V(Xm~&&PL?@b5F}T~FkCgz6oImxn)Oa};1BJGK!qbvYBK;dm zI=Chn2>(c6QG7|>_u7de;s0EW$+c8PzWFkV;}N_=QDADSh`4tSv)BYi81{k+UVt+k zC#ilr(sGa}3zxBH3Om}OY7_xB$2XMvHWOPGN0UO0_bqxx@M^kR+?)&#+C*lI^CcoI zvjf?|WE;{?q-h;NSzntP^C4!W6Po5GJyXJ`v%w1*BNKazl^U}Yr&qF7anQB5Q^oS zwIqtevyTU8za9S*$0uw5H;&&|Mh3kme2QgELJ((0UEB1OBTejgMIrtkHl4epC<=b? z4a#ed-fe|+4xzgX6W}mPI@kT5JpSv!rh2DZYt)9qZ7@@7bPhM#8l)y07lc@)`1@la z2)V!4`4{l)%%SK_6Ym>ReyQA}1c9VX+J1}Es!Iw( z5(xNdB!(?az=L%KBNA}vAYOof;jkVW>VE-N(`G@-sO935T}{EIvzUurw9~O!ZtOeu zVoIK_a`4F`a5%Ax(7E7m<^Hj3E^bw}aCQCa_~S$`uS5jXR~wlpBo(!HHm|Jgn;vH6 zubWWBX|rWongtJn0&8Uv2Ji-&?K;q|rlHHOvX9j+Tftyi*5QP>X#Ut+{XH=2Yf%N8 zRb)!B>0a&vcH$g#o!gmgE)W9~1n|rY=Z4JnJNq~CL=_N*y(B~L#@D1JvCsXv3Iis* zrizLo#>3mQM#GS(SAO!}vFV3F2w|8$@x%=OTQP&VgYAR{M}@E5*L*We+?Zc9+imp( zk=YPntFTb~501t)e+Sl%B+8YZY_b8Mc&w;I^iQ_Q{owOa7vK~f+lk_`LrQht{;Z&54EBqUN(w?uMz=2;Tj zuaS(p-*I)LaL2{G)pk60H<|#4T)PL0=H7C4o&c-ru+Q0ml$S?5Bv^3gLi*R2PxWW~ z>R-`PG1WFAwd!Th=Lt{@apZr(F?Fq_6t32}8KgLl*Tvz*dlUG9)w?nbG7Q9Mzb!w= zKS-Bd@W{JK4Z710v6QoIcHNUSPM&qO=Ax0)s6Kp#^qe@b-_wo#M_wnWm-;JDlxJSeCD*6&jN=D30lF zVlSOKvBYOM^Y#wdK>2LDL!s!cm}z0Hs*i#CVSsFUeWk_kJX*X8%Uc7_?>9jIv1+om zy3@3(b3ZT6&v#P>)$l*gC~hyOPMQ`g$saqZTWvRX0R#ChMGY1WpXO~A`sY<5_R|Dj z_@JaBVKH;xRPx0fW14_3D@Mbc8x+)0=k2Qxip|$p$j}mU8Yb(84B8)t)@ws1bK5I# zRaH@Yt4+Z3uolY|VIGA|Q8C{10Tu$#GbpT`*+$|dvU1vhfiSAp+%H^r$d9oM&U8$% zK8!_hXQ5^S3Hw@EJL2p`D=9T2TUWU<6s=MbBnvT7>lN>F8jHB^_ zVDW>KlAde|rzbED^#*%OYaiFDC*LnFUFzc(aD!}kp{)iEj4``e5bWmm7M8c(7n)R0 z!GGZq57(TrC{un}8W$_R4!pm_L}f9g1&)a7oyq8yf9U6BS3sM-=Z|QIJ<4;ugP{FO zxz^tE!r1a%2Xi{#K|ia0$Z__m`{QiysIOfD>X;Q+=yOv%x;I!0ni=)q>m08m5KDd$ zI1DhV$nwDb@>zTj+lx~qq8Osht)fedIo}K0qj4gArACkogG0`ii08pX^$zgtLqwLnJIM|s*lp`YeM`GZ1*-_5HizoQT6 z8%k+FhErUcrcLLRX&(T>M1+m+$J1j4Cw2a897vNJ3o0lyAqrRpN;mK=M(rt9l3{4sN^tbgCt4^`SvlPVpUn!=Y6l{snVPO ze!W@NxYSwV!p)=HbQB*8$oVT7l-FmD? z8CvZVb+)qHmAb{AN-?}Y?EK(t=tq`Had?<+lHW#Fg1+++)zSmyu?E!tqK)*IwiBSf1r>@$fcW(~Ywhq(L~o*8>FW+HMar z+q4_xx8%MrP!|W)$hXvE3zV5r>FZGg)3CXWA8{WfIc4Ju1oF@#BuBvnKoMZeF9id-{k(nql~OevQg(JKi)ah3G$h99u_4dyTI}{e6 zSa$pHx+dt}PQyt&k@Da_->Lj%{tFkq_}&rSu&dU-((!REb0*rm%S@+#ndi0=C^T^( z*KRg)VD(7=p2T%~)XLQBrRY2-4V(PZE4J0JVLjMer~3m+m)c?k>ve*1D$JK4Q;HnU zDHAXcCvV0bC9DO4c|forqEZ(eHntlnt3M%Ct9_NBiXE26ZY1^qC?sLn1}CPNr!hmJ zWYZ*cuTM{3;ROrj@wlV7BXzQ4>L0Gpl3l>7^Q#Jl0ow%5|_|6-IAGuV6mKL#+)phK9-aMPA(oxH_dr1&BfxXEDzZL|5}al&|l`R|0ISx2G+Qv4x^I_M$y9 zt`CQ~NOa~^CR?Qrx1PMXgQysL2O*O;K`2XvYV=D36iBQmAaMOI7|wg!{VmvFC)M!K zF7D+MetFG0z(D=pX14k_41nG-!wucV(W5g_UHk~?JDNrlDbOgw=Y4|E3q0rpqx751 z#YZ6t6I%9{$3C8 zeMWKtuO(LKTOxt$YQOS&|6Nu7b%>&8$;=Dm4tjqS#g3JaT<1XLRhOzZkPmCc*Zu0h zrjnaVbZm~2$t)pDOuP4w)2czc9o>LwjZc4p_${TL_Io5BcE3gLsib-sdrfELQl<6V z*ZOfHQ(0le!KYKmJk|rE=93c8#Jf=d(QzYC5TRFwW~?)K6P<2F2JQsA7ktbtWG#~EBzXk z9U9d>acE!Ktm$%=!}~tMR2_a@qYIMe2;fE(uiJMPk-TzKJ(o)E>L=%+Gkp(abJs!~ zUxKIKrD$!tHe?Tay3U+sLKRPlNU%F$oc;s$6h#T;4(X3uLS97z#eZ*t|I(Yq(`?4u z3>GXgk18a*efNI5aH5jBpFyk|ps?`skvt$3OolMTeWAZ~= zP>9cug{gwPVgKs+ra{odev*MUTln+GKJ4FPi^r9V#{8v~cI(U%tCoZyPJecmJdZT?`DIv?ys=`QVpWK>Q@5taNwMZhRv4**H6Zw?`?; zh+rIX*S!!3i5Y*T-;v`>8Yg37hZEa#KNC(uL;I?2jO$n#;!N1CG6U|`^Q#K^tRsGy5WKR~C)JBcU%yvrwlhR9Qm{j(`#eh*k zNBRV=H#JK=I?5AqkH^{54#RYRQP=t3HRz#$RF}Dq&d8Tw#|!Ol=8aS)-QE!4v4Q!S zB0CF#c8FnsacFVg=KFhR3u)&wJrHnLN0$79^TQu(&b^S;cAq7Kp==KLJymr#X}3?7 z%xbt(>cL_}vSUG(k5@!C_)nK4hk}MpcQHfSIogBt#m}nNHcNC&(95ir#*9Cc3BJNBWD5g? z(62$o`z#M^OITTn{LPHMFZ{+%xrQcQ|1FZK$4A#M$pab0GL*B@s>)^Ezv!q64Rh_@$huZHlk9D4zt)-pK?EaUCV9~VAS&jIm1kVTWp zrr@d#M&G}*^JG#BS;Q?{dbQuMX#}cn#YCoj%NANbApZcJ-XgxkYA^R3+wi!=ZuuAa<~K)5?{20aQ)Zp zC!6+#x8lJYSphs2aDzThfL~}O|Lgud)#tY2QLBI%iDE+Jup!@6Io@oQ8BY5a42^rF zx-T>koqk$#J@Xp%YRZ#a0w?0$@I@8GZsTJy%Lfs|8BG>)L%HNfbk&oX7gxxa!oQTV zd(pt8^(HjOa@Ltf)XFG5ammm`G5m*|FgGgR-g0ZmNHD#rI50MEw@iirboFR;U4g^N zNn?mYJjAGraIPpZooS*!&x{7B%Z4Rb*175Gd=gGP6NiU^d3!^?O!Z-sMTGfZbd~MO diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 89b05d015822b156630895d5a86cb048d0decbf6..4021b573d7df9e690f217a8548ac9c93933b2922 100644 GIT binary patch delta 9996 zcmV+nC-d0nWa?zF7Xp9l+S5}fUusWmGQ;!QvMb2QB{=qos{D$lbEG)-TxA&!_}+>n z=Z|snZm|@9*Df4%VlS7Nvf*`XD=ykOx2}=1!~{|#y?ctFb+MjW*j>o)V;4>>^!b4x z=L58?DKzeUeemx6WjlAtn@>gRwu)T(o@D>KhACR|I|@4MtL%SMZ~;0F+_2xW-Ze*D zIyB$?=ccx8AxI)mCI?FPX!8Y2Dl!q9Wj%|XvA#Q%-Iq3X~X(vaY02dugv zX{o_0IK_wIdxc;cKAPtb#Aud>(pWzj-?gzc81z+l|E<5&g^3Mmx(~_Q8C~#QRkB`A zk&`0x2fqxk3m|_89*K0jKj;r9NBwbsG`)C?VC?@7mcZyT)Zw zJMQYb-tqdN9Z$GxVB526&hYr@_O|02@2>^cJMLDKl>zc zDkA+WK_G(Jk?$!ylhU8FpZc6kca^>$qaIBIk{o?bahdublF0m*++ z01eJBa1ehqfn^(a8e?z;DMN^hm~b5a5^-a_249>%IO=DZ9DBK1Q{`Mf24?*$P^#>jLd9qb=Y@jV0j6NX)g(n6s`LF^2q{X@_uC-iw;-~*d>DK zgYDcM{wYFUufeO3e#DsNSfdEbImSprwVV-(k4%5m2C=Se)ehy2xGI!iA&#u}OgkQT zw5VEY#}og;?`WePleJ}a`18m-5#aoW@eOC2-t-$Z5bQs==3=zz!~Td)`|cfDuKv${ z{Aab^*vr-bO_wvYne_)V++S}->opqm?g!dabpsJ$T?O-FocoV+0VWijnTSw4!_ilL zl!$+gLbX>b*qcVpMcVqOl~HY)^6uf+U$xj5tK!_GyqRrS#5k~Q%{%MrUA^0Yhc=LP zAOVBh>%_2X4`d#J1XOdtOTmGTV^;VA!z}*SyA5S`wf`lS{_m@I3xoV?f&Tl~U$yG+ z5@|&RUZQM#*Oth{obxFr(Am5vhHWxLV0aPfqR}7{o62)Ws;b4F`X@(&lc5FXf8(KC zxliHTrM81Uo>Wrp@OAmp-Pc?HiK_*4%uD_q@+Jl$!Q5$qglegYL5y#??ngLr*2D#K z=uF`p0mHT|WUw&;w$PE&w;ut2^stnY$ZfNvXA|;DP|Is?y)!HzaXX;D& zd-hSaW9??G>wSZNV*V$pVdg!Wsn|eA^ZoslOYd`)UKaZaZ1`l9ujXe2Qw%NqO-N2H zolnrJY}qsD)iv_jY-Zd0ELL#v+Xaw-H3=`6z-5md-jEv-yaqWu7&dXSe@k6p&%g{( zW5H}0_Z8S1|K$P`QV3p|2wGqTHe&>cz8_b}AEleR3IY^NM97G+A?xE%KH{aL}a~oD-b({U^OEGZm zwPPTc_w0IsUBDDm^bETIe-jbZV6PZ9!x!$4h}QWqfF+)b=Y2=W{|y{3KF=mRd@#Vw zb^y9Z&V~){KWhY57#RqhoSk-rLuA2ko11Xl1G;OsBS^RaItUP(g6PM=OYZDbWNjFy z@ZQGe4LSP^ph59HrW?*YqJiVJa_oCd=7->nxD-Ltqt1y(2;UIye?iT#<5B=Q(K*rmSDXS z4x<5$1p@KU&cp}(vt}PB@$K1zo>+ZCyN8|1|lOYL$0{149 zr3p|1Jjj#x2|ON$8QHzEkK{>Xv!WX%+MM7#_kXQsyL(+OPJxvsX2)rrU=uh@wp>IgUm`}<>_9v-#bhqV zoKSyzD>4BNs2zec3a|@iwzEVgm~H?BUVd%|KyYH4$N;Y%7T8z-OiXO>oIVJaYl~uo z-91=A;|`fYD@;9J^Yu~)KC!13&|MtHGjyBDwyzpZ%*`clW1G)`LVw+(927doZaS$; z8GqQ@S?ipi_-Y+{tk5hnGP&!TA+2%?nh_qiV)LS$N!ATxH`OxM9eZWFkXJIez{o%i zZlLK1ihP^)aaZs6I-2hva27qmKCv(&R6F)Jn)8hHd*)3Pk zvR#$QR9PBPxl-CfCKd6rt;V%8Cy6x9sZfX#VwhGDwQX`qjek>mE24E(HdVj;WP(XA zD^rPCGof(Ud}rClomI@x3MM9!@2aroC{I5x47& zxa88^lrLx!lXCH2m}2*{vV@paUm?1sJcA<2S)l__akVxA!EH&jhCYuQXQJSiaDkea9`pj20q4E9?Ud4DM?GSKzB%&aR!8;n-VsAX4} z^n=UA8lf1pF0TeMZnrM`ZD4wz1Jf;LoDcMFMpB$emN|rCW#wIGKQC?7`(%3R) z+$6B2PH!>7rpw8SYB>E+O|7ov{ z1@C5Jz&|0^g>%W5_{^M#3sh%l{2}0iI_U91n0uApy}!PG*ZvT~nP~o0l8+wT6t!o~ zYs}x&b-jDQ|GC!nWB$*-wT|W`%H=hBBvz1TR&RhN$9{O#qLnq@+JWm#Q(w)qhVy zGp2#%7?#Ob^2knsJ-co}7fu z@gh{Z5O*__`jKQW?aZ_g+(K{*!7T*05WEuzep%-n4)lJ;Rw@w^{D|mV_pU~GRS=MG zoBGA8nJ2fxNB4 ze%eX&+9ym>d!IkS$MiLEGHkfbnPH(z;c^vjXMS8^#+1K{82$5y&F0z+&hVT-F>>EE zaqMfaqwxwKvIECT&QQIsmMP)vv8n zinxT;x0Er#De-}YXjM8yuA`McmpFG1?vHFGMj0E90@w^T3)D6jQA!zhBRCnuLq=6& z5hdNM)krYC9rGdScG_mhA5t+C{#N{V8|oW{FT~{s!-i(!0&bRwP(A|p&=Mik#KkjW zI0(9kV}3aVPmxzDe2~?=T7T7qXs^p6Xl#HgqTCCCh;hb_5}_krjVlDL%H_Odgc_;o zB_rHSI#P<+wz^ka-K(wcwPR$OWNhdWI(m-XSmsNeWTF(U>=TZ{hrB39u?Lf)UU1M+ zs)1%r0Mpj|N7*)xK{OD$41=;|4p zBO`{j@;=A}jd}$}6U4SrW;D%jTWqu~Hrf^&ZHtYz#YWp=qx)^gyR!`vb^!r;vxE~R z0ReN9suX(xL6asGAOSOzM-?@H9_1EDxkS|2c(zEIgjxm(J=Vyd+XD4x?58xCZo-80H ze6H64s{y}s0ZkK`!CbckRzunKLL|A$sm50pKZ34CJtD?2<8G@c5*;-(HG8jXMZu?P z)5|=EWFNUq`yX+E+nUeE!B z@>KcY*KY{V7gRegUIBecYaG39lcN@K0WXsk7dHXVlT8;zA3?@$kx-(=Up3WO{MCpO zi@&z0!U38fYJ(vVDAyG}a8F$GLAYyv6Vq!&?mBCk*dr?9meV zb>Z0e@vw3laMZC}Lah|0dxsDodL;gY1X~uoaBO?#R!>xtaMcX>%ez~gzSJ6m))4H- z5ael;S_XK!WPKu=yQ$RYHt(mkXA1Ugkg+K&e+!b+I#I`-_3GF&L4qq^lh&-aEo;_m ztyyc$_Sl+5^hvG$dRHuCx)Y9Z(%QG^twH;$;c3mvUYL~@(_2jUF#VI18cTmZ$=%h?1pdTcE-|f>r4gZ0$&P#P z*0SIc9-6V=@lLhYyS3hXXT3wcX;-US3-&@S*g((S>mR~&oxF?)l}Z+@W(r26`KFCm zn{v?_ue~&0ZI(rAw_dc}>gLuhxZxBIzuH@q|AYv%k%sBAwwGtyWyb~(;{o0ZubKtM0~{P`pG}>#4hOx$0EH@FW%a;aPv;o#3Io^RrSEa}Lo;kS%qNmW*>bZl^gC z)LcLp2)N;8x_}fw2LVLj)MBk;0_Xy}027x&VxYs?hj1mjocd_#`zo~+K4HQ%O}Nkg zUko$Dx>}#0bBCy#th(@=(WgDtxM4yHPHl%)Qnn}oRbMH`C5n=(>kTDX+xmY2 z$-E-vQJR_f^Du*9} ztuhu}!fG}Sr8qFx%M~-!f*5eceZVBfTwBNiE`<~|cDCPcw&Tk5Bl3w-T*dDxAZj)S z3YMx(ZT3{rjxsi_3S{NB@5^fLK(l{ZJS0sfOWDH1Rt4zh8u=vA`lepOW}c#@7%(6K zQ}!RrLME^YaQQP42b%lM2&^32K&}hy8JHrbjcY-{1k?tQ`z@F@rjp4~&DMY_UT;Ke zCbtqNxHWf*S~$+wX6Ol;cYf=&{g!O%s9}^&o*sT7D`=WXJbi_~q1bxjDWrdpuO#x@ zrwCeSWM;nxuS6@KXEPVkd`p?)CTBt%rCMq>EbnyjBI8@r1S=j+Wg1CsnJrVHdSeL)Z28{h$37RLz(F&XRt+Yz&A1{~g9 z%Qo%+o1a@?X*=kK_^tUEBi?^4H}5V2iPR_G8d7xi-k>U2D6QCeM8J#Ef6? zVC=%d2D(6wcT>|NEuGkw1u1eESNw)xDslNqjM$!uFp!+V2Rh!bMCj5alMv z{&!QEXePgEnP{~4B??|j%uZ#4RhB|HW-49uWFZv^@6G-HK1&(apet0-=BYTNdgyXeJLT0>FX^I z--!4yfA}4w#^Ms?t~{lP=Q!HgEmUy3$%Ox@~q{x5T02dLH`HlM zz`h_SG43fYSCD@)Nx6uw%$1Ckqb4(AL?hDg=5Yb3rglw=(dByca{C&y>Fc4}pbU3hWtJd3QVr3_^-F zm?92heo&F1M;d~m4|fefTy!ubu$H*31Z5ekl$D`pyUTxhFISa&8JqIN_xy>Zj;&YCu$h<+`UBLL` zJ`MCkht%c^c(s)}*7MZ&Oy1p23~;0e|EnAd+*7scXY30K1b}~dWWhR-{3w~G6eu9L zU9E}oU7&v|AxD9JaJ3LiYJi{zYjfa5!#ypzArBB!mut?_b`UTTv|KPnGxmeoPzoLD z`b*)hGVQlA4KkATg@}BD&fN#wslPrQC#1SU9Te&>T&j-KZ)UMN#q&-Q_4j{0c@GN4 zw@cdRgW)hEN86WPYAn2o4-ewI*Y@WXBK}OhjxK-aQkGiFLiNoh*_1vP@m*W7Te&H74^{8&V3B|x}s+|g6T&iz*eq4e}S%f!uL>}awGETh+ zZ}8|d1bI_KmmBAmJzY7}`y7GWHq!d6ICYen0Ugt-`oY#Dsb=D>Nvhinxk`GVgh<7K z*ARc13SzGuquRJ@8+R>M>~U_!^(9)`_jTs7f@mY6`wgFH4lFcuJ#4tQ8#V*w0EZpah?(SjhF<1G^G1c_2 zU_GXS@kfOH+z_~? z_7YOe^mr3YdNGYnc3b8Axs-E|n?`>W$YR}PsyHEe==T=`n};XZEDrj{sWnspL&~O- zqGqo+h0&tI6{m>y?r6=)AMbPpyzoYW%1Re&;>1p{2^=Q+jAxfmm#x`>cxKAI3y%gg zO$WIyG64>#@z5LQe*O}fV7dVi{D~Zw=bAxqVw=bSuSD<-6B8R8EFoB~EsB2)cK2Wf zjXPuptuWPn&4X_cd}2>6pu0GXBMKYz2&j0gPCvGu4|6k|0#UBN%#$S5%rZ}s>Nb~o zBt1}qf#PKzKT;H`db`lmF7(t@?NM$9lzWcdswMM+_luR-PgN{ZWKK>|dp%#hyaxL` z%hi^104Xkvk(sTa@uHc+8g#tOT?IW4dXc|H=Odybo-DYrX8?jZz7LAef$0XE zo&H3D;62^S6AD8{A)gY}-a;gr@M=huHQ+l+9qq(kE>Hc;Z}#KT{~^u{KGy!1So*)O z-YpFBuLb(=Uw_p^^(IDrIOz9oy&73wZ8?6f&GC0FTHSxG=>l?I{U|;N$89~keXeK6 z#QPc>cfxM|$$N7w&g1N8iPx`?D6p0PRFE(o*|CtiaEYkHt@fbT(XMTO|EBjP&Y?@+ zJE<)W9qrtnb1D8E6El7H8ZVJc;d14Xb)bRLPvsl{BaS2FS~c!yZw-p?MLJ0^q>n4? z#4oWA@fUx>^9A+3SX8uPH_iyA7+Mz=GI{gt+GoO;4(UV3+W13Ru8vofTNRha!>cU3dz#!UFS1c5vL{Gn zhwgtP>r1zoD4ZwZlPn0`C+Jp+=LNiH2lBjM0F#*w>{(-r*^(|ugZk-blnx*8B2UNN zo?Z~6Z$Ncln%4Ak_Zqo%&z4S;$vZGHJiDH+dU@x!h}snXVIS`{6rB+hJ@VsRvQB;( zc!73kT|#2oOM+at16D)e=OY$oZMzMgQ7wNRh3KI!jAO>$*3W8;jj*DE3Ew00phoV? zTyvcmS2~JuZ_>KrQzXArTdW;lbTUkal2Xa0*>gVp2bib_3dRw$S3Z<6VWBGH1rk~Sq%If>fw#9!g zi>+SS481TxuT|LU3OmT!RVh^Pt!bXy2278MlFG(uWV`?Dqvfe)oK9`!OtH0tv(g=r zA)z4Fv6bFdwrj}tFl$qyCjgW}qvCGFD22RfEpq+VL~hrr2WIY?V(ah&&$CjHdfrA; zGVe2-Z;*V>z4RaxJvNrcl^&E5Q&E5IXf*3i#^dP$n)UUAfq8@urhQ}_OyH<@G#gCe z5RSEu_T}8VNb~sU*z1*)=v&LOAFl26t+GiG zKAlLwITiCxE`0=C%L2t=A7pp^9+hd%TZ>4oq({b5Wr8lgPnm|pIQO&6$YXyxt0=H1 za0LxaH#}GF?LEX6oHEWQ9qq$a{P!htk#o;@nef5n|NY|f3uUD!B&?KK6ELarbc}D6 z7kFP(9t=l7Nq$_lC!0JG@u#z%qpYpILet+NmomsQ>KM>~NS+N9p)g^L7#G)@l{n!$ zobY&|-+tuz3rH8&e9Hgo>#cvx6z43^B$&&uRh=STZjB~A5XDD+H)xAxgS)-Z+*T%z zaWU8$^Zh}8I63N%`=jwzqNHijRh%z)wWpe#D#*lIRzAF%Gxvjfb5%E_w~pP`9J`mb z`S9o{YYV>k2B*ldpo0X~)iJvK3<1rk?S)??_gd==Z}#;`YgD&er&x z=$quxXNkcT#M~|%EO_F3`71}$Y6QkIf?NS(vUl2uRvnu^*0W0P2yy+0=(%m&RV=y_ zry<{)lSEejsDgp^spgnxDd{SfInslz6xWh6T4;m(r&P?fcs5q75R%_S zBCdDzPPe0X^xKYhiJ+++f9-Yp>_SJseJYzk;W1HdZ@g%}>AikS_;@A=4m;Wslki6p zHNtV*8wV${C&K$+&ow+hU8%BhH&I;Nn zHM@%SX=@8<1sqG))r#Ly@lMceY)&SycQ6`{h6jW0cychF&EUaghGzO~td9^vk=oHk z`JlS)<+x}^BYoVRLj7RWotg)OAsik|4Sjq7XZmn|)-`$~G&JLxk~tKwp?k;B0zvD| zz5a&j6h9&44f8)P*W@pVsdlV;C%0(FT2Jrk2i@*Lw|A{ij(fdh{pjCXNBhlosWV&%I4R2oCNArp=1kmo%|A;oX(T$@*__x8x~++Evg-*Q)NN02UD4{UgH{=-K)$NI3ZkNTtWZh}etJ4?`Sq<4Fh;h@(Y z#2to+<=O@(QZVf4z2QV34|?N&#Gv$#2L175*dH7<9Zd?DY2%#FEtyHId`8JkLFe;H zrW8x-%*`cCWw^6D15@Sp8=alkVI)7+8BTAqrajHhGIGP6S(C8X^{sK!9ITcV(x!2> zf{->aH*ZWxQ=aIv3TYBxpHoO<2y5RX2dyk@z%@Tox?NM+mk4#crqr%~DOJSRc1`KI z*OVl{+O99{PvE{?UuxHv+V!QEv%ch@IU+94pua<#Ht@PHX?$&p>2^KXA3pTjrkL() zifPPwZ4q@}q_#!W7ExP7{UH%`O1+-ZK1wh(n1?*E+z!O8#_XJL@ za2vR{m-Q3&8u5O@NB;AF<7zE-uIe4_g#XP`wepKBlsPWYqp7m_K44sWc8kyG_wCk-lpPSmYg&>JMnH(tDqv_Aw7{6&jXo&RF3q#M|I0rqi5dSy+hN?qnNJD~~9kA+x zq@@P0;1nN*?-hb+_-LL#5TjWhN@M+CeAmX(V9;0H{kQ&77bZ5O={_WHXLP}LRmple zMNW#$AN(@FE`Wa^cqG#8{-8gc9QDWj(fBs(ocH99t(^UdTscn`$hf<3?0bf^l~glE zAyYA@`0x_VG2;)J7xopsaBO?l0jnPPdg}_Z-Y339?0O$Ccz+FEE#c~G`2EEvymhIA zNv>}cV=G6QbI6y{?Bp=8ZnN&Ou54Go>8Iz z?YOJ!ddKU7c0A#(fo;#OIm6?p+uM$ByuTJ$@3^Za8Y%ID$B$&VJukrf{S(jz(Ie|1eR^wX^g=YqzoZ0V#0CwOT>-!8hmm7;84#nIreh3rpQOB3Kl0qAj{x< zy`8SHMKL*i|40!rktsg%8JXGK>ag$5!159j(_RuDDO&aU<&y=(G)jwk+w-_b@pCTq*;@aK_vBEb0#;~UO4z3De-AlQF!&BbWbhy4+q_T4+QT>YQ@ z_|Iy+v6rj=n=WT)GwTm#xWC?v)@wBA-4C><>INdhx(epUIQJjt0!%14GZCS9hNG|g zC=q`fg=()>us4mGi?sDmE2G*p<=w-tziP2BR>iqVc{AIvh;d-qns?UKyLz_)4{adp zKmrE0*NI`(9>_cb38?0Pmx2Qw$E@%LhFSctcN@y?YX3_t{ohyb76$p(0{!=|ziQRt zCDMutyhPdft}T&?IpyJUaNr{N4>FeY z+YyF${l4kW+yx%>j^Om$01rl^f1x>Be{=f(%-q3r3C)rD*vEKo{-brYtF>V;&(xRl z_w1u;$J)(W*ZT(l#QaZG!_0d$Q?Y@L=KK38m)_?py)5<<*zj>bU(L@5rWjiIn~0?kli2{>ud>q!7F^5wySxZY&#`uffc*m%?Iu0bt;+r|!n3XxRaCM34h1qXP-R z#6*w6&ac=E#HD@%{LT%bHkd&JTbM#7a*!eiIEXqJ-9yXeZ@#e|<~FRv>Nfk+mtx@B zYsWw?@7eVNyMQUC=oxkae$l5SY z;k}K`8*=s;K!f6YOgEf)L<7fb<=FR_%n!jCaVdhPN1YRo5WXSYe}kG~$E5&r$U!FK z2fM&?_+~a6zUYYff?>~seor?yM7+*8z?6T@DANwI5cF<(^sx)pE}E?^)}sgLEWvsu z97Y2g3k2eyorw?nXU#rN;@h(aJ&8i0*dUh+P9PBrvh^hlOYL$0(VD~ zr3p|1+{=^q2|OPA8QHzEkK{>Xv!WX%+MM7#e}S7ww$O;A;*gQPJ zCeN!c4h+U=){Y6LSoE{rw||=L?sd611y-7v9jA4IP2e!uauK0?i5OY41M$ohlerjk zLjCQn$OJf`b_mWWz%H2C&Jvkmx&aV)`MDhc!HI1m1H5`zU}FI=F|omO`XE@YEs70x z_h1E$J7fl}F!gxN*GnPz#GYC}cX1fc&}}B$zG^fvHBYRcCD9V)g_ z9P|AS9qm0a;}<+>x_@x6fi95a-PH6*ODDF)Q-l~-{DxpEaXGr?=xsqyH-8RY`ekJ@ zrA)A4L3a_oRAYxx^s|*I653yic`%14FykqLxi;OSTHc_`_}-Fr52q4I(_T2qh}-o> zTyp7d$`>?=NxAqhOtE`eSwc*zuMpi*ojc#I4^H1A`H!Do)i#nNKMoeP^v3Q2K%jwynh@OndD_=T_M_Fv|2_jyTYU& zTrSoK#h`V0HIQ+;b=hwN)B7BlZZYG0pz9e)aUxmb1QG*Tr;x&H2NHKCks1}q$Rd`7 z7$&5Ude0pC51*a#w7C^R&LRK1Uu0&pnyrf|Io&BPW}eBE!7nkL;MHIJ{s&dxz#QKr z5?(($<$uay(*<()s5G|eHDmaz(n}<8SXiT=jl)-`gLrADvI<_rL!SomI|*+tY&JKOOdUGg9%qM6rl+ zo?5Z7z{ZF$)Df0e%f${UUiQZ~Z^FIe$6&5p0!N`Y-BGwriEon_qRv1tyxV z=W|}(C{@D5SUV1L5n@2;0$!kC?!eW;-4LTOINV<#k!i6^R#IKccu1v?|0OaIzQ<(l zlkhM9vqmmGJJpT{9sieKCnb@Vc;=pn4|uYGgdod%I!JjGS4A3|sGLT5L6u5l%b0Oj zynh^PbrOu1{!_qOkk%D3j>mnG?zMKc<8DWL2i<0~MbF&GP>6v#bFYx-m-zjsy*3uS zn~4Gcgj^TSC12t*a~>{GouToEfD7uN#|L5VReJaS`ubh_LkMT0`BO+Jo;9yA ze^b}>?g9VjTGx;HKmXP`nwKb-|IoQT7k^xw+w*ig3M8IxpKhP{IcuS|q>|#9HnQ*0 zsz$3Ct!gAxqvUywG9#mUm|!BQJE}3Ik1;CFpp8hLBq2MZU)hDYqN(HwB`U#iM61fB ze#f*&c4TCzOR~Fx0!g|b(II(-GEW=IoE{RqR7o15ic>ZLJf@P8{s>*F#u!&W34hI) z29{%3CSS=TI|cUay4|cy`L(O2b5YY$=6R08DlY`qLP=?3&=>jqsXqHo>18sSwzK)!A2 z7q4c%C|Z1Yh36zlg?Q`U6$euV@qY$mrvbNH*(_Di-*iB*@OhQkAbXPUzr_afwhH@c zC(&!4FiGuw{sbS>*Tl)N;WlT6g)W85Rk)q`afKOE{w`wl&mT6MYcn{*a{|T4eb>aX zuf2}OD}2Zf94k3P^}1T7gtN!03UtIrL+Op!m@2+eZ38d=kfrzRiZ7#ND}TbTtYj(T z5?0?*#ssIt2Nt4L=@7Y&R{C7x+&#EIvXvNQY&Z&FGuSLp+gwB`W!R12WDE}(RgFcI zbhB0?!Sr^_hoswSn<0Nl#ZdTL@!xHzZxp@|mmdrpnu!azSt3ID2;4(UgisR~&xqk5 z=pv5!_FErWz{QUw(d6c8>>uPJy-ak=$_ zo!YVo&sg@L1%dNHca(ANw9tvGy0!GKvTEsZg=gdF9=^l#GeWtuleo|aaEcF477!CY z*Xw}QfM2?Rrisj8uG;~tq3n7gl3e9f<133FL06+55#yL~w^bC0j+!)@z1Ov(;8V5f zWu8N_k6fnxkGQ~X&FACc%m)0vfwTh&HP~V=`n?7^G5ldW(VCF+LH8(=Fcv9G-APt? zEKD$&zhhs&63zs#XH@YNKFl>WJsCHbu0{W8HIC^@Mq!w`jHTvkhT;Mvq#oZ?V3``WEZ=3G2rhn>XS}RwHCABeXko&kHbDh4r8hEuOb{ z-r{+S=X-?beLZ7mjDWC@h#&`255j&&n-7k?WUe8+WZ?V6{ z{ucXx_X+#E89U4bntihGk%!_n&^|(C`}iJdtQka)bKhcki{UMXw-~-p7~ad+qb2a` z!m;n;VdXU7sAIW=S}9ET4k14DNc;&2wk&wz*!Ik=o~R_@su}Q?ceglwsWk+xA=r^2 z$kQmb4DfWx`b0K&Q>o8w-cM`K6zo|)V^dgv79^*2qK-Z5)v;%S1XsQ$tyynd)~wfB zv(}pJu{De6lUn`9cMr^b$@U_ZDfO2s?AKbn*5Yl^;teu(PYT$+M6mWYl7L1j>o&D* ztGXQv+HA&pMZ3`2tk!1jjm_H4`2(#jX>Ey$Eg5EP_xl6)0&mNFe@#lx0vo>`jeF!OMiZpyQ`fE{E59>Vp=ClBSNK;9rxa? zWx*pnG-JQxoocOjYrXf*dWU+`u2!`c?4??;aqeFK5T@(oWkje{vS2k+Fe1%2ZM@o) zi`IDUrSWRBELywuqV3isw{F1|Ka~$PGx-V$RkU8HsVP`UsyRaz>s@QhT3fbbb`$q`@G_8Y{8(lle5;K?WI8rwMS7(nqIqO zWB-h6fmIg*+f~5UZttVr?&a3q@Xm;@ne!i^viZ7IatJGHbgbC9$;XeC+ zG0Y6>YJGyv9incs>cVqIpY~Ma1{swBys>>dwH;bX*`fqgeWe_iC`zubHwgD~ zw@y&&1hp1k;LR{&U$&={SH=RFrx?!bU`{|J3wNfrZM_DsFardpm*1cAjC_)+9DWG4 z%2;#>tJye|;=o)lSIkfgV!##m0h1VWZ6OD^6jIdK*?zm(jw{oT$R|p16~Cu|sM#1O zSgJO)*;7RuWo%j%$jWWsm(|>XW`DJKNSaKRvW17O3ee3p@=2ogO}&K8JVi?}U_b(< z>_3);Okfk>@@FCrH20ekSUI+VTo>3gFhxuo*Mfoxs0|?ZTQF@*C6l9?tpQcM-iX#r zZY54|Ywi@a@F-)Op(kkG`K{OXTe7L6hEY0sdiaH`plKrU^cDVwV(W>gkbgqHlE`nL zB50kFnf)5P60Llm&0IwDEoF+EoC$H1YN^?*~j8of%mX=om%hxmu+kfh4zaz8?7csd&l$#v; z-%Vwrnf$6{qS4-$D0nF`JCzMqSqkBpsdUkkg;XTGQ{%woh^VTt5Q=EouF6ENERCqt zscQ|l{XlDe}B#;30$Q0rGzw=lZkReB4ahKrRnZdgtSejl*7Q5YJ!xV6EM1hhnFw$d{YG-tzE` zh!69J-$80DE>Z5vQ;K+wqn+JC1-CoipS)>wlsUXyA`?T3tbYw~5iyw$Dei-%SV|Qx zx9<_d`P@NsCNE%SJKm#*H{{Y=%wi4{z_ajW=#u}UjC8pvwoIe5hbtupxsNKWW%=sP z-REAv)8!uY2Z$|X26w(|-Ckci)(ptH2o0`nz(LRiY(~MCqusghREp*E)H--AS z3vv?Up5k%^DSwlci`e^zzvQivNAR9^p{$z_X}#ICiuihj4EJ8xI^ZN@2WnK6FAy=s zdTTu}^yp;4VHnyvJ5_~1k7OtZh6L6Ux0RqQW0kTp^lW!I?|;Rr@=(v%lqbIDM?~L0u8=_) zc0=oQ?Lbdrsw#B`MY(!YyhMloBgNXCK|4p!V+~YL^X%T_DSQ^6b3{ev4f5^+#vk`- zpdUJR z3U8HZzm=(mGa26j{JRPf?bearLX5?sn6yul;#An%lM>P2{i zN1q|cn;N>@IIryK%Awxp2;8=j)@Q}3QDz2oOsnb#Ta%=kiMJ-HZZqU6>46d=6$f5J zWPd7%y>g6d&b9y2A>d6i zm50Ox#109vYZksok(^J<0tQ^W2!z_g5Pt(&Of{NK%iQm|b~~Xs9}LI2x!YHbucKs8 z%+mOH$hJt`Gl(~%|Jj@u0YVmA?v~a~^3?K&3F@}mc|I6Ua&xz?npuvy%3qGDriTUV zF%^_A%A8{MaYFLY?=J>64^OaJ9Q2J-Yp4K*luac? z&0cW|qeX=)P7&?h(VCM#-suW>;f(^7l`huAiJf2*I85{z&n}-XTeAc4%#?c<9t~)k z4su;&0vu4|p*PI^{3SBMbORvx6FDx=HG|;9Hjx2diQpS1CN?-&La|00eV<9~7Sh(+xN~ z{fPp>d%Be;6o!mKJ|(KXg-A5v)sQG_z;~27+KIhfp8A>J?8l}5L!23Wto<*s^nYKy zTNvbD3-sT={;G-UO^o_*(C^)PHL|?ga{OGIba+?Ln`jUEBWtP47#bLzljH zQd=B4+POXFQv5q6X8P_mULu#m<;o-LKm(V9Ng|sl;E?e40}|9RGv==P1ykmG)c0%hbvPxPh04pY{yXM zX-6^jROz{=zDgybk{`rZE2WB%o^h-;5>Y$X7Jmk93xl?WL4UHspix2aed`iqQeD2Q z$0Sq`H15Tf);-}web;#21^Z))33N8^iDC0aZ06LvXf%j49ljknhiZYGz-QY++{g2H z%Luu;gnNGUj`qpM(S~N(Xn!j3!nz!pW5|F&=CqeX)0Y<5o8<0ka<9C|MxDr>Adwxq zkAJK$-D09}o`g@bAatLgTPdCw@SYvW^L_zLW;U>AjV)$Nx*!eer=L+ee87u59d~>Bll&l zxlW8L9mTjeXDZUr?zsY*xJEa>5j;d zP!Q|bN^dLMHDr5`wJFgP07{`zaW`U=Lf*6%xqfRRw`-A`uf4ZJVFQ4J~9p_aMU}R4W@7i z$681Ga(OOQB|lm^=ykMD@X=#J{62x?Dw<#e3A-Jnd3<#2^-4~f#R?avb%nd$~5P#MWj~JBV(yDK^NbrOv7QE`&nk>F@K#^6xb8E zf(E7=o-6nE9%2hl8RwIZ_Tei2`x3dxxo5mg_+aw?esTGQvQiWhR?4gim{fT>#<$7~ zye}#bh9jUPKd#!7O`eGO(^=19)>dDk>FF1l<$v|{R)1!Sa~5b4%;ndrPLVFRMw1?h;v>Hsw8gT)-Ck&JD-*}K z7;KIC{-8gc9QDWj(ReFS(zNI*&KJDeQ%z14WMVBVA70Iw`$4_AsvFW<$8Kwm-OJj1 zcr?n|f-kBDY%qup-PA;HZnVPi(4d9&-mMSBr8nx`{5#S`{XodYkW@h zP4eio#NY~IZWj&~Jn_B!m7{4j0%I9Lu7EMwJ8eX(md&4JmD~~H`VrA{+qkP(bSF+j zzBea{to%_01MO4IG0#%cRV;I)2U{twC1teG2Ki5^m}~KDSXCh=bJsw(*Jmo?V9G>X z@93RwNAKvj9qkf9Q#=0J>-5=$j(+=8Hi5!pqT1eg(R|Z;{g&|YOb{G)v?V6tk0fe@ zrPGnDn_racPcz(K4Wn(>)b1O6fyOXFZNCEYe@hd+9=;xC%EGYq)lUyuRGNb&B zY~Gg6%23VTSBa&^_K+$}`q*PRbH4aC@(PnZkMEy8f}Y&l+wS~*Nf7!%ChJF&;w&=( z$CDNS%25)jnL4HXG-Q!yoT-_Lkk40H~0D* zrc?ZckT=Z#xLlLJAg0=}?w#DC9cw+kryq2?2i@MaJ~{67j`gE|YaQ)3+oj&HFKm}; zTUpl+8<7OlN*Br&FKjDOvpb4rYO-HHQYNb`*&&by^&?sKvvYwkf7fQVvxH2nO-RuJ z#eYjAJNZT^NrgkpUfAqjbE(yx~#bN`;A5*q)(ncy+IKNjr zFmY0r3rt+rJI$H6@0x#>UeZW(w6i&}9dwCYd+itzT!>uxu6;twi^ayp2DG%}-qB!u zbTrXNlfj_FZiz@&uRAyzjQgX(m|whlfPX9PxZ4|#2NS(J9*_0la{Bp`i!ZKrJQ{Sg zkNmH%8vJPP*fL3i96#F&U)Zjg_V>{CbUCs-NuCWFc7s5cqKSczWV7Au3~cNvZ+lm1{h>BT=y z74$NM9jlYNoRr%nK--jt);ESRP)?G{W`o8LB=s`8Nwrq9Sq z5=@_wmFB>-q--_~rsZXGJ78MrD}N-x^ch)6g6Xrdk_OXW4KPii`EEVa8qJpn(@|F+ zb$dsBiOH?ON7$M!LDPP(*X{L&gQK3F!Hljev2!5jXO!Y6QVB!?siVQ5HyG-Z!9Y(+ zhu+mEgVAu*Fh8U5QFk&p8XfgV)p51HnAXD8M#NMVS9c+%Nnm|$F-@ZD^M8tI1Y&21 zinEcE_}bM6PJF_NXvFlsora4$GE2K^1Y6T%} zU~b-+kfuD*XBE;Uz&@vt#t_!NM-Ez9*nn$(q;$Kcv@a3rc1@{WQ-7+6ukD)BbFV2$ zfVEv;+MmFEyS~(}FSYASFK2zpL32c0oYBJ-b^jJhpL^}K%?fC<0t$e%%?jA3tbiwmr0)rwTH!Wu zZ!ha7>^0*3gpd5^$A8sY>|E75+6n)gr)uRFStxT{phr_>^L@a$^z0U&(eLRO{f)ql z)qF^9AC@r`yIp2P_-0_0@%ZRHseWcmY)i9JnLvL}bBTvlYXC;JQ7aZA497D^_?nT+ zgbFEsj+n+u1TmuRibWb@3Sa&mjtEMxmFcTW;f`uo;`mcSh8{S4?Xq<5zShdlKXHeadFk>@{z#lQ>)j-EesXCTfUg&4;N8VJl;Az~1Ir~*38mjtj!k?I7ZP+Zow;TJPrp4vf*e-# zH_OI`YmweN)4Z^-fuRIV92mak(YT85-@o6w*JK(J1H1{qFMqrK9riD&9~$%sEQ`JI zWMH_2;vckk7XM!Yo&o~u`sfz-F0nyf|0|wKz*E7u8#J+cSHwf6iQ@_`t)Ex|o(8JE z=&QOuAc~H_8}`$hA_Mo%kZqrTkO205*FOS}*W{X7QxNpd3B^7^_NsN@?OQ-BJI-=V zeN022fL{oHC{%YOfnR<9i%Ty<&vSi>O;%>X{z;0J)c?klS+iLqSz{R6N7rO=O}>Bs z4kZ|bj)VL;JcVm&aep$J!8L&r^pKC7xO+pN4bfzN?74vz4M*}hGlZT}7_&mJXK1q@ z#tb`%$q@d59M8sajprX&(r1fcAD$|*EKBf9=uFtJ@j`+ZzUxl^oO>9ajutl(M5Y9IZQ7CQnW$q*TE^K7y;8ZD8LFpO z)w;qMsKwC@%M^q*WpyXK5mqjg%jXo$E6t9 z7P*5G41F7(!WpGraC&lb8)fMku5&U?K*X`D{{j@u@E>L)NAu6#12)iH%K8B$AXW0U}4>&BS%>P52-wTn-Q79^*g*YgWpg zKZlnu(|gvKLgyrjPwO|6l9XL!yH(Oiy~kTKC6J~-nlBA$YU2ucU=d_nKk--W*_MH>JQGpg z6|mAec$dSL>0c4K#g4sudmZ#nA`{yv=sn6hzFbqPjG zMA6@i>?#*WpD$~y)9Eq2?Rsp>H8bIGg~NSm4!19FcDTt{Z0Bj?!iR9Nah+}Z)>Zq2 zQ|*+J3a2WZs&J~psUFIy4wQ1I`VkZCBbxY)|Hkv*eAh{KCwcs9Wj%bZ*09XpnPqai z*h=DUdD~5`6^^%4irfXqn@IK3E8CHR5DLysOsF-rN>;hgEED*Qe1HjM#yPsyZ%q(LDEMi)$ ziHwF5+SD@G*JBSEci3D}VV!jZ5HSG)pINRM3TD0R!uumUVN#B!b9M3)85n5~fjJw@ zHKYybL<{b)ylt9;Sqku&c$pVSO&7;sjf;a;VNJvnf$nXKwjp@`s>-n zRS^I6G5YIUmVuibsQ@GU}YrbD(x&wKBV>(de zfuatz5|_IJA8TrIi8a+!RZ-QxK2+rjW@Nb*JICex3<~^cy4D{LwUIU$m6+6luB&=q z9_zZCmkwEx$NHc@XqcbDXsC?!;b5o@wzsRhi|I~wwGlC`YghLnrg_79Xfe%O*Tafw z%EV5in-3-SRgv{ke>lh)|0JzJ%P*Ih*nQG28rS{NE<)4&(Jo@q{n5@F$$iq!+sS>> zE?UU_(Jn&G{n0LB%YD&KSvt?h?M%*}{YvLZ?rZWu8;tg|m=uk3iS--EiaPG=s-kBB zL&|ft!AYqxRAse4mPfie%5{o1)V0yLuj#|4SCdxEh;`0GOJ?3y9#Aq1rt@%;S!zpn znVXj|RRL%BW=w0-Z*+FP3nQD?I@i;is%cNNvy6?)omG>tOnPhFG-paYu^-=_3!~d}Vo#|nE7W37N$e?YXE-M%`S=!-AUZF8hv#D9wJXQ?#1YeW5$v;HdKE`ZyL!Yl173wi z?TXY2iz+Otu&B?{qK1V1B}{1-_Fl!Q0C6hd2}3GQ1$60Dz+%C9dwqRD_HlW6JGte* zD7hoM%Cn3>zQ|o;<)9p2kganA{bQ1Ib;rKIX#P%o=HhN0605ts9GT<0zBLQf&z$K` z4^fJJa*^q|-Y-vl;uwXTB-I>_jNm?&Gz?T8f=&HLc$=7 zwDK?rpWSj*bteZo8JkhXmJVpa`IMpYpk48{}e`D)*M&p<~pIigk5urk0 zpff}+qXno~g4s{TUh?kS*0EPt)t1en)%_=(V`Pf&_KA@ZfuhA~l2}b@3<;|h&twrBrE~1zbcu~ z`3n)two!y_f}NqVx<9C_mOy3JKmnIKq4feTzjD_v;PNvV83C8OIx_uA-&5we>+Pw) z{~@;gznAZ42KlcU{^RXinBDRy@GKsC6R2OH{s{GJqjJ>$726mE_$oTtj!jO)pDVr3 zH&k<^+XC*z7K-Chol?{;0Cn+-s&K5rvA#~ns*kH2tK;7Do;8jORk=|#u@Z-H{^2Ng zjpd$^RZ{K{c^qHD3L{z1dIPr&bVhJCK%6q}r1x}7z(y+X(N)V5s>;FR|=Tlpol z?UJJ&QDSO_yE^7!+s|CN1{LrAXI4_Vbu3ku7qK$Yys)r=qo)da5o?NYdw4b5I)PTZ zp!*#|s~IV-i&mHTR8u7w6+VkQxrqg*?GbO9lZ{Jzg;S^k{|fvo@bAtpdZ?7U=u3?3 zvncjA?}5rxNj~=+<3?nEjn4iO90bu$GE0v9BQmIUj|(~UykF1kGsh&(ER%P4In|7| zoPD;Z#BQ>1`y1STQ9J6LO@IIJ_H8?7&$l{XzG+)_qozOe))u!q1&%uuj;poLxpo{i z&EjegrlG-LIH<|`IBoHoINx}tyMd=I?0;C9#(g;XV<%$4a8Hc;gjC@^qyGi-l z+iy27U(??UCK0pq&Z%k_@JOjNKSxL+e4p@rFU|KU74hx13v9Q0M7y>^**z7*?vr(g zb8-13FbOGG1-B!~k?vH)I;I7t6`+aDXp3lduOwQXs#Zj+yTtTY5=jHM-Yg4N0mX^y z+8ZtvtSi{{VnK$L4VMen1Rdnx1%S@*QY%mZaQy9LsU1D=#ifAG5c|gpK!7Q=$n7<8 z&>T>7hXDdp`~U)MxWo(qbpbQ)=oV4Teoz$L0VeKdXg7G3f%R%FrD77ALJi9htKzOe zZJp67;@Tv)RNk3p6qS}&ak8bWr&+#5Za3*qww|4psK8dWCN(xEidKbcd5BEh;wFP{ zy*jDZEADOoiGsTivF+oO=v2u{X~xKA1~G`p#BWwqN_MKgU8Oq9TKf`RXl706PM(7^ zqRHloDkOXt3GY{2pk!kbBY-UgJTBOne8<%_A>J#-gmk|O=^j?xU|fy~@B0m_a^+KC z2YKI$1Ah}lr5_iYCdR9pH%yJ6sGe)WoNh_EA}n)&1b4OwJ1Iz9PMgyYEP=j{%AI=>p(~ghac0J4)LhaWU~+9iGE(N9pvT1Wht^ z;Q1q@Cbcj;ho2l8_~7gK0=yevLJ8hu&o>*9(ZL%Z{PMTs-C^&FdVx+)z^d3A zR|dL6DE>h^7t#ME;C6ve9S_ZL=L+l8@xJ1z1Y8AtyG0YTb4^@i7&xln%KV8X;HseP zi?*)o1ES~zykS4hDbjK00$JAO2MJ)$bG#GqctdWeIR$>_l2GgsWUX5V-o6FIw4y9G z)WbCJ2>6BIhg@|h68P2gzBu$Ma9ziv*kEOr?4P(;LH%!BnKhd=k~N00eR4yVH{|>G z?@)q%VB5%Bz;n2v7WF5i>E942K^J+*j=DGS*bq$?r>^6h;c&#CQ$y%>b7Pk4^%QOP zL!V=YqXT$*mIoep9>em^WpMVg2*sJ zwvaXU92a}kWc5su23Eh98y26=yIiL@lYg*IVY*Qq z6?|LOaJ!VChyM*s4;%2DdI4sG;d)p{l%<4?TS}YJQgWkJq79YC>|0k>wA)(=niR)k zk!wSmTGU&>^Z^2yW`0|hxn-lfN<*H97X0m0bCfw-xl20|Jrj0JLCZLsp_M8ZGegz% zs$5qX1C=z|*U&B81l-LcQ6F^D*IJ%{miW-&l=HnE(^nT>pky))#RXRhb` zSp44%lg`Zfk54^W)>xbJP~=yFCKfh0kw{#s0EnD`HxtLPw&8=ga4|fHdW-`NY*;CF z{v2MuNbgx=a-9<=KCRzON)mRFmBWZUb5ZK{ibd%+O!YaZAcbZ4@a)FWM(K<`gA^g4 z-FzG)I**gJMDja5?Do%&fjMDq$ZAuVcGVBn0Ifi-uMoMG$$fL6t_DPx2c~%qtt55O z$H+3t3?`WJsTZcy12c2>p&DPdbB}jsN+3;vG+!FhRQe_Gz$C~rf8wv$wM-pdy9T1X zD`16n@Ggg~(!U}y;|2jm3^WD`N?N-D2?89nLV?==4l+_*Z8_@^{yv@hn6hzFGzo@F zMB(4d^ePuepRa1H(&-Vs-Fj@tH8bIGg~NSm4p$v)cewFb?B;2s!pCs2QJqcu)^+=Y zQ*D)!3a2WZs&J~psUFLzYQtiu`VkZCAsYLQ|Hg~oJjafACwcs9X+3#2+MJ8Z0}u+BOGh!_BY&n(v*`SVVC;r$VwF)2sWg);exbd1yo-mH{Obk_$9Dgj*i*cis@l|4gGE0Gu%_H=a4FWLg*O-8Jo4tfQL#6_ zBvXgeakC=D=N_`h3|Y=?UYLEa-OFdlFx>D+@A)H?V@>^xZHKi}k+q=&KcgS%gpcFvYie5N zPZaf+9OfA#4_OwrOy7p*-E7jw@pYK-J@Rpe!cv0W4B??V9QNfj?R8p>zrA zbmf6M(7Ho56HYLZOs@>O+CY&@n33g5?3@?_ zCQR%!y!lXIU%Rq4><#)E;~%HhX!+#=6MIP7dEDM|t--nUyYn_|vP1&@k-dV=h<<7E6SSr0SZt63uyh2*HUEM)Q zYnYqYCZstedQ>6J8rWkBY0APn_t=YW&jsP_IkBhImKAETrzG~2cC@czPwCiuN(F{h z>@T%v;a==7iTx$9zw~nUmpnYf#1GGl-{FN=cx}ruK5@jfSp@s+mtMsY)3zQlO@UWo zQQIQ5!lDX`DlF==w5S1Le+g6ChP_vDDnOhHc*2m1Qvq!{6|h`#-d^8akbPWT-i~ki zFAMI-uJf!SkS{aWSUD(17i6p4K>rx$T;H+JF`B&-pSrkPg~a+UFGuF+u5ZNx)ibC1 z(?yhGkBn12*ZJj%PaLC=k)(>lkrLd;f(CDdzEb~WxCF_ae&l$-mLBFZkMd>DrXhp3GRMLiMMb9TNzXak-@xuZ@KFDdMgqJZdge zr5LH9>JR$U?r1oioZ_h}pK8VcpH5V)pN>#p8BDba>Y*W&;NRGs&1n>q=aZu&DS)P_jW*T@XzCOwHZ6ntH^_Mj15+p63nr9`P`wKPoSQSsaAZh%;IX@G!?D&UZuHh#v4M@+jZ?s6{qp-RRu#B)?R6VW$#8XyjGS zr+xm5P_wSAma5r(`t_0gT;)k!%hs?{fZOnKx6R+$j)89r*lB9oSln{)zFR9naT}(Q zBIxZAgWhg^vQCUlJ4Pn|Zl4$#5hz-$CW+Og+K_O!s4ii9QL_SPk1 zI)5QzS{4eijlVZkRt^W1l>(^D8Ytj$E3{s~>U)YDceOng z_&>yw|M%+sTqplE$A7$i3)5R3IiAI1ZvyoT)E}aLrB{slzhVm`A76(j+p)ok_%o#s z`G#tSbW^}R-$HRbs#S{G2B0opQ5B9=IM&zcSk-=+W3`=o-m}J0p)xm$CT8pqEY{su<%9H$#pC^?T&bpoNQg%%bh|M_*dXxfq(aQ(Y;}@i@w6h zx(H)`^B$;7l;m^I5pG1**YNBw!M-2vB(vnuKO&u)_c)hB%lh@yK66Ck!ZdhymlMrs z%GsxTO6(>Jx4*^h=e48S+4T1hZ{Id^_I#)F<=eJpw`%$`Z*6|7Q{cE`;kZisoEyhc z(JZd_U}_o+hJ)&?kJA=!i1UqSvKx3x*16CkK)C?r&l!~WM^Axr-m{&FlKfFHSZa(@ ze-G%+IJ&XZnd!!fC9_uPW*e|`UWlI~niQT+c)FM7>4qioo|s7=dwBO1s7>Ko7NPdr zI!ZItq#H~%JGr7HykRT!w+-I#6|5wQwH2{PCP0b+DfNJqQAq%=l*8R+M!qS$+oXKs z?RT4(Z|ENclZe@Q>r}N3c%)F8pCcp@zEAkR7v}pExg@^bZh`Igk7(CaD7&X(*nKkZ za3(IF1SSCm>)>`IKGL0tSjV)$Fnu(!7;O=)?v+HVQ@SP5>aH;Tm4wp3tv9QJWk7M_ zIM$X+1)B=?y;zW9Wy|G)4M7`ucRrwVywVEf0~~!jTWLoJd~qnCbHx5Jec)qCO)|S7 zHd+9R?l3@LiXVWFb%z)}pblW>9nBEM><2~u9bn>a1Xhh#8Cb7YQYt2)3DmF(u`2Eg zRMr`#B(6<-OXZzmgi&dE6(?P~e46E%WVTIz()H}EL^-y~HL12aQMf8p$wQ>#7S|bk z>(xoMT5@muPvqZyh-@FHL?=p?N;5_lGl+gjCVI1?RI(HG?JL!3)|!{-Tr(?5cl;cj z9!@sT6d~dJNVryVfs&0$gaCFB@Tg#I@*P!Ihj_0U6Vm-Eq`OyggK;$`yze)x%N0+7 zZRCE-5B#kkmVR7rn;5Ta-ZC|QqI#|gbFwAHim=K7PHzHPRxyYk4%mAl{6s5qBl2|q zDhqBay<$?jQmymH@Ko)t@1?!)rK5hy)uQNxaJZ|vg- z$NG-Z>PuMtmH88gcZ&+ogYQnpHl2o)&@2QC0Ax*UFHOuajD`-+S)vn z1HCxQ7LXU`;KFtrt{Qn#udJ&!=?(c&wcFbR5VTYvMq$ZZ5-}xXQ)U*JdV-Ex5VL+mNIv;oeA>r=co)Y`omZMa;3zy5= S<^Kl&0RR89CBiWV<^TXQJ<_cJ diff --git a/gateway/node.go b/gateway/node.go index a0c120d39e1..87a8551b1f4 100644 --- a/gateway/node.go +++ b/gateway/node.go @@ -51,6 +51,7 @@ type TargetAPI interface { MpoolPushUntrusted(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) + MsigGetVestingSchedule(context.Context, address.Address, types.TipSetKey) (api.MsigVesting, error) MsigGetPending(ctx context.Context, addr address.Address, ts types.TipSetKey) ([]*api.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) (api.DealCollateralBounds, error) @@ -282,6 +283,13 @@ func (gw *Node) MsigGetVested(ctx context.Context, addr address.Address, start t return gw.target.MsigGetVested(ctx, addr, start, end) } +func (gw *Node) MsigGetVestingSchedule(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MsigVesting, error) { + if err := gw.checkTipsetKey(ctx, tsk); err != nil { + return api.MsigVesting{}, err + } + return gw.target.MsigGetVestingSchedule(ctx, addr, tsk) +} + func (gw *Node) MsigGetPending(ctx context.Context, addr address.Address, tsk types.TipSetKey) ([]*api.MsigTransaction, error) { if err := gw.checkTipsetKey(ctx, tsk); err != nil { return nil, err From e961766e4b7c8813816371e8cda1d2e490160a48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 16 Feb 2022 10:08:44 +0100 Subject: [PATCH 186/385] fix lotus-soup build --- testplans/lotus-soup/deals_e2e.go | 2 -- testplans/lotus-soup/go.mod | 2 +- testplans/lotus-soup/go.sum | 13 +++++++------ testplans/lotus-soup/paych/stress.go | 1 - 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/testplans/lotus-soup/deals_e2e.go b/testplans/lotus-soup/deals_e2e.go index d9be97f6cae..44eec2d7ab1 100644 --- a/testplans/lotus-soup/deals_e2e.go +++ b/testplans/lotus-soup/deals_e2e.go @@ -208,7 +208,6 @@ func initPaymentChannel(t *testkit.TestEnvironment, ctx context.Context, cl *tes t.RecordMessage("creating payment channel; from=%s, to=%s, funds=%d", cl.Wallet.Address, recv.WalletAddr, balance) channel, err := cl.FullApi.PaychGet(ctx, cl.Wallet.Address, recv.WalletAddr, balance, api.PaychGetOpts{ - Reserve: true, OffChain: false, }) if err != nil { @@ -234,7 +233,6 @@ func initPaymentChannel(t *testkit.TestEnvironment, ctx context.Context, cl *tes t.RecordMessage("reloading paych; now it should have an address") channel, err = cl.FullApi.PaychGet(ctx, cl.Wallet.Address, recv.WalletAddr, big.Zero(), api.PaychGetOpts{ - Reserve: true, OffChain: false, }) if err != nil { diff --git a/testplans/lotus-soup/go.mod b/testplans/lotus-soup/go.mod index f227452e7ae..94673c08119 100644 --- a/testplans/lotus-soup/go.mod +++ b/testplans/lotus-soup/go.mod @@ -9,7 +9,7 @@ require ( github.com/drand/drand v1.3.0 github.com/filecoin-project/go-address v0.0.6 github.com/filecoin-project/go-data-transfer v1.14.0 - github.com/filecoin-project/go-fil-markets v1.19.0 + github.com/filecoin-project/go-fil-markets v1.19.1 github.com/filecoin-project/go-jsonrpc v0.1.5 github.com/filecoin-project/go-state-types v0.1.3 github.com/filecoin-project/go-storedcounter v0.1.0 diff --git a/testplans/lotus-soup/go.sum b/testplans/lotus-soup/go.sum index 23877f87b44..62a41703a05 100644 --- a/testplans/lotus-soup/go.sum +++ b/testplans/lotus-soup/go.sum @@ -418,8 +418,8 @@ github.com/filecoin-project/go-fil-commcid v0.1.0 h1:3R4ds1A9r6cr8mvZBfMYxTS88Oq github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7LXep5bFEVOVmQWHJvl2mgsGo= github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8= -github.com/filecoin-project/go-fil-markets v1.19.0 h1:kap2q2wTM6tfkVO5gMA5DD9GUeTvkDhMfhjCtEwMDM8= -github.com/filecoin-project/go-fil-markets v1.19.0/go.mod h1:qsb3apmo4RSJYCEq40QxVdU7UZospN6nFJLOBHuaIbc= +github.com/filecoin-project/go-fil-markets v1.19.1 h1:o5sziAp8zCsvIg3KYMgIpwm8gyOl4MDzEKEf0Qq5L3U= +github.com/filecoin-project/go-fil-markets v1.19.1/go.mod h1:qsb3apmo4RSJYCEq40QxVdU7UZospN6nFJLOBHuaIbc= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= @@ -473,8 +473,8 @@ github.com/filecoin-project/specs-actors/v7 v7.0.0-20211117170924-fd07a4c7dff9/g github.com/filecoin-project/specs-actors/v7 v7.0.0-20211222192039-c83bea50c402/go.mod h1:p6LIOFezA1rgRLMewbvdi3Pp6SAu+q9FtJ9CAleSjrE= github.com/filecoin-project/specs-actors/v7 v7.0.0-rc1 h1:FuDaXIbcw2hRsFI8SDTmsGGCE+NumpF6aiBoU/2X5W4= github.com/filecoin-project/specs-actors/v7 v7.0.0-rc1/go.mod h1:TA5FwCna+Yi36POaT7SLKXsgEDvJwc0V/L6ZsO19B9M= -github.com/filecoin-project/specs-storage v0.1.1-0.20211228030229-6d460d25a0c9 h1:oUYOvF7EvdXS0Zmk9mNkaB6Bu0l+WXBYPzVodKMiLug= -github.com/filecoin-project/specs-storage v0.1.1-0.20211228030229-6d460d25a0c9/go.mod h1:Tb88Zq+IBJbvAn3mS89GYj3jdRThBTE/771HCVZdRJU= +github.com/filecoin-project/specs-storage v0.2.0 h1:Y4UDv0apRQ3zI2GiPPubi8JblpUZZphEdaJUxCutfyg= +github.com/filecoin-project/specs-storage v0.2.0/go.mod h1:Tb88Zq+IBJbvAn3mS89GYj3jdRThBTE/771HCVZdRJU= github.com/filecoin-project/test-vectors/schema v0.0.5/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ= @@ -1411,8 +1411,9 @@ github.com/libp2p/go-libp2p-record v0.1.2/go.mod h1:pal0eNcT5nqZaTV7UGhqeGqxFgGd github.com/libp2p/go-libp2p-record v0.1.3 h1:R27hoScIhQf/A8XJZ8lYpnqh9LatJ5YbHs28kCIfql0= github.com/libp2p/go-libp2p-record v0.1.3/go.mod h1:yNUff/adKIfPnYQXgp6FQmNu3gLJ6EMg7+/vv2+9pY4= github.com/libp2p/go-libp2p-resource-manager v0.1.0/go.mod h1:wJPNjeE4XQlxeidwqVY5G6DLOKqFK33u2n8blpl0I6Y= -github.com/libp2p/go-libp2p-resource-manager v0.1.3 h1:Umf0tW6WNXSb6Uoma0YT56azB5iikL/aeGAP7s7+f5o= github.com/libp2p/go-libp2p-resource-manager v0.1.3/go.mod h1:wJPNjeE4XQlxeidwqVY5G6DLOKqFK33u2n8blpl0I6Y= +github.com/libp2p/go-libp2p-resource-manager v0.1.4 h1:RcxMD0pytOUimx3BqTVs6IqItb3H5Qg44SD7XyT68lw= +github.com/libp2p/go-libp2p-resource-manager v0.1.4/go.mod h1:wJPNjeE4XQlxeidwqVY5G6DLOKqFK33u2n8blpl0I6Y= github.com/libp2p/go-libp2p-routing v0.0.1/go.mod h1:N51q3yTr4Zdr7V8Jt2JIktVU+3xBBylx1MZeVA6t1Ys= github.com/libp2p/go-libp2p-routing v0.1.0/go.mod h1:zfLhI1RI8RLEzmEaaPwzonRvXeeSHddONWkcTcB54nE= github.com/libp2p/go-libp2p-routing-helpers v0.2.3 h1:xY61alxJ6PurSi+MXbywZpelvuU4U4p/gPTxjqCqTzY= @@ -2941,4 +2942,4 @@ sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= -sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= \ No newline at end of file +sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/testplans/lotus-soup/paych/stress.go b/testplans/lotus-soup/paych/stress.go index 2f90308d8ee..4f107bf5b67 100644 --- a/testplans/lotus-soup/paych/stress.go +++ b/testplans/lotus-soup/paych/stress.go @@ -125,7 +125,6 @@ func runSender(ctx context.Context, t *testkit.TestEnvironment, clients []*testk time.Sleep(20 * time.Second) channel, err := cl.FullApi.PaychGet(ctx, cl.Wallet.Address, recv.WalletAddr, channelAmt, api.PaychGetOpts{ - Reserve: true, OffChain: false, }) if err != nil { From 2ebc111b708b9a333c51070591c14808b09f550d Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Wed, 16 Feb 2022 12:46:03 +0000 Subject: [PATCH 187/385] Use the same host and datatransfer as markets for index provider Remove the bespoke instantiation of libp2p host and datatransfer manager for index provider and reuse the existing instances used by markets. The rationale for reuse is the following: 1. Separation of host introduces a discovery problem, where without gossipsub the index provider endpoint will not be discoverable. Using the same host as markets would mean the chain can be used to discover addresses, putting less empassis on criticality of gossipsub considering its set-up cost and lack of message delivery guarantees. 2. Only a single instance of graphsync/datatransfer can be instantiated per libp2p host; therefore, if the host is shared, so should datatransfer manager. 3. it is not clear if the assumptions under which separation was decided still hold. --- markets/idxprov/host.go | 5 - markets/idxprov/mesh.go | 23 +++-- node/builder_miner.go | 1 - node/modules/storageminer_idxprov.go | 141 +++------------------------ 4 files changed, 28 insertions(+), 142 deletions(-) delete mode 100644 markets/idxprov/host.go diff --git a/markets/idxprov/host.go b/markets/idxprov/host.go deleted file mode 100644 index 5e901a560f4..00000000000 --- a/markets/idxprov/host.go +++ /dev/null @@ -1,5 +0,0 @@ -package idxprov - -import "github.com/libp2p/go-libp2p-core/host" - -type Host host.Host diff --git a/markets/idxprov/mesh.go b/markets/idxprov/mesh.go index 097513d42ec..af0d1118966 100644 --- a/markets/idxprov/mesh.go +++ b/markets/idxprov/mesh.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/libp2p/go-libp2p-core/host" "github.com/libp2p/go-libp2p-core/peer" "github.com/filecoin-project/lotus/api/v1api" @@ -13,21 +14,23 @@ import ( var log = logging.Logger("idxprov") +const protectTag = "index-provider-gossipsub" + type MeshCreator interface { Connect(ctx context.Context) error } type Libp2pMeshCreator struct { fullnodeApi v1api.FullNode - idxProvHost Host + marketsHost host.Host } func (mc Libp2pMeshCreator) Connect(ctx context.Context) error { - // Add the index provider's host ID to list of protected peers first, before any attempt to - // connect to full node. - idxProvID := mc.idxProvHost.ID() - if err := mc.fullnodeApi.NetProtectAdd(ctx, []peer.ID{idxProvID}); err != nil { + // Add the markets host ID to list of daemon's protected peers first, before any attempt to + // connect to full node over libp2p. + marketsPeerID := mc.marketsHost.ID() + if err := mc.fullnodeApi.NetProtectAdd(ctx, []peer.ID{marketsPeerID}); err != nil { return fmt.Errorf("failed to call NetProtectAdd on the full node, err: %w", err) } @@ -38,17 +41,17 @@ func (mc Libp2pMeshCreator) Connect(ctx context.Context) error { // Connect to the full node, ask it to protect the connection and protect the connection on // markets end too. - if err := mc.idxProvHost.Connect(ctx, faddrs); err != nil { + if err := mc.marketsHost.Connect(ctx, faddrs); err != nil { return fmt.Errorf("failed to connect index provider host with the full node: %w", err) } - mc.idxProvHost.ConnManager().Protect(faddrs.ID, "index-provider-gossipsub") + mc.marketsHost.ConnManager().Protect(faddrs.ID, protectTag) log.Debugw("successfully connected to full node and asked it protect indexer provider peer conn", "fullNodeInfo", faddrs.String(), - "idxProviderPeerId", idxProvID) + "peerId", marketsPeerID) return nil } -func NewMeshCreator(fullnodeApi v1api.FullNode, idxProvHost Host) MeshCreator { - return Libp2pMeshCreator{fullnodeApi, idxProvHost} +func NewMeshCreator(fullnodeApi v1api.FullNode, marketsHost host.Host) MeshCreator { + return Libp2pMeshCreator{fullnodeApi, marketsHost} } diff --git a/node/builder_miner.go b/node/builder_miner.go index 351a65be79e..d24beff80ec 100644 --- a/node/builder_miner.go +++ b/node/builder_miner.go @@ -170,7 +170,6 @@ func ConfigStorageMiner(c interface{}) Option { Override(new(dtypes.ProviderTransport), modules.NewProviderTransport), Override(new(dtypes.ProviderDataTransfer), modules.NewProviderDataTransfer), Override(new(idxprov.MeshCreator), idxprov.NewMeshCreator), - Override(new(idxprov.Host), modules.IndexProviderHost(cfg.IndexProvider)), Override(new(provider.Interface), modules.IndexProvider(cfg.IndexProvider)), Override(new(*storedask.StoredAsk), modules.NewStorageAsk), Override(new(dtypes.StorageDealFilter), modules.BasicDealFilter(cfg.Dealmaking, nil)), diff --git a/node/modules/storageminer_idxprov.go b/node/modules/storageminer_idxprov.go index b8333441b1e..649c5b09433 100644 --- a/node/modules/storageminer_idxprov.go +++ b/node/modules/storageminer_idxprov.go @@ -2,181 +2,70 @@ package modules import ( "context" - "fmt" - "os" - "path/filepath" - - "golang.org/x/xerrors" "github.com/ipfs/go-datastore" - "github.com/ipfs/go-graphsync" - graphsyncimpl "github.com/ipfs/go-graphsync/impl" - gsnet "github.com/ipfs/go-graphsync/network" - cidlink "github.com/ipld/go-ipld-prime/linking/cid" - "github.com/libp2p/go-libp2p" - ci "github.com/libp2p/go-libp2p-core/crypto" "github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peerstore" "go.uber.org/fx" "github.com/filecoin-project/go-address" - datatransfer "github.com/filecoin-project/go-data-transfer" - dtimpl "github.com/filecoin-project/go-data-transfer/impl" - dtnet "github.com/filecoin-project/go-data-transfer/network" - dtgstransport "github.com/filecoin-project/go-data-transfer/transport/graphsync" provider "github.com/filecoin-project/index-provider" "github.com/filecoin-project/index-provider/engine" "github.com/ipfs/go-datastore/namespace" "github.com/libp2p/go-libp2p-core/host" + "golang.org/x/xerrors" - "github.com/filecoin-project/lotus/build" - "github.com/filecoin-project/lotus/markets/idxprov" - marketevents "github.com/filecoin-project/lotus/markets/loggers" "github.com/filecoin-project/lotus/node/config" "github.com/filecoin-project/lotus/node/modules/dtypes" - "github.com/filecoin-project/lotus/node/modules/helpers" - "github.com/filecoin-project/lotus/node/modules/lp2p" - "github.com/filecoin-project/lotus/node/repo" ) type IdxProv struct { fx.In - helpers.MetricsCtx fx.Lifecycle - Repo repo.LockedRepo Datastore dtypes.MetadataDS PeerID peer.ID peerstore.Peerstore } -func IndexProviderHost(cfg config.IndexProviderConfig) func(IdxProv) (idxprov.Host, error) { - return func(args IdxProv) (idxprov.Host, error) { - pkey := args.Peerstore.PrivKey(args.PeerID) - if pkey == nil { - return nil, fmt.Errorf("missing private key for node ID: %s", args.PeerID.Pretty()) - } - - h, err := createIndexProviderHost(args.MetricsCtx, args.Lifecycle, pkey, args.Peerstore, cfg.ListenAddresses, cfg.AnnounceAddresses) - if err != nil { - return nil, xerrors.Errorf("creating indexer provider host: %w", err) - } - - return h, nil - } -} - -func IndexProvider(cfg config.IndexProviderConfig) func(params IdxProv, marketHost host.Host, h idxprov.Host, maddr dtypes.MinerAddress) (provider.Interface, error) { - return func(args IdxProv, marketHost host.Host, h idxprov.Host, maddr dtypes.MinerAddress) (provider.Interface, error) { +func IndexProvider(cfg config.IndexProviderConfig) func(params IdxProv, marketHost host.Host, dt dtypes.ProviderDataTransfer, maddr dtypes.MinerAddress) (provider.Interface, error) { + return func(args IdxProv, marketHost host.Host, dt dtypes.ProviderDataTransfer, maddr dtypes.MinerAddress) (provider.Interface, error) { ipds := namespace.Wrap(args.Datastore, datastore.NewKey("/index-provider")) pkey := args.Peerstore.PrivKey(args.PeerID) if pkey == nil { - return nil, fmt.Errorf("missing private key for node ID: %s", args.PeerID.Pretty()) - } - - dt, err := newIndexProviderDataTransfer(cfg, args.MetricsCtx, args.Lifecycle, args.Repo, h, ipds) - if err != nil { - return nil, err + return nil, xerrors.Errorf("missing private key for node ID: %s", args.PeerID) } - var maddrs []string + var retAdds []string for _, a := range marketHost.Addrs() { - maddrs = append(maddrs, a.String()) + retAdds = append(retAdds, a.String()) } // Get the miner ID and set as extra gossip data. // The extra data is required by the lotus-specific index-provider gossip message validators. ma := address.Address(maddr) - log.Infof("Using extra gossip data in index provider engine: %s", ma.String()) + log.Infof("Using extra gossip data in index provider engine: %s", ma) - e, err := engine.New(cfg.Ingest, pkey, dt, h, ipds, maddrs, engine.WithExtraGossipData(ma.Bytes())) + e, err := engine.New(cfg.Ingest, pkey, dt, marketHost, ipds, retAdds, engine.WithExtraGossipData(ma.Bytes())) if err != nil { return nil, xerrors.Errorf("creating indexer provider engine: %w", err) } args.Lifecycle.Append(fx.Hook{ OnStart: func(ctx context.Context) error { - // Start the engine - err := e.Start(ctx) - if err != nil { - return xerrors.Errorf("starting indexer provider engine: %s", err) + if err := e.Start(ctx); err != nil { + return xerrors.Errorf("starting indexer provider engine: %w", err) } - return nil }, - OnStop: func(ctx context.Context) error { - return e.Shutdown() + OnStop: func(_ context.Context) error { + if err := e.Shutdown(); err != nil { + return xerrors.Errorf("shutting down indexer provider engine: %w", err) + } + return nil }, }) - return e, nil } } - -func createIndexProviderHost(mctx helpers.MetricsCtx, lc fx.Lifecycle, pkey ci.PrivKey, pstore peerstore.Peerstore, listenAddrs []string, announceAddrs []string) (host.Host, error) { - addrsFactory, err := lp2p.MakeAddrsFactory(announceAddrs, nil) - if err != nil { - return nil, err - } - - opts := []libp2p.Option{ - libp2p.Identity(pkey), - libp2p.Peerstore(pstore), - libp2p.ListenAddrStrings(listenAddrs...), - libp2p.AddrsFactory(addrsFactory), - libp2p.Ping(true), - libp2p.UserAgent("lotus-indexer-provider-" + build.UserVersion()), - } - - h, err := libp2p.New(opts...) - if err != nil { - return nil, err - } - - lc.Append(fx.Hook{ - OnStop: func(ctx context.Context) error { - return h.Close() - }, - }) - - return h, nil -} - -func newIndexProviderDataTransfer(cfg config.IndexProviderConfig, mctx helpers.MetricsCtx, lc fx.Lifecycle, r repo.LockedRepo, h host.Host, ds datastore.Batching) (datatransfer.Manager, error) { - net := dtnet.NewFromLibp2pHost(h) - - // Set up graphsync - gs := newIndexProviderGraphsync(cfg, mctx, lc, h) - - // Set up data transfer - dtDs := namespace.Wrap(ds, datastore.NewKey("/datatransfer/transfers")) - transport := dtgstransport.NewTransport(h.ID(), gs) - dtPath := filepath.Join(r.Path(), "indexer-provider", "data-transfer") - err := os.MkdirAll(dtPath, 0755) //nolint: gosec - if err != nil && !os.IsExist(err) { - return nil, xerrors.Errorf("creating indexer provider data transfer dir %s: %w", dtPath, err) - } - - dt, err := dtimpl.NewDataTransfer(dtDs, net, transport) - if err != nil { - return nil, xerrors.Errorf("creating indexer provider data transfer module: %w", err) - } - - dt.OnReady(marketevents.ReadyLogger("indexer-provider data transfer")) - lc.Append(fx.Hook{ - OnStart: dt.Start, - OnStop: dt.Stop, - }) - return dt, nil -} - -func newIndexProviderGraphsync(cfg config.IndexProviderConfig, mctx helpers.MetricsCtx, lc fx.Lifecycle, h host.Host) graphsync.GraphExchange { - graphsyncNetwork := gsnet.NewFromLibp2pHost(h) - return graphsyncimpl.New(helpers.LifecycleCtx(mctx, lc), - graphsyncNetwork, - cidlink.DefaultLinkSystem(), - graphsyncimpl.MaxInProgressIncomingRequests(cfg.MaxSimultaneousTransfers), - graphsyncimpl.MaxLinksPerIncomingRequests(config.MaxTraversalLinks), - graphsyncimpl.MaxLinksPerOutgoingRequests(config.MaxTraversalLinks)) -} From a09f386537e14f563eb1fa87f8b1fe917a930111 Mon Sep 17 00:00:00 2001 From: "Masih H. Derkani" Date: Wed, 16 Feb 2022 13:07:09 +0000 Subject: [PATCH 188/385] Remove redundant `IndexProvider` config now that host is shared Now that host is shared having separate config for listen and announce addresses along with graphsync limit makes no sense since all of that is shared with the markets host and datatransfer manager. --- .../en/default-lotus-miner-config.toml | 24 ----------------- node/config/def.go | 13 ++-------- node/config/doc_gen.go | 26 ------------------- node/config/types.go | 15 ----------- 4 files changed, 2 insertions(+), 76 deletions(-) diff --git a/documentation/en/default-lotus-miner-config.toml b/documentation/en/default-lotus-miner-config.toml index c0392cc4a7c..da9d4315eef 100644 --- a/documentation/en/default-lotus-miner-config.toml +++ b/documentation/en/default-lotus-miner-config.toml @@ -273,30 +273,6 @@ # env var: LOTUS_INDEXPROVIDER_PUBLISHERKIND #PublisherKind = "dtsync" - # Binding address for the libp2p host contacted by indexer nodes to sync the list of advertised - # multihashes. Note that when port is set to 0 a random port is generated at runtime and may be - # different on every restart. The format of the strings specified must conform to multiaddress; - # see https://multiformats.io/multiaddr/ - # - # type: []string - # env var: LOTUS_INDEXPROVIDER_LISTENADDRESSES - #ListenAddresses = ["/ip4/0.0.0.0/tcp/0", "/ip6/::/tcp/0"] - - # The address the endpoints at which the data associated to the advertised - # multihashes can be retrieved. If not specified, the ListenAddresses are used instead. The format - # of the strings specified must conform to multiaddress; see https://multiformats.io/multiaddr/ - # - # type: []string - # env var: LOTUS_INDEXPROVIDER_ANNOUNCEADDRESSES - #AnnounceAddresses = [] - - # The maximum number of simultaneous requests syncing the list of advertised multihashes between - # the indexers and the index provider. - # - # type: uint64 - # env var: LOTUS_INDEXPROVIDER_MAXSIMULTANEOUSTRANSFERS - #MaxSimultaneousTransfers = 20 - [IndexProvider.HttpPublisher] # env var: LOTUS_INDEXPROVIDER_HTTPPUBLISHER_LISTENMULTIADDR #ListenMultiaddr = "/ip4/0.0.0.0/tcp/3104/http" diff --git a/node/config/def.go b/node/config/def.go index 75e2a08a3d2..4db43753ecd 100644 --- a/node/config/def.go +++ b/node/config/def.go @@ -2,6 +2,7 @@ package config import ( "encoding" + "os" "strconv" "time" @@ -182,13 +183,7 @@ func DefaultStorageMiner() *StorageMiner { }, IndexProvider: IndexProviderConfig{ - ListenAddresses: []string{ - "/ip4/0.0.0.0/tcp/0", - "/ip6/::/tcp/0", - }, - AnnounceAddresses: []string{}, - - MaxSimultaneousTransfers: DefaultSimultaneousTransfers, + Ingest: ipconfig.NewIngest(), }, Subsystems: MinerSubsystemConfig{ @@ -232,10 +227,6 @@ func DefaultStorageMiner() *StorageMiner { }, } - // TODO: Remove hardcoded defaults once provider library exposes them. - // See: https://github.com/filecoin-project/index-provider/issues/108 - cfg.IndexProvider.Ingest = ipconfig.NewIngest() - cfg.Common.API.ListenAddress = "/ip4/127.0.0.1/tcp/2345/http" cfg.Common.API.RemoteListenAddress = "127.0.0.1:2345" return cfg diff --git a/node/config/doc_gen.go b/node/config/doc_gen.go index d7c500e6716..9d4f6088214 100644 --- a/node/config/doc_gen.go +++ b/node/config/doc_gen.go @@ -358,32 +358,6 @@ see https://docs.filecoin.io/mine/lotus/miner-configuration/#using-filters-for-f Comment: ``, }, }, - "IndexProviderConfig": []DocField{ - { - Name: "ListenAddresses", - Type: "[]string", - - Comment: `Binding address for the libp2p host contacted by indexer nodes to sync the list of advertised -multihashes. Note that when port is set to 0 a random port is generated at runtime and may be -different on every restart. The format of the strings specified must conform to multiaddress; -see https://multiformats.io/multiaddr/`, - }, - { - Name: "AnnounceAddresses", - Type: "[]string", - - Comment: `The address the endpoints at which the data associated to the advertised -multihashes can be retrieved. If not specified, the ListenAddresses are used instead. The format -of the strings specified must conform to multiaddress; see https://multiformats.io/multiaddr/`, - }, - { - Name: "MaxSimultaneousTransfers", - Type: "uint64", - - Comment: `The maximum number of simultaneous requests syncing the list of advertised multihashes between -the indexers and the index provider.`, - }, - }, "Libp2p": []DocField{ { Name: "ListenAddresses", diff --git a/node/config/types.go b/node/config/types.go index b73e957f600..a06ec886c34 100644 --- a/node/config/types.go +++ b/node/config/types.go @@ -163,21 +163,6 @@ type DealmakingConfig struct { type IndexProviderConfig struct { config.Ingest - - // Binding address for the libp2p host contacted by indexer nodes to sync the list of advertised - // multihashes. Note that when port is set to 0 a random port is generated at runtime and may be - // different on every restart. The format of the strings specified must conform to multiaddress; - // see https://multiformats.io/multiaddr/ - ListenAddresses []string - - // The address the endpoints at which the data associated to the advertised - // multihashes can be retrieved. If not specified, the ListenAddresses are used instead. The format - // of the strings specified must conform to multiaddress; see https://multiformats.io/multiaddr/ - AnnounceAddresses []string - - // The maximum number of simultaneous requests syncing the list of advertised multihashes between - // the indexers and the index provider. - MaxSimultaneousTransfers uint64 } type RetrievalPricing struct { From afc29ed445126228765a10bf2f2028c4d1aa429e Mon Sep 17 00:00:00 2001 From: Aayush Date: Wed, 16 Feb 2022 13:04:48 -0500 Subject: [PATCH 189/385] feat: tweak v15 migration params --- chain/consensus/filcns/upgrades.go | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/chain/consensus/filcns/upgrades.go b/chain/consensus/filcns/upgrades.go index 2fa020d3db4..116684b9f44 100644 --- a/chain/consensus/filcns/upgrades.go +++ b/chain/consensus/filcns/upgrades.go @@ -165,13 +165,8 @@ func DefaultUpgradeSchedule() stmgr.UpgradeSchedule { Migration: UpgradeActorsV7, PreMigrations: []stmgr.PreMigration{{ PreMigration: PreUpgradeActorsV7, - StartWithin: 120, + StartWithin: 180, DontStartWithin: 60, - StopWithin: 35, - }, { - PreMigration: PreUpgradeActorsV7, - StartWithin: 30, - DontStartWithin: 15, StopWithin: 5, }}, Expensive: true, @@ -1264,7 +1259,7 @@ func upgradeActorsV7Common( root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet, config nv15.Config, ) (cid.Cid, error) { - writeStore := blockstore.NewAutobatch(ctx, sm.ChainStore().StateBlockstore(), units.GiB) + writeStore := blockstore.NewAutobatch(ctx, sm.ChainStore().StateBlockstore(), units.GiB/4) // TODO: pretty sure we'd achieve nothing by doing this, confirm in review //buf := blockstore.NewTieredBstore(sm.ChainStore().StateBlockstore(), writeStore) store := store.ActorStore(ctx, writeStore) From 384999556c95b2638f1b5f17a3456c781bc90936 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 16 Feb 2022 20:39:43 +0100 Subject: [PATCH 190/385] paychmgr: AvailableAmt -> NonReservedAmt --- api/api_full.go | 11 +++++++---- build/openrpc/full.json.gz | Bin 27021 -> 27027 bytes cli/paych.go | 2 +- documentation/en/api-v0-methods.md | 4 ++-- documentation/en/api-v1-unstable-methods.md | 4 ++-- paychmgr/manager.go | 2 +- paychmgr/simple.go | 2 +- 7 files changed, 14 insertions(+), 11 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index b621dd9fbb9..4c4d6ebf936 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -859,20 +859,23 @@ type ChannelAvailableFunds struct { From address.Address // To is the to address of the channel To address.Address - // ConfirmedAmt is the amount of funds that have been confirmed on-chain - // for the channel + + // ConfirmedAmt is the total amount of funds that have been confirmed on-chain for the channel ConfirmedAmt types.BigInt // PendingAmt is the amount of funds that are pending confirmation on-chain PendingAmt types.BigInt - // AvailableAmt is part of ConfirmedAmt that is available for use (pre-allocated) - AvailableAmt types.BigInt + + // NonReservedAmt is part of ConfirmedAmt that is available for use (e.g. when the payment channel was pre-funded) + NonReservedAmt types.BigInt // PendingAvailableAmt is the amount of funds that are pending confirmation on-chain that will become available once confirmed PendingAvailableAmt types.BigInt + // PendingWaitSentinel can be used with PaychGetWaitReady to wait for // confirmation of pending funds PendingWaitSentinel *cid.Cid // QueuedAmt is the amount that is queued up behind a pending request QueuedAmt types.BigInt + // VoucherRedeemedAmt is the amount that is redeemed by vouchers on-chain // and in the local datastore VoucherReedeemedAmt types.BigInt diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 53dbbc6c5cb8486ce2acc67f62bf4689c0f171bf..db9366703169bb100e0c4bd04e6047b4f8dee184 100644 GIT binary patch delta 26956 zcmYhCQ+OX?*Y#uDcGB2ZV<(N%*l27g6E(JN+i3W2(Aaik+x+@G&wKFAoZR=>ea+0C zYp=b2D`pNnX$~A9je-OF@AY}sZR4`mp7`}mL)qIvAyHMZb)Pq)N=ay6o_W&=qwYN8 zjL*p(mVzAK6k!`J-%gQ!>)o(D9;yz4jz7UJJCnabCVvJj@WPOXAjScbfCA&^rjbK^ zOG9^q03Hf!#x!WN4g8OwNN_g@exD7}vMkK#^UjkMAkr%eHGn94e-H;bBKEOu@@9)FY=+Ed2|<6$y_O75 zx7X7YC5FI~F|1vdCX$NRDsB>3_UE`r1A7! z?30hg&VOk}$`B4Pup zBS+ch6-hH=B?@5;a=AC(k@4NX-tm&bPu)`Ooty}Athxi;=F#(@?S%1&y8u>`q8L+u zXz3H4X-Of+!JvMiyCNPM2S6d}X8pSj!ywsEVSEfR*bRG8VbNa%hR|E_hz7`yc8%<+^8WhzXzP3Y#Iol!c3tC1Bb=+lFFl{6KOA>1 zFm8E`Ct;<;2LVo_75tYhHVCw7G~_k>;Q#JMA7$(5`eD<^n;V7>VEeukz{x(G^5*Xv z9>zOiy(5Uf+2GBr4Sp)3ucXg@UYgmsJf<9}X@`zHdy{D*>~f0z5mRWzHpAwmFJ4i* zGDGQSInnhU6w6e|59{%Bz%axvt}dpsCC#)Tqz050eXwTCM|;pqCxR%O5-fsHJ%ex)w`~iHIvS3LL>Q zVv9QrckF=U(KK)*-6bnmUb`tMI8b{hf_n6|@7=UbUz4U4A@U>mT(HwDTR26l4||Uh zKV!*SqsuX{Xc^HE>S5wM8|#GY@iGlI(ejGdWj;ROHC*9WGF3ugM9|ZkS z8*dA|$2GN;p_e4dW%=@YVv>Dpt{w9w^c~uZ9|}QzFhEVym?VO3&!ODrpeeh{wplgo zL5?=83x#}M0tF!!Ebx zL#|*4@Ujaz_Q;8x7fHPo+odC6zZ|~K{Rja{<0(b&#h4RIrzOaoojeXNnBCW;&bE3@KNYlk`PHc`2Z2 zJ}(IDNV8k)tktwfjLDV!ijVl1xqCP&=oNlzHAY7z(JcP(57S7cq{R_mmSj?x*v5cY zY~KxyqUVBc+il)%V258@t27RbBmJi)dk7{y4vbT6R|{LV`q36G_xCo=STzF-O0QhO zcws|QqkRl+Mhg|Y-9){_xa1-sM?nA`ngYrwBzYP>c)*U)TD;F`7>yKS955#9)1pO_ z;@NY4JV-2NsysJ?dgDbZ#=HG__WBbXj}<{|6psW}=E5Xx1X2lvWKbl(vm4TbQxBZ6Xtto!#JeaP&Dgk*S$Do%~Ag-=dwkq*vkKz{~^MmL{s6PtbUj7=fjCpL3H z=MOP{AiCicb0M0#4@PDGu&OW1Msik7joJRY{jacX`;(x)G6BJtCRS4kxCZ+#HGquS z-Bp+oZ~RbvBC@+dcy4bW`Gb$1nO!&OLGdMw;DUmcO#_}wfw+cHnQcHV-^glf^0;)C z`yE96?@e!e4>$ek2ca38MzpXL}H(RXJm#m~}aI#dsR z+b-#$1SgFE4E-I?jbCR+n+jmN&C%4p^sYxLay?5&N7x2P?NfGa{jz*CZ@NIYE^g{U zpE_}keu4VUDu@F4nM7njxKCmAV2xo-bBZnfO%*Vl;v+OJ84I$Zqx9xdYXmW`(RO&G zZl-=vos?Z0I%BtT!1FVCFU(U4`*z+p9((%GSrs>d4JT<|P+3EB+zwnKnWete6Pe)f z+Jp}y6o9jW=g{`5@JWqz#E_J(4TE%H9f-TS1%w_e=|&{zE9Ni}tByNDqGNK$1VY>t zeSn%Y&V}-O`nB((umtZ-3xRZb5h&4#u$Tnq2n}MGl~|gRig3&pv_%EtnULccEV0V$ zNXkLEE-%>_#T4EpsyT-XPK9n}9}G%1Wb!(OlDP6TC=HjKH;{|NDPyH#UzbvvW)~go z*>Fwym)D3;CikMN7hNvNUUT464Lz1rwE@%AHM~m6tl#jbRXP4%^$1ozO>~&iSUkS1 zL92f`^2Rm{1b4> z{DA*>OdOu@2YdSH@qFtYG4-!!LA)f@!?^05%KHjDygh%OM7|jMyO+`drB2(Y_5oje zX&>^gg5S%;$po%LE=lo#%dhV*WoyyxyA$EI6QOJN)0%4K88YRnMICLLyPn3C=;zca zG-a(xsi6UGS|vZ~&1Yt3YuZ-s`~j#F2OHU6MVZrIb)m~E*BngSV*AvoeKs6qybSEc zj~6G<6l$uhZ%9h~&Zk723Txfa(xWW91p*tp?I@KWz7R=zhiE1-!BBTb?{bNB7VWWR z_Ck^;UuF~UG2db$35)as^YJmU9Zf&opO17I5_sdgH_Fpc9ZC{+|zXNOP1#s=f9Mz*Eq#pBmq zL~ja@SxUCq4bST#Xs$n zXmbiWNd#!%wY_o;1G2S_;m?Y`e>*LoJDO zaG^~QM^8UvKVKv}1OR;TQ2zwszJM8|$YFgt^Vzb$13~_oOn4Ba-)PdzqMwjwsh^Rd zt+9E{Zdl`Gi*T3xGPwGqb|Z%4uRRvz}RxS*oai9G?!@mm`%GDdV+>Py+F39TbS|A6n<}_VQZ8&2U|?27$Gc&ZP8%pl*u@LLXY>$ z+mj3d`OS1HQOc&7>crKSHtWoh5=6wEL<44x?wWMb7VZ1nMcx|V|2oxMH}m@W_iyKh zAI|%SA?)Vi+9RyPRNGb)&)vqL-QC~4m$uKpNf*Mm(dRSYR;fLNhmvY$l=O*88ziRC z;#hx$0wDCD{h1$>PtM6FREEh|nf*ry*T^alPs6H1`#MKz!`Rw}DCMJP#XB)za;55E z8O=?7xYR@OSaEdmJ6odma}J)T0agJ_eK_vB=x&;vcK=l<(TXhh(CjOGD;;4 z+~h+P6rje%L9y%E|4A<D<6St}wx!lyM9mK>?Zszism8A@Q-s&I+x8X5wU zf$TVqx9-X@I;OOzEM0PLeuS?Y9ZGi&f`>X$y$v4lwIHc|y2O)=`j!L_M5cQ|3KV_IeLCzxw;qMv2)S(CTiKB<5%WSZZ=Tr`Rns38X!-aTH z?N=aL_@X&>sk{jL?Bz)f&-+i+nVnYbV98&U=!>n;(w}zvi)M0KCyM)P*uep7L+-#(@U+S4h2mq>Jm22!YddMb3miKey$QE;qu`8r0%L#e%5 z7p7lAL!7jh{dnn?u+);lrR|l2t{fezzLyNNCgRtSm#UJ4oei{G%ZJHN@du%h4AQUb zW=gp8P%J92+cfnAb8xnSt;X(cz}#TrRF4^DNEZrZxrI4Wm3xN`lb;a)NX7I^1YlUn#Px*Jmp>PDfB{;?>z zuwBYgosJT-w6=yzI-^Jo?d7m}N^9^IQ%yP$ZPBv5%UXn3Vfb#(DMT&|Hl zpN_SGq!$KNuN$ep8TND_C;UkOu&Q*CMyXLKsfO+#lDXGy{ ze~~bP?hN|aKt$p#HM28}!s3j@5`HVOR8TBMm)63?4R=Gu@s|tiQ5juO7hsM4y+dpq zp<>9(Yy#4ih9{2zDd&Sl`R@YN&V#Sl+9rk`#F=Jr#lu)?1uXcD_85it#C08#S9baF zfe5qGQyrc<#$bdPWfMvOJ?jPMP6e%JwYBRF%%MHh4sJ>pSE*w=5l8^=4_U4kt#t8 zj$v~5ur;aN2&2_bfX!x=+oo=}#cM?>cTdEhaH^!FzI=8}%2U|_<9kHKxcZN9J8wLv zc!8oJPN-D?yi{XS4n<6|Xi^f-^tXpcZqS#L&hMSD*bCOMfA_bYr&q+&8*Pp$=cCiT zx=c#D1JOL^FIf;&V-|99qSjU}ZjJO#?mkC+z)ydDxD!m>^@b_H2)pZf%ifbTE*&1- zr}Xs{10f~hH^a7S|!EQsHL=V&jH;v3;-FlLL zZn05#%17mQ!2ca)N*%;8kQ#-p(fmihCwasiLb5IT@WeGZ8afK$?ktQ+dsL0&lT?_vqdtA?I4j zviAhsEHD-;F72yUOLVhU_7p~-{Jqx@vQG3U^c~8>pUp?c;Rk1hn;j<=WRm}KV|F^~ z;j8}8MbX~=D|usL%|7em+IG$@*4w>Pp`NY?!Rb*OPt6Fisv5_ zH0WDt#1)4O2IW^?J2@N@$$dhYFL8Bao}~r~WiOMzOXiwMoJh#&{N9AjMYqFZ<{Kq8 zSBU*IHyPTl+GHRx|9P^$BNU#e2W&AED_?i#0D2`~E|%KdIhTD@#zQnR#;UTf7#iBS z3D<2yZ90n56zlsYlZ^^{Q{uO*reh$<%weodk*{N0}5qR=a) zxghdS(1qr<{#Bn`y^cJY=Lx*iPnzHGzDMY^e)oc7`vd(^~nAY-U&<*RxmO5}O2PIu^=hmJ5FJ`az3 zZPM&|72LyMI+ipa?klYt@ameeHb567taYW=&O*AV$nzJyOz3JqA-ErMxnWIitRHM9 z8_g0==*Eqo?T`Iy&mR0afF>T9zp2_Q`l=6|ildt++v#Hio0xs>8OxXQG!L&xX&wYF zWip~&Q?>j%d&S6md&ic z@eTK}^s5E=#@|CKQ1G*4&!*D0f4!=bUPifdpT+fXMx0zVei(Jx0^Dw!kcbK8R?WXp zUP)j;nh0b5YVm}=f%Vk&*9<|&^^C;}yH!qJUR_U2F#7IT1mqU=epSWa-@<^lV%N;A zAu7}4a(-{Ao`Dv3m0k7VFG-BagUqXWTWnOj@I*sSIXroOSP84+P6E*^^ug1^6U#*fr7|7yJFK!-Gcqb zmaods)7cnx1h=U)1h*7AR%+Yn^`7jY+%A4$8vmt!7@TCLU3Es=suIO}bDNdB5u6gv z23_-DHk4qn=Yv3Kx!F^6aq7>2GLt{d5vvYi=n&DspH1v5Q>t>~A|_V!7@_rH982YF z+iuT|bXd-e=sfa^ibM%MR-}?E}@Xvm1 zkTAIeNxSBVj5c4B|2&%;rL*|U<5HgaK>p(W-rA1o%-ar|F(r%`K5eTzW{dc9Lq|4r ze=eOG{5p&ij!atR1acZ)nxgiW`>1B6ZJO6HBbQ+AHQ4#XL$)LrscYUn8gM|9_bGn`{bLb*NW3h zTi<1_N5Led5J!215(I>;lz#zOMatv)z6%v$FBOkC%CH3xZkvQMj}TqsV>jt4A^daw zoO9~K{~$e~P0*pw@kGL-s|mp;6%kVa7a*=^Rw7t9)&b~6W7pU{MLY4FROB0Z3Z103 zHgmnraWrreB#0T4+PrjG6xWbJJa&yXo`Ac42O&4+sic~XoJ_UzOERB+-dyq6O$t}I zHI_?^pE?W@NMF{by=cwUOS=ZNhRiBGaCrr#-*}om5pv7FziD#50=;;Oe7S65_ZFdWoFhV-&arAkd2lCtxG1ct;=; z(&;+2$v!$xS~*F9S*mK^-9#c6)<9k(uy3rQ`cG|9aR&?c3EsgRwkTTGb(9W@ z4^ZWH_8;K9Bg^UKoWC69Suj;h0i9+lu*q3>i@zbUVd)p$xHitgz(Ajlvn;L=me5?7 z*c4Tg-v8Y+Pc03vigtBWGW`vnL-iYg=}=hM8B_^@L&YJJqo>BjJZ|u6mjgZf`54Tw z@YtvVz2zBRp%75`C#icC3Wdl6WBnbgY6SaInnG17BknHkYS5SoF9{-Tt`)Jk$L+&k z97x^0siPcYxxQy#bPbIxj@4vhaqS$o3DV zK0zW15cFk@i;yD=x|87Ti|hO;+v>l?HQUB$->~Xl@d!R)&yhWQ+B&m5%-iLkO*crWfQ#XB? z836?qjn2G$w3s(b`=j^~8pR#}V|AnDN>Gb*FQQW`INcy1zDrQyNzFW#SRxPw+6zHruQt=SZnJW^H|H@LSO-^ygNoS&Quk zk*MEzW!1S*m@fO7PAlyx=%o8h%<*69+G-EWMCxS0ZtHuPEfzc-f&;ez%A+bi9jCfx zrURt-FX_DJC_-CkB!AtPZ#ihH^0Pi>{N-*qe$U}AP2Y8Y6c}gHliwaaWXot`Eb2TX zdBKIrh1`j6h9JHx3-a=9%KF^)D~yL?~Q7vT|^iQ1R#~b zf1M(F z_R9K3jqH`jI2bhF9H<#F+cf%a3s>Y`oGydw zsBiESHQk6^@rY%^l*9AbA&zMav~P@!%Yj9X&-U#6W%L(J``Ph6(UMclAbJJ4~bO>(E`}E9X$mW9Pz3fkW;6AU{tmd`t79SCA- zie7ruCzWF84`>QnRuU#D0d)e5W8OVfOd`}p(D^t?r0@$mLCw+uB+bz%6Ncl1y~n0FWQ2%T%$bdHz@!Umn|;dl4g{T49Gx>I{_w192L z&@M)+4ov2;1gikEU&B8n_%uj&|2;3mo|8X`qkLh47V;qN+CeEjP01c18HNW(c;T@o z+(JM`!2||^e~<(z;EMr=2z&rR+ss|$*~jdNCQ`e&@dE7`DxQ&HQ=Qm75xeuS6;pfy zAJ-Uok_U=J<$&eS;tDzoa@!tXOxA*~)J~EGoOYx7Ha;TX7pCLWELyp*J->pTSc$s+ zoFtPI`2=^@oF~+WI!E=)-7M+ z*&vuxjPIeM25$U3guTqP`~+W!Bc2P>w<NfCOxZEj?l{pwlf9YFfXEmXSQ_9&I@UrRgG_q66>|9Fxxmb-bWL9J*V=>DJIj8e?V9)FT-Fn!j!pIo@j zAb!ul(3i}pw!8FT4ZQHx`hr9Ytk`v_wqx0TVshUO?0k^=aG%hrVE1u^py zK)zFCwVUXRW%$it$JQ(d!lga_xMB!^6Hz)`UIXjpD2AC7jC+7zRBYb$e~c_l+Y;6Q9bUnJ$0yi?i5!+ji#mn91$(rt=*FU#X{F z>F3XbZjvXY(fv&5_|0#lU1kQ{Nk%C(@lTv^+E`AU)c$o}a@^wE^jb(hwAsfp#98S+ zbM|p_xo4C=Sun4vbX#RkLfp^zDOwK}4_{9u6ei}2O6_hU&KIF3SQ0o-Jwjg5FCEMB?Pgp7b7m2D0%N(ukJ8DF3O(K=Iws!}oJ%w%f^^=Di?AW^VV zHWQ>iWtnj}@z_470(lCkLR4B=o~el9B8}OEhe<|E{bE`PRlU31NBW8+bwB zk1fWxKbaL&yl6pS94JS{J7j1vU^E73Q9r?06Tk=9OFfB{FGnR&H=XW`iYyhrDOG`1 zS2yw8Vu;+yqvIfmIsr7Puq0xoe>?1O+bTNh?B01Qk59AE&$kOdQ7lCJ+{>t;L z*x{vGtUXFQia!c4YL}8Z*^<2s~QI7_d#`0}nA<)eT z7l?{DgmhO^-H^0L^YBRL-odj8DmF1imRXf=Rf@Nb2pGE|>SSWGTF&`iCuf-%?mo%j zwo`RrsJOX60UPBx3ACSY7NJi_6__CFeMHT~pJi37eHNT3zN}JUm@H!Pld{u2)UKE?+XbA=Qqz^g?Uu?a(dU6Tt6~jllwn~ zDc^E_jq4!jl8EgTG)|bpUum2R3_UU!c?}xoDGQ%F0oaKS64#ly-#(g9@C=-0p??d+ zUx@sIJobQ_B|dYjUjiAx`VgO;BlsB3QyZ%rov9mV*S2eE8Dc-B=ABmuxpQgx{obf9 zlI&Uwcf(ZTOg1YlgJ?b}f24(0m0-3WFskarK=3D;fsd zxdTdb1Ah2G8);LI7WjpWpIk74_bIj4T{`|8{r(fCc?m1~O7NDNW}3-~J{C7XI-d0? zVg}}qbhlAob2o&YHZ3RuA?V=btLnHrsjt@~SSR21UO*D05(=-7#P(e!GqGdoD~tVz z&oVWOV}!(4)=Kv;+Jot&|NQa4>-X{d;mB(3H(HEIW+nsgPNo zO8}e~@4yh-<(rLHMDbDW*$9=J295A|>P(0CcRpwmq@V#r-7~R3fDf-QR#5x2=)f99 zR)ES++F;u4ptUQ^fu2x6lLrtBIOmT$9`orKHPFbW$7TI(ZzaE|zGRC(N#n*{(IlIr z_=09PyW~cLx0jWMLdu|!@dfOG z&GtjetYu}n{m51m>W!QdmM)M^^8*PP=B$vHTsuQQ`qsh*0d&i^Y3H0SB5I zrwW<#cgrw_J({_Pgu5~Q_yc>2GTj;7il#UxW|K0luT7?jDpq+lN-jGiz$_wc$eqwLj`E#4!_yd98?t#+QEbOqi{#n0_)nqIGZzlk$;l55qRj6K$L1o$HW7{gb>_`-N$ zbp2~R#^bh;!8suqB|^TcJ_>l?%4i2?K+Ni>;kDLMxX#D_{UqKgJ3(lvO;pn|R5bE` zeo=_;9CjyW8Ys2zc&_{fvBJ#Gaaxd4uCOdeW#%lI(@;`bTY*{V5?P1-&%dD~9f5hG z+OsfM#3N^o2tMmd`ihkd;B3Rdf|FrEB`c`7${OKO;059*9%g4pyRo~kynFs^QFY@n z=m=j3M+iQ1n~~r=7m*)RBGtZ|&|Y}|_q)?^SURE|bLnWA9fJGCk~$IGt7+@wa%f&e z{|@QaiMv(Z9Ym2LfX1Lp85twcEIRAIDp_L5n86L3J(oVrV6;U7ZJT0Sa*%@ z6~uB1hlf)Mso0vTFdQ--_|NQRtXE`!hg4wURK4z;JD8Bu67vI3@}cmr5*(8wTSl%A z$KD@N%Q~IFacl0v{0ev-Yqp|e7&nXQ^U8@Ezvf1asJDz?=Q`bx!aHcN3eO8SsfA5P z*&%u~|8%xK!JjukAj_`T6q`QbX(eUFomnJ)6>}>oYpEY}$-cQG6Q+Cghv{)V(yoQe zP@&b9v6^Da!(;#G*Gce3sM&FqncO9vqBnVHC4ZY5L3T^$?~eE$j`F3lZ-yjt8j}V7 zJY~Wcdm_?&r@sVd{@&EpQA+{5_+b~~^+tU0qd75-qH4^5)hM)LM}9@_^jlS^`lF?l zQeDC?lSa&99{B3HdubZOZqTEc<$0aRs8bSzC%E=tS#N0I&B;+Q_dovDWr@5(2;s7uKyMaJC|(qy39bPj*>_i`IAAj$?%AjdEID5u0+K%5NO+8^PI|B5 zrFk)9?bRP_O+Ra|zPLXTMV_B=1zWzye)t3MhwRs=RboHcx<Ye9$I?K%N2%MYR+Q|0OMN~Vc*X#1G}kw^yB6j^qb<9O8+4x>UHzxy z=R(8sm&!fj&nWu>$)8{u63z@3rR2lt^se3gLfT8L*e1gqBgogee!fzCdId2=rC zz_$h1ye`8hrE$6jZS=8X!MW?2N~R8gS*~DSAl;@0XAqbA1*E&@bacahUn~$0Lm}pO zJ-Q+<>_5+R-9xi8#^FEmJ)!`%LTf7wGUE?_QGr2j;Sod_(lzGr z)8auXZ5JDXX18AyJQAy6ImMQ4Wr5f!ll3CoOATW%VFz$4>q5mfTHP3M_to4UXd zjd5+=-LN91qRysQ$3jvmt5?D>`=0pP7}Ho9WmiU%Rgvi>o4M1*cD+W~h(Pdwc(L*y z?jgwceIJoks|$Ba*NtbLJ^3Si6sS{omz&3K3UvN;VdRj{@q0qNN7=p)Ax>h`&`D+l zO4?=ba;oEj`zWMwB{(iQn>@7ev{Dtmzl0}`{NP`LgHfB(2@MJMlelP^>IOEZ8$WUq z?FOAa-3s+)9;}&5_O{zWw==7$kT=urG%K&nW@BCYREFx)k7I(o1n2MeGJwnSWqH6V zV+)iHZ?|^2*I1ruRaHjVJr#K_sc1ig@Wa0zP3=ACpI=Y6%(>13_Kp{yt8rHAyyr;Vnla$fwO-y?x5aBQQ$vWanD-|H0qUb3o%X}`=o zovd??jpgZXQMRp%Y8LT)20UYYek;Knp5q@74u|4VxM&sW`(H$aEu(TJ$^2PdxR0&{ z*>M~^)rZq1r2!J6Ta*_HjYyT$YkOn@$%i8!Gsp}c{{PE{H274yMEIhWSj10o-&|Dq zvp2abg16Qd?wKpHD|IwNB_7lKlYGLMP6YLz=?cJ+suShvCF<(wCS$KSnT<~*FC-`X z1r5qy6Xt`;vR~js;ag-9vsZO!JO9+1-Z+{O`OSdbby5}Vo}Yke#vsgyYpSdmiD>u~ z1;IDVfW*U1Bohi2mQ=$0r0?PUXdJj0t^Vt^PN}0bHZqL8I)pO4wwBMuFpB7@59D<~ zG9S>0Q0#AYb?2ri$4f`NRS-LUN8I?cwTCZH}*oY}+crY*;oD*dsMtYW-8nO|r zRN=ukC)qxifB6Ksd~!>|JQ_^=-{kd$dXNBpp>(P9BG0tbHYlAO|Fx)sitZpCDzu_< z07{S?t1o?yZ*MuNi)NQf8cpq{YUewnAG=@X9Z~o`%N8VRBsd-=TA@t;65+Td=Yi@e z!XDzBctm_TUvhMSt*Ro}o1bFylknVr_^=7>mDO2X4=(G_niq`v~g8HlE^aU6%o~q zcDNw_g7zPJO_QPB$T{#mhx~|zzrP?^jF?$Y&w5)H9+?T2hwdIGPk)AV8Tv83yWIsg z_cridg7kZe2ouAWo7SWay?v{7VSOLy*rBf- zqHd_uWm~J6Qs2(bm{a@UftY4-(f{k!-KX=wxA|?DbY`NW(WO)IxcZ~=BZS59{$S55 zyzAerjze*26o_w_$s;6RYT3WAw!EmpZ!>pc;Tb&J8)*ae+#MZ>#2^Yve*xw@Ujk&k zoeW-(HcO|3jhtiKCBD9lWa*N~p1hKjCHyGD3sa3F3)7HR?X7dv`eo5ubDwatR?4){ z(yCZt;34So10ZNV8Hl;gv7MaU6LzaYXumxVA#PDA0ojGmH-d724k;K9g4RSEjqq$e z!L>Ke?CURb~rA@ME@mrRK?*um}J7tHQ|A#eUys+j~!b08M|yC{g=&C>m*{PHsD;8sRuKwH^W<+ zgk5&>Kw4gYv?-ZwGTMNs=4u>ib5f|U#nw3Ide&{KgjHl8mDDCxv)@=uE-8om7%Qoh z{D(?3m&@<{w>-mIJO;^3Vv2hRU=?t9h3i+!X-2*$g z_I>pe&g|7{kz<%pEQdS!QPHpewpWQ)C#r8fX}&*W3F4~}ECUp)g7OR7ntpY$o~`qi zuy(}FZqtjRy8l}|9Ez>w{Z_$_Ug+oqq{J@W221~qZ${F$EoPC^Rwh95uq?z~u2-|5F<3|z1{TtYV0PD8)R;b^4I*@w3m#VQg=8Ft zKnV8pA;3CcCeaEq{6=8(SaSbAkP2U>n6sqrJg_>lagO*gLeO<@)L24$q%w zWRtfYC+vLL7YiwXa<*<$e{0kP7t@-_entI5W9OQvF4O}nLLjQSNvJ(@_kek_4yW@p z=xm+&Xi8ep9(Nu@1nWXH?j-7NgKl=%$lqR#vIyqaN%PMH3nM!B$yHwLEqH)$M7&>< zxU4hWz9NdKJXf{EUF|L!SlQp?`a_P>p^BB!wL%g72mGNATc_9~MA_|d5X+DfA~r7Z zFz(Jd{I_rYz3xMzc)g4TQIaevJ-|gE^Y6&laGiRaLL-AJiZ7-uiNV{DG_>A`y8&%e z-fE&nn!>TypNt-Q{X>N@Kub5Xinpdp7 zI9phNKU3XlK`yTJ%_gaWh{*B6zjy>#geZOZw^;E|PoR+FQS^e5LYm+d&<}Rb<~(-* z6qSBe61VLATsRszw)6IyKT{FTxX_i#j7%A<WkcoOU&7!zxK0h#;o57!zc(l&%STgIhJ(*b;SIec3we zU^8$r<6Ac7vvzzcwE=E`d4zg|wx1P=RdoQf@r9d@df{KVE+l~!ETg;`oY~?ikxG&+ zscnvqUO0b`uk5c&4bg1Y39AY%5d!5sA5EIX%*7>r>)T^1va|X_z4MfTvYLB&)NRvN zDC`p|-hhliz?P_c&|&(&u;du&|H5kj%c@~|I32hPFCgVq-sqB&kRr=Hcl=3eAz=g- z{Y@86TQ|S|A3l&!_YWVi8`(Tv8_mn`{Zq>lYm%?|L#j2y+?86njU)AwB)}bq!1c zeHBkir%Gm_4GTOOG*UaiCuhOoWT7aRD9OTjP}_+S$*dp&TWWml2dPxsm;W0=*_VE* zVOqh=A@9e@NnoA8%qKZOw=(w%fuN8dT3e<2L2KzpW>wE(vj^#;qQK+)SA}<%nmmKk zKT9ushtR?^=SG)V5=4jB%fX`Yqa-|R>jSh3NEoo7$2z9Yb&LrMPTTlwi#=WZ;*_5o z-;930EpJdD%)gbBohzQFCv7#9O8&H$%U7H1u|KPX*9F;gt1uW;!f$+IglZzfwbz}T z9q(v;CtGSIGFWS{!Uo6+S6!t_IOqikQVyOxixB1^R$k&vVKPtUT|J%5RYRS z&_KyYRaO=nb2Z~-WMTBrq=*iFzkl{3W*2wUq;v6k>( zVD2r&VGb$bJ<>$~zW}HxSJ$}d`oY&>gi{%EqT&pj28h#l}rhNoSv6^`pXG$^uL zbNQK4nK<&|0CG&GLNf;)!{bY2>L5u)MEn?UT+k~-)N#7yIHcHAe^X$5o^}TiQqiya zgdH{fnIZD%7J3|bSsB1oAvyucmjRHMqCPh+$%Q~2Iua-rY5JWYcFfA!cnV` z&cnDvK25W7i%9k_e_u}GspE_hN%pK4)d1TMk|fhZ;b3Ia5q&SZ^0K7bn`-Ly0eBYKT}W9t;BH4|AUm+~6SCyCl!S359;XzT#mBXe7j_e|+b~k&M0c#8(9~1bu)f zQqU%~1gV5}7PYBOL>-7(XhHUzhUr@)yz`O(@EklLR8o^2#0)TwLKTBLMiUw#a6MOj zl_RfXKXue7N_I=1Dq3pyRNJ*64yO_Hk>~^@3pI>FX83U+^oANxq-HOTg#I9L5C}>D zj05UjF(6hvfAWQb%DStXI!p{|FQP-?cU;cQKZ#eg5W_UV7q9P>a z+C%x_7UDCAb_qgag5tosxZee z$ggxye~JL8Mn(r^PbSFYDY;8h@iCq&3|1Ab{ikH{Pw~Bk929)$F_m&H0ymIwroWPy z7M>x6BvZp|OqlXdjgchB=_Oe@-m>Q(YM9D;Fpn7rGkC4#C5UV2g|&K`>Y6^FnTi&F!%Df1G!$DMyF1ZCixZmyMiqbbVzR8!zk` zrMy3Hsg5;t!TThE|?*Mb4=t0>m1$!FD(clV4Oy9n#P?(m&AhvV8&u3qs|wsdtGydx)!A#^^pdI9d%ts zp-qB!A>$Oj{TR=SmoAlc9Ts|I0zLHYyM>C&Sn4nMv(QnyTbIiGK+e%TRB=hZe|(XT zfK&=%2n3!>BeNpp;SkHCOfuXq$q_G=n;b+f+k4bOYnLRvN!jFP)7|OH9u(z$xW&Zj zO?$m*2&U3F=HFRp$$FJ&?nXQe#k8|ka|yDPnbNXdNimreY>s)C71Cdfl8rNXqrHJL z$-YuiOB9gVbYp^jd9`3`O;qTaf2GxwW6IP*h?KRE=(<)#N!YaVIDkn+=kA>LLpTlm zU=?a%-P&nZIpZUElZ2TMa`ClY`dR8&$MDMPO9?b)SO+Mvrut>O=Gs{)4c{SNebC)X zwVqMkg#Xgrx184z@%T>hnRrFm?KY)Q9f(lMuk-|yCe%mR;9hAR6jf|+;??sW0oBQ zmBL4vN$TZ9Xv(x!e@d|ae+%9jNWYuyp?h{V(Yfs&7UalFmde?gdu{QN4{p?lT@R~q zU3KG5)18_nQG0>CE7bLN%{prLL_2D3f24ZM251%im@rG`IGgpwy^Y;_3U0!yLeN_pI@l0L9_6byaOO&yuGH16b<+@loNtUDTQYWEMdmpkc z@B#AbEAA!U&VwQ;oYF0P3!#)IYibfpNxJt=;>hTx<+gl|uYl4k2IMvN=GDnC2(s)~ zH<-@=1amP^GD#Z+e>9TY@`*GX0>)_=ikG>3sA>AYzV0+OznP_LzUgrO54jAu{pl5V z+w2ci1&t=feXxnDby*hZQq*BfLty%!0ADLX_yY>DDVdHBOkclj%1bU43MOb38$s2- zYa2nea`!eu+8YZSLG!f4Mwp9ID&ge}GT;Rei#Z+A8c@^6ehRGC({Ydn6IVP$V?bF?jUPRSfEl36_}hXF=}n>!at{u%Sx z2^^!KoNe};!-y-7^`3Ms4+n3EpMRj|^l5}Wbc!PVQfh#5rW^f2F;#f{eW(_f7@%|H zaT--Le}4iQ|2_1@S1zy-KsGZUeed!1OY=LnsFsX<>yr+p;b}`D`${%Ry7bqt$lz*D z+IA->jLB)0*e#uuZM#}E$=cE|Cz=hn)pNc>ia2ArrlX%^5vtB%nXHf&)3Cf|tom45 zf>yPRWw_EktPd8RZ8zl(P|D^MMjU%MgrsZye{h-33Sh0Bv28Zm2DYted>8s^1>kb5 zn)@cr7P!K7VOH6}yY+>4b>?kD!ImJe*68gIfBYna_`%BHQPcT)H68R?uCxwXh+uM2r2kMO{ei&2ou;H0GOTXj(e7%Jm*}jv z5&q@tGa1Xbp{RW#GQ9YhOz3iuSYo9ylCiFx4yJn57}#LQGQ%c_)aa4vS2DN}>P>PL z?vtR5^>ra&@v*_|AiTpoy7H}|XVfBUX4YBj>DqB1h%g@NblvH&_6?7dRIkl!o* zRQ8Zzy2vG_Z^%pF;%$hd{3B8AvpkTa(V(d#b1#n7b^50P@~22YdvhDgtMiZG;tbuu z$S*uk)V5hi4b5+8A-k{cNbGuvxYq1o1~PqV@y$0MRUG(>-KGp4a%mqS z=m(f|Jx`yfv8n-_5V8}WX|s*SZc?hF)HM5MD=ss}%v1AeQhPE5ep+HeBO?M_iccpM zom5E!frKQS&iT+W&AuI&oN_|5@|gSx4sSsN0@~%7iwPu@dOt+3aerIH>boFp6HGBL^wfr%)%NS&IwlRr-GJGpNo_e-<9eAQ(|35)R*68}*l z<5x|2E9Ani^a|SxOHq9_e^II2&nYoGK`BZ$MQP?~b`+AjZ?+;*@>H?ElaCH^GSJCD ztBBD26fOsXmfqV027S6A`2d{HG`h+^`G{`H55=;MXt19oX30+@RsL`W$rRv}IFI&DJ40e|m;h1Q?l9z-G*wW=6~U*;KTu*m1}z*4?AK`sKyzrc5|mJ{o&< zMkv=RsHc)*8z5xvx}Qeqkk03rD*zOZdf9iWVe)RbU+PE3GCOA@>-n3|WEl|3Lcq&P zCC)|`B2Vr`ru#L@Dt)Brt9Hg&VuxZ}M@862&w(C-4E(TwjJBZ+rLihUi`I@@3;OLt3Fxi;)U2Oxb4F1eb+c0~aT*HuJr(_fNk)kFwKkn@C-A*4z@0@U7 zZI?O27UgYb^PSZg?gv5YHPBnk(*3h2K0QMoy+#5P6yKZ}hc=RD`J)`_>59?B$nb8o zb3B-RY+JW57_HBSufli5kh>lBg0|jj%)=&?2)(J0e{?MrwWz=1MeZ3POT{d6gZFo+ z-0X+#29e?+A5&UPBpgb?3)vSU}Yrb^*y2%u> zu34I~_BHb}`q4$Z?!H)>^DWuqTIsBNM&zfQgUp)$0cRm|eYHh428YYfL`LbhqdOPr z5Q{q(`SZo-?$QKI%2%=<1XMBKU6vLof3*>)aEv!hr%jD_eoU!FiuDR!s->&?Or2zD zxvy>9?nUmr8S<_ez!Q1#y?7^`l*#)?Dlvt8{s4c$*z1Vcq-MtFPM_cG?vS&Kvf0T$2 z$Tk7Fm>9Y8v;b#_%L|GU_a1Y1{yIUp{LWuvvX`&?&A+tq)}7#Mz5l8rVb$L%G*u;k zYURpGh**1$7ItM%EU7*;FUPB;S)NwUY2P86{j&;pM$NgA)so!*g!K01#P;@xy)vzR z!M%}c0JZ^+mGfhQ1CAoYYr@nXe-#XZRE59@0ZhCg_L2WsH+9O>&Q4cs-jPl3(7j93 z@6zv{ijvni#L9-}`{#Hvorwwd~xhW#DiFvPhJr3u(B3thZnWz;m#d3j_#TynE_ zfy3NF(Tn3+zk{Z2#c|lD2hG8Ed-z^6SIWj_ZMnPIw%K~odEaJD<0G!~Y4sIYzz3gh&b{tUes+ z+R&|vLK7MjA5a3k8N_6GNkj{C#Ann8H#kTR*#bz^=mG{8Dv(kG--Ol;WaJmF=xK%s zt>sA6grQi|5f+M1f0x4y1e9JOAH<V%>K_IhaH4&17-$SSnWCJ@L$gL4YD~0|{q< zQ-BDIBYguMx`iGO7P_gwW5i@O5u+pM7I`s8z8dxg`0)Gre}xLOQWPrq!VI9lV;G3W z(#xI1JUPVv#wGcT`Alv1V5TXJDW4U15CcmiJjDbCDMNF(5T69W2tam8SnPR-u}K^R zif(D&olmMM4rE9v_KM zzW{Us-a!Vge_;?KCTGJX$%-*NB~XB$AsEM8lL-Pq`3yzsJ0XrDraqu({t2UTZ8^Logc1)8RRuN#hYPsUVhE@-lej zf|?g5yp8BQcdG)G;87I(Lx>lRZQnt5g6Eja9l3Xqy+!B{hS|&02+eUk*AG5OEjifR z8V*ji3NR?&i7*^g?&6J;1wSl*5>kF((=$(goHw_aD>S<~9Gpp2R?WaW$bOeM9lZW7 ze;iUK34BlzxWDg^HYA7V05bFzp##O2c=G8QMQ<3#b18d`7wU8>B2b3nWREUzGWcg` z5|f0o%)g_0p>h|!k?ILkauGpg6u2p2KPBD>T$h?VO5YBKgQGav+S}cKO#i1Q&J5mBfcP*1)UMnd`RiA)-?wLKaR-p0h!f+SZ+%CD&$bWi=m)IZny>9u}*t)FvV z;8ULIlV;_4JQgr5l|61^xQS7i7%Ix3WtZD#eu>*`m1{;S?olZVyPv>>`LS)U!pU=@ z=0^o-Z)(S!I<(uuA){x1UpIEugsosVo2V5pPb|~pRArefhKw-FapAV*EKeq1+kTL1 zTMn=7ShN`wEza9~NGaaix(y8h-=V5j6gFdHYL2!oB}&Go9j(=@&a!KT)$vj)pA+0iCV7W zhb_b(+OFbGQ_kLV1S4-I#7d`)#k6{dy+wJH2#)cF4DFY>i-sWF0b@!7nem=YPbj^L z!=<~9DHr{1JenPUGtUPJ4jc9$Gfo0ZuNW9Z?+U~r;1mQxD5`{S>7_GjM@^-F%l0Xa zyl+@uLGK|PszaorlHSO>nV|?Jdzs1Z(IvSgA3t5Z*#mO7(q=zWZDf`ABQFUA=_g22 z{gx>{m(SCZ8y^b$gT}_wB{@7k0(=IE-cmF+*Yt?|;$i=P7qwM1G>D$*F_1*XJcFwI zB~h;QB(4@EmV5G`#P7zPZ7t4Y#?7t8@{rW-EXrOFfj%uP`}HRb0(zq}v-*E#+ijw< z6fPT}ycMZtkKCy%5V$0gGzC(8xh+e#W$Cso-Iiq^Cm{1G{O+QBH@7yodPvZ+^ON$6 zRNrTk=!lAc>r9MSR$IP(?=@!6BB@6p6 zU!hMku+(YGY!M}%5|d7){Dxd(Wfi2Va|KEB28lX%$*+gra)2myu9y zIU88?iCo}$mQ?%=jDkfsRj;dBWwF+cKDtCkFL#^LHLFkf4)MyAA1$mfhgB0nT(?5(fdmBn$0N@{ZF#^!@;s|mi=*sIb1aUS5F+a}sQq)W27%S$7cxCK|qACEU zyoB1$;o@p@{+%ws`gPMqEPs4B#F4skolFHh3>FCz>;|wK2-@ceE|FLYm>ZgH0M4a4 z?U8bGf0twoZsIzv|*N38>qDq?`BOC@85iTCZ9d9A4qO@WXYH9cD%|d#EqUEZuf`|UL zGHQBgk-W5$FVhd?Lk@ulvy*sASta9iNzygvxNqmZX(II(80K z)?E{=sX*Fpx_3lR`=|#982wc67u^x;i#h?7hK;G>YwHe7lhm!8L^=UMagJTBABdSsd@ z12?6=?ku)zXZucqyIg*M9G4%*<;QXPaa?|!pJ#r(sLO%6Al{)sW(Ux3Z+;n-mzZBq z!4vg)8*M6sUbRhiIk+6OGOF?%Hu%BKrX^Hm08i3u5e1%}!$?30C`>Frxj9hh9~~zC zD|M4#gdn4&KlhSDWNUU^nI=#i+w`%8|0j3-OJ}sWrs8I|E*)2Yvdlt?N%^8TYk?!H zTW{W}TSc1$j-*#Daykf`ggXmyqZ$^Xg(bp<2@&I^FOfe4a|B6xBdU-%l>EX0x<-*$ ziB|yLzy+8@bPh0gA$LE+P5dzq$|11&p&_PI(m1@Vx-aY=q>+P8#md4yy_An7i2P~yQtiAN_n zUe_JnT@X)Qg5O1M$eI;W<0*LZEPcPs_>hJA+08LnsuvonJ#*{ZizDSIR=eVQmp~4z zloEg~7)SGV@}SbQR6pFgS2ms{nau}@TI%;_8eO62_(+|9nmd3@x)=_zudhKI4i2Pr zOnxOkl1*W*!)U6^b-VKCTzX8l3SJudB9ejVo10tD<$o8On|t!V{|ttMH|na_>X)e_ zrhGBvA0PI^Fu-C-wLagU8>en}1SW&oG9Qq-w@HXvD8|Hx96jfFj;fqVT|HK%Q(?T| z%W61#roNSbEr;10X*UenyzJ*@Kw~aEx(p1jH|q|H3E>fs=a|by+fA5f_3MD(Gi9B~ zG9TD<2_Q5G_5lj>{51nZvuO_!Fh(F2NQhIwCF3oj4!Zvr55NPXK(ef)$(qD5KIA* zH=CwMTR&rRNMoX|JYG`y06~wEH-tx6vvfw~4Ru2696=5%>wO)HMo#HD*R;QU8yLS{ z4F~eCg9S&GHz*4Nr%)*AUh$+NnL8FOh1TleF0^1 zP5eQ?vi|lrJI;|8UiDA7C4R|uuJ+jfeX$DLZLt+~eAIxSh{QEHcB@Nkv=}dorc4R!$#@(1NNKG44po8_n+HaU^#L_y& zL|)`~t6rgK+c94O1iBFDnkyy+KaX4kWFYs)Ey=1yW*{4zMUw}=-Nbp0fJLT415o$Y z?fmDcyox*znjZCZ?dpAS9_y3s*IRYz0T#sjoy=i$wI2jsH@r*&mHz8S$A($E56?z_ zftz}_My}y7j;2WNbZO^>2fY~@f;qer>j!fXQpWH&kojSxADdGZ-_Jl8p=(TI7A*21 zHY>ZhAKg6Nt~*Yhey`Og>B{@EDVhGJs?FYP)@)4b_Gc?+>R9GI!ahvSAE=F50H+YU zJz2LW`(Px;sP5eJf_Q)E6>uTbf^`yqA9)h?Nf*YH2Fvzr^R%l4iyG*b@}nDV6>C+uQlJaVUA}^Yk0Tj#D|)jM`!}$fY&9Av0KV{BGtiH zE%GK+5xt{)Nj3a8t>yw>Rq2s3^VL^{lT+h2lEUgiTQ1K}PmAMa&H04nQwOL+7@}F( zTD{fU%O;^MvFjB5 zJGJN1E-YJsnwJQ9NG3CbAjK8Q=7tx<|BtuDQ?!ha>=acU8yz%FmwBzRa?A%XS+ zJfw+9t>)6jY12;PzfZP*j}tey+QA)NiNphKW57i$`jfklwJurIIX=hDB!0C_%29wV3sqXLbVAxg081fu!5HI!T1*3kMk zzN2s0h4>jheT9X8RC6=bX`4ha^uExL9T+uWs<^D*<>vw&%|X$DsfcmWqnW7j)(Cg$ zzI1aAw5mDeWPgmE9j=TcgLUE#PO$qx@_2N1(SR=kslk4=B)_8mU_a8SqVVuE-K5mH zesGh`B8^Y)3P#>t?v-9@FrW-WZ!eV~-I-uNk`;|!f9oyMG}rxp;{So`TD92 zva%~S>3}QpRo&y)T%o?r-;v^cu&HfF@>+1&ijbm9DyT8K+coGx$Gkz@2wE1$X0$ux z!Pjb*PLRTzHF(9GRPCM^N7?)dD)!z0)c$)jv`){n6RSR%o?I1bQ8|y3|Y4 zCV($bm&1b64fc9)P@T-KKw^1xA`P>E%Q)iPfHO1#wVH?A*y9*%$I4I;3?Y{hCShz> z@Xx7!-uo#39yR(?D;}JcD%CGMEjQMWQL-w9l^BsSvW?%?D7Y=3iCmkoRf+i+QfIz} zA|F_eTnLTjRmUOX0ZqWz)S~0^MtR=k>0@*+C17|lBCL?%%vp&9?)QSAJG`)HYf-R1 d`q`r*OK!d-N(*cds0e>Hh2mk;800030?7eAo+qkkn{8dnTUQCiwJhtUHiK|XMY+&d5nNf=WAhX8GBQu*%x!a@>U1yXb(+c-6KVv$%HAkh8mMx*=NfQE=f zp*PqYY;A0B><)$lOeS=&_iey2571z5a6);^z}e{`*griU41WjLC}NlrS!3(P#@2Hm zT@Stw2Xn+{)MtaeFW&|P&PCO?I6xl7Wa9uqkCJzYzaczY42Adl^l zC(rmIL`-)st3eI{iXs|41>Y{oCC3xMHjW8L5rIL0M)0qH0fGZn@RCP}#}N@vhTu&U zeWd(64nrDoH z27;6QIu7Xg*EwVyMZdxj{~AX0cJY5xL^h`M|2x^*+b>C{e;)wDBwBkmomlkQi!0FBmUm z*_ik!3Kp150T%0cjtG~VaAV~S_c0EF3b8F88e%?`&p~j{*Y@kphP8c!0>sg$@n79m zby~d+0ejfrIK=+4wVk%p%c?f1s>ip5j(z!;fTunJ5t^U~5ieVj3f&$aAN7Vf_0%kf znsPn~2gg1l98Yis>^#JOK8VEXV~B8pJsAon&sCYR*hQXh1Nwf17(+h5X=@wcmVn8yLfo_PB_gx(eM(_X~xc?ux$0R$gJ zsTpLmjXVGu7djx$H zEya{ccD6r}Uibw!eHE7{6W(2lB6j1s9E0H*g9gu@w9K(5lJL2v28xus7Ho3dJcL8e`fFY{++&LeC+GWr(`kgJkR#FRh1?`fA6+cT zIbs~nL$y5QB0tAd+v;y=B#ILlNb`?qLQUHNWauqI@{_eRG8KpMqwG^^ye-UAsXATS zbKeG-qdEJL)VH^;8RY8+FpA(p4#!vq_hI@={IUhn88_`nc*dK%5ntFt%Nxm9piNnm z&orWo(!jKT{8}=brSTLPK)31@Y_}cp6=I=F1E15G?lOuzE4ZKVt=+5@IY|b2e%zL< z+GK{Dv)MFxDAbLe=Neevr3tTk8+QJ4JTSBG*7nFk0Z#efN{VpOiiJX)D{rj~Cl&fv ziVe~&mE)9_L`j|}52Vf42UwYe4UJh;+qfi`mpW zU1wRU_43~_E980qM#hzA}g`8|=L!bnV9F;yz03MAZz%= z$$GTuM{fWt?5)>!SJMS;KN7tsTUSdMKtF~awbUQEj#}Wj-8P-Uq}^6^TXprVnv;U- zZ-jk()`!tfv-RN}B8cJcb_ZR*+MQD$N?zdbTxikDjSRZAUd;;`h0R8Vq;K=geX5@+ zMSXR@u-t^yo#Cc$ZPb4cB^yZ`1o}WE{gs&CHURQrc?sBtQ(tm`YFELK~yXdHv+0+h?k5U`eC6VrzhU2C4NqM-ol-%;J<7L@v z8)o(h3Y=^uZ@_u-CjkaFwTFGd3OfDqwT2)x54b@3)6L^39h89o3lP_P}3+}X= zh8sv}yX`L>RgcG7tY_2}4$RbfnLLv6;z%ApDZJa8@GeZRl{Dx{g9A4lL-0$yqw&Uo#|gMMk9YjcSihgvK?;Y@b-2VU3;@@H2D7YPB3(pTum29X%@{l zR`VzDQs16{kHmkzFF&}puzhJ|+0c{T(ut{)U2es$n(QOSLN-97vXR_x*|YnyS@sAq z(plb!XLT}0eFC8v9*2SdNlvega1m|xsuF4<>jg(oTwkv_8)l`;f@{emdR0@h$u8?C zxp$VEr}1BM7q(LgI&FH@)g!)qyY;f^dV9%fq%(g5$TzdxNYn~u<{Q5=kXahT za)?==tidBIga*I_bfWA=WgjhPHhP$5BL{CCymj#Q?&RF7rXUk3r%rDytS0A@W^CkK z-XN@N+DpBpt466;*~bbp&={Ys3{2@vWMGs$n9wK_h!v7hg|I40LU1udSsU7=IlwHj z;s_zb040CuIj7GlLCT|73e|aD94Aso#=qjU2C}5}m3Ofu;t=~zB0pe>T)Ay3|zyLwWN4{Y8Q^e&l{Us4HBD;423FR{s4S~AgAvf%v?EaDf z^*>J2Kf(WA5_#AU0N>vikN-D$%n$Zu;r)Y40{-{;^XJc=KmT7{QUA-&&UDM4X&m@^ z7~p@;FN*vp{9ym-5XeD1;rj>1-}_I${^<@Q?)Wew+q2=eo3zygYQ_?(#AxoV)jVF9 zVnka>rOK)Gq@^xk-9>5YY+2N_bnk5ry&r-2+gcLtsK)irRsgE%_Q%+*Jup?tUe6m+ znwRTPx_8qBQ_HHFxJT(&`%_RHt8489=KOzI?~b8tZ`&}G{Ru~ro}txvi_wx@#PJ%S z-I4Pc-QNKd$`8&Ca+m1}D7|7}481D}o6~#T$+hg1RjKggmn3)5oY3SBcy;-qab=rO z@?1k`M#<1G(?v$dtX540jkN^au06Sjoc(voz_lsBWG+ml}4_W6>=Bn=UT_Q6R64d2t90tD30>bQWSIbRt zNisPqr9FJV5O^CpcTi7`mx0&i;}ZVSNhhKA-!sH@;^tsyTpIhm8}on znllmU)_Tc9lu@>X0VSPIXylDtfG^dDQU zpzYU9&dcW<^3H%lS6%`rq#-l|7oWy|iF!-Xg>Jk7UFeqD!;6e=3xj7uN19@iLyj58 z9y8KPP9qr33ZUZ`I{xbyW$u6cWegemMcM!ZMl&cPPoGKLFgJui%-ec;?0iGU{qCpgzZMK((g>io@fxJ1AJUS0! zvCnVR?oU>R0v>eb9;ZMCCccQLF=&sj!~UosoovLL%|W`@FIeQO)3z&E$=8cRL4Yo z$RXEdHj=`}M^Yyb5sEhC-y<-lG-xug)pWbEv8{eMiE1v$Yi2nmqCELX=pJJDAQ^vl z3s;@1r_Ya%q!J=8ZOK{bjVIMi|D8D#jqb#eNG}vS*1ENQH2Qyy($DYyx&7z2|NQ$J zz5gE`zT4er(eM9t;C;S*fAIEv`#pO@-(B2BA5N}+`yW2(ZZprw9{r?Ka%W>a*&6NC z`C%Gc^bGL`qiYx(Ay}TBHjFRVQXS`ul0tJBT_L_9${rtC^0-_NeKNTs>B|9CnVgip z5kSe53LujX7WjXn#27N<14@7zbZ_jedQR_*o4x4D&D@?m*&4m5^S6@=OMJRhj68HG zKVX;5Xg0CjsX$2R!{Z}?443OMX44I352MX?R*x$BSJZ6;f{<{7;eSx#c9U~DaK`$F zY7#cqVQGT%?`$-`Q@98y^py_vdN`14G*RG2+xkIehBopQ>EP`qbMqG?7*^(eD|WEL9v;t$uXHl)feY zDQ3q={v&@jvzYHfy6%8_Fpw{lpDU+=u`C!z^L~x+>D>JkEBDdl-Xfiq*MwOqZ3aWp)93ymQXic_Ey`8Q3KcAJq`!SQl zOcqItucvF4KgdvbRhqi4li*AsCtIV}b*{^jalXaGmnk#536Z3_jr-#>^K!+1$0%BS znoLl%98xEpG+wgE8tee8jbYeGo0OmwbTWBl!T_H^4rcHg0SG)4afpeOEyLWcii}nU zo=|^+K&a1Lo;qj72LZ<$x$m<_{%HhH?f3plwx23)vE*Lb1(c1Vvb^gTq)DYFx#X9* zL4LsGG{WMIjNkq{VMqwn?1}vQ6h#LMo<4$$IU-zgv}+ish6)dli5DTrvR+VR2Ah`; zP7#t|YF{lB^SwYo-Oe;kyO$X33gH6fSE+wMRoR@iP86u-p;NVFwpt7zo!GV=Y5-bk z7wlkBtirveMP!!|v1XB3tMwg>p}7svb|&xEk*Ba>T?ETK65ZLXyM!Y_)jLEEVOM7$ zRk;p@YJEqd(8Qx~i6uid*pDS6CC&z0>W-&~ph%0`!~HX5&nP<b);Ho||i zwQ!+)Y+CBhcHJ!ny(#2z#xa@D&I}@L!6LzWQgpd)YP8#%;^P|ZEtRFZatU(U2Jad z$^ZT%l(NuYUg(5Q6`dz^TJFc9iSJ*(f0b~TUSmJ6tsOxQg_Pd=Hb}f_tE0Hzfyycu zfYMrX$AH^A!@(K6k-=*cb@qGzP8z1JoM-|nGNICivrj8Zq(>7wqiy|hF(rS^AMOtn zNo1Amv}A@4XOIx2&jOAK<`}ADm5yrh8Db$N>dSU)LeMh$uGT~9OK&U+`Ce_an8_q? z2axsqHIA7v6>7qc**Q|^HYfcl!?;tAry}FAs?o^~kmt7b+K6FrDDKS`(`Rhf zc4X!@WtBFSZPBW?MoPs})5g}Uc$;mq7Q@UcbvX&n?Z>v(pxjQc7?0Yb-3XJrx}we8 z#_nh#YB;Y}EbT}4TU8SY^#k^}i|ESHwdqDn3s?m?MKV8x~~ zRi(kV>0$Um?u;745NHFK7C9>!2vr+(Cc+pKzPs}jJW=1p+B~RQtu_!|4lW0sErcn# zmNr67h#AK#X4)DEfk%J+{=6X7T;18dxSj1jFUF-t|DSvou&(=Wr}0kzd&s2YW5=zR zRPP~reXhN}0@xRcT(;NJ{xjq9%?!zl^_f@L;qj4J+|nsISZG&eXN-Ta#&{RQzQj~s z*2S=wyXbhn!sP~4d5J&3Q}E=ODtLz2a<-z1_IS#d61j|_=$?P^T-|Pvz5ua6iUn_g z5OT4JIL&T3IOl*~GUKGnq)D+G{cLNvGjuWSV2c{PJPa)ZNPMve=oO9}PPJPa)&pGuy z9;d#CWu z0RotGmf%lBliGlaW{PQjY%a)SG0=9-+zm#a3gy5wU5~oD!?>ldO?CmXemR zw}5AjHZqr7%N==4j{aqA#-OX-DjsEp>dfLju%F!6E4Wbcy`6nrg(vRUwsthwdr^#p zRT;~x9PlgAxHcQiY=&vMqm@mNz|N3|@O5HmlaGH+A@<)2WFwwjP!0p}M3d$Ws?MOg z&IZ-t;LSB6T!tp@?0%8k1vX;3u$8RL4bGl;f9)#HWb!!eiJG@qSqLmCZZrwya7l-g zmzB&(-J&g;2B9iGVE^ee47tY;eb8iYT>8|FjM`ZSLvRoILz2C^}4P3ZoRCX7X{ceM@x4JmyBC+=buw5kf z`x1%$KEvgm#@H#65%06BjyO4~UI&nM+I)Wrj0-UBDR}aXaT>uX(y6r1)vtYawHzWR z9rt)2+Zc;Yr1q484E!=YCCCTaIKU*L^TI7{iGuqBzj}u4KyN2`aVJ@D)(*2*-utdw zpJnLSP|_~Ka)u`o9}x4IkgdfO$RFTs`B@Q0T;Mrk9L_^gVrz3tdV*m=jsAI#{{DYR zrI&w86rh{2vTWrjwW^UDuVsxc7@{L$(X(b{y~@6Tl^HVs^&hwFdeInn=nT#2HCic9 zh}lG)4AXHpHja;$rVTNh>nC|gfxu;qDIl1*vTg4&O&^>*z7aJ*JDem z@nUz>ymuIfQ7$Y)=Pgufsct9vki&l@Si?qkpd-;?h7?C&Ole@T*Gm2NwdJY?WNR9& zA`5bk<{@W*QxK{50ID49$#j4l%x4lQs%U)a^W!6FwV^V8n3$yAws6hYxU>B{>bjj9 zf#kiwzhztFj|u(d7~#p*i)GNIij%DuuN&ilCX4Yi#NDluSrc_zI$g8+$U*UA>zyr{?stC+YhrEpswChB zVlKU042^($na2X!b2ME?lO!#`O81T>o7{sV5Wf zqCT~Y`c(KvHpH0=qpiwW`1qB#u*%EqPEX3qtG8_%`Ndl`rewSQL?t`(0(S1feYpp( zE6~_#3^*dg%>;STT)cjDrK{UBzL0pkh?6LnvzYn#_wvBP$yg z^8_^j53^HG{$PMmAAzxYMk~^!Nq0ywfg9jrhAzn*@fj7XTP_L)_zZF#u!zSD_z=x0 z5z9A<2@y*@ag&`LB7f<@HH z^q3nbW|9K!VKIhG)$I)+{qU@(&g6NrwYyVutNk5hZy3jO$kAJb4q^N4U236L3lY=F zHgp^c>6Iyy_)4El_3i?P=ZOD?7Ei$w_2d9gk4a;^#8Uqa_kY>VHe20juNvfXm(4P1 zNdIJD3K^In1Uwk_r+egP*i!S*k}`1}GLih-h|bO5A1U#)PtYH7ODeqn4zd$G$9%B& zTK>=rDSdewp*fD{i8dhlp$v%Fqp;Et3^L9)Cewk0CYcwph*>cZaHa{%r87IianckM!Kz^rJtvohy&}j^74z zEjKDpH`awHDXSM!1AZ})<8Fcn5X>upN+pOiUdvJj+ z`w|yevu&)yUThR41`v+ej7MZ=boFvNib;h0e_l>*$~C)dcY|_x5$fmk5P9VmT_3dVVQNt zG7cBmjO6W3KX#3bo;$W} zV2l*zn9vBoOOn6|PQeUbBQV3$83^zd z3h<0lAJ7TF#0z4ub?0EN_>vHqY(e7E~@XMg)nZmO=GGk2p>xvs1) zqq)qkoxpR7@Q;ynFKdD;7|d2HM(<$z`#zPev`~hh=^y8a_~#+=Y7F?rnpUDNBd8Zw zqq?ECvfUdr<<(|+E~PFQ#DpQ9s>RZ{k5SO$T^*+nJAK&c!|SXM7ulla9{m7s-y*f$ zS}x|K<_`+u<$ulydh)0$a&pJ$9iw-Qe!Up|nkojbYJv@Ykhf0veg6OkP<-;XIzh34 zHYq8pEMPfn6nJ8B+n`86gQ+V?d(lP{s2JdKC7?tT^nIo-;R8<9ahWUvpvP%{vD4Ps zmUG`NPitd*sKN$y&eo6I*ZL=C^;lD3@VX{ajN)4F5Pv^I3`N(dyqxT$fzg6>Cr!nDxP7>xngItDc@!}{#ga-={C6$uIM0#!>u267x z-=25$%gvh5FKT6;p#VXKx&?VEH_-;-<>6fIEsb&~tKQY9B)i$&se*_|{Yao&x>d)E zbYA3>w|@^iypn}G#~N%-cVFXV>*ZEWh???p?aT?XCVrN(XVP#d>Rw@xwhCX4F3l_w z-XT2}i0^%?V-AHkcB(jck+vm`;%|D8wyV{o<- zAf@L<|G_{^0xFlXmIF!ZEoT5+YigZHa3bNMihqPrO}GXb(nMeC7fh?YP$)D|>l`NE zUZ8mxK#nq>FZuWbn>I53LLa^OdsPr#Z}02NGb=X6O6-$%XtHu#LmA&rT0CRkGI06~uuc@&%^)QE|%928V=riyA` zhkpa@AfcyIdrRy+3Rj5X;2cj0R7>{TK!t5;ny%hGG4heQj2whwEa_QUdiZ5baJrZsB*Txe{JdQkzYgK2AHGy@>ChsfxtR>Kj<~v!Xd%%XV4E|6v0Ir zC(F)hBinKIl zg1%a#6?vs?F=v20LBwfy==p~52)DzYpD|el-Sm(4(8n@Gl7MLyZ%_E z#AWZhc4lt;`!M|_33;D1#RAu~fqzzs(6fsDY%rsCyLlyeowEFH)hh&T%P{0+Akd|O z&*@Be)-fKn1h~H{(?eF5OtU~9G(GC&`oL~dy?jv<5Lq(zcS!Q+V=|%L&d!VmTDeq= z@y6i{Vj@kzb#WCwV1mgsX@BV%n?Xx|XKeWaE_bWAn4t(sk9k5lSRf7{S$_bJ&gXK= zD4%)EfQpvB@i^Tma$o<>g5yYQfQuCSvu}atcX35Df#Q4XW93tNBduwhgW=#K;x{z9 zG9R7Goc5~xxy(DB*satXwSJ`iOg#{vQl|(K<&j@`nAq*RNoyL7u8`^_vjD2DRpy(~ z&gjMKm!nssU1?lH*O^MW5PyW&SnXD@_Pq)46psV+mPYEMbV@Yzz|`Q1NvTQ7lP<`% zdP08fwolMgS||5nqRoYGgN@Ve+-*e}9KfzOg8{U|lLj;CRyAQv{VZUE>-?YqDr<^_ zcWa_!ZPWIBl(+ z`*3jx4R=TLl#In+AdJ~e>S|054j5rB=V&f!^cS?UdLnHhnDd|dk^WO(hY73x;{0Bm z-;48mY3ui5NM1vcRieGSN|p+V3g)`h|Gs~fHqRy=pnreK7r*1TTvuTAvL;@69xK$v zfoq4abSq0?R#O~TiGRAPP=q}M(-j(#SS8@=4$HEUF9{1!NoWD6#pFjqwU!|55g@b9 z(8z%t2XboS{dJWpk2uzAH9D$MFr6Oi^iap59gB8)=mXMSUe#ov$fM}r36EmNyF?hQ zZs$jsiPO&R*j{W7%GPk4(PnEwR)Hwuv>u~z761VV4rj>AoR&M`vRo4lkW3djjVPz;V?6ot^~+cNShjM`A&=QoaF*+_5tmgp z-yWnDN4Nx^<;e?CBo;9P0i9wG2EY@q8K49}joWCNBD=qEvK15VP*^nz`vV5p*W@c# zJ%@}OGFl5{WPdKrvcu$^1Cc8BS;1*)idit5FW&@ADDUO2SG5H$80>8h2cLdR#`-3T z(vPolFb;-;_gLLBgkx{8x3xVI+E8xOciR4XDDAuz70FiNd!oo#1z8KpU_!`+)H==4 zwDGKd(W(imL$}5<6tmfR`8_N+^=h*&k47r`PZ1G3sDB4kRcOgRuf{6Cs?h0=!dK<7 z+Q6(Lv2|!m2I39^5UTPi-cklJ2&VWNk;j>Y!?AhC<{g_aviYsLMQHGsr>oAYQ zJU<5WY=76Kk&B^=mSGOrp(p;I)#!{en};ad z8=Md`VZ~d-x-yntvT9wzH0zZ+A?QC}rRkfzO zd$%s~oLpuKnReUUx^ms#=A}?_9j|-pety6$&um0Xm_R~O0%|gZuV74q^!wYh+yy&x zcgLKoxpSy;He}~&?(U8m0Ow^>K(X$z#G1m0)!YuVf4v*FBzjoqyI^)IvWxB2&D66js8^Sxs@7q< zOe&OR76!orKqkPFv>XcdJ(Spq4do(E@stKqmn4Uz<}#j+*g=#83lNLlbu&W*q>}B| zO!R;We@21N0E`g%g=hBUOL9p*i%MB*3~>S3Hiu=a@eK|FFpUvo0EU8NMi_DgCJ0>; z!4Q2wNqYF^%^)V?V=J!Pp96CT|F%Z~_1a-AhngH}TIJx;#TKjb4rsOxJFV4et&aaX z{_C{XbykL6Hw6ysA!e9WxUe3~!8TFCR~OMkVXQ!8TTLOs&R4rldfsrGG2lDxU4?e;^i5N+FjU72q7v{rF22=ONK{#kj<@gf8n@>M$z_p)!J&b`jmj_%QA32ePXl&eWFV6H>44#loDwPp0`@Swwk4i7p!=Z`S&#xtc@L4oTmU6?C1cEuZ0= z!p4r&&7a_4yUug^@?P$;R~5I)1&pwp+LAWaHCl$#Nu5sWbW*32K17}LbzR7IhNmky zG`II=?$?yxv$t}kf2(r6LfGJ+T(1W@qrFo#?y0Kb0Fnbp4j?&z^zZ=E_U2|?80S>Z zuVS;$wa}xw`{Jq0rcWSV%yNc%Q)ec17mpLxmtJl#2 zeBT2?+=q2rwp%+3uv2iHg5wk%r{MIY;B3{!To(X3LXda!f96(I>r|Rl_1FeqzE_`8N}pGNWGc8PGc78q|QjP`_p5RS!f@vPE+E^f6{~lLgToBL4dfWo|0a+%kJMP z#i5{WC`T80vrs2VC=`fEK)oyA$B_)GnLvK^5);fZ48Rx$LjSOenW4s4QdFjpfiS{e z-%7=OfIDU7f1>{YAsM0>PcZsQWjbz-Yb>z17oqde0&8^L?I|+W_6p{WFk+qpq z2lE}wcQD_<{D%nhx9bA=Gdz8V`2ID-0UQVDKq0tJn7^W(HfI_S0IX$5*s;?gBlJrY8Bqphtq*gy$p-i&_-18I7$Go;gY3SO zKNKx3f4~h60zfDTD4C+@lE5%TFak3q?>RXh>v-(4{CI`EQk5I8T*PWdg+lhas3Mwr zprvM~uPplJs_LExE^Do~G&)N2T&}IOQG)J^X7k|FifwQ1ylfPuf1qx8@y*&R2vT_h zv9dOz$hbotBps)nS9(U0sdK6FK!_qt{eEu! zG7cjSP)NO5{skhw`PhkGCwgs<8Qi2fo$$v9vKI|GAvD9qWP0w+kRJz~t!jm4R?`th zo4P?uDQ0xtAkK_-yGpbC7_GF#B7LT8yH@Xjk2u5uQ+Bnyrsy;}$03(-NMm7_<}v@y zf9BZlSh-3hc6Oz((V@eamzEaVqb057n3X-4Xa4=-K88| zS9!485G;L_Na;O=NiXC0WI$}!aM=GMoZT<9oAU3WJ+ zT>SO5#OMzv;?R9?7A!kbxw{e0Y05cGe>tZq=QPz5nt#<0>i!JP=`~U*CObiTvw?L= ze`M0t8+paE8S>y(9vjs}^*4Qqh?zpA`dRO&IcrI%cch9hU?XAA3+*q>{u)e>4Jw za@mF$fpk)sMTpI4;2UX?0(yfYfDcPQVX z{0E5gw>BH%sSA|2LQM6n`j5rXRq^=X} z28N+Pu-h6dvcv~Ci=J?2n78cA>@e*E#I);7?LEM<4jnpl=+L1IV;rau5*r5L0UCZJ;l&3NdwnW|;WmZ^2yCFL;f>L->g`)h zV1W5T75Uy$3>A8BQL~QFZ)G0bNOh@v6?4naa|A@k?I~P%v;82Tg5ncM+S?9FEm&F)o`NUIVOhPvC^cR!H#XY{iYkKZ z<;6o)iK}EqdR}s0j#1Whv+dMGGgT`u2~+$wCVqQFR?&w2hI@86gM^?UUw`=q%oXp& z_EtR%w+*E|qVg-1e~l7##cZIQt~=Np=!kIhkS~-Ou)-pdw^tleGQrUt`TKLOtqnS$ zZ1x}}s$8b_&1Z=DIU*cO!blth!@+;YC^kF#gT~$rMP~^42pJ@_gm`%(+G?fgPzq?q}-JNG=|z7pY5Rv!~1ni<3zU;-A;5n(Y^kn zd$%T%s+2*8Gzi2HJIQKY*`^0Zv=n0LL6)c{VdwkvbsI2ZKWZ z!6EgL2cF!_ur~ub5J(n?&=YT;htRu1e%gzeyQeya$Olns2H9*QZIE{8K9AolQ@Knxmc^7 z8U`36euEH6-M&JIqm4^)F++fb$P+uoPf`xZJUe3rlHyLwDK%_^f+Q1I`u5(& zB>~UD=NTe^hMaADnoOkYhQNw)4=7I_8Nyj-f1cyOgE2$W=SR1agqC9x7^b2U6Yzvk z0Ao()kYi8Mn#_}&K}^Z7iej<#$@FP5av-+9d=ES*CSZ&}h$0PNZ!n+Hm`kZEkS|Ox zBSNCqP%;CuOSJ%yzX3jqEhw`Hp=(6IjTpBaAeH+EWGujc8x(oqo26RSShe#6|(Z857WEgZ!my3O+s6L$^Y)>%O_O>R^Z!$7Jle;UVh(&ALz z{v8!nyLaKIm{RQA6rG#mnwn_Wm5uB)U3c#o3&p70;>N8}YdJ4z2#wOkykij#tuhqEQzBBQDSedIc5%|LPkxAQi8s0^jiMqKr& z+ZmXgsmIdP)9$XIv$r^Vi?g>pMte)YhiXD#+sU93&+4pNHTg@fjaO$C&MpwQrj)NM zlHF~Jv!SuY;S70K=OH3K9CtN{RW{W(zEyud1y9D52DXScPf|6we^uYBBc3gd*+E+e zZ5_0A(AGg)2W=g+{khQgr%+S{V|C2#pApD=U9suQra&?#xRQbQSI4EYnN>0AQ+=z_ z26f5~s}bi4P%{~Zi|Xd!rGu9aUOIT`;N^pXmz7CJ;-Czj^h3ijM|VfWi~9|XUNwcq zN}zxYyRjN5l1;P$e?<8cOwXkHG#By4zISvtHZ(hj7EF{gP=>8V54%!TOMtJs6)&SF+0Tk7!mVB z4IDk%Y>LdM*<|-v5k>>{4%J`2R-ZfD0oSD=B`OVwUGc0Qf0^^XM$)cdW9uuL|2vxm zolUT{P4Guwxp!d4fgJ~S?lstXuu+6YTTK!8lCUcAc#c=YJF1C0^R%&0l~kLb>b|4p{T zZ5-a-&Z28?c8vzoCir74!Y-C~PkeDy6aHB3K~@e0?TcS$J=F8! zNap>)1O${`jiGl1keH+b`{X!ei1)`jb06f+JaVM6-qk6`ant_J*W{wBI#EkrSk0bX z-lmmDf2|&6lj(kBq+7Al_!R}KCvARU2I`%f;E0kj9l{EqTPyA^YS!`eXKD+6P$|l4 zc>1$ra!tMEE~II1y?BnAv|BK4*>4nUAglOomU+!jIXRYGT?{2n)dtA|ghJQaa)aRI764iEpso3)0+t$fZ>BGuAdqGX!p%UL`zYPoUA25iKHUPha z>;%s-AMCxBKi(pA2*d2?c$A?V zlNVSZf35At-O~LVY+z1_|9e`*2EV0xhZQL%_Z-GF-Xt-#jhw|_Fh6!Tj{>zmDw_7DcEri=Skt3IHzm+1S6?@B)q<@cH(RI`FV%wX z#}|TG&I`9KXQ}2~+kTL1TMDo3NVIYge^GrprP3*t9hFLR{!)3_#vq%DR?E+; zg3l0u>haBtGNew~m_DroW5jO|QpacfhU)V_Sq2;)AF)ev@#*N(9yp)TIPd|VVFoz7 zN)GS96Ox00NHPb20b!{=5;~l=awLRJ$ z$V6OzkH-t|5$y5M$S~_3zyQi0gH3ft9YQWR>}d`oY&>hN{^({~-+L+`5j)_MOi#O7 zD_qxkXi#LgCi$5XnK<&|0CG&GLNW&(-Q!Em)IpL8kN7d(xS&^vsOxmgaY(VNCV$8H zeA^vBNX5A719sHVXS&FvTj+7%Wn}m6_&a8B>{5(ShcrXZ%Kg@kPaD#(j?~*(RClvbm`ih1jppjss@_(HdN7DDw z6JHg~5cC0_NJg8~5=|v-XI`6HMbwU%g&yR{X_&q>+&eD`0MEe_LS<`mfS3WsQK)=S z$7n($1g__5ta9eH@2B<}MagODQ`MF_J=Jf~BZVS31q{yx8ZjJ>vs#z{A5SJo4v8RsL!&EjtyE05Q9m=6MD|xT zLFxr9)=c)LSh4vDx+F2-SbeT^sA7kUK`2tCS9CTp$qtf}FBU;EeU~KbaIEGyW+;-} z#Io=VE+mN>W^=-neQJzkbDUn1rSmOE{-K7bYy|U|aWI3|nqSf=LLLW1 zXjx3HsVQWaL^_r*(5ut=y}zea1P8Xr_z^gBb-pj;PT1TDTYt}S$C_evINi2|TYXu{ zDSOvfma(zIo>9vCvzBUKL+8BjocEpc{yHs*$K#{zocGrTcy&Pum@@r97>R z&$+uX;BE}K8w2jffK#E@N`-be2HcGScVoca7;wyZ?U=EMgvWpIv(JYb!}Ti~Sy0R)WG2u@SKljxFokO0hB zjHF*UhgaGq$44*#4F98InO&nuod7cqdCUN0*+DPs_kY~Buomv{@OIQW@oVGRtys8L zCljJ|g91?xLE_Gye(c#()dnw3XiXuj5KlNg9)P!963^<)1g#NuXH@z?WZ&zW6zZCl zdelc65O$PxSqp6fybB(u@a@NVUQD`FmUURjkqPwBx9=7rE+eTw=g-1G?XoVF>4BW1 zd8qu7e1G{O?*XX<#1IHPmwIMJ$ipF)SDB={T@oW+3O6~4nz#2TgVrucc$2Wnt){z^ zl|2Z``;f)N$xVB?X)vbJJm%k7NXdGUXr4wq48gRsRg(l+@=U4Ot|XYu7HqD0mj%*a zjFOErc%!X>GRVFXQA-4n*>z)peVJOYwInKx%zsjA$`NHsAwtfPBnby5P28P)+xtf_q2u1Py9 zx#2s+t1r4+$(E${Y8kDbwFx4UblIOmV+_I~LP*-bX<$oOp}rsV3sd(RB-T z38JdTYW1CH5pue5MCTBbb0pZV^a6y_R0Yai&t77b6Xmn+ZA4fVu}h**WL4U0O7+vz z!hBapHfGs1P|19hnxtM%grrPs^(O@DzklGJf%LmM9=d0D6P?-aVL^^OXQ^DBxz`pS z`QS!<*!9pF*Ht#|H09JRvDyplU7@boHS1ctC(=<<`y<6;HbJY%$As`|0jVN|IQi)0 zqmz$LK05hWkdH5#a*>{3##f1boYl9FGWg|d+syk}FO7#^E9c(Njb=$~L4zjKfPa~s z1<8ET=o&=}?O}n587s)e`TGfJmzSlnuPR|NpQ%aMK7dMZfil*V=j=9xTo*ehiE`AP z>m)7I=0ny6K0scb;$GtIJSdXPDLulsU`lDQrY5$OgnRGAj*MYi9?R$G3Mjo|K&G)b zQzye9$f94}U_Jv7%*8~>AZ--TNPiy7C){iZ7^h(0?G=}8_6LfBMwQ||=tR}BEOT@z%CMy_F#RupuazMD0lCztb`F~?y#Z7ez zgi|0MumbU_DWLcXrB`uyeAJO0>DsHgTD4|Ry4NP-`^u~-8<~awRZ3BWc!bflzMpt} zlwJnWVQLlD*AJcZmE)7kEWJy(1C-sU4h9sWxbb)M`eVptf^;GhDUo*r#Kk zOW0@g#xB0KF_Ed2t1nBdwcEu-G-;--fh_6qQQw+=vDtKMT7A_c1cQz`w$XsSl5M2m z%j#P)Z`qYy>d~x1R~DX(Yl*sTQkLl3m`rG-f>;4KrZLwFw+zE^w|^|!F}+SnBeSpA zlru6{$}VN(_U>qRB%X_bPzD3}H%1<+46EDKA3uw*vbVK4+Lke=WQ-R{te%y_03*W9 zlZzz&jQQ*Yj!{sKHha!t#FfQ*Pnwp8gEz#_KhSIXG{PP_MUj3fB|tgSjeensDm?x^ zRGUjo&^hurjVii7fq#tu9{S=d7sv=8o0*Tk_n7_C{EjWEC3D~UrbB6Z+P08=C7U2! z`s-Ija5WcgyBie7;IAgn}v!6r}s*Yiq?2s1A zu)Jri##q{dR<(?6xKbY02Mf=(n_>qjVRH&2jy)Vg($#;s+<(prV6C09ZFbrQwymgq z7shG@;Busz=O)b>xWaW|R@uS3^@VqJ>TN^8mLRWI>Fp1H{3M0=!Sdiy)BSq29Q0nU z)DBv(V56C)@R{QM@loAn`_?+M(QAK~?yCl5ZRj*9s@ItF7xRVY+-qP;HOqJAeDh-G zj^a@|0np+?et&~j|E#qx?-cl-sld0h8apN3Dd|p0|Dj6y1A&7(O+hcDTiw3L@ikJj z-Bl$owX@nm_?NHGq%YrwYV8w|?#0JsLYITY5-E+IjCK8VP}QsEzy?E>2{u8bMvqLt zlFp4#ACfD7M}gU7^k*M}rUdYjC(3Fw67so1{{%L^xDbmm0+=eoB z{t;Z9p&J^rbdrqBc{Z1QmuH~MKdlEuOjX$=aqJz|HKj7`)IE9ci>x7x|(wjs4@Q?2gU^02(OU%Y4v z$)ZrhHN*iN2WT}1#;T@P!*A-z0iGTcZi(0m{WpL%v+=Gltvp(5q*f%A0ffic9s_WQ|qmt;Q>>89b$opU2}lW(-pzwa4Ms*Wus@voPjD>`Op?NMphW zdw)CI-Bq>f7OgDRMH(G)F0lHSO@UJ+TY3xQptJu`*1&2^evJ79qrl%d!2GTF!;aUh zt{WJAsojqJJ{_Yiv)7cRoE{{UBnRIzFv<*pi72>8jheZeKaTG^zHh_#ORKz`>awDQ z#e52m|EQ4htERXWa${Foh3%Q8sJ_Wi-z^MCF4 z>L04N;wa_&+?>)X$7%bk0W7^O?|O z84$`sz{^S{#zqz*Po71l=QT5_+btiZCx2kb5-^ht)00R?YDO& zsQVY-Q26#?XyPO;IJ4I zzPnQcy1sl(8@0n+84Zo6wSQ@`jwmZP)HcA%pwB$C4YS8d8io`*C5O0=6g8>!ac7tB zcKWz_=a~Cyr_33)C?7MM@2uuPh_~yj8w2?f^U*%9w zSM(-EhIONz;lUhZ+q#9xXni+)6}l^?+?}u&r1e%~95yLL=uHKuYkwiAMg0{Mxn~Vo z3T7D_yuVB3<~VE*h!hQZr&94mpOL#WA}6`pUK+38j`?>s_8p_b-nYRSyg68Kq<_on zEdL$D0Q1GZ|5x@@=6B&R=uq!HWFIimkHoNB8dP%it85ne0kvqkL~v_4lbeK9!f*De$@MyYsH5_3j~^Q5rtk9yu^wetz*l{_ za|d_s;LaV~xq~}*aHc7D?yv^vY^O0?o`MVVqEhWGlQy6%*V2mC4cW$qy*q57_rC2M zrLkFCJPLGqF!16)rWq7KDLGmIkOM~N2q3`*C60pWC9)7jn1A}0#7xg>R(>9#Kw3?b z#xW(#MM-hYb*c3v+ht|zN$#BuNY8E3@Ag{ zuNe#iM5fsjX*WNNIh{<>XP>3Bq3k5P;VPT{tlbdB7E%TBmD2W=(_+ob6H2ef(7VbL zafG}8Dx{aAr+=+?Y&JwIk61N7Rz-8)!lp)Ua;+;=OoUzR5V-5OYF19C zHD9`Y-DC+_*DS4A`(@>tuL-HX(DGvr+{fG0BXy?7^$l*#)?$}x+J;?8{2UOU&cpUvtDZMqB7> zl4ly^6n~2l$Tk7Fm>9A0Gy`Xd%LGMOpS6& z(W6ne0X&u)ZVwvs)HmQnlcb!vKs?aLU__Nse^Va`ZpRkHLq6cN73!;!v*qEIK3HWD z3x7-~*U`XO_Igj=>vjKfvniyKo})id#Hw!0wpseR4f`D5FvPhJr5mu_7P@%D&Zz02 z^Y+L_xFoZ8fx_HI(VOF1zk{Z3#c|lD1Cd-z_nR?5m|ZMnNSw%K~o`P^nr`O#KW z0Fg5UeU-Vg6DvxqujsP7uQOWm1*676OliDqXfe zlqbAU_3ep1bg!b&gvP`NlmKrAF&SPG(Zd|^8TG*p4w6f@01`F3fWd`wq}0GSY3l|u z@(Wk(X@Ur?rAX9-q1e+A7J^Tg!+#6}lwKhp#GxV^PZE;SZom|>=Mf4c>?KW6@?6rN z6%(Y7k)ChlgXaJf(UQyz$B=de6+=TlFc#6q2R1##dhCR9Fo)cm$>QR%6s&r9;+Y47 z07c*i63zgp01*~PIs+ZLg&q$Ux~soq#AGxPV<6}jc`--6n)U_w@ca3Na(}Z@EmY8j z89;x>Fc6)k$(_VHImG_PCHai`Oda=Nrdt|QJ}b~5CYDBciU|x-g641`J_&*mfb5d6 z*z*u$lQ;+#DWT~^55dh0dox){d@&H?la~2}v%XPV5z3iazrT9!##FGh% z1SdW`J`$gP0q6w0gA825Ab&Y8e z{osR?l7qdi;owv=gMV^PgyEp_6mL8ZeKfs}MtH}g4BhbAf=yrCUfqU&PssMo#QSG= ze!V@L(<^>6_HVD??GBTW@&lWmdGh1Dxy4+e+0EhLOp3B<0^ULPyUcX(`n&vbNSSQl zgW|ybeTTFoIXwrEp|=PfD7wUxPuD1V!#JKx-fO&2w^I>;(ti~vdvt-5$v;Drm?SOB z_&aJ8Dt6HuDV{JT7ZFrSfm;&xOX7{db*Z|e&MsnIp+mB<()pM zR-VUW0n<|6<9`;0TNs6fp}Y)Q4!LdQm$=PQxhA9{k4l-@{RAS+k8PU@Cr^o59~Dh| zQ#<0+rQH?=8NK?tk*gML1-aQmt$2B286Kx9%3RT9gjvoDw=HLRGx^%~gIwEEcx^|b z&7^2{-sVF}_TJWPXfXH=Rkfh7nHy7bwCyPoGB*8asefj5mt702j!CJ6bZt8lEofU; zOQd?Y#g)m+7V9Y!t(Kqnck8TUiJ^mm~o%XSR092?&62d#2?zJ z;!ab{-hXohBX1_yN~eRxw0eiLMR}D7j`4q6@@{4*LdjWXa(Z-0F3HDF7jO1}Jb$gUIgeBaS>^M{O9Daq3DQu%XrXDjFJ%p6NM|jf!;!RryPzOzDYV zElM=^tJ1CdcIGuk}cO$I-5<5 zFYzEXuKZGIci@n$s@3oE-De%|MN{N&b$?mXxJlYk)yubX2VvcESH82JEcCy8g+A55 z(x5G)MU-etR5}&%8*+`6m6NKD6(rRgBaCq1tjbu;>%H z!1FAq_!}4ni*BM`SG9^_tvh{mfs9`6Hic_epYR>xl_5V`NFm+CU5lVLVT^Kw^?xmZ zvhlW(J_$AEowwAFUq&ukmceTSoawqG4g!El=GvdcCl$?L^J0RsKc=4lqQHhB2j_4h zz5d4tK+lUK$dPDQro#}8vmuBXs>U3EQ!qt5t$0aL_D%{`CpMkfd_-ciDTLBW0hC<) zq?YlM+J{ecL6d5ma6ywEa?qsvjDK%mHpS5|CQw`f;iiq;HO4)mUK=AzN>|?y*Bo#w zkeg97!Ng~2nzUcT^o2YI%){JAouJmC#m9*jlfB*y6^&9hI5D5yHe`Q%5>T7O)ohz8zP=9>#lw1v+8MTC&Y5Zn}7D2^o^at z#z{0M(H^!$Teg4g(($*qhsdIPE<1lIJO6Ny&gv18Y(|?&(#K`OZR|B2(*AcfT_oSO zWp_WsB-7TIQTpcTrOCu!shIJ<9qy`J1+6Q#LT{Z+EXI!cAyygtsi<;*DQ}^+Yq+@E zoPDPYuzuZ?h~S>2D4qq{a!x`eHy# zIG!Vb1sxOUA;77MCCY$D{T?HUI)rGC5KGIX!U4Qo!UhAr#lau)vVVj|E^l%00Tc7* zK^zgD{XC)GmHFD}ID2@87>cgZ5oY5!N}~I;L_b;AZRJLhst)y&QFf@Rr>{fJ@~m}e zB>9?;TIjvnY)bo(V1&Z}Bf`a_xMLQws+Lv^LM`=veOO3uP_$h1RnXAiQAW)OErOR; z(q-C#e8?g2V0IHv34g0(o-Rr1sDlH5rPPb$r7A)JB0O3oH|)}eI2;EkY3`C_Ej>yL zk`u5k4i$>qu6&?SQNrTuZ{E>|UsJxj)s%K5;Rt7FiW!d;i;ENp8b5L)MS*wG3{czS%Q)-XT5cAFa)JzjQ{6YszkR>%ws*+bpD*loP#KGaOmn`tVL=6>VZT zvb}1S(}CF})LF0_)v;hLEMYcGuoy3WiToj$BS_MWsDk5A@(Ty(8bx9!UIBOm7hn?6 zIl$bx+<*NHGx5hbD7(PwhX$KYRg)mN=R5pmU7Vu@@jk$)GoH|Om%@q0J*^w*V?$^3 zH1Fo5%koy1XrW;Tj~9R~h==@*OY%F@wk34SBP0U?Npqot5)T$iJUY(ty6)=kf_N$k zeiyzWYgTZLr{Kx6^!+mBLl)}iG{+#Ro@uE5%zvYAFOHOwcc z@q^66<0Exz?f^1rVmQRUPJ=ic97yh%{7P&jn?hZO z(NwAHcID5xw3uuatTggPBpuN=H@BY4|1LH+_vC;784L$+RI1nNm#HD9oEY+t5Bp&l zV1KctTHo)_%~Q7=fyrdHj0dFhHVIY>#hmz%qvssYQI#>NtHr8xD~uOxSq*p3)VH#w zFk2(-rXgFG{bU9-*21HU!0>vr?xL7r9`SgNx!knfn0Z#e4hTL|+KDXlflZeHLZiVx zKw+M~W?*P`?Lh*@2*d&jaSE7x1t1{kCVyA}FGBLvT$!BI8SKU-A&B1yC6CV{8c%2H zG?h@lzX-{NxwPc^?-BIXeNUN}&dg_gfxRoWLH{^=tFNt=PXh#F3XsffnqF=FjL9L5 ziAs6Ar1AlR9wl!GkFX}`jLHmkLh2kr4lC<@9g0p)={eVJfB7~re!UtFEjH$yb{`x>%BP#5kOX8kC5&evYTM)!))c6elo{hZj214uVS+&UwWMi{w^5C}{JI^&>5vkAs)V&Qm|9?3uQ<3LE z)1zLlU9At!VtumxdaEuxz=C+clR1p8_Jg47ftT4prTx0muwmBj!?IDJrrxZP>o|;~ zDUv5$+IZnXZ-$0o4zI-i!5oB?F+2`rd>CoR=2ZFjGZ04T8q=5si@b}?$|mkdw@$a~ zu2ZMqYqdqX^0{ooz8J=d+b7bu8l^VIL;<57a>|fK!OwnXEgLeK4G3 zRCn)rLA*co4!DqE!8);zd=vIT7siwZ%g$``ZC5iEHPJ2kONr=aCR3mz+a5PFByacR zZdB-sdm0<5jUx-(L0Kl zR6~E$ZZ6PO6&@*5Uw?g7IJq@`BU@PAY0Jg=>1lJktht|%eChyoa6>dJTZ^|^ec5bn zRdu;Q*)qYUJN4y1DyFbr;qs0_*A;#51=6Ea3t!bZ`Kx8}=2k4cj@v|4wnu^5N9i}T zSe6pUY`+&@-U7kPc8~7a6cAyAuOUa^3dsNw#)eu!K-~N7lz;!EbzW)NYa6Gu3!Uj9 zU^4%PoOYoA*En*uIrB0aTh$Ms=5*_U2-nv&DI(SOcn`b6&G*nYV4j8PC~dMQi;+p< zG7cent+o&4^+Ei&`GYge6t>oAbF=2|j9OR6^A!ZLs=UPAS~KG=dYx+jPW8ET2+KC0 zrX@lilEKU%NPlrfa=76Iu`k~kvRhyJmz5ci8R`BXd)L;}HVlRTO2p&TB1nN<-nL2b zu&zP^?FD#96O&rarHj+1oy32iY#%3XZnc9ux)Ny*TNmHrbBT|?^BrKyGOeGz@9SA` z-_FXMH>7rOOR8)`-4hBoKe?1Y4FpK)K?xQp3B2TMIp*m9)&aW#^TT(2g0hY(FhN=S{pSy~ zxo4N=`Yv{Yvc39OKKEVDmCk~vG7+BIRDaklijwn>UV?qP?$gKU>&n3aBW$MUW%gFS zSkr(EEPsOBg?)K7KbQVG43OuejyX4EYkS& zu3+TdKVW03H4+CjuhvEO>H}p&w|TVgcRLUL5d+k`M($`4(BSk zamW~lnDaK=IOH0k@6Mw5&)Worcp1VEKUp;g#@cfWTTn+94aLYyaMJ0*L;flm;R`n= zC`)G>;$N=k>&5Tq$j+YKKUd+(o`vx|&3~redhV<*$jOUtHCeW5-ONa7-5r|3`%~m% z&R?kRNaEeAj02mkl;a2c*wv53`YQqX({3h&eSco7<+gjv5;tjY`5{eu_jjPqgOlR3 zNs+?i?W~EkHN6e$ZBR!WBxg3uvVX9j`bSEpKRWx^3au82K(E7AmwIVB1n}+Ya(`J+ z8ep#%2i3*w3M7_iC(!jXjRRcB~8q!4Ps8VG+ho1^=Aty^r$m zQKLV#;=x&|QvJfya%24%C96_ci4iFy+xW0X!EO0U-Qk5rTZ@AA(a#heQ3U|rd8rHl diff --git a/cli/paych.go b/cli/paych.go index cb9035024fd..92c1a13e31f 100644 --- a/cli/paych.go +++ b/cli/paych.go @@ -200,7 +200,7 @@ func paychStatus(writer io.Writer, avail *lapi.ChannelAvailableFunds) { {"From", avail.From.String()}, {"To", avail.To.String()}, {"Confirmed Amt", fmt.Sprintf("%s", types.FIL(avail.ConfirmedAmt))}, - {"Available Amt", fmt.Sprintf("%s", types.FIL(avail.AvailableAmt))}, + {"Available Amt", fmt.Sprintf("%s", types.FIL(avail.NonReservedAmt))}, {"Voucher Redeemed Amt", fmt.Sprintf("%s", types.FIL(avail.VoucherReedeemedAmt))}, {"Pending Amt", fmt.Sprintf("%s", types.FIL(avail.PendingAmt))}, {"Pending Available Amt", fmt.Sprintf("%s", types.FIL(avail.PendingAvailableAmt))}, diff --git a/documentation/en/api-v0-methods.md b/documentation/en/api-v0-methods.md index 2061d7fadb7..9444444f569 100644 --- a/documentation/en/api-v0-methods.md +++ b/documentation/en/api-v0-methods.md @@ -4061,7 +4061,7 @@ Response: "To": "f01234", "ConfirmedAmt": "0", "PendingAmt": "0", - "AvailableAmt": "0", + "NonReservedAmt": "0", "PendingAvailableAmt": "0", "PendingWaitSentinel": null, "QueuedAmt": "0", @@ -4090,7 +4090,7 @@ Response: "To": "f01234", "ConfirmedAmt": "0", "PendingAmt": "0", - "AvailableAmt": "0", + "NonReservedAmt": "0", "PendingAvailableAmt": "0", "PendingWaitSentinel": null, "QueuedAmt": "0", diff --git a/documentation/en/api-v1-unstable-methods.md b/documentation/en/api-v1-unstable-methods.md index 966a0348c49..22e85901c9a 100644 --- a/documentation/en/api-v1-unstable-methods.md +++ b/documentation/en/api-v1-unstable-methods.md @@ -4457,7 +4457,7 @@ Response: "To": "f01234", "ConfirmedAmt": "0", "PendingAmt": "0", - "AvailableAmt": "0", + "NonReservedAmt": "0", "PendingAvailableAmt": "0", "PendingWaitSentinel": null, "QueuedAmt": "0", @@ -4486,7 +4486,7 @@ Response: "To": "f01234", "ConfirmedAmt": "0", "PendingAmt": "0", - "AvailableAmt": "0", + "NonReservedAmt": "0", "PendingAvailableAmt": "0", "PendingWaitSentinel": null, "QueuedAmt": "0", diff --git a/paychmgr/manager.go b/paychmgr/manager.go index 081ef4c5d19..ea77c67efbe 100644 --- a/paychmgr/manager.go +++ b/paychmgr/manager.go @@ -151,7 +151,7 @@ func (pm *Manager) AvailableFundsByFromTo(ctx context.Context, from address.Addr To: to, ConfirmedAmt: types.NewInt(0), PendingAmt: types.NewInt(0), - AvailableAmt: types.NewInt(0), + NonReservedAmt: types.NewInt(0), PendingAvailableAmt: types.NewInt(0), PendingWaitSentinel: nil, QueuedAmt: types.NewInt(0), diff --git a/paychmgr/simple.go b/paychmgr/simple.go index 5a23c7f2c05..3d0992efec7 100644 --- a/paychmgr/simple.go +++ b/paychmgr/simple.go @@ -417,7 +417,7 @@ func (ca *channelAccessor) currentAvailableFunds(ctx context.Context, channelID To: channelInfo.to(), ConfirmedAmt: channelInfo.Amount, PendingAmt: channelInfo.PendingAmount, - AvailableAmt: channelInfo.AvailableAmount, + NonReservedAmt: channelInfo.AvailableAmount, PendingAvailableAmt: channelInfo.PendingAvailableAmount, PendingWaitSentinel: waitSentinel, QueuedAmt: queuedAmt, From ca9bcc90a5cc3d9bdf4049c238dea0f6bedca0e1 Mon Sep 17 00:00:00 2001 From: Travis Person Date: Wed, 16 Feb 2022 20:35:55 +0000 Subject: [PATCH 191/385] lotus-seed: set current network version from params allows automation to correctly set the network version for the currently built network with no variable inputs. --- cmd/lotus-seed/genesis.go | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/cmd/lotus-seed/genesis.go b/cmd/lotus-seed/genesis.go index a27cc0a2f7c..89feec33a6d 100644 --- a/cmd/lotus-seed/genesis.go +++ b/cmd/lotus-seed/genesis.go @@ -508,12 +508,19 @@ var genesisSetRemainderCmd = &cli.Command{ } var genesisSetActorVersionCmd = &cli.Command{ - Name: "set-network-version", - Usage: "Set the version that this network will start from", - ArgsUsage: " ", + Name: "set-network-version", + Usage: "Set the version that this network will start from", + Flags: []cli.Flag{ + &cli.IntFlag{ + Name: "network-version", + Usage: "network version to start genesis with", + Value: int(build.GenesisNetworkVersion), + }, + }, + ArgsUsage: "", Action: func(cctx *cli.Context) error { - if cctx.Args().Len() != 2 { - return fmt.Errorf("must specify genesis file and network version (e.g. '0'") + if cctx.Args().Len() != 1 { + return fmt.Errorf("must specify genesis file") } genf, err := homedir.Expand(cctx.Args().First()) @@ -531,16 +538,12 @@ var genesisSetActorVersionCmd = &cli.Command{ return xerrors.Errorf("unmarshal genesis template: %w", err) } - nv, err := strconv.ParseUint(cctx.Args().Get(1), 10, 64) - if err != nil { - return xerrors.Errorf("parsing network version: %w", err) - } - - if nv > uint64(build.NewestNetworkVersion) { + nv := network.Version(cctx.Int("network-version")) + if nv > build.NewestNetworkVersion { return xerrors.Errorf("invalid network version: %d", nv) } - template.NetworkVersion = network.Version(nv) + template.NetworkVersion = nv b, err = json.MarshalIndent(&template, "", " ") if err != nil { From 36aa243c5699481378bae874c7af6960541be087 Mon Sep 17 00:00:00 2001 From: Aayush Date: Wed, 16 Feb 2022 19:24:28 -0500 Subject: [PATCH 192/385] sealer: fix error message --- extern/storage-sealing/checks.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/extern/storage-sealing/checks.go b/extern/storage-sealing/checks.go index 56b0677c468..dc045ded216 100644 --- a/extern/storage-sealing/checks.go +++ b/extern/storage-sealing/checks.go @@ -214,8 +214,13 @@ func checkReplicaUpdate(ctx context.Context, maddr address.Address, si SectorInf if err != nil { return &ErrApi{xerrors.Errorf("calling StateComputeDataCommitment: %w", err)} } - if si.UpdateUnsealed == nil || !commD.Equals(*si.UpdateUnsealed) { - return &ErrBadRU{xerrors.Errorf("on chain CommD differs from sector: %s != %s", commD, si.CommD)} + + if si.UpdateUnsealed == nil { + return &ErrBadRU{xerrors.New("nil UpdateUnsealed cid after replica update")} + } + + if !commD.Equals(*si.UpdateUnsealed) { + return &ErrBadRU{xerrors.Errorf("calculated CommD differs from updated replica: %s != %s", commD, *si.UpdateUnsealed)} } if si.UpdateSealed == nil { From 355b73843c031c73134bcba2d3c1dddfac6d8379 Mon Sep 17 00:00:00 2001 From: Aayush Date: Wed, 16 Feb 2022 19:34:45 -0500 Subject: [PATCH 193/385] makefile: add make jen --- Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile b/Makefile index f7b13cc188c..f91e74e3356 100644 --- a/Makefile +++ b/Makefile @@ -345,6 +345,8 @@ gen: actors-gen type-gen method-gen cfgdoc-gen docsgen api-gen circleci @echo ">>> IF YOU'VE MODIFIED THE CLI OR CONFIG, REMEMBER TO ALSO MAKE docsgen-cli" .PHONY: gen +jen: gen + snap: lotus lotus-miner lotus-worker snapcraft # snapcraft upload ./lotus_*.snap From d835cade1509758ac74eff31803e1adfa778d516 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 16 Feb 2022 17:47:25 -0800 Subject: [PATCH 194/385] chore: update FFI Updates the FVM --- extern/filecoin-ffi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index a220a540a05..d65d3770c90 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit a220a540a05d6d683cf2b119b36e172da94c580b +Subproject commit d65d3770c90ebdb8b3282f11fdf10a84c3ef0355 From 74556edcffbd1e39eb38e54ff8e3bc43b84fe8f5 Mon Sep 17 00:00:00 2001 From: vyzo Date: Thu, 17 Feb 2022 12:52:52 +0200 Subject: [PATCH 195/385] don't fail reification on missing references --- blockstore/splitstore/splitstore_reify.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/blockstore/splitstore/splitstore_reify.go b/blockstore/splitstore/splitstore_reify.go index 14648a65217..dc44ab21c06 100644 --- a/blockstore/splitstore/splitstore_reify.go +++ b/blockstore/splitstore/splitstore_reify.go @@ -98,7 +98,7 @@ func (s *SplitStore) doReify(c cid.Cid) { s.txnLk.RLock() defer s.txnLk.RUnlock() - err := s.walkObject(c, newTmpVisitor(), + err := s.walkObjectIncomplete(c, newTmpVisitor(), func(c cid.Cid) error { if isUnitaryObject(c) { return errStopWalk @@ -137,6 +137,10 @@ func (s *SplitStore) doReify(c cid.Cid) { toreify = append(toreify, c) return nil + }, + func(missing cid.Cid) error { + log.Warnf("missing reference while reifying %s: %s", c, missing) + return errStopWalk }) if err != nil { From 6feae1993d3ddd7e4babc2b68e30962f5ca48e7d Mon Sep 17 00:00:00 2001 From: Darko Brdareski Date: Thu, 17 Feb 2022 14:24:42 +0100 Subject: [PATCH 196/385] Fix PR comments. Refactor random addr generation to use a rand seed. Remove unused lines in tests. --- chain/types/mock/chain.go | 31 ++++++++++++++++++------------- cli/chain_test.go | 23 ++++++++++++----------- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/chain/types/mock/chain.go b/chain/types/mock/chain.go index c69f7f56fad..9a911c98738 100644 --- a/chain/types/mock/chain.go +++ b/chain/types/mock/chain.go @@ -2,8 +2,8 @@ package mock import ( "context" - "crypto/rand" "fmt" + "math/rand" "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" @@ -90,19 +90,24 @@ func TipSet(blks ...*types.BlockHeader) *types.TipSet { return ts } -func RandomActorAddress() (*address.Address, error) { - bytes := make([]byte, 32) - _, err := rand.Read(bytes) - if err != nil { - return nil, err +// Generates count new addresses using the provided seed, and returns them +func RandomActorAddresses(seed int64, count int) ([]*address.Address, error) { + randAddrs := make([]*address.Address, count) + source := rand.New(rand.NewSource(seed)) + for i := 0; i < count; i++ { + bytes := make([]byte, 32) + _, err := source.Read(bytes) + if err != nil { + return nil, err + } + + addr, err := address.NewActorAddress(bytes) + if err != nil { + return nil, err + } + randAddrs[i] = &addr } - - addr, err := address.NewActorAddress(bytes) - if err != nil { - return nil, err - } - - return &addr, nil + return randAddrs, nil } func UnsignedMessage(from, to address.Address, nonce uint64) *types.Message { diff --git a/cli/chain_test.go b/cli/chain_test.go index 841cfb689f7..48c4af05de2 100644 --- a/cli/chain_test.go +++ b/cli/chain_test.go @@ -188,11 +188,11 @@ func TestChainGetMsg(t *testing.T) { app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("chain", ChainGetMsgCmd)) defer done() - from, err := mock.RandomActorAddress() + addrs, err := mock.RandomActorAddresses(12345, 2) assert.NoError(t, err) - to, err := mock.RandomActorAddress() - assert.NoError(t, err) + from := addrs[0] + to := addrs[1] msg := mock.UnsignedMessage(*from, *to, 0) @@ -283,11 +283,11 @@ func TestInspectUsage(t *testing.T) { cmd := WithCategory("chain", ChainInspectUsage) ts := mock.TipSet(mock.MkBlock(nil, 0, 0)) - from, err := mock.RandomActorAddress() + addrs, err := mock.RandomActorAddresses(12345, 2) assert.NoError(t, err) - to, err := mock.RandomActorAddress() - assert.NoError(t, err) + from := addrs[0] + to := addrs[1] msg := mock.UnsignedMessage(*from, *to, 0) msgs := []api.Message{{Cid: msg.Cid(), Message: msg}} @@ -321,6 +321,9 @@ func TestInspectUsage(t *testing.T) { // output is plaintext, had to do string matching assert.Contains(t, out, from.String()) assert.Contains(t, out, to.String()) + // check for gas by sender + assert.Contains(t, out, "By Sender") + // check for gas by method assert.Contains(t, out, "Send") }) } @@ -332,13 +335,11 @@ func TestChainList(t *testing.T) { blk.Height = 1 head := mock.TipSet(blk) - head.Height() - - from, err := mock.RandomActorAddress() + addrs, err := mock.RandomActorAddresses(12345, 2) assert.NoError(t, err) - to, err := mock.RandomActorAddress() - assert.NoError(t, err) + from := addrs[0] + to := addrs[1] msg := mock.UnsignedMessage(*from, *to, 0) msgs := []api.Message{{Cid: msg.Cid(), Message: msg}} From 7823363bba0ea96b88f1727e3409b81cbbb21863 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 17 Feb 2022 16:29:27 +0100 Subject: [PATCH 197/385] lotus-miner: Support update files in storage find --- cmd/lotus-miner/storage.go | 39 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/cmd/lotus-miner/storage.go b/cmd/lotus-miner/storage.go index 6f7a627f60e..0fea2a3a578 100644 --- a/cmd/lotus-miner/storage.go +++ b/cmd/lotus-miner/storage.go @@ -368,6 +368,7 @@ type storedSector struct { store stores.SectorStorageInfo unsealed, sealed, cache bool + update, updatecache bool } var storageFindCmd = &cli.Command{ @@ -421,6 +422,16 @@ var storageFindCmd = &cli.Command{ return xerrors.Errorf("finding cache: %w", err) } + us, err := nodeApi.StorageFindSector(ctx, sid, storiface.FTUpdate, 0, false) + if err != nil { + return xerrors.Errorf("finding sealed: %w", err) + } + + uc, err := nodeApi.StorageFindSector(ctx, sid, storiface.FTUpdateCache, 0, false) + if err != nil { + return xerrors.Errorf("finding cache: %w", err) + } + byId := map[stores.ID]*storedSector{} for _, info := range u { sts, ok := byId[info.ID] @@ -455,6 +466,28 @@ var storageFindCmd = &cli.Command{ } sts.cache = true } + for _, info := range us { + sts, ok := byId[info.ID] + if !ok { + sts = &storedSector{ + id: info.ID, + store: info, + } + byId[info.ID] = sts + } + sts.update = true + } + for _, info := range uc { + sts, ok := byId[info.ID] + if !ok { + sts = &storedSector{ + id: info.ID, + store: info, + } + byId[info.ID] = sts + } + sts.updatecache = true + } local, err := nodeApi.StorageLocal(ctx) if err != nil { @@ -480,6 +513,12 @@ var storageFindCmd = &cli.Command{ if info.cache { types += "Cache, " } + if info.update { + types += "Update, " + } + if info.updatecache { + types += "UpdateCache, " + } fmt.Printf("In %s (%s)\n", info.id, types[:len(types)-2]) fmt.Printf("\tSealing: %t; Storage: %t\n", info.store.CanSeal, info.store.CanStore) From c9748724945c6e454d3fd55516aeff9b3633a310 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 17 Feb 2022 16:35:09 +0100 Subject: [PATCH 198/385] lotus-miner: More sector-related data in info all --- cmd/lotus-miner/info_all.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cmd/lotus-miner/info_all.go b/cmd/lotus-miner/info_all.go index bd1147b2263..fa5a413e704 100644 --- a/cmd/lotus-miner/info_all.go +++ b/cmd/lotus-miner/info_all.go @@ -96,6 +96,11 @@ var infoAllCmd = &cli.Command{ fmt.Println("ERROR: ", err) } + fmt.Println("\n#: Storage Locks") + if err := storageLocks.Action(cctx); err != nil { + fmt.Println("ERROR: ", err) + } + fmt.Println("\n#: Sched Diag") if err := sealingSchedDiagCmd.Action(cctx); err != nil { fmt.Println("ERROR: ", err) @@ -192,6 +197,11 @@ var infoAllCmd = &cli.Command{ fmt.Println("ERROR: ", err) } + fmt.Println("\n#: Storage Sector List") + if err := storageListSectorsCmd.Action(cctx); err != nil { + fmt.Println("ERROR: ", err) + } + fmt.Println("\n#: Expired Sectors") if err := sectorsExpiredCmd.Action(cctx); err != nil { fmt.Println("ERROR: ", err) From 6d32a2f29950c48f3e21db57da27e03dae896261 Mon Sep 17 00:00:00 2001 From: Florian Ruen Date: Thu, 17 Feb 2022 17:35:33 +0100 Subject: [PATCH 199/385] Update client.go Bug fixed : if hitting return instead of filling with a valid value, the CLI crashed (line 796) Change return err by continue to ask a valid value again --- cli/client.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cli/client.go b/cli/client.go index 634bd18e5b4..e9a25f5208a 100644 --- a/cli/client.go +++ b/cli/client.go @@ -795,14 +795,17 @@ uiLoop: case "find-count": afmt.Print("Deals to make (1): ") dealcStr, _, err := rl.ReadLine() + if err != nil { printErr(xerrors.Errorf("reading deal count: %w", err)) continue } dealCount, err = strconv.ParseInt(string(dealcStr), 10, 64) + if err != nil { - return err + printErr(xerrors.Errorf("reading deal count: invalid number")) + continue } color.Blue(".. Picking miners") From 78817bd0014f0e751824521ce483849d8f31a7d3 Mon Sep 17 00:00:00 2001 From: Florian Ruen Date: Thu, 17 Feb 2022 17:57:42 +0100 Subject: [PATCH 200/385] Fix #8100 Bug fixed : if hitting return instead of filling with a valid value, the CLI crashed (line 796) Change return err by continue to ask a valid value again --- cli/client.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/client.go b/cli/client.go index e9a25f5208a..ae8ad857e31 100644 --- a/cli/client.go +++ b/cli/client.go @@ -801,10 +801,10 @@ uiLoop: continue } - dealCount, err = strconv.ParseInt(string(dealcStr), 10, 64) + dealCount, err = strconv.ParseInt(string(dealcStr), 10, 64) if err != nil { - printErr(xerrors.Errorf("reading deal count: invalid number")) + printErr(xerrors.Errorf("reading deal count: invalid number")) // TO DO : Use 1 as default value for number of deals ? continue } From ddd369e7319590194087f3ecf60f08ddc6713aa4 Mon Sep 17 00:00:00 2001 From: Florian Ruen Date: Thu, 17 Feb 2022 18:53:21 +0100 Subject: [PATCH 201/385] lint reported errors on CircleCI Commit to fix lint reported errors during tests on CircleCI (remove blank lines x2) --- cli/client.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cli/client.go b/cli/client.go index ae8ad857e31..68d57376d7c 100644 --- a/cli/client.go +++ b/cli/client.go @@ -795,16 +795,14 @@ uiLoop: case "find-count": afmt.Print("Deals to make (1): ") dealcStr, _, err := rl.ReadLine() - if err != nil { printErr(xerrors.Errorf("reading deal count: %w", err)) continue } dealCount, err = strconv.ParseInt(string(dealcStr), 10, 64) - if err != nil { - printErr(xerrors.Errorf("reading deal count: invalid number")) // TO DO : Use 1 as default value for number of deals ? + printErr(xerrors.Errorf("reading deal count: invalid number")) continue } From a20c6cb04b634508c34f5f60570084b91c69b022 Mon Sep 17 00:00:00 2001 From: vyzo Date: Thu, 17 Feb 2022 19:56:50 +0200 Subject: [PATCH 202/385] temporarily disable reification big reifications can use a lot of memory during sync apparently. --- blockstore/splitstore/splitstore_reify.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/blockstore/splitstore/splitstore_reify.go b/blockstore/splitstore/splitstore_reify.go index dc44ab21c06..6529007471d 100644 --- a/blockstore/splitstore/splitstore_reify.go +++ b/blockstore/splitstore/splitstore_reify.go @@ -10,7 +10,13 @@ import ( cid "github.com/ipfs/go-cid" ) +var EnableReification = false + func (s *SplitStore) reifyColdObject(c cid.Cid) { + if !EnableReification { + return + } + if !s.isWarm() { return } From 6ce93210949f81adf1e1db45396c08c71f052b1c Mon Sep 17 00:00:00 2001 From: Florian Ruen Date: Thu, 17 Feb 2022 19:01:52 +0100 Subject: [PATCH 203/385] lint reported errors on CircleCI Commit to fix lint reported errors during tests on CircleCI (remove trailling whitespace) --- cli/client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/client.go b/cli/client.go index 68d57376d7c..dc4ab86e630 100644 --- a/cli/client.go +++ b/cli/client.go @@ -800,7 +800,7 @@ uiLoop: continue } - dealCount, err = strconv.ParseInt(string(dealcStr), 10, 64) + dealCount, err = strconv.ParseInt(string(dealcStr), 10, 64) if err != nil { printErr(xerrors.Errorf("reading deal count: invalid number")) continue From 899a65ae870d84deff4ed06735808a0b26ad3fb1 Mon Sep 17 00:00:00 2001 From: vyzo Date: Thu, 17 Feb 2022 20:13:46 +0200 Subject: [PATCH 204/385] fix test --- blockstore/splitstore/splitstore_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/blockstore/splitstore/splitstore_test.go b/blockstore/splitstore/splitstore_test.go index 6b7e60e6c50..c7f9cb6fc2f 100644 --- a/blockstore/splitstore/splitstore_test.go +++ b/blockstore/splitstore/splitstore_test.go @@ -496,6 +496,7 @@ func testSplitStoreReification(t *testing.T, f func(context.Context, blockstore. } func TestSplitStoreReification(t *testing.T) { + EnableReification = true t.Log("test reification with Has") testSplitStoreReification(t, func(ctx context.Context, s blockstore.Blockstore, c cid.Cid) error { _, err := s.Has(ctx, c) From f6e545bce5c698fab1337cdb9fed0cb5694575f1 Mon Sep 17 00:00:00 2001 From: Jennifer Wang Date: Wed, 16 Feb 2022 19:31:45 -0500 Subject: [PATCH 205/385] typo in variable name --- cmd/lotus-seal-worker/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/lotus-seal-worker/main.go b/cmd/lotus-seal-worker/main.go index 2116dd228d3..9e6843dbf42 100644 --- a/cmd/lotus-seal-worker/main.go +++ b/cmd/lotus-seal-worker/main.go @@ -283,7 +283,7 @@ var runCmd = &cli.Command{ if cctx.Bool("commit") { taskTypes = append(taskTypes, sealtasks.TTCommit2) } - if cctx.Bool("replicaupdate") { + if cctx.Bool("replica-update") { taskTypes = append(taskTypes, sealtasks.TTReplicaUpdate) } if cctx.Bool("prove-replica-update2") { From e3f5b7c59f36875123b4ac6bcd57e4975d1a5580 Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Fri, 18 Feb 2022 14:00:01 +0400 Subject: [PATCH 206/385] update dagstore top level index db --- api/api_storage.go | 3 -- api/proxy_gen.go | 13 -------- build/openrpc/full.json.gz | Bin 26585 -> 26588 bytes build/openrpc/miner.json.gz | Bin 13088 -> 13010 bytes build/openrpc/worker.json.gz | Bin 3917 -> 3917 bytes cmd/lotus-miner/dagstore.go | 36 ----------------------- documentation/en/api-v0-methods-miner.md | 11 ------- documentation/en/cli-lotus-miner.md | 15 ---------- go.mod | 3 +- go.sum | 8 ++--- markets/dagstore/wrapper.go | 10 ++----- markets/dagstore/wrapper_test.go | 2 +- node/impl/storminer.go | 15 +--------- 13 files changed, 7 insertions(+), 109 deletions(-) diff --git a/api/api_storage.go b/api/api_storage.go index decd534d683..bccb7baf9c1 100644 --- a/api/api_storage.go +++ b/api/api_storage.go @@ -226,9 +226,6 @@ type StorageMiner interface { // IndexerAnnounceAllDeals informs the indexer nodes aboutall active deals. IndexerAnnounceAllDeals(ctx context.Context) error //perm:admin - // DagstorePieceIndexSize returns the size of the piece index. - DagstorePieceIndexSize(ctx context.Context) (int64, error) //perm:admin - // DagstoreLookupPieces returns information about shards that contain the given CID. DagstoreLookupPieces(ctx context.Context, cid cid.Cid) ([]DagstoreShardInfo, error) //perm:admin diff --git a/api/proxy_gen.go b/api/proxy_gen.go index a4024ab729a..d0d4757099f 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -647,8 +647,6 @@ type StorageMinerStruct struct { DagstoreLookupPieces func(p0 context.Context, p1 cid.Cid) ([]DagstoreShardInfo, error) `perm:"admin"` - DagstorePieceIndexSize func(p0 context.Context) (int64, error) `perm:"admin"` - DagstoreRecoverShard func(p0 context.Context, p1 string) error `perm:"write"` DealsConsiderOfflineRetrievalDeals func(p0 context.Context) (bool, error) `perm:"admin"` @@ -3876,17 +3874,6 @@ func (s *StorageMinerStub) DagstoreLookupPieces(p0 context.Context, p1 cid.Cid) return *new([]DagstoreShardInfo), ErrNotSupported } -func (s *StorageMinerStruct) DagstorePieceIndexSize(p0 context.Context) (int64, error) { - if s.Internal.DagstorePieceIndexSize == nil { - return 0, ErrNotSupported - } - return s.Internal.DagstorePieceIndexSize(p0) -} - -func (s *StorageMinerStub) DagstorePieceIndexSize(p0 context.Context) (int64, error) { - return 0, ErrNotSupported -} - func (s *StorageMinerStruct) DagstoreRecoverShard(p0 context.Context, p1 string) error { if s.Internal.DagstoreRecoverShard == nil { return ErrNotSupported diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 7ca70d7d9a7bfd719c101badd45b7df84a32d2f5..7ea7df180ebeb98e5d18a7e2193808213a17cda1 100644 GIT binary patch delta 24118 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 delta 24057 zcmV)-K!?BF&jH!b0kHN00gjXR0*rqz8dlih40%`CROz@SA@)HeW*Ga0H@S8z%dty zRV-%JVF>ZjgtAu-##rF6g=pi_|Vg77)F@mFAJ|3|vG!Orxw||H6g3iOg#`6hU zOh!8sJc<{)ag27huXiN;OqQw!irt~~W0MS9n=czA!#l*KtnVfmlG=Yu1+8*r;hJy?2T_M@}A7^h*BT6TgHu-SyCP1EOU6=Vb_>9RRjR_y@y&f*BoH+_` zJ4e80Oit-J*R;QU8yJ7TUJVEGuY&~_M5_s$!bnWTK0mY~`5EEqj1Tq(n}gxtz5XG6 zF-eJYflJRQm8087+X>+hh%q=tXUIc1}A6-nz zIbs~nLp43*BtOSf+v;y=B#ILlNcWE*p@!`MGV~T9`N>*3nTmhi_)-2T)!!EGsnnb< zt+{Ul%+Z|vNbcKv*9`Xc0~kecA-iKtgZnW2C3)F`=}ek-WIU72-Iy<|q2)v}5olA^ zlrxR!qSP_1zm|+0AKRE)QKA!v=9J~R)pT9W*Z$F)ZcW*8(jz7KwAKsjw@4tI<4vs&9 zeQZ3pm_8NeEf7F>gC8@d=eDQ+J`5SWcQpO<$+rIQJQ6K>9vjjVHi@JA9S zB+SeUYI;`QMs#le{wS8ND);-7m!}b$<9Mzge30=+ zgFWSBkdv}(1P=#?$46xwev?`~EPoq(7ejlFyzna5Z~a3eqlZ5P!+|u0lx(o`LiGFv z4zb_kB5UjYFeiOC;HhRpTZ_e*3mvNJIb{QM%}Lg_rDQ(Zw4)b*753J1yQ}Mhw(p5v zldY>I0-zs9kDBU_+(s=(+-{4`5Yld`x~01MQq5_>^>@NPKJUZMX0!L<9e*N-;qHD1 zUB5bXOLtOMfHq(#51aTwh9Vde_Oa?6r+BdjyVyc6PQy-VS*`yt77I zyW3VenjMo13A|QS)+wPnt!)CY-_YVIc=F|Id&QkL({KVQrQ80{QFVW;)q2KVVZ%)A zm&q+DFOKB)lft{bDeuDYT4{rxRNk;8x5E*e@rdk&y%$~9DjrFU+)A% zSLxMsf|N$ld}B3!0x$I)3HV6-`|^Wp58Ibko((wfMOk@KzDj&)H z);%vr&ALaZkJtdV@HhrtRW&Rga*I_bfWx5~|(ue%)P5WsO;GW2hEw3MZ_ucKYSP zDxmGnrc5wW-0;~7YJZ2%EPePx5N=oc^`E^*&_A3(Vrz8qS+ml~=yg;zvQMH9g6CyQ zhR;&fBIKR4p(1pRBK|83!(ai#I*{iW7$6Aw$QQzXin!dSza&COWamyGp?rp-Ay5ZA zN$hC-~n>A~*X1;QRaH@&6`|`N6&{ynk>>z<>WffByX0^XLDoE9!sw z*_o#NnZ|*yy8-_EqS$}J5B8r9f$YQ+zJFl+z5n#Mzohynw;8BS{ee@U6rQ6mPJcTx87#c`w^(WttIJ>YC`{P6`-nazm45G z0#lXjb-y9yd4IVLrCT>cFtx6#$$OOcwLb&JiMrN7U@o5Z?gYyAD;t5bKjA3SBea@q zF(}z(9IpY|9VL&^{2d6PeCO;ScbTt%(klkW(7TebIX%an9Lr8cl}b;3Npc6x2~Ey` zSC=0eN45zi&&3dA4L}e;jv`g`k|bxf6Bkc^V(>oXDt~v7)yeVuBF9Hd(txPZJy`T2 z#1k?>}0i*)lOF5FIoMf>CohR$U3JoS9Obhl_d7lA10WeEL4A3oR*;b`H5%y>{62+t~jjVpS zTnvep41aD!Jp{=;7bLq)hf&`n=ywz&2>N}TxE6H!gK3(pCb=QnGo5?Md6SuVp@IRG z#BfKg@4@VT*>sHS3_-uMp463X;)=!#zI-27(`($v6@=Pv;AWgI(U}Pg>Top<17F?( z!t730%SCZXGCeA_LmFcQZ-8K*IqmvjwX2$-6@S}_`mx0!i&C&nSN_&jAiZu1@;^ts zyT;X(tvBA9Zz9svdbx)v<7|llN*bNe$U~Dj2o``L&Qcw$kh;*s8{l`Q0|`ASGk&_= zwVz?>KeoGqMw?B+%jX>O&VWK!UIHkjBQygSpT>WQdP~uTCfo@G`Tzq)Gbkc=rIbmZh7$|=X|`Yp zd_0+4k}={pNSEX{6sT3;kjcY9CXHTP_hr@$GitF@8rp4%f9|v@a(FV~_Xy1c@7Y7mo2zj6$s`!9RHi!??n}1+f zkIWd!w<%4GP>QM^;iMNs4lKluMXm&;0SVf5kbNx6$sr{ zb`%NK2@xN1$aR^Gr10^Pw8=w+q7C`?2#hHWnjCC3&93ZhtM5)?nhW-tMNWw+Pd*a1 zhv+^?`k$S`Rr~7c^W!6Fgvdi%a(`5MlSwthe`mo&qdN&C(i6o_v~F!5jeeu_^Sgg; z|M~4d|Gq}=|A&X~cK2EI`+psHpKsqEyglE3&)(2?7q`)elk4C9hfliu%rmw}KWUfT z`4~^OMmu$Jn8p%4Lp;Lh8U{xQmPe77Zl7hR>9TazbSqusiAJ2|n$ zr#r>SLx=JMc3F%jiRD2BLPH-O9|>f*+>S9xH@H0vn(e$ERs64L+Xw_9;ReJ1pd{=j z7j)p9^$*o0Y|O*b0O#M?Sbu(}a1l`GD;w(da3JSsV!(~I^@GaHRo#Z7rAe6M&nkVm z!Eei(n6s`wK4bD#T_jj4y(%Z1z3>**?F6^I)D|U|NbD8FwdQ!4s7@I%Bz1%mbd*YI zCy*bqK(3X>{fXiqA~+wb_x56o?x%RUkM`dwvT~WD z0C}87gFUrX{_FPEukRt7{i=TLY|CGRq2~Dmimn2rZ|xUrMJ(>O5uKliu{+#9E2oOl z=I`E%mU2L`+3m8)e1Fd>GRRc)CM}hCwyZ7)O?qb|sPf}f!Bv-Sgw6u3$(N~@v$g!^ zv+{R8X0n^fBx&*Wbj|Vy8S17=L)Uc>oD1Y+YiF}AbXf|{x0v|y%FJ#`B&lu_{`ky1 zT=CyAiWZ+H6BI3n)JY?ahb%IJ9bmQ54I6EfGL(W&Cbvu&;D0m7!3+kYnv35A+Hk$<0}=wQLqM{qGmgiDEb4Fg4}@bH*;5rQmh z1x04EdHLWJA%6*`_SHl&-wOoPZBNtmdx_4jkSj% z+qOXsKr8)%9XyIvxVJQk>~2J?nPk>xeFtY~ZUM9%$-52YDJ)o*!Loovx9SezNKo|- zkwe%u7)VvFL!sK@?hq` zkb6EHU?T9nOx&(d>m^Bbd;|k$aXtu(voa35cFmY?tVDf8L&{*#>%~~-9P-2>N$ysv z@-Clqd4F-<-nT*W*OzaDkE)BM;$=ymzI<~VB99~gC|0)^luH~&NQ~(Pmb5oFH@BY4 z|1LH+_vC;75k^_)FE4aLr;5)LIxV+jLE`(@?_VX{rPtWcTWd#Aiqsf;on2Tcx8}e1=#^iTbh~NeEs>-_?9bW9f}aA>XTI z7BhJX+yP|$evM;h422r7V|I>IztrzPXza~Ug+rxw&41#v#J=u2G|3Q1ktwD^UovFf zB!5KfJ6>~(;M+hU0~Mr?o^$cE!T>fTPMe+nRAAg`#8Xl5Sk>s{2gpm?dTYdRI26}r zi{UdCYdbb`i?Yg^%9d!=TjNT_5@};;R=mv?S&MFFmAdQ%=hkCeZ%}TfSM*0M(Qb^% zRb4?dx3D{Uh#K~*l}P*1?N*gY)Q-(^G=DW#oAQzE)oQ5{vRkw*HvRJe^v33tCs?`p{%YVV; zptFZCW!KV2s2MTyc*RV610nFJ-(M7@8ml`y7q_$B=fSwt>Hm}W0@ii??KGb0e-D`q zeC)XNlIlHVug}rzD}jBH$z^LTZ9j7^-^`FaSf53O9UdQv$t{DDgM|)NcFy<*>x_3f z>`OxBRb38yxr&bGD;#c6m6yZ=JbwjGo~eRoh%FZ@s%Ve9d?}O51d47M&(-M$84C~# zq*#as2q71Xh|}zpg9{GmF@1oiInJ6U&!(0t64~!uFIuZiF#vHeMJ);!t1Mg)Fkgj`HVj^q<=vhEOY{3 z5Tuzucv_ZDbt$`>x7{|~#{>xxD+ugg$~VkAKzlP_l;$ptpXrz0{L7dpMQ(wbCG;5lFyk4>n9;run}BPp9|`9=A1L79 zm?qT$2Z#G-RWDYswGx6=Dz+v=O~ziuOWFIoGjEb1dyFpc?Z$i~V$q~`N~|JJG9q;% zB`sm^0ndmw3YQ$^jxr|4|1vRS@Kx^>kFr8_Zt)((Pp%Hp8{t(aR=SU}wlf_&V{k$w#LU`)>uZ5l=2Chk=U$=TE%9eii33d7S=4EnBQS1eP2(x`cAL zq{Gh3O75g?*%nQQP?a38|MVI1Xv@R>^a8m&l1+Bqs4-WZOn=YXkP+C@F$$-6mykb#TmOV($rH zyG-o&B@_F7hJVXDjk!~#Al_$J9dU9}y$&GjYx5;AF2J;>;K?(_X#}T8U!{Gne(kfX zNdOPWhJGljC?J#@g zx$nC9S%!`cCG9dSXLurs0WqHm-CDc?`2)NyKP$qB3x7OEjKg^-N^EUz$w)9PxY0k) z(cd4bjPh@Z0yG&b&sL68s~WlfTGr@-Avz)!J!)3otLzI{xgqmk|8eWC7may`&d{7* zqm>ecm?Y|Sn9jSgaeTD&+7OdmKbMCT7+jVrB*#D`f9QlEsu#VfoorC<~UVrSqZeBZ#!zh=Qq4N?dQL0->KIAY-*07On=ty*!A;l3GQyN&TwNkr%ExD== z*}6un*n*s+dB_>y6h!Jhfa(tRWH`VL<}-;DRW`o#`SFqT+EAH4Obk+QOStB1+}U~_ zbzRPlK=NMT-?Fdq$E5ypg79SP#jDL`K`6t-%9HmRlmR!hj2mwS0oRlKAYKKY%HZW@ zlU^ZCe|@j$t(w#?YG$6H06~VjC3z~7Xan)`aIW^0M!Aty&uUb%-5l;z!9=8fB+xBg zs^djEF7nCShn-%@BAjCl7N`Mtd(PT>sMg-7CYOj3e_5X~pZO8I>8K5o>OV^pB<-~LwMP}s&!8Yonm^JAXMq)MgHrM+Kix>_r zf3SC@a?t#7_VzTQbW*k1FZ27Tm){1TF*&3$QNaXDY8@cxQ6jg3lM6Ls;;R4!m7J-f z+SlPg2T17Q)X@@qk0KOeI5@{s0@alLHc)Asnue?QNQ``DF5?bDF_xdPOk{FO&$<5a zU%m~DU$12LBsw`*a8x;3-@mqu_Q=nne{TcK(R}$;8P$ovIz>O|Iol#2!H8$j4`39* zMVcqeE@&fLaxHqAEy#|&&6an!4rfcZ+ov*Cy9)_&AweBOg3S9?O>z38WJa28uQkIq zLZoY2y99=`t(c*NA18^b#-ZhXxMf|{O(f+ASgb5V|Mk}O{1oUl31A-9*Tt+FfA4KD z@OuP(HAgG%mA1v40rCVBr`@6F8^R;p4tsvaWEFJNKiW@8enxmY;~JX2*FQ8&Qzc{` z-JTQ4O2S$zpCJ$7P>GO!$eVDXABqPj=lj!Xgr>q^vqaDZkgF53PHn5drO}mCGl5*$ z>e4+iYzL5`^ZOnpABKuZZ)q2uTzoVt$Kx`ZJCC=3DYk>P}GCgE-$#e_kLDQq2t`F=a)yo$(36Z5>e}|-uJ|+{|e{Ju~AkZqL zVvIKqXAl$V0kJGeZo;$ns(BqQbtoCneK+Y%qtO*otz;fR)wH_# zX0$VU@%rWH)o52b*U)ulQZ57|HeS0GynSy1JjLSxy`_=*D4i}EdSGU7#h}z&%9BpW zwst~(?zX?6r!-IQ#Xy@A-v%3}%emW(G9-XqYlZ-5hbIkT(yeMDf0+82z=qWMK?zjW z6bbLvWZnJ{QW_jU?#)hPHfxWAbJgom@RzT8@8}#)3G%hE^%Ok$^3^7IIM+r)@Ni14 zUHEXZ3k_#S^PG&uUm%RxOxkKpb`BV6F6U@2YV?=1vU(tGA()Gw`jPQdUx$gP{^H_Z zT-=L`dubc@VrX8&e~?wGy}L=4Dv1i=x-|a2f0H&ZCLUmXe<>Ef&p^&qQ66meRQ(Kzx@kGCN?h3*u(Q|L~iJB98X%g(X9 z4&dz7X5B3S0uUU|ke3B5cfw^k5)F_{7dee6r|M%o`SSJ4SN&L0Ip>haY$-U)wb+Qu zs>rtoX~iBcf5B&Y_CgeiNz6b%r`Ur5@Wg8dC;?F8Hkw|M-CsJ{iUD^htQv*=0R!x7 z_Eo5!Lq-l6tpzeNr)D`|^3H)smH4cXG&RL6gw2<40w$E#a@V8U0v8PSHiv^xza@Qr z6GiFAS9dTDhJ*K5oic=DZ?LzuJrdSXZqavI{<=}9 zo#uGjcve4Y)d1C@TVooE(d<0^9vGb3s=G%cRsE-k2pQA^swz;jzgJ@wU{z@JN8zh- zUu|Gkk=Z)5B@=N60SHz36mKbq7z9&%jmYD?gu{t>C+3})FN*o?y318k(Q}5v0D7ng zF<+o$e;byyqMR?Z`lIB0xwAHMzQ}BYRb3MCH<-^rqzKFr;Vv}Gg=RTp_?{TU&a`!y z$6=lygLy`E*GNe<93WWUpViom@-`1q zwl_E-M#4(AhTIO2o8e?$C`k_j$nF14ENY4wU3pIv&OrkO0a z6t1Tf`^m^sWU^r$WGyQ?3_O9rqu~P3$y2!m^p&P+DTwY)@U+#6XviRIj8R<@*?bY3 zsOr-Q(+Km$zVAl`f6F=k2T3gW9#3adc^c17=#74)ZIOe;TZGOa$5cGu7!3!fQB2Sw zf2Dy>Z^&S8cQgH81~WfhqX;pM=TLP-)NC2uT}SF$1vbog*7neUNlWSn>2df%Pi<6u z#i&&&Z);jjU5(4i_>#)ffTD=^T3- z;CF`9z?p}}Fku`)zrPsEd*M}96QRU=`uJ|LRqbqdPF1z0t9!RD^PHS!3Ym6W+`4kz z+UBKHavhI*>UMs>DbK7&ON2neQUYo+gs)&sg7o`av)m;+b7#j~sJRQMaz11ie`@Z| zju`;wWm7`2?zzO8(umcZ4zoQQwj_I4=d)mTX~SgeKQdQXXD#cL?2o=^(P>tvS)FF> ztXbVP-0m9gJI6b(n(}R+hua0JhLze7638x{Ms4>I^WZN8;y~Z~<2*5N(i~$%5i5X$Y5ttx!NrXW30VV0?n>T})h>xwL zZhryH9pc*_1=MSYwH#`4sA-jrN0(cyDmtLqJM64hXSF){>*TMqTG!bae|p`NIIM@9 zVOHtFdTfzFWe$MSe~CX$O-0Du~WrP6+2bzRIzg)I|uTrnCbOaQ$DYA6o{$V z2`s6)mhphnZ#)Sou93qogz-^;V;92caI(Y6E`+fHk!?4n z1Up~tH0gQ6Y0}(wes&OY*=g$Y=HsNTkyXav63-DHEs}{r4ec#^?!-!sY2z|;`f44lXDlORZvk^$n zu!cJouU}L=+to=do|IB9HyXe>ru&JPDvm>9?TUVh4v7v3hHHd$o+GIK6&7$9p=(TI z7A$}eCX^u`?EAhnTcRvz>X-u#uaFY$6B-2cM%c?rBJY9Acyn{)NuLnI(=^+nc#4Ml ztvYm@yc1Tppru&>e{(j?7f-oK_BD==bb(8fD-l&UN6?Mh8Hw`GZ)S+kkU9~pR=!{* zS$Mh%18hd)zz1UlF!3S;8S)jKhkMw!(dJ%fZb$d%FmlFq`3UtokMWCp#qI7IrQoT` z)?Xdz)h?g^<8u?0)A_r7P3Nzl4bSJ+4CXjVNC8;>my30mCa!x5ApH(Ox`VwA_Bz<>V6TI{U19HTT@pqG z#!eN+>56-G^;Lmy`Pt4YXjgO9C)~|CTEx4JSU2HBLrErjDnP4_dXJLOtOT~+A|KgUshh6dlmq_#jf1_%5l2wfP0iGTcF2h92gQOL<5OC zPDlyFQN&c%KII6!B&sDCY=8^nN*6lOj6u0^4#r5;;uIjl;s}8Sja3dn-GNJjZlTA6 zg>21ae@B$$Gfb}JUob)&{UXlNZaJ`tca4yTLu?%L&cBwINQ&;to=j3#W#YqZ8J(+# zl~drsAV|Eh#V!>1mxCed$dk1`YOdyxv_sN&{Z37aseakhPGr)bNF>w{3pF|Kv*0%FbEL0v{TZwmWjGY94Hf7jPZsJ+5())k z5>W37_;DnYY9^3hy~G4_3rRqiI76g=Lu75n)WLiQ^Bv50F#jRK{83#Z ze}<>;5Z}LsIDq2-9Vi6X3G-LbX|t!n^H%{q1yAyjzZtn#G~RIeQqE3ji|VWUf4SuP zr5YBKtC*x)oknt_fKCj!{|ie{HQ+PIli>Xu%x8WCZwR0fU?C#>k-FcxyFkhs%oLE; zn!>Pk6`?x~8UEiPeyXle>nb^Q_0Y6$sI;Z#=5hDqbfAW!RfKNhhR@Q_O0+Tq%&O7--L1_VQa1a1OK|skA zMVADIA%YQ@A$iWp$yg_2m)(z7SSwX`?DUaE-<(z5?}5vx z^>&SpvOJetD{YLR`(oKV_-n_tBMwkVy;=SRBEI?9 zsa~ggZMPZRpgEiH$0)MhhC3m&z{O;G?#+-N2c5lY1v0DIh=QgjXsN}FrW@3mLAR?m z%lFaBN-Xkc>b7h34)};ee;hF7SIb+9&Z2V?a+!oQCU$8Y^Y3i7{f4e|;@6`oqaMbRU8R z%YjtxY=jG%azRrrXvzgm^@QeMHKe*fLvwnK)D@GRAiYUoovuGJ`RWb67dmTy1yYWi z6u=9}Dn9)+43t+#C$*VGbe_8oN$pWU&qE<+xic>QK=D*ENO z%r_^_msqpn_Riw1o(@*79k=dI`Jdq(UT1FaL0)=?@*T=|DBq#{2Z-{wHXHJ(3zWD* zPW7z%kHz?1@qEuY*mK>lLi5c?z9AQA6^`#UE~H(i&gF340d@!29bmuDfZai02Z0>~ zb`ba>Lg1~2e~kG8V674cZPdSukcpmP+ZrpfBnCLk zo^WTFw;asuFzo}xwCl|6J;1UK9XfRA(4j+z4-p-XYSN7>qz8G-S_8wZY8@ujp|DxO zCKQ*IYB=ni6>4?XImfDCts1;t%us}6hAKiiSRf7{e^~&J&gY2mBIKXW7flb+9Z)F@lZ|TDqWH8m)w_a zlr>#!FKV)xs+pIhDSjIhzda(Wpkcq@o*m90e<3Ky*I&K>bH#h{y;XO^Eko&#sQgN0 zr$k*b8z`si4)z8*BiuaX3*`o^@JQtS6^E2ea5P8${+w%XgH9-0dhi)yevSyovMmw^ z!Eo^3F^bK)f6&;Qq38@DA0dNkd(@_S)Yit#cc*RbZr%rTygJs+4{auer34@x9Q)$s ze*~L&C$r&=kI=ULPUe5rH(ot;=Y3WZyES<_D!Y+J~}8Xsxiv)0ZMiSh*{O zVsy1R-`PV|F86EO!>K~23Y{u^jH>WuO{PyN(+_D7h%R>0eY&!}h2&v>;}H8xHJK*d z;KtUJTKTXGJUeqp@T~{3#C-OAiC>~pe+=Yl9bz9uf*U4x0U%%~m^@cy#+Xdi?8&mv zAs^tB+6Fl00L#6DxymE~f!??p0tgPNk38_?W`?~P(1|LtM0uWg`#gl+74p+o#MnL6 zIW9hkQZvYA8+o@$KN&;2rlwj~QSz!LNu*p^?@&iE@($UG5Ucc%27o>$6S`E`f4oCA zf~E^bR()BX*Z${hl&zgax?dRjeq=LjLi%Ds)Z%;nvK^{V!FmxU_8~ui6f$20;yyIE z__`)_SR&rUSe+s0FFFhRltP`Hx0HGDuPzy9fK>26V2_)BBc6Sw`Ftn z9$wYIrjvQA<`A{~$RE+oDO?DA-)%}~^;fl)zI@egvhxsm!d%jHt<0s2jsC2rT-TNx zPtF=zGj7Y)P;QFZUedBJuXNMi`U^ZqC)B(8fJu6_Ncs%krq4cLa*nt}e?R)kn_C`9 z>iZt2k!hnCVf#mr!>XYD?U<6J415 z)U7Ju&iA);)JByCw;@u?26z7D8X4T_21>3~A#!rNbe2o=9C;DqrxC()dGMs_h|Fq> zbvTewl`>4)IM|aDB7B zjOt1gM@fio(%Js&4;V=8EoJf9#m29J>v3w_(1f zF4}b!BRe&RM%BXVc52k9+v043QERy@X*fjM#l2&3aP%=rkY`O_zwpw^Hl&0{v}C0n z;Rtz(YTN5qa}-;H@2uTNca7@yi>8x++HBkR%i6f6^l3ssVlE8fYy*avirzBlJ)ON~4ds>QlFKFgaI`rK_ivJazsS z=WlWTmPhGt>337@CtQ=;n1O7qgB}aattsd0iez`2j@fH$aX3TX)p>}B564{{VwI%& z#<%Lvr{Kw$(!dtc=2@x+x9WR!#IvP7J80{mt%J4>+B#_Kf1s^{wm%oz{uGX?V64t= z_%l)-t}8Zu*_7SG1XnUe>FT&tl35j#K2@;O3U$f`s}bi4P&4U<%h%!HrGu9aUOIT` z;N^pXmzC+6j{ri~9|XUNz-_ws(i%9x;vRZs@0)rD+8Y65BZ9A0gSSBHc1 z8IAY^20@o>aYp5ir##vMQHPivVs?o6F(T%Nn!<4VbyMCkEhf9?iZBS+2ULIgTD|XV z2V9q?l&EwdcEz*0XD<30Nxy!LudnF-@9YwEKEc*Lf59JpbKutzrf)+5>?x!&MvfjM~Sn`y=#s` zEOMnND>A@m2!!!Cz#h0li)1taoya#+e2oY=K1!Znl1GW;3-iI&Z`n%@!6KP)lRqCT ze`p|mf~eYcBp0`9(jTjp90VUQLD5?n2fTgOn+h7W@^Oqe!FP&(Uot<`B@Y`3!PEJui;H4dydUKtSo$ z7*VoBTB(^2rFW4t)#oCStrw_)Q4XQg;<+naOJ{pwrbB~j&9xQ*Y{l?wyj5Ye*p{gD~ z8~JJuXxoQd}-Wv!Zjt*a%I{f9Uc9VS{SBNp%#$DI%`N7K)JKE8&Eeoos@-Y^-a+;|6JPkX5?Y6pNdk#> z>g_wE4awm-fDC`VMd(2BC7yh`M$sF_@f?b|W4w?^^%M~p@P+y40w;rih9)sdC|^(x z1J#ScrrPU6UMy%{L{N!JHzn++#2bM$Q#}B#W$%ZBqd0IT%4Zw0n4zdgYO4feLSN5jF}nCN7y`9jj>n94!-)IWbr{d29KUhBu#`Z?zXKGE%9 z@0&y%=keHsL6FKGH!tp92ag|&eF`ew*4U2wj5sD zv1k<_qS}9SMx`?xvcW{V907uDq3hhG$XXtRlzW6=!0;4=iEdVDjZ45?iYZd^-BH2hL|S4t&68m;ny2lFd7Cg%%88!Z?Ed|KHngn~QS&nNhAy zyDWe1%lyPIQ?->-Ep$p_U0cj%dxvjsZI5;b@**z3$L)pp2==&XWVm$?U;yQh!KT`y z4j~s3_B4kPHlDRMe>BBx%^D2OdNS}068X8p_zk@ z;qfIhb&#YYB7TfFF6b2^>NwqU98zqmDKLLNPrCyMspwaI!j2mL%n*5W3q20JtPEhP z5S@VJ%K*qrQJ))^o11^{uEHtGwU;$l;iy$e=V9C-pQc&4MI`%|ucd!b z$Wc`&q^2xe`4saowvczKN{>O2Y44UN(#&xnL%b&ey2axF0guk-Lcqu%b~C;)7d$DX zPqi>J0vBO~Kok=I1pyjQXR^j0AHa=}Zdw|K5xvGf^1)1=nUw*SpJ#{w4+a79hq+G& zZg3FnU6SYEghD@GU-2*mG!kM|zVmc5~i`vvCq7K9? zv>`R4chP7(4x-<)sCxD-yR=9zYuPH`I z{aDC(k+7hjN@nYOA#|iU9png!FMmAAH=O%2Gd!IkQ4x}I?Vl@ z#j1>o&ITq~L2~fLBuIwul4K2z)fmSNMN*o4G?t?PRhVNK2CItJ{!_B}r}$n%4hlZ>m`b@8fg4CT(_cwU3(t^3lBr=fCQSLK#z>Om z^pY$cZ`tz?HB4nan8%ER8NAl=l135oI3U8xVrouJA-g0pu!MnLgU;{$Ii(^vutmm? zAegK3c_FvM=62Y6&O3kBl%vDhwk^Wy%SKK)y1ufEjTiQeQr@4pRL2^+;C&ao?}GQ& zX-Yhv7;P84?dbM@W9%YwV-wkOqGNLmtP!kg)nkkZB8WhvSTSGixRa@;2ap4?Z>5v>B!2mG)kIH3sjUu%J%sAvR z1CV7Ky{zAT+rocbxWmocQRjEcF-sS?H+UtxIKoAm?Zvs<_>1Om^cky#P)aERqm zCK+y*F#u84~p_W++yPNroG-Y1XF1o^Y1LQWW7o> zcOxE#V%piPxdd6tOljG!q?k+!Hpjfn3h6IK$;KJH(cVCrWM8SMB?`!Fx-r4Nyjrle zCMxvI(rSOoF=c8YM9Nx7bX}{WBy3uF9Ka-^b9YYrA)E$&unM)XZtXOyobeI7Ny5wr zx%k>H{Va8?V|Zotr34x?tOJx-Q~k14bM35@hVKxsKIm?xTawzV-Dvf!O%jo$$^Hx) zqZ1YxLeln42U{Wv_4%M*m^#-W#okyQc7LoEiNk-;E#jV=GEY2fpKszmW|?T`411uN zBp!%mv)y!`;yc98Ao1y(AjaNCbbf%KC#7IFMN~zs*4~L0A*UNhbPh2&M?&n%C_p$( zO`zQI>?KY)Q9f(lMuk-|yCe%mR;9hAR6jf|+;??sW0oBQmBL4vN$TZ9Xv(x!e@d|a z3*LVjNWYuyp?h{V(Yfs&7UalFmde?gdu{QN4{p?lT@R~qU3KHA=}yg(sJ+1673zAs zW*xPAq8&B2KTj>0eOwRd37=jf-L*h4dycd!CVZKOwvXHjpTo} zd?L+;fN>gz;$Zs)s#^Dgwm@xJU;3uj&$wS zLakbhC*5k3^L=H}l=aLa{wn1tLOjCgTAxomK1vUR=rpwo>+6Ru_{z!2WuD$8QgZ#i z{F(~E*G-4aKfve;@g!`klO)WMSWO(}NG%nHxzY_1F;}j=JS_IlLMY}rQ{I1*IFw@W z4f7&;BdvoID$NERkXkJ$6V!IDPlhYXPJBA?xkP+6FYMx58yA_Hx%#lQn!8;>L=!S? z9b`$1kNVW~i_NA})9R}pAsBSDu?+(DMz(PUUsm5zc*~~jt{%-QbQR%Azm}NWCTEGg zjmd;YDv1?Lvm9o1sa(j2QI}*=DM<|1V{2L<= zRi@SL8jqi4SlQd!9Bs>-Q!>YkWLA&LVSo|g=FUZuf5v=v0>>yQXPZ6eFyhK%y(eAE z!@(Qk=O5@feHvj8ouWv;lp3I%=|;a$Ocfq~AF9PA2Iw4loJJMRpFn@ce-C}}l?!YH zkj>0T-+R3M()^AsswHFJ`lLf?c-m6PzLHInF8%c@GPs(Pw%rK|V{%$0c1tH^+pbnk zvbHqLiDtuX^_=gJBFF6g}gsO8`CM%@HG%T+ft3H;Npj9nn8Lo5>>w|@7TTQtG zl(IR65yu`5A?X@FT&91s0$6KjY@3a?fo&@q--W(f0k|Bi=Dta@1+H*im{oT0Zhhfh zoq5|(uqDW=HG2EQA3w<;ey}olyXkzrnhts`S6T-xM6f}oDSf7Re|%JT*uJ&RY_!_n zq5G;1SvxvSj_NJu{K0%-Iro~FQjPMR1>d~bxublPP64zykl%k`)jw-(%R2-9XBzPB zyvEK*cSgE1(toIt{y^a1s43}%46EDsIKD;!fgOJ0YP7qWqVWZax*bJ%zJ4RpDCOY+0o8cLQ2wJV8#!uWR}gWFuPSePQM zL1DH=?C_GYh}vQ0{2c67J6YT|tX3_m)dO1|R`m9Zou-s53N>6q9KdmaRtsRPBDETR zQ%?@?^q6o<#8zm(0koOKyTY_`Z>^D9kx_GRMX-P=0dxYOLTA6QWP3$HHxCjpM)I_% zAHf>}Xarb@h>K}|bck&kVlyXx%|NCvEx!5YqlyE6@uDe%hg{l62>JmgUC-0!X{>4h zCxq<8XWDF|v740YC^gN#*^0}IG4s@Xn$(_5fuEL`(8!1Ym*Ue&MJE-P+Of$TtFT** zS5_lzBw!4YO*%!S&Qfc%iggb((AcDB2lYSk32Jk>=W9da&+ z`j<_KQ>0jW3*(@3{82_=H6cI7e1cKnZyaF$R{UWn>s8YYg1$tzqr6Z1Xe;bBXQ`wI z2`9fpv?&Ob?`%doL$o_j5|jPEd-HO;MV8njM9t?whTMlsr}J@8qL{oD6g_&?+J{KZVPIpr!XV zfkB^cNIn4PGmWnDPd=iX@aFK{7@8=$KQ4qGNxsH`v-f8vRD; z=Xd|y{`1>^{(X(!{|^t}?e4Sa_y0QZKHt7SczeEo{hqy{?=Ehm4=2~Z{STiEh69;o zNKEqDq_v+h@#)PeJ?9c^U&!%)m4+C|Ad%6|=*8=oqgSKdSGfu>;_^!-8|3nikV8rs zA}nSS^1KOPC~u8du|4fVdumA8SOVn%H}-Mb?KKoPY|Jq=h<3Q>zD(PgJZ;(3Q?qr5 zj-FwE6#+)(6tEfdrkT;Qel``YDs~*Qigowsu6}v(x+xQmmXF3>oe|2l3hJq(*airh zyY8nEI;8VC<_Z9Xqh9u1YM8v+?U(wIvCPid$a?-JG+73OvJmjHQi-#Xg~*e8k?DSo zvPvH*`l_9Ame`>f*HIDn(Q}}OAbAFhfxo4H@Q;dEk24eo&_jnXgdXOLWW@Ai#e3>N zlxjcsDwY2g@6s-}1Oq=TAfs(4Lusta(W12@*MffgP=dNoVjD5hGQh%^X+I<;!+t1w z$cI}_?dps%w>|qq5Zdl$W123ZmD0t%ir+pX(gugcnDE`58qoFSYf97(b7edBZ=C)Y5f*eTh>eWa*K&5t`fe7Dob(K{#HSKDRIutj;B*?ea; zhWkN~dJXgzvvmI~icimwN3W5<1jRQe#-WYmS^g-8db(mXF*3Xx?HmtgAKTU~3`Xm- z;j8dnG30KCy`ZhP8uPG8B|>j1BwY)CMJ?*Dc#(TX$Wk%O+~EBkDmVLKyFsLQ$On~* zCwhzUjjteVE8IK=n2Cl74zVRySRDVCgneu<;? z2uZp9maeWoYe=rw?n51ycf0-2FgAVfKZyA#n*zRS%k4Y3eFwMi;PxHdzJqg3xqXK< zKxd=Iba@Ic$b(9?r%c*_vK*xqy&ICohJ83}q4mD~9HqWldprt!c`)$eKwdK_fKsxx z03Zj9&JjRD3`!gY(?et-iZJzmFNt|Qt6BMZgaYX`Nr+=gn9GvlgzHl8Nw&($-jm!r z8fk@Q;0I?co_z7;`$Aq|ZLf zU_;qRcEVMX{;b0g#S&5l@|9BhDrm9h{ zuDd%+bG{{eTq~V*&xrh#bC6l{Kj186uCKPp#^7-InaC*Jc68?=9b$3kB7eRZeX%qF zlk%192LV;gcbBCFN^JyxDjeet(`i%VogY(bkz&1qmul&%K2s-ITJCEbw|kL0Z-%@p z2Jl2)d@tTfCuQ>fkxI82@z}0(Za6m zi6zyC=H+;`G|SWKIqf@Svwv3M&Zs#zvRab+pOD_ZoY>wTu~(+GFSs{S4Zt?Qv2uP) zaKKSycuknvqk=(ykg5!wb5+S%!f%{#K`9lCdE`dylSm!{vP>33=R zAM{bE*G<{;J|ccYqpOeNT_+T35U2p5Pr(ykDO01|QuJt)Z2*sD!tFt0p8E!zXtI=Z z7l;RX8;qzj>Tl{JA??_Lc*qBwwnBYXdbZr%(g&+7Vu1;N*8Wuc2Vtc;olIxml`hf8kuE^wGzD0*>R>vzz! ztvC+*^q@KTZV%sU=1SSvtSxsp+csM-I`7-8sXW?hN+5EEps#MO>?DfP>MMrq?&}*Z z`En(lHrZc)oUYjm3qO9wK|Z5easU~M&iujv6J;K&+r`Pk7O}M1^e?-wa_?-s^U0l8 z`qF0VqaM$8=}T_gUelcN)cV3@&3;RZuK6xr^=%&Z>DrguO_?a;Pcg3szQQD{PA;sZ*6 zH-nfAFNtVjj`)oF;06cDAzJ{68ePEPLIqN4;G598fsFjZ6+O)mp|u=|nlKb=I>JKn z>2jEVfq>F0(cMJp3SbDjWm?wwW-?${7 zF`udJ9?UeQG3B!Y4`N_xgr}ImAZ2I{7vhs37y-yG35z`sF*b>VV39JK4)hS*%&<3; zmBbeV0lq>20-wg?06k|RBEFoL`_AZJuTgrTV$2GJ5Nh286heVLt=$Oz)&!GuF8zXr0_Hi4Tgol zO{r~wW3FUmG)F!dF8~Coj{^b$B|PwdL@k5_t;?w$2ON9i?eh?NLYgJ5h{1ZQ#j#BM zK7(wwkvACo`TSj-V3lyvkV9oWnSW`O+D3}9{y^jhHWkDYOI`+#Tu}4Egtrl$=WbP? z5iI}wJ1 z%3ZwiIP}rHpLOn!#wQ*YZatA_{c_>dCjlNGQKOkx3)AwnxLk z+n9J-kmL$U`8Ab;?x}y6`sZ3dz1EMf^>fY(e9AL@(yTm>#{#CMvd2w-3^y?f6GKHA zwCr-*%r9}9t#Zvs#XTxzVfPc5Fh92KRXBN0)cmL*?M>~NQ-^k2IArwf>&C8{uodiP z6Sd;yiDi16sw{KGkP&7%F5I@9<;mo0+YfSW%i*;hi#CIz#d(_#DaCtRx1k~6J5<$* z!e(qt&C#}{M9J8+qqUlU)me6}usU8!CA4eXo@hnex>};uyG^c4U$&S}nQFECyuVxD zI+iHvP6J=n!A#+0La?-`swx^*Ln|k}VF7elHpxh}T?MIG)6U7Cw?bMsn;I;wuUe}x zi`u8sR`yZbdWI>rdR|l~jGZvYIz%ce>5aUb8H!M{mznGy zU6M=k@zcedJs@{~D{b~8)kao%Kk|}5kbZ(R)o+>NbNM_ix$&W}KWJ<`U6RA&Bfw{n z=q*KKb4`!PFCO-PQCmergXoza14&fOGpNd666H!y;%ZT1xhD@w{BGRY*5W*7+}v6$ z4@vFLqU`k$=+nZoUw^_Npf@@*tN&-V-6kqa;j#hBTajvi_Q;*O0)a~+NmC%jm)o** zTb6Fi(rsDxaRM^0!tXB1cXMlVtA_+FJ3lGENcDXtiH@ka&ct|SwdLFQUZd8z-8VN> z!6W1;ABYloz0KvmMA>lgULObRlGF2jdX#LrozmHDVtk1QX>sMJO1lk*WLB+ymhV2> zcsos*ztv%XN#i7GM^i6P5g^cX5Kl@chq{7EhIC$&$X=#nPYl5k0r9&*y8 z`;2dYcboF)7cWp;0pX@Z?i%BsP_K=XCFQGch--GZ70AsvnqcCy^qRC^!}NvR2F%0U zM}0x9LyM0SEhcNd87dm3Y;a=!cHi8EzU?pWZE@Ret9xo6ni_i9bSXgf&C}ggkxA$d z)KTSi+3j5~IW`+Io-J#xed@F7VQQzua?G25{+jfSox{dyG^f!XwnkgFe(kQ~Z|@J0 zMfcq8{H5FZhl6xfkB}5I+D(!^E;DZ9ujz2@e^=K<@@-o-_d{GVZJimVZ=N2SOyZS_ zH~zQ7U6r$-b;VZbt&@wzSTR4uD`P(tRRJ*NCDe8f7gw9}?{opyubVDn`QyVOj?|TZ z>trh6VX#P$U^jr>K+rx%aEZiHz}(Pm18^?YX^)hf`@1A#a1+<*m9#|VJiFCL{gPt< zURDz@SyjAAzHU{9;f+gjF~dxVZ}CdTn}Z0ceuA++7!VVV=LlfI#{_x^aH?{NGT>3a z$4sIQA=)Fv(ln_E056xY!GLdZ@P|BqETNIhTO54A#Qb>>M}%iTPpEfgzBU@p9-bkF zqHA=7**K1p>^?2gPu6r>y;0<rk^iY8{9qU-MBby;qw}*FGc|;V{66 zaPcVacnet-r4^GP+WH94TXvl7GHn! zjz0XF%H6G|Yey1^aE7Ls@n~^Ish*fCh~5IR78j8e<*}ulEi~A46G^^>4#q`oAD0;x z%Ve)+EiopN@*rvH7X~6qWe#S42l#)+#Uv$7v+kN`O$E|+)4d~l+DAP=!04xfzvzx& zU(^BcMGopYsJF(V)j_>}B=mRW6fVsL2gn^iF9OUlcfKi065i`=~K;nZbQVC>#q;$=0mGUT= zU>^|=0Uw2Yw&BwAxb!?OJ+~xA)xcoRSKaR_f z7Y}3aU z{-50SFP+iinu?njb?La0WfoFQ$``#^3mjS9dh<@*D%vD)B)w{p(?QrI+*ybl)vypP zED<(Lh!`(@iToj$BS_L4QH8{zSnZ1IT>?3wcc$%9JIQvGn}UfFn-WHuip zYN_9!X>^66<0Exy?f^3BVmQRUz6NnPIFQmY`IY!cHifwkqp332?aH5X=`qZz{fx;WjfuMQcuD001U*XL5FTO8 z(ixRE)CsL~1Uam%_jM>5Ii=@Z)Bf^pVElSD9LT?a4i+3$-k>Z9oI;_bd&QHAWbRma zL7}M*siCTm3DKL~#NGxp|>8{UE~i1(eA(@dp9R`rF^^I7eQ1)j#2u_$Al5+GGFs z#VTxnx5ZY}{h9P@Gk}GO+a}$DoSR**WRwrOfu4et?FL&{;$BPjelVN4@bAO$mo#Jx zrZfH7k?~9$cVoUFHEm3R4%P>2zhSNsOY0O9d6D0(dWE8G$9x44=t7`tu9y`3JaP?? zf!rUrB&!ygfoyCRO&UQOf1oyM0h~hY_GI0j?1PaUqq=j?3*!BuSHOi#3)V?| zLZ-k+wmfcTNS^M=ov6}x*kh&y44@Gpl)KQa zpAfpGPj~!`BOmK34t8n|>wbnofcOD_3?T8^hiT+$Tc$pE3ZCfADLg$Uyh#}3$T#F! zG3m8RvQp%~ULNFGG2=VN`k4;w$R##NvM?qwATtF0G=Jl)SH!V)`3kBQrum_2BwYH^ z9k?&9;TJV0KGfViLK7GVye?sk-BQjIsSdtskvFM|=pE%ts^PzBH5d4*N{^I(nXkSo zoSYiJkrY-B+H!e*dRiR2HRltOPaU8RVTfjBYxP!ZFPqd>HJ1yVEmK^&QD6R}atiAi zF3%WrozeGRAw4>?@MTSqznUg*ZpFmwxJ*=KdlaZ+lzu~tWmn>u^m~crEik-n_2`yO z1rbL08gc}#kW3I^ET|O}#JyjCPWew-7nPR1wh2nR&^J8~1{}<@&1Tib%CQ-ovhN^F6dpm}lWSN=f$QF)~?PCLu(t)&8NpJ%}H-d~lAL z($aceb9P3}tK<0!3RzWN5^k-9aTmKz(Z5rBF73jy1*mz6kcVV4GYC?DT#;;UctPyT zH-_%khyG<{2IP%&I#X8P>(l8zmj(A{Ntw~+R?X24wRlc2>ndYJ)oM4L1a6O~)nh5#2QJfBuFR7jo0Qy^8&aZthgSD&ChVSHXok%EZ*s zrfOq1yOdmkUWTWl-y4@?{~F>zCTte=vK*B?Fb>!dFyw{XFLtlCj6a_T$e*II2NUCpv=Vt9~@EjbRoC}1VO~0OZU-gHyQ!_$o_Zh)|;B;Y6a$r;wQ>Etm zdAcvqQ5<9h`tlfO6#MZS=Qv!p_Kn6>pjE{tr~FT5XV)bu>G7VpwVT+^k$f`R+^LB# z(z6Cn%UAMSt{*%lZEjKc@^!r6Lb*QkqD9E*#(9>JcbR$>MSFB8Yu1~uN-$bxcuLF# zB|5@D%v4&L@+Ap>4|PE`X2@0F*N(}ORotfnF3qp9jbBm1-ppTe#CdIxwmlG7@S-t7 zN_^5JHAZ*2rYW=$Z`yC9Yi8SKf*kVoV>?NgB!%x+;AMTXm3s*vMe&!UVs`?t%5#{_ zJ{ysuW4zV5_6usJa(Eljx%vAeC7!-2{|}iIN98Jb2iXaKo@14_;T>de5jy;T>|Mcf z!XOa+700vfbku5pqB9