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

Include verified-clients and remaining data-cap #795

Merged
merged 8 commits into from
Mar 11, 2021
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
3 changes: 2 additions & 1 deletion api/client/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ func (w *Wallet) NewAddress(ctx context.Context, name string, options ...NewAddr
return w.client.NewAddress(ctx, r)
}

// Addresses returns a list of addresses managed by the user.
// Addresses returns a list of addresses managed by the user. Each addresses *could* have
// verified-client information. If VerifiedClientInfo is nil, then the address isn't verified.
func (w *Wallet) Addresses(ctx context.Context) (*userPb.AddressesResponse, error) {
return w.client.Addresses(ctx, &userPb.AddressesRequest{})
}
Expand Down
1,292 changes: 686 additions & 606 deletions api/gen/powergate/user/v1/user.pb.go

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions api/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ import (
"github.com/textileio/powergate/v2/reputation"
txndstr "github.com/textileio/powergate/v2/txndstransform"
"github.com/textileio/powergate/v2/util"
walletModule "github.com/textileio/powergate/v2/wallet/module"
lotusWallet "github.com/textileio/powergate/v2/wallet/lotuswallet"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
Expand Down Expand Up @@ -86,7 +86,7 @@ type Server struct {
mi *minerModule.Index
fi *faultsModule.Index
dm *dealsModule.Module
wm *walletModule.Module
wm *lotusWallet.Module
rm *reputation.Module

ffsManager *manager.Manager
Expand Down Expand Up @@ -239,7 +239,7 @@ func NewServer(conf Config) (*Server, error) {
if err != nil {
return nil, fmt.Errorf("creating deal module: %s", err)
}
wm, err := walletModule.New(clientBuilder, masterAddr, conf.WalletInitialFunds, conf.AutocreateMasterAddr, networkName)
wm, err := lotusWallet.New(clientBuilder, masterAddr, conf.WalletInitialFunds, conf.AutocreateMasterAddr, networkName)
if err != nil {
return nil, fmt.Errorf("creating wallet module: %s", err)
}
Expand All @@ -261,7 +261,7 @@ func NewServer(conf Config) (*Server, error) {
if conf.Devnet {
conf.FFSMinimumPieceSize = 0
}
cs := filcold.New(ms, dm, ipfs, chain, l, lsm, conf.FFSMinimumPieceSize, conf.FFSMaxParallelDealPreparing)
cs := filcold.New(ms, dm, wm, ipfs, chain, l, lsm, conf.FFSMinimumPieceSize, conf.FFSMaxParallelDealPreparing)
hs, err := coreipfs.New(txndstr.Wrap(ds, "ffs/coreipfs"), ipfs, l)
if err != nil {
return nil, fmt.Errorf("creating coreipfs: %s", err)
Expand Down
14 changes: 13 additions & 1 deletion api/server/user/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

userPb "github.com/textileio/powergate/v2/api/gen/powergate/user/v1"
"github.com/textileio/powergate/v2/ffs/api"
"github.com/textileio/powergate/v2/wallet"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
Expand Down Expand Up @@ -55,12 +56,23 @@ func (s *Service) Addresses(ctx context.Context, req *userPb.AddressesRequest) (
if err != nil {
return nil, status.Errorf(codes.Internal, "getting address balance: %v", err)
}
res[i] = &userPb.AddrInfo{
ai := &userPb.AddrInfo{
Name: addr.Name,
Address: addr.Addr,
Type: addr.Type,
Balance: bal.String(),
}
vc, err := s.w.GetVerifiedClientInfo(ctx, addr.Addr)
if err != nil && err != wallet.ErrNoVerifiedClient {
return nil, status.Errorf(codes.Internal, "getting verified-client wallet address information: %s", err)
}
if err == nil {
ai.VerifiedClientInfo = &userPb.AddrInfo_VerifiedClientInfo{
RemainingDatacapBytes: vc.RemainingDatacapBytes.String(),
}
}

res[i] = ai
}
return &userPb.AddressesResponse{Addresses: res}, nil
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/powd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ func setupLogging(repoPath string) error {
"deals-records",

// Wallet Module
"wallet",
"lotus-wallet",

// Miner Selectors
"sr2-miner-selector",
Expand Down
2 changes: 1 addition & 1 deletion deals/module/records.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ func (m *Module) eventuallyFinalizeDeal(dr deals.StorageDealRecord, timeout time
}
return
case sm.StorageDealProposalNotFound, sm.StorageDealProposalRejected, sm.StorageDealFailing, sm.StorageDealError:
log.Infof("proposal cid %s failed with state %s, deleting pending deal", util.CidToString(info.ProposalCid), sm.DealStates[info.StateID])
log.Infof("proposal cid %s failed with state %s, saving pending deal as failed", util.CidToString(info.ProposalCid), sm.DealStates[info.StateID])

dr.Pending = false
dr.ErrMsg = fmt.Sprintf("deal failed with status %s", sm.DealStates[info.StateID])
Expand Down
30 changes: 26 additions & 4 deletions ffs/filcold/filcold.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import (
"context"
"errors"
"fmt"
"math/big"
"time"

"github.com/dustin/go-humanize"
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
"github.com/filecoin-project/go-fil-markets/storagemarket"
"github.com/filecoin-project/go-state-types/abi"
Expand All @@ -19,6 +21,7 @@ import (
"github.com/textileio/powergate/v2/ffs"
"github.com/textileio/powergate/v2/lotus"
"github.com/textileio/powergate/v2/util"
"github.com/textileio/powergate/v2/wallet"
)

const (
Expand All @@ -34,6 +37,7 @@ var (
type FilCold struct {
ms ffs.MinerSelector
dm *dealsModule.Module
wm wallet.Module
ipfs iface.CoreAPI
chain FilChain
l ffs.JobLogger
Expand All @@ -50,10 +54,11 @@ type FilChain interface {
}

// New returns a new FilCold instance.
func New(ms ffs.MinerSelector, dm *dealsModule.Module, ipfs iface.CoreAPI, chain FilChain, l ffs.JobLogger, lsm *lotus.SyncMonitor, minPieceSize uint64, maxParallelDealPreparing int) *FilCold {
func New(ms ffs.MinerSelector, dm *dealsModule.Module, wm wallet.Module, ipfs iface.CoreAPI, chain FilChain, l ffs.JobLogger, lsm *lotus.SyncMonitor, minPieceSize uint64, maxParallelDealPreparing int) *FilCold {
return &FilCold{
ms: ms,
dm: dm,
wm: wm,
ipfs: ipfs,
chain: chain,
l: l,
Expand All @@ -80,7 +85,7 @@ func (fc *FilCold) Fetch(ctx context.Context, pyCid cid.Cid, piCid *cid.Cid, wad
strEvent := retrievalmarket.ClientEvents[e.Event]
strDealStatus := retrievalmarket.DealStatuses[e.Status]
fundsSpent = e.FundsSpent.Uint64()
newMsg := fmt.Sprintf("Received %.2fGiB, total spent: %sFIL (%s/%s)", float64(e.BytesReceived)/1024/1024/1024, util.AttoFilToFil(fundsSpent), strEvent, strDealStatus)
newMsg := fmt.Sprintf("Received %s, total spent: %sFIL (%s/%s)", humanize.IBytes(e.BytesReceived), util.AttoFilToFil(fundsSpent), strEvent, strDealStatus)
if newMsg != lastMsg {
fc.l.Log(ctx, newMsg)
lastMsg = newMsg
Expand Down Expand Up @@ -125,10 +130,27 @@ func (fc *FilCold) Store(ctx context.Context, c cid.Cid, cfg ffs.FilConfig) ([]c
if err != nil {
return nil, nil, 0, fmt.Errorf("getting cid cummulative size: %s", err)
}
fc.l.Log(ctx, "Data size is %d MiB, its calculated piece size is %d MiB.", payloadSize/1024/1024, pieceSize/1024/1024)
fc.l.Log(ctx, "The payload size is %s, and the calculated piece size is %s", humanize.IBytes(uint64(payloadSize)), humanize.IBytes(uint64(pieceSize)))

if uint64(pieceSize) < fc.minPieceSize {
return nil, nil, 0, fmt.Errorf("Piece size is below allowed minimum %d MiB", fc.minPieceSize/1024/1024)
return nil, nil, 0, fmt.Errorf("Piece size is below allowed minimum %s", humanize.IBytes(fc.minPieceSize))
}

if cfg.VerifiedDeal {
vci, err := fc.wm.GetVerifiedClientInfo(ctx, cfg.Addr)
if err != nil && err != wallet.ErrNoVerifiedClient {
return nil, nil, 0, fmt.Errorf("get address verified client info: %s", err)
}
if err == wallet.ErrNoVerifiedClient {
return nil, nil, 0, fmt.Errorf("wallet address isn't a verified client")
}

pieceSizeBig := big.NewInt(int64(pieceSize))
if pieceSizeBig.Cmp(big.NewInt(0).Mul(big.NewInt(int64(cfg.RepFactor)), vci.RemainingDatacapBytes)) == 1 {
return nil, nil, 0, fmt.Errorf("the remaining data-cap %s is less than piece-size %s * rep-factor %d", humanize.IBytes(uint64(pieceSize)), humanize.IBytes(vci.RemainingDatacapBytes.Uint64()), cfg.RepFactor)
}

fc.l.Log(ctx, "Attempting to use %s of data-cap. The current quota is %s", humanize.IBytes(uint64(pieceSize)*uint64(cfg.RepFactor)), humanize.IBytes(vci.RemainingDatacapBytes.Uint64()))
}
f := ffs.MinerSelectorFilter{
ExcludedMiners: cfg.ExcludedMiners,
Expand Down
6 changes: 3 additions & 3 deletions ffs/integrationtest/manager/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (
dealsModule "github.com/textileio/powergate/v2/deals/module"
it "github.com/textileio/powergate/v2/ffs/integrationtest"
txndstr "github.com/textileio/powergate/v2/txndstransform"
walletModule "github.com/textileio/powergate/v2/wallet/module"
lotusWallet "github.com/textileio/powergate/v2/wallet/lotuswallet"
)

const (
Expand Down Expand Up @@ -86,13 +86,13 @@ func NewCustomFFSManager(t require.TestingT, ds datastore.TxnDatastore, cb lotus
l := joblogger.New(txndstr.Wrap(ds, "ffs/joblogger"))
lsm, err := lotus.NewSyncMonitor(cb)
require.NoError(t, err)
cl := filcold.New(ms, dm, ipfsClient, fchain, l, lsm, minimumPieceSize, 1)
cl := filcold.New(ms, dm, nil, ipfsClient, fchain, l, lsm, minimumPieceSize, 1)
hl, err := coreipfs.New(ds, ipfsClient, l)
require.NoError(t, err)
sched, err := scheduler.New(txndstr.Wrap(ds, "ffs/scheduler"), l, hl, cl, 10, time.Minute*10, nil, scheduler.GCConfig{AutoGCInterval: 0})
require.NoError(t, err)

wm, err := walletModule.New(cb, masterAddr, *big.NewInt(iWalletBal), false, "")
wm, err := lotusWallet.New(cb, masterAddr, *big.NewInt(iWalletBal), false, "")
require.NoError(t, err)

manager, err := manager.New(ds, wm, dm, sched, false, true)
Expand Down
4 changes: 2 additions & 2 deletions ffs/manager/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
"github.com/textileio/powergate/v2/tests"
txndstr "github.com/textileio/powergate/v2/txndstransform"
"github.com/textileio/powergate/v2/util"
walletModule "github.com/textileio/powergate/v2/wallet/module"
lotusWallet "github.com/textileio/powergate/v2/wallet/lotuswallet"
)

func TestMain(m *testing.M) {
Expand Down Expand Up @@ -194,7 +194,7 @@ func TestDefaultStorageConfig(t *testing.T) {
}

func newManager(clientBuilder lotus.ClientBuilder, ds datastore.TxnDatastore, masterAddr address.Address, ffsUseMasterAddr bool) (*Manager, func() error, error) {
wm, err := walletModule.New(clientBuilder, masterAddr, *big.NewInt(4000000000), false, "")
wm, err := lotusWallet.New(clientBuilder, masterAddr, *big.NewInt(4000000000), false, "")
if err != nil {
return nil, func() error { return nil }, err
}
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ require (
github.com/containerd/continuity v0.0.0-20200228182428-0f16d7a0959c // indirect
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
github.com/dustin/go-humanize v1.0.0
github.com/filecoin-project/go-address v0.0.5
github.com/filecoin-project/go-data-transfer v1.2.7
github.com/filecoin-project/go-fil-markets v1.1.9
Expand Down
5 changes: 5 additions & 0 deletions proto/powergate/user/v1/user.proto
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,11 @@ message AddrInfo {
string address = 2;
string type = 3;
string balance = 4;
VerifiedClientInfo verified_client_info = 5;

message VerifiedClientInfo {
string remaining_datacap_bytes = 1;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is string since the native type is BigInt, so in some extreme case, the user could have a lot of verified deal capacity.

}
}

message CidSummary {
Expand Down
38 changes: 36 additions & 2 deletions wallet/module/wallet.go → wallet/lotuswallet/wallet.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package module
package lotuswallet
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exploring moving away from module package names, too generic.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good to me.


import (
"context"
Expand All @@ -11,18 +11,20 @@ import (

"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/lotus/api/apistruct"
"github.com/filecoin-project/lotus/chain/types"
"github.com/ipfs/go-cid"
logger "github.com/ipfs/go-log/v2"
"github.com/textileio/powergate/v2/lotus"
"github.com/textileio/powergate/v2/wallet"
)

const (
feeThreshold = 1_000_000
)

var (
log = logger.Logger("wallet")
log = logger.Logger("lotus-wallet")
networkFaucet = map[string]string{}
)

Expand Down Expand Up @@ -257,3 +259,35 @@ func (m *Module) FundFromFaucet(ctx context.Context, addr string) error {
}
return nil
}

// GetVerifiedClientInfo returns details about a wallet-address that's
// a verified client. If the wallet address isn't a verified client,
// it will return ErrNoVerifiedClient.
func (m *Module) GetVerifiedClientInfo(ctx context.Context, addr string) (wallet.VerifiedClientInfo, error) {
c, cls, err := m.clientBuilder(ctx)
if err != nil {
return wallet.VerifiedClientInfo{}, fmt.Errorf("creating lotus client: %s", err)
}
defer cls()

a, err := address.NewFromString(addr)
if err != nil {
return wallet.VerifiedClientInfo{}, fmt.Errorf("parsing wallet-address: %s", err)
}

return getVerifiedClientInfo(ctx, c, a)
}

func getVerifiedClientInfo(ctx context.Context, c *apistruct.FullNodeStruct, addr address.Address) (wallet.VerifiedClientInfo, error) {
sp, err := c.StateVerifiedClientStatus(ctx, addr, types.EmptyTSK)
if err != nil {
return wallet.VerifiedClientInfo{}, fmt.Errorf("getting verified-client information: %s", err)
}
if sp == nil {
return wallet.VerifiedClientInfo{}, wallet.ErrNoVerifiedClient
}

return wallet.VerifiedClientInfo{
RemainingDatacapBytes: sp.Int,
}, nil
}
23 changes: 23 additions & 0 deletions wallet/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,39 @@ package wallet

import (
"context"
"errors"
"math/big"

"github.com/ipfs/go-cid"
)

var (
// ErrNoVerifiedClient indicates that the provided
// wallet-address isn't a verified client.
ErrNoVerifiedClient = errors.New("the wallet-address isn't a verified client")
)

// VerifiedClientInfo contains information for a wallet address
// that is a verified-client.
type VerifiedClientInfo struct {
RemainingDatacapBytes *big.Int
}

// Module provides wallet management access to a Filecoin client.
type Module interface {
// NewAddress returns a new wallet address of the specified type.
NewAddress(ctx context.Context, typ string) (string, error)
// List lists all known wallet addresses.
List(ctx context.Context) ([]string, error)
// GetVerifiedClientInfo returns details about a wallet-address that's
// a verified client. If the wallet address isn't a verified client,
// it will return ErrNoVerifiedClient.
GetVerifiedClientInfo(ctx context.Context, addr string) (VerifiedClientInfo, error)
// Balance returns the balance of a wallet-address.
Balance(ctx context.Context, addr string) (*big.Int, error)
// SendFil sends `amount` attoFIL from `from` to `to` and returns the
// message Cid.
SendFil(ctx context.Context, from string, to string, amount *big.Int) (cid.Cid, error)
// FundFromFaucet funds addr from the master address (if configured).
FundFromFaucet(ctx context.Context, addr string) error
}