Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: import deals #335

Merged
merged 1 commit into from
Jun 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,14 @@ build: $(BUILD_DEPS)
go build -o ./droplet-client $(GOFLAGS) ./cmd/droplet-client
go build -o ./droplet $(GOFLAGS) ./cmd/droplet

droplet: $(BUILD_DEPS)
rm -f droplet
go build -o ./droplet $(GOFLAGS) ./cmd/droplet

droplet-client: $(BUILD_DEPS)
rm -f droplet-client
go build -o ./droplet-client $(GOFLAGS) ./cmd/droplet-client

add-debug-flag:
GOFLAGS+=-gcflags="all=-N -l"

Expand Down
26 changes: 22 additions & 4 deletions api/impl/venus_market.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/filecoin-project/go-fil-markets/storagemarket"
"github.com/filecoin-project/go-fil-markets/stores"
"github.com/filecoin-project/go-state-types/abi"
"github.com/hashicorp/go-multierror"
"github.com/ipfs/go-cid"
logging "github.com/ipfs/go-log/v2"
"github.com/libp2p/go-libp2p/core/host"
Expand Down Expand Up @@ -1204,11 +1205,28 @@ func (m *MarketNodeImpl) RemovePieceStorage(_ context.Context, name string) erro
return m.Config.RemovePieceStorage(name)
}

func (m *MarketNodeImpl) OfflineDealImport(ctx context.Context, deal types.MinerDeal) error {
if err := jwtclient.CheckPermissionByMiner(ctx, m.AuthClient, deal.Proposal.Provider); err != nil {
return err
func (m *MarketNodeImpl) DealsImport(ctx context.Context, deals []*types.MinerDeal) error {
if len(deals) == 0 {
return nil
}

addrDeals := make(map[address.Address][]*types.MinerDeal)
for _, deal := range deals {
addrDeals[deal.Proposal.Provider] = append(addrDeals[deal.Proposal.Provider], deal)
}
return m.StorageProvider.ImportOfflineDeal(ctx, deal)

var errs *multierror.Error
valid := make(map[address.Address][]*types.MinerDeal, len(addrDeals))
for addr, d := range addrDeals {
if err := jwtclient.CheckPermissionByMiner(ctx, m.AuthClient, addr); err != nil {
errs = multierror.Append(errs, err)
continue
}
valid[addr] = d
}
errs = multierror.Append(errs, m.StorageProvider.ImportDeals(ctx, valid))

return errs.ErrorOrNil()
}

func (m *MarketNodeImpl) Version(_ context.Context) (vTypes.Version, error) {
Expand Down
118 changes: 83 additions & 35 deletions cli/storage-deals.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ var storageDealsCmds = &cli.Command{
Subcommands: []*cli.Command{
dealsImportDataCmd,
dealsBatchImportDataCmd,
importOfflineDealCmd,
importDealCmd,
dealsListCmd,
updateStorageDealStateCmd,
dealsPendingPublish,
Expand Down Expand Up @@ -199,18 +199,29 @@ basdefxxx,baefaxxx
},
}

var importOfflineDealCmd = &cli.Command{
Name: "import-offlinedeal",
Usage: "Manually import offline deal",
ArgsUsage: "<deal_file_json>",
var importDealCmd = &cli.Command{
Name: "import-deal",
Usage: "Manually import lotus-miner or boost deals",
ArgsUsage: "<deal file>",
Flags: []cli.Flag{
// verbose
&cli.BoolFlag{
Name: "verbose",
Usage: "Print verbose output",
Aliases: []string{
"v",
},
&cli.StringFlag{
Name: "from",
Usage: "Where the order comes from, lotus-miner or boost",
Value: "lotus-miner",
},
&cli.StringSliceFlag{
Name: "car-dirs",
Usage: "directory of car files",
},
&cli.Uint64SliceFlag{
Name: "states",
Usage: `
What status deal is expected to be imported, default import StorageDealActive and StorageDealWaitingForData deal.
use './droplet storage deal states' to show all states.
part states:
7 StorageDealActive
18 StorageDealWaitingForData
`,
},
},
Action: func(cctx *cli.Context) error {
Expand All @@ -220,45 +231,82 @@ var importOfflineDealCmd = &cli.Command{
}
defer closer()

fapi, fcloser, err := NewFullNode(cctx)
if err != nil {
return err
}
defer fcloser()

ctx := DaemonContext(cctx)

if cctx.Args().Len() < 1 {
return fmt.Errorf("must specify the path of json file which records the deal")
}

fpath := cctx.Args().Get(0)

dealbyte, err := ioutil.ReadFile(fpath)
data, err := ioutil.ReadFile(fpath)
if err != nil {
return fmt.Errorf("read deal file(%s) fail %w", fpath, err)
return fmt.Errorf("read deal file(%s) failed: %v", fpath, err)
}

data := []market.MinerDeal{}
err = json.Unmarshal(dealbyte, &data)
if err != nil {
return fmt.Errorf("parse deal file(%s) fail %w", fpath, err)
var r result
if err := json.Unmarshal(data, &r); err != nil {
return err
}

totalCount := len(data)
importedCount := 0

// if verbose, print the deal info
expectStates := map[uint64]struct{}{
storagemarket.StorageDealWaitingForData: {},
storagemarket.StorageDealActive: {},
}
if cctx.IsSet("states") {
expectStates = make(map[uint64]struct{})
for _, v := range cctx.Uint64Slice("states") {
expectStates[v] = struct{}{}
}
}

for i := 0; i < totalCount; i++ {
err := api.OfflineDealImport(ctx, data[i])
if err != nil {
if cctx.Bool("verbose") {
fmt.Printf("( %d / %d ) %s : fail : %v\n", i+1, totalCount, data[i].ProposalCid, err)
getMinerPeer := getMinerPeerFunc(ctx, fapi)
getPayloadSize := getPayloadSizeFunc(cctx.StringSlice("car-dirs"))
deals := make([]*market.MinerDeal, 0)
if cctx.String("from") == "boost" {
for _, deal := range r.BoostResult.Deals.Deals {
d, err := deal.minerDeal()
if err != nil {
fmt.Printf("parse %s deal failed: %v\n", deal.SignedProposalCid, err)
continue
}
} else {
importedCount++
if cctx.Bool("verbose") {
fmt.Printf("( %d / %d ) %s : success\n", i+1, totalCount, data[i].ProposalCid)
if _, ok := expectStates[d.State]; !ok {
continue
}
d.Miner = getMinerPeer(d.Proposal.Provider)

if d.PayloadSize == 0 {
d.PayloadSize = getPayloadSize(d.Proposal.PieceCID)
d.Ref.RawBlockSize = d.PayloadSize
if d.PayloadSize == 0 {
fmt.Printf("deal %s payload size %d\n", deal.SignedProposalCid, d.PayloadSize)
continue
}
}
deals = append(deals, d)
}
} else if cctx.String("from") == "lotus-miner" {
for _, d := range r.Result {
if _, ok := expectStates[d.State]; ok {
d.PayloadSize = d.Ref.RawBlockSize
d.PieceStatus = market.Undefine
if d.SlashEpoch == 0 {
d.SlashEpoch = -1
}
deals = append(deals, d)
}
}
} else {
return fmt.Errorf("the value of --from can only be 'lotus-miner' or 'boost' ")
}

fmt.Printf("import %d deals, %d deal success , %d deal fail .\n", totalCount, importedCount, totalCount-importedCount)
if err := api.DealsImport(ctx, deals); err != nil {
return fmt.Errorf("\nimport deals failed: %v", err)
}
fmt.Printf("import %d deals success\n", len(deals))

return nil
},
Expand Down
144 changes: 144 additions & 0 deletions cli/testdata/boost_deal_query_result.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
{
"data": {
"deals": {
"totalCount": 2,
"deals": [{
"ID": "1b4b8f7e-6b55-4f71-93d7-be1b46ea00c6",
"ClientAddress": "f3uxq6uf56zkfiwuyqal272lxn7wjr5to7qhzd7x5u43zjt53bv4osiockngso4itca7onyucapwh2kn3kxgjq",
"ProviderAddress": "f020523",
"CreatedAt": "2023-06-07T15:45:40.164474+08:00",
"PieceCid": "baga6ea4seaqp77vrfncm4kdvsls3zg4idxmeow63yxa52p47tswtolxdhdcosmq",
"PieceSize": {
"__typename": "BigInt",
"n": "16777216"
},
"IsVerified": false,
"ProposalLabel": "bafybeihcume7lo6p3dauy4bk2c47k2ays7xr2dm3wgxnsdftygfqmpyoka",
"ProviderCollateral": {
"__typename": "BigInt",
"n": "0"
},
"ClientCollateral": {
"__typename": "BigInt",
"n": "0"
},
"StoragePricePerEpoch": {
"__typename": "BigInt",
"n": "0"
},
"StartEpoch": {
"__typename": "BigInt",
"n": "632345"
},
"EndEpoch": {
"__typename": "BigInt",
"n": "1150745"
},
"ClientPeerID": "12D3KooWAQZaLb11Ljk9xisShhCgFQNQFPEA1Lnb3APifu2aFPAS",
"DealDataRoot": "bafybeihcume7lo6p3dauy4bk2c47k2ays7xr2dm3wgxnsdftygfqmpyoka",
"SignedProposalCid": "bafyreih7qaddtjxu66khjohckd3gkp42p3x5i2fhw5xjw325rnb7wvje7q",
"InboundFilePath": "",
"ChainDealID": {
"__typename": "BigInt",
"n": "0"
},
"PublishCid": "",
"IsOffline": true,
"Transfer": {
"Type": "",
"Size": {
"__typename": "BigInt",
"n": "0"
}
},
"IsTransferStalled": false,
"Checkpoint": "Accepted",
"Err": "",
"Sector": {
"ID": {
"__typename": "BigInt",
"n": "0"
},
"Offset": {
"__typename": "BigInt",
"n": "0"
},
"Length": {
"__typename": "BigInt",
"n": "0"
}
},
"Message": "Awaiting Offline Data Import"
},
{
"ID": "602e4ad9-5a0f-42b8-afac-af90c93c2719",
"ClientAddress": "f3uxq6uf56zkfiwuyqal272lxn7wjr5to7qhzd7x5u43zjt53bv4osiockngso4itca7onyucapwh2kn3kxgjq",
"ProviderAddress": "f020523",
"CreatedAt": "2023-06-07T15:45:11.478651+08:00",
"PieceCid": "baga6ea4seaqp77vrfncm4kdvsls3zg4idxmeow63yxa52p47tswtolxdhdcosmq",
"PieceSize": {
"__typename": "BigInt",
"n": "16777216"
},
"IsVerified": false,
"ProposalLabel": "bafybeihcume7lo6p3dauy4bk2c47k2ays7xr2dm3wgxnsdftygfqmpyoka",
"ProviderCollateral": {
"__typename": "BigInt",
"n": "0"
},
"ClientCollateral": {
"__typename": "BigInt",
"n": "0"
},
"StoragePricePerEpoch": {
"__typename": "BigInt",
"n": "0"
},
"StartEpoch": {
"__typename": "BigInt",
"n": "632344"
},
"EndEpoch": {
"__typename": "BigInt",
"n": "1150744"
},
"ClientPeerID": "12D3KooWAQZaLb11Ljk9xisShhCgFQNQFPEA1Lnb3APifu2aFPAS",
"DealDataRoot": "bafybeihcume7lo6p3dauy4bk2c47k2ays7xr2dm3wgxnsdftygfqmpyoka",
"SignedProposalCid": "bafyreics2zkltd4puxyksgiequszv2qvy3zvw7hlko6nnb23tdxhylv4iy",
"InboundFilePath": "",
"ChainDealID": {
"__typename": "BigInt",
"n": "0"
},
"PublishCid": "",
"IsOffline": true,
"Transfer": {
"Type": "",
"Size": {
"__typename": "BigInt",
"n": "0"
}
},
"IsTransferStalled": false,
"Checkpoint": "Accepted",
"Err": "",
"Sector": {
"ID": {
"__typename": "BigInt",
"n": "0"
},
"Offset": {
"__typename": "BigInt",
"n": "0"
},
"Length": {
"__typename": "BigInt",
"n": "0"
}
},
"Message": "Awaiting Offline Data Import"
}
]
}
}
}
Loading