Merge remote-tracking branch 'origin/master' into feat/signing-backends
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
package impl
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/lib/backupds"
|
||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||
)
|
||||
|
||||
func backup(mds dtypes.MetadataDS, fpath string) error {
|
||||
bb, ok := os.LookupEnv("LOTUS_BACKUP_BASE_PATH")
|
||||
if !ok {
|
||||
return xerrors.Errorf("LOTUS_BACKUP_BASE_PATH env var not set")
|
||||
}
|
||||
|
||||
bds, ok := mds.(*backupds.Datastore)
|
||||
if !ok {
|
||||
return xerrors.Errorf("expected a backup datastore")
|
||||
}
|
||||
|
||||
bb, err := homedir.Expand(bb)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("expanding base path: %w", err)
|
||||
}
|
||||
|
||||
bb, err = filepath.Abs(bb)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting absolute base path: %w", err)
|
||||
}
|
||||
|
||||
fpath, err = homedir.Expand(fpath)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("expanding file path: %w", err)
|
||||
}
|
||||
|
||||
fpath, err = filepath.Abs(fpath)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting absolute file path: %w", err)
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(fpath, bb) {
|
||||
return xerrors.Errorf("backup file name (%s) must be inside base path (%s)", fpath, bb)
|
||||
}
|
||||
|
||||
out, err := os.OpenFile(fpath, os.O_CREATE|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("open %s: %w", fpath, err)
|
||||
}
|
||||
|
||||
if err := bds.Backup(out); err != nil {
|
||||
if cerr := out.Close(); cerr != nil {
|
||||
log.Errorw("error closing backup file while handling backup error", "closeErr", cerr, "backupErr", err)
|
||||
}
|
||||
return xerrors.Errorf("backup error: %w", err)
|
||||
}
|
||||
|
||||
if err := out.Close(); err != nil {
|
||||
return xerrors.Errorf("closing backup file: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
+28
-13
@@ -6,8 +6,10 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/dline"
|
||||
|
||||
datatransfer "github.com/filecoin-project/go-data-transfer"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi/big"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/ipfs/go-blockservice"
|
||||
@@ -31,6 +33,7 @@ import (
|
||||
"go.uber.org/fx"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-fil-markets/discovery"
|
||||
"github.com/filecoin-project/go-fil-markets/pieceio"
|
||||
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
||||
rm "github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
||||
@@ -38,8 +41,7 @@ import (
|
||||
"github.com/filecoin-project/go-fil-markets/storagemarket"
|
||||
"github.com/filecoin-project/go-multistore"
|
||||
"github.com/filecoin-project/go-padreader"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
|
||||
marketevents "github.com/filecoin-project/lotus/markets/loggers"
|
||||
@@ -57,7 +59,7 @@ import (
|
||||
|
||||
var DefaultHashFunction = uint64(mh.BLAKE2B_MIN + 31)
|
||||
|
||||
const dealStartBufferHours uint64 = 24
|
||||
const dealStartBufferHours uint64 = 49
|
||||
|
||||
type API struct {
|
||||
fx.In
|
||||
@@ -68,7 +70,7 @@ type API struct {
|
||||
paych.PaychAPI
|
||||
|
||||
SMDealClient storagemarket.StorageClient
|
||||
RetDiscovery rm.PeerResolver
|
||||
RetDiscovery discovery.PeerResolver
|
||||
Retrieval rm.RetrievalClient
|
||||
Chain *store.ChainStore
|
||||
|
||||
@@ -80,12 +82,12 @@ type API struct {
|
||||
Host host.Host
|
||||
}
|
||||
|
||||
func calcDealExpiration(minDuration uint64, md *miner.DeadlineInfo, startEpoch abi.ChainEpoch) abi.ChainEpoch {
|
||||
func calcDealExpiration(minDuration uint64, md *dline.Info, startEpoch abi.ChainEpoch) abi.ChainEpoch {
|
||||
// Make sure we give some time for the miner to seal
|
||||
minExp := startEpoch + abi.ChainEpoch(minDuration)
|
||||
|
||||
// Align on miners ProvingPeriodBoundary
|
||||
return minExp + miner.WPoStProvingPeriod - (minExp % miner.WPoStProvingPeriod) + (md.PeriodStart % miner.WPoStProvingPeriod) - 1
|
||||
return minExp + md.WPoStProvingPeriod - (minExp % md.WPoStProvingPeriod) + (md.PeriodStart % md.WPoStProvingPeriod) - 1
|
||||
}
|
||||
|
||||
func (a *API) imgr() *importmgr.Mgr {
|
||||
@@ -114,7 +116,13 @@ func (a *API) ClientStartDeal(ctx context.Context, params *api.StartDealParams)
|
||||
}
|
||||
}
|
||||
}
|
||||
exist, err := a.WalletHas(ctx, params.Wallet)
|
||||
|
||||
walletKey, err := a.StateAPI.StateManager.ResolveToKeyAddress(ctx, params.Wallet, nil)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed resolving params.Wallet addr: %w", params.Wallet)
|
||||
}
|
||||
|
||||
exist, err := a.WalletHas(ctx, walletKey)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed getting addr from wallet: %w", params.Wallet)
|
||||
}
|
||||
@@ -151,7 +159,7 @@ func (a *API) ClientStartDeal(ctx context.Context, params *api.StartDealParams)
|
||||
}
|
||||
|
||||
blocksPerHour := 60 * 60 / build.BlockDelaySecs
|
||||
dealStart = ts.Height() + abi.ChainEpoch(dealStartBufferHours*blocksPerHour)
|
||||
dealStart = ts.Height() + abi.ChainEpoch(dealStartBufferHours*blocksPerHour) // TODO: Get this from storage ask
|
||||
}
|
||||
|
||||
result, err := a.SMDealClient.ProposeStorageDeal(ctx, storagemarket.ProposeStorageDealParams{
|
||||
@@ -197,6 +205,7 @@ func (a *API) ClientListDeals(ctx context.Context) ([]api.DealInfo, error) {
|
||||
Duration: uint64(v.Proposal.Duration()),
|
||||
DealID: v.DealID,
|
||||
CreationTime: v.CreationTime.Time(),
|
||||
Verified: v.Proposal.VerifiedDeal,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,6 +229,7 @@ func (a *API) ClientGetDealInfo(ctx context.Context, d cid.Cid) (*api.DealInfo,
|
||||
Duration: uint64(v.Proposal.Duration()),
|
||||
DealID: v.DealID,
|
||||
CreationTime: v.CreationTime.Time(),
|
||||
Verified: v.Proposal.VerifiedDeal,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -612,18 +622,18 @@ func (a *API) clientRetrieve(ctx context.Context, order api.RetrievalOrder, ref
|
||||
return
|
||||
}
|
||||
|
||||
func (a *API) ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.SignedStorageAsk, error) {
|
||||
func (a *API) ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.StorageAsk, error) {
|
||||
mi, err := a.StateMinerInfo(ctx, miner, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed getting miner info: %w", err)
|
||||
}
|
||||
|
||||
info := utils.NewStorageProviderInfo(miner, mi.Worker, mi.SectorSize, p, mi.Multiaddrs)
|
||||
signedAsk, err := a.SMDealClient.GetAsk(ctx, info)
|
||||
ask, err := a.SMDealClient.GetAsk(ctx, info)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return signedAsk, nil
|
||||
return ask, nil
|
||||
}
|
||||
|
||||
func (a *API) ClientCalcCommP(ctx context.Context, inpath string) (*api.CommPRet, error) {
|
||||
@@ -709,7 +719,7 @@ func (a *API) ClientGenCar(ctx context.Context, ref api.FileRef, outputPath stri
|
||||
|
||||
// TODO: does that defer mean to remove the whole blockstore?
|
||||
defer bufferedDS.Remove(ctx, c) //nolint:errcheck
|
||||
ssb := builder.NewSelectorSpecBuilder(basicnode.Style.Any)
|
||||
ssb := builder.NewSelectorSpecBuilder(basicnode.Prototype.Any)
|
||||
|
||||
// entire DAG selector
|
||||
allSelector := ssb.ExploreRecursive(selector.RecursionLimitNone(),
|
||||
@@ -845,5 +855,10 @@ func newDealInfo(v storagemarket.ClientDeal) api.DealInfo {
|
||||
Duration: uint64(v.Proposal.Duration()),
|
||||
DealID: v.DealID,
|
||||
CreationTime: v.CreationTime.Time(),
|
||||
Verified: v.Proposal.VerifiedDeal,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *API) ClientRetrieveTryRestartInsufficientFunds(ctx context.Context, paymentChannel address.Address) error {
|
||||
return a.Retrieval.TryRestartInsufficientFunds(paymentChannel)
|
||||
}
|
||||
|
||||
@@ -121,6 +121,12 @@ func (a *CommonAPI) NetFindPeer(ctx context.Context, p peer.ID) (peer.AddrInfo,
|
||||
func (a *CommonAPI) NetAutoNatStatus(ctx context.Context) (i api.NatInfo, err error) {
|
||||
autonat := a.RawHost.(*basichost.BasicHost).AutoNat
|
||||
|
||||
if autonat == nil {
|
||||
return api.NatInfo{
|
||||
Reachability: network.ReachabilityUnknown,
|
||||
}, nil
|
||||
}
|
||||
|
||||
var maddr string
|
||||
if autonat.Status() == network.ReachabilityPublic {
|
||||
pa, err := autonat.PublicAddr()
|
||||
@@ -170,9 +176,14 @@ func (a *CommonAPI) ID(context.Context) (peer.ID, error) {
|
||||
}
|
||||
|
||||
func (a *CommonAPI) Version(context.Context) (api.Version, error) {
|
||||
v, err := build.VersionForType(build.RunningNodeType)
|
||||
if err != nil {
|
||||
return api.Version{}, err
|
||||
}
|
||||
|
||||
return api.Version{
|
||||
Version: build.UserVersion(),
|
||||
APIVersion: build.APIVersion,
|
||||
APIVersion: v,
|
||||
|
||||
BlockDelay: build.BlockDelaySecs,
|
||||
}, nil
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package impl
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
@@ -9,6 +11,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/node/impl/full"
|
||||
"github.com/filecoin-project/lotus/node/impl/market"
|
||||
"github.com/filecoin-project/lotus/node/impl/paych"
|
||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||
)
|
||||
|
||||
var log = logging.Logger("node")
|
||||
@@ -26,6 +29,12 @@ type FullNodeAPI struct {
|
||||
full.WalletAPI
|
||||
full.SyncAPI
|
||||
full.BeaconAPI
|
||||
|
||||
DS dtypes.MetadataDS
|
||||
}
|
||||
|
||||
func (n *FullNodeAPI) CreateBackup(ctx context.Context, fpath string) error {
|
||||
return backup(n.DS, fpath)
|
||||
}
|
||||
|
||||
var _ api.FullNode = &FullNodeAPI{}
|
||||
|
||||
@@ -4,21 +4,22 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/lotus/chain/beacon"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"go.uber.org/fx"
|
||||
)
|
||||
|
||||
type BeaconAPI struct {
|
||||
fx.In
|
||||
|
||||
Beacon beacon.RandomBeacon
|
||||
Beacon beacon.Schedule
|
||||
}
|
||||
|
||||
func (a *BeaconAPI) BeaconGetEntry(ctx context.Context, epoch abi.ChainEpoch) (*types.BeaconEntry, error) {
|
||||
rr := a.Beacon.MaxBeaconRoundForEpoch(epoch, types.BeaconEntry{})
|
||||
e := a.Beacon.Entry(ctx, rr)
|
||||
b := a.Beacon.BeaconForEpoch(epoch)
|
||||
rr := b.MaxBeaconRoundForEpoch(epoch)
|
||||
e := b.Entry(ctx, rr)
|
||||
|
||||
select {
|
||||
case be, ok := <-e:
|
||||
|
||||
+52
-20
@@ -26,8 +26,8 @@ import (
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
"github.com/filecoin-project/specs-actors/actors/util/adt"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
@@ -197,6 +197,10 @@ func (a *ChainAPI) ChainReadObj(ctx context.Context, obj cid.Cid) ([]byte, error
|
||||
return blk.RawData(), nil
|
||||
}
|
||||
|
||||
func (a *ChainAPI) ChainDeleteObj(ctx context.Context, obj cid.Cid) error {
|
||||
return a.Chain.Blockstore().DeleteBlock(obj)
|
||||
}
|
||||
|
||||
func (a *ChainAPI) ChainHasObj(ctx context.Context, obj cid.Cid) (bool, error) {
|
||||
return a.Chain.Blockstore().Has(obj)
|
||||
}
|
||||
@@ -250,11 +254,31 @@ func (a *ChainAPI) ChainStatObj(ctx context.Context, obj cid.Cid, base cid.Cid)
|
||||
}
|
||||
|
||||
func (a *ChainAPI) ChainSetHead(ctx context.Context, tsk types.TipSetKey) error {
|
||||
ts, err := a.Chain.GetTipSetFromKey(tsk)
|
||||
newHeadTs, err := a.Chain.GetTipSetFromKey(tsk)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
||||
}
|
||||
return a.Chain.SetHead(ts)
|
||||
|
||||
currentTs, err := a.ChainHead(ctx)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting head: %w", err)
|
||||
}
|
||||
|
||||
for currentTs.Height() >= newHeadTs.Height() {
|
||||
for _, blk := range currentTs.Key().Cids() {
|
||||
err = a.Chain.UnmarkBlockAsValidated(ctx, blk)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("unmarking block as validated %s: %w", blk, err)
|
||||
}
|
||||
}
|
||||
|
||||
currentTs, err = a.ChainGetTipSet(ctx, currentTs.Parents())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("loading tipset: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return a.Chain.SetHead(newHeadTs)
|
||||
}
|
||||
|
||||
func (a *ChainAPI) ChainGetGenesis(ctx context.Context) (*types.TipSet, error) {
|
||||
@@ -281,6 +305,8 @@ func (s stringKey) Key() string {
|
||||
return (string)(s)
|
||||
}
|
||||
|
||||
// TODO: ActorUpgrade: this entire function is a problem (in theory) as we don't know the HAMT version.
|
||||
// In practice, hamt v0 should work "just fine" for reading.
|
||||
func resolveOnce(bs blockstore.Blockstore) func(ctx context.Context, ds ipld.NodeGetter, nd ipld.Node, names []string) (*ipld.Link, []string, error) {
|
||||
return func(ctx context.Context, ds ipld.NodeGetter, nd ipld.Node, names []string) (*ipld.Link, []string, error) {
|
||||
store := adt.WrapStore(ctx, cbor.NewCborStore(bs))
|
||||
@@ -300,7 +326,7 @@ func resolveOnce(bs blockstore.Blockstore) func(ctx context.Context, ds ipld.Nod
|
||||
return nil, nil, xerrors.Errorf("parsing int64: %w", err)
|
||||
}
|
||||
|
||||
ik := adt.IntKey(i)
|
||||
ik := abi.IntKey(i)
|
||||
|
||||
names[0] = "@H:" + ik.Key()
|
||||
}
|
||||
@@ -311,7 +337,7 @@ func resolveOnce(bs blockstore.Blockstore) func(ctx context.Context, ds ipld.Nod
|
||||
return nil, nil, xerrors.Errorf("parsing uint64: %w", err)
|
||||
}
|
||||
|
||||
ik := adt.UIntKey(i)
|
||||
ik := abi.UIntKey(i)
|
||||
|
||||
names[0] = "@H:" + ik.Key()
|
||||
}
|
||||
@@ -418,7 +444,7 @@ func resolveOnce(bs blockstore.Blockstore) func(ctx context.Context, ds ipld.Nod
|
||||
return nil, nil, xerrors.Errorf("getting actor head for @state: %w", err)
|
||||
}
|
||||
|
||||
m, err := vm.DumpActorState(act.Code, head.RawData())
|
||||
m, err := vm.DumpActorState(&act, head.RawData())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -495,7 +521,7 @@ func (a *ChainAPI) ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Mess
|
||||
return cm.VMMessage(), nil
|
||||
}
|
||||
|
||||
func (a *ChainAPI) ChainExport(ctx context.Context, nroots abi.ChainEpoch, tsk types.TipSetKey) (<-chan []byte, error) {
|
||||
func (a *ChainAPI) ChainExport(ctx context.Context, nroots abi.ChainEpoch, skipoldmsgs bool, tsk types.TipSetKey) (<-chan []byte, error) {
|
||||
ts, err := a.Chain.GetTipSetFromKey(tsk)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
||||
@@ -503,15 +529,11 @@ func (a *ChainAPI) ChainExport(ctx context.Context, nroots abi.ChainEpoch, tsk t
|
||||
r, w := io.Pipe()
|
||||
out := make(chan []byte)
|
||||
go func() {
|
||||
defer w.Close() //nolint:errcheck // it is a pipe
|
||||
|
||||
bw := bufio.NewWriterSize(w, 1<<20)
|
||||
defer bw.Flush() //nolint:errcheck // it is a write to a pipe
|
||||
|
||||
if err := a.Chain.Export(ctx, ts, nroots, bw); err != nil {
|
||||
log.Errorf("chain export call failed: %s", err)
|
||||
return
|
||||
}
|
||||
err := a.Chain.Export(ctx, ts, nroots, skipoldmsgs, bw)
|
||||
bw.Flush() //nolint:errcheck // it is a write to a pipe
|
||||
w.CloseWithError(err) //nolint:errcheck // it is a pipe
|
||||
}()
|
||||
|
||||
go func() {
|
||||
@@ -523,13 +545,23 @@ func (a *ChainAPI) ChainExport(ctx context.Context, nroots abi.ChainEpoch, tsk t
|
||||
log.Errorf("chain export pipe read failed: %s", err)
|
||||
return
|
||||
}
|
||||
select {
|
||||
case out <- buf[:n]:
|
||||
case <-ctx.Done():
|
||||
log.Warnf("export writer failed: %s", ctx.Err())
|
||||
return
|
||||
if n > 0 {
|
||||
select {
|
||||
case out <- buf[:n]:
|
||||
case <-ctx.Done():
|
||||
log.Warnf("export writer failed: %s", ctx.Err())
|
||||
return
|
||||
}
|
||||
}
|
||||
if err == io.EOF {
|
||||
// send empty slice to indicate correct eof
|
||||
select {
|
||||
case out <- []byte{}:
|
||||
case <-ctx.Done():
|
||||
log.Warnf("export writer failed: %s", ctx.Err())
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
+66
-56
@@ -6,21 +6,24 @@ import (
|
||||
"math/rand"
|
||||
"sort"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin"
|
||||
|
||||
"go.uber.org/fx"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"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/exitcode"
|
||||
|
||||
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/messagepool"
|
||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi/big"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
"github.com/filecoin-project/specs-actors/actors/runtime/exitcode"
|
||||
|
||||
"go.uber.org/fx"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
type GasAPI struct {
|
||||
@@ -50,6 +53,35 @@ func (a *GasAPI) GasEstimateFeeCap(ctx context.Context, msg *types.Message, maxq
|
||||
return out, nil
|
||||
}
|
||||
|
||||
type gasMeta struct {
|
||||
price big.Int
|
||||
limit int64
|
||||
}
|
||||
|
||||
func medianGasPremium(prices []gasMeta, blocks int) abi.TokenAmount {
|
||||
sort.Slice(prices, func(i, j int) bool {
|
||||
// sort desc by price
|
||||
return prices[i].price.GreaterThan(prices[j].price)
|
||||
})
|
||||
|
||||
at := build.BlockGasTarget * int64(blocks) / 2
|
||||
prev1, prev2 := big.Zero(), big.Zero()
|
||||
for _, price := range prices {
|
||||
prev1, prev2 = price.price, prev1
|
||||
at -= price.limit
|
||||
if at < 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
premium := prev1
|
||||
if prev2.Sign() != 0 {
|
||||
premium = big.Div(types.BigAdd(prev1, prev2), types.NewInt(2))
|
||||
}
|
||||
|
||||
return premium
|
||||
}
|
||||
|
||||
func (a *GasAPI) GasEstimateGasPremium(ctx context.Context, nblocksincl uint64,
|
||||
sender address.Address, gaslimit int64, _ types.TipSetKey) (types.BigInt, error) {
|
||||
|
||||
@@ -57,11 +89,6 @@ func (a *GasAPI) GasEstimateGasPremium(ctx context.Context, nblocksincl uint64,
|
||||
nblocksincl = 1
|
||||
}
|
||||
|
||||
type gasMeta struct {
|
||||
price big.Int
|
||||
limit int64
|
||||
}
|
||||
|
||||
var prices []gasMeta
|
||||
var blocks int
|
||||
|
||||
@@ -92,25 +119,7 @@ func (a *GasAPI) GasEstimateGasPremium(ctx context.Context, nblocksincl uint64,
|
||||
ts = pts
|
||||
}
|
||||
|
||||
sort.Slice(prices, func(i, j int) bool {
|
||||
// sort desc by price
|
||||
return prices[i].price.GreaterThan(prices[j].price)
|
||||
})
|
||||
|
||||
at := build.BlockGasTarget * int64(blocks) / 2
|
||||
prev1, prev2 := big.Zero(), big.Zero()
|
||||
for _, price := range prices {
|
||||
prev1, prev2 = price.price, prev1
|
||||
at -= price.limit
|
||||
if at > 0 {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
premium := prev1
|
||||
if prev2.Sign() != 0 {
|
||||
premium = big.Div(types.BigAdd(prev1, prev2), types.NewInt(2))
|
||||
}
|
||||
premium := medianGasPremium(prices, blocks)
|
||||
|
||||
if types.BigCmp(premium, types.NewInt(MinGasPremium)) < 0 {
|
||||
switch nblocksincl {
|
||||
@@ -151,7 +160,18 @@ func (a *GasAPI) GasEstimateGasLimit(ctx context.Context, msgIn *types.Message,
|
||||
priorMsgs = append(priorMsgs, m)
|
||||
}
|
||||
|
||||
res, err := a.Stmgr.CallWithGas(ctx, &msg, priorMsgs, ts)
|
||||
// Try calling until we find a height with no migration.
|
||||
var res *api.InvocResult
|
||||
for {
|
||||
res, err = a.Stmgr.CallWithGas(ctx, &msg, priorMsgs, ts)
|
||||
if err != stmgr.ErrExpensiveFork {
|
||||
break
|
||||
}
|
||||
ts, err = a.Chain.GetTipSetFromKey(ts.Parents())
|
||||
if err != nil {
|
||||
return -1, xerrors.Errorf("getting parent tipset: %w", err)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return -1, xerrors.Errorf("CallWithGas failed: %w", err)
|
||||
}
|
||||
@@ -160,8 +180,14 @@ func (a *GasAPI) GasEstimateGasLimit(ctx context.Context, msgIn *types.Message,
|
||||
}
|
||||
|
||||
// Special case for PaymentChannel collect, which is deleting actor
|
||||
var act types.Actor
|
||||
err = a.Stmgr.WithParentState(ts, a.Stmgr.WithActor(msg.To, stmgr.GetActor(&act)))
|
||||
st, err := a.Stmgr.ParentState(ts)
|
||||
if err != nil {
|
||||
_ = err
|
||||
// somewhat ignore it as it can happen and we just want to detect
|
||||
// an existing PaymentChannel actor
|
||||
return res.MsgRct.GasUsed, nil
|
||||
}
|
||||
act, err := st.GetActor(msg.To)
|
||||
if err != nil {
|
||||
_ = err
|
||||
// somewhat ignore it as it can happen and we just want to detect
|
||||
@@ -169,10 +195,10 @@ func (a *GasAPI) GasEstimateGasLimit(ctx context.Context, msgIn *types.Message,
|
||||
return res.MsgRct.GasUsed, nil
|
||||
}
|
||||
|
||||
if !act.Code.Equals(builtin.PaymentChannelActorCodeID) {
|
||||
if !builtin.IsPaymentChannelActor(act.Code) {
|
||||
return res.MsgRct.GasUsed, nil
|
||||
}
|
||||
if msgIn.Method != builtin.MethodsPaych.Collect {
|
||||
if msgIn.Method != builtin0.MethodsPaych.Collect {
|
||||
return res.MsgRct.GasUsed, nil
|
||||
}
|
||||
|
||||
@@ -198,30 +224,14 @@ func (a *GasAPI) GasEstimateMessageGas(ctx context.Context, msg *types.Message,
|
||||
}
|
||||
|
||||
if msg.GasFeeCap == types.EmptyInt || types.BigCmp(msg.GasFeeCap, types.NewInt(0)) == 0 {
|
||||
feeCap, err := a.GasEstimateFeeCap(ctx, msg, 10, types.EmptyTSK)
|
||||
feeCap, err := a.GasEstimateFeeCap(ctx, msg, 20, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("estimating fee cap: %w", err)
|
||||
}
|
||||
msg.GasFeeCap = feeCap
|
||||
}
|
||||
|
||||
capGasFee(msg, spec.Get().MaxFee)
|
||||
messagepool.CapGasFee(msg, spec.Get().MaxFee)
|
||||
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
func capGasFee(msg *types.Message, maxFee abi.TokenAmount) {
|
||||
if maxFee.Equals(big.Zero()) {
|
||||
maxFee = types.NewInt(build.FilecoinPrecision / 10)
|
||||
}
|
||||
|
||||
gl := types.NewInt(uint64(msg.GasLimit))
|
||||
totalFee := types.BigMul(msg.GasFeeCap, gl)
|
||||
|
||||
if totalFee.LessThanEqual(maxFee) {
|
||||
return
|
||||
}
|
||||
|
||||
msg.GasFeeCap = big.Div(maxFee, gl)
|
||||
msg.GasPremium = big.Min(msg.GasFeeCap, msg.GasPremium) // cap premium at FeeCap
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package full
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
func TestMedian(t *testing.T) {
|
||||
require.Equal(t, types.NewInt(5), medianGasPremium([]gasMeta{
|
||||
{big.NewInt(5), build.BlockGasTarget},
|
||||
}, 1))
|
||||
|
||||
require.Equal(t, types.NewInt(10), medianGasPremium([]gasMeta{
|
||||
{big.NewInt(5), build.BlockGasTarget},
|
||||
{big.NewInt(10), build.BlockGasTarget},
|
||||
}, 1))
|
||||
|
||||
require.Equal(t, types.NewInt(15), medianGasPremium([]gasMeta{
|
||||
{big.NewInt(10), build.BlockGasTarget / 2},
|
||||
{big.NewInt(20), build.BlockGasTarget / 2},
|
||||
}, 1))
|
||||
|
||||
require.Equal(t, types.NewInt(25), medianGasPremium([]gasMeta{
|
||||
{big.NewInt(10), build.BlockGasTarget / 2},
|
||||
{big.NewInt(20), build.BlockGasTarget / 2},
|
||||
{big.NewInt(30), build.BlockGasTarget / 2},
|
||||
}, 1))
|
||||
|
||||
require.Equal(t, types.NewInt(15), medianGasPremium([]gasMeta{
|
||||
{big.NewInt(10), build.BlockGasTarget / 2},
|
||||
{big.NewInt(20), build.BlockGasTarget / 2},
|
||||
{big.NewInt(30), build.BlockGasTarget / 2},
|
||||
}, 2))
|
||||
}
|
||||
+40
-34
@@ -2,6 +2,7 @@ package full
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/ipfs/go-cid"
|
||||
@@ -9,8 +10,7 @@ import (
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/messagepool"
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
"github.com/filecoin-project/lotus/chain/messagesigner"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||
)
|
||||
@@ -21,9 +21,7 @@ type MpoolAPI struct {
|
||||
WalletAPI
|
||||
GasAPI
|
||||
|
||||
Chain *store.ChainStore
|
||||
|
||||
Mpool *messagepool.MessagePool
|
||||
MessageSigner *messagesigner.MessageSigner
|
||||
|
||||
PushLocks *dtypes.MpoolLocker
|
||||
}
|
||||
@@ -112,12 +110,19 @@ func (a *MpoolAPI) MpoolPush(ctx context.Context, smsg *types.SignedMessage) (ci
|
||||
return a.Mpool.Push(smsg)
|
||||
}
|
||||
|
||||
func (a *MpoolAPI) MpoolPushUntrusted(ctx context.Context, smsg *types.SignedMessage) (cid.Cid, error) {
|
||||
return a.Mpool.PushUntrusted(smsg)
|
||||
}
|
||||
|
||||
func (a *MpoolAPI) MpoolPushMessage(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec) (*types.SignedMessage, error) {
|
||||
cp := *msg
|
||||
msg = &cp
|
||||
inMsg := *msg
|
||||
fromA, err := a.Stmgr.ResolveToKeyAddress(ctx, msg.From, nil)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("getting key address: %w", err)
|
||||
}
|
||||
{
|
||||
fromA, err := a.Stmgr.ResolveToKeyAddress(ctx, msg.From, nil)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("getting key address: %w", err)
|
||||
}
|
||||
done, err := a.PushLocks.TakeLock(ctx, fromA)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("taking lock: %w", err)
|
||||
@@ -129,38 +134,39 @@ func (a *MpoolAPI) MpoolPushMessage(ctx context.Context, msg *types.Message, spe
|
||||
return nil, xerrors.Errorf("MpoolPushMessage expects message nonce to be 0, was %d", msg.Nonce)
|
||||
}
|
||||
|
||||
msg, err := a.GasAPI.GasEstimateMessageGas(ctx, msg, spec, types.EmptyTSK)
|
||||
msg, err = a.GasAPI.GasEstimateMessageGas(ctx, msg, spec, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("GasEstimateMessageGas error: %w", err)
|
||||
}
|
||||
|
||||
sign := func(from address.Address, nonce uint64) (*types.SignedMessage, error) {
|
||||
msg.Nonce = nonce
|
||||
if msg.From.Protocol() == address.ID {
|
||||
log.Warnf("Push from ID address (%s), adjusting to %s", msg.From, from)
|
||||
msg.From = from
|
||||
}
|
||||
|
||||
b, err := a.WalletBalance(ctx, msg.From)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("mpool push: getting origin balance: %w", err)
|
||||
}
|
||||
|
||||
if b.LessThan(msg.Value) {
|
||||
return nil, xerrors.Errorf("mpool push: not enough funds: %s < %s", b, msg.Value)
|
||||
}
|
||||
|
||||
return a.WalletSignMessage(ctx, from, msg)
|
||||
if msg.GasPremium.GreaterThan(msg.GasFeeCap) {
|
||||
inJson, _ := json.Marshal(inMsg)
|
||||
outJson, _ := json.Marshal(msg)
|
||||
return nil, xerrors.Errorf("After estimation, GasPremium is greater than GasFeeCap, inmsg: %s, outmsg: %s",
|
||||
inJson, outJson)
|
||||
}
|
||||
|
||||
var m *types.SignedMessage
|
||||
again:
|
||||
m, err = a.Mpool.PushWithNonce(ctx, msg.From, sign)
|
||||
if err == messagepool.ErrTryAgain {
|
||||
log.Debugf("temporary failure while pushing message: %s; retrying", err)
|
||||
goto again
|
||||
if msg.From.Protocol() == address.ID {
|
||||
log.Warnf("Push from ID address (%s), adjusting to %s", msg.From, fromA)
|
||||
msg.From = fromA
|
||||
}
|
||||
return m, err
|
||||
|
||||
b, err := a.WalletBalance(ctx, msg.From)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("mpool push: getting origin balance: %w", err)
|
||||
}
|
||||
|
||||
if b.LessThan(msg.Value) {
|
||||
return nil, xerrors.Errorf("mpool push: not enough funds: %s < %s", b, msg.Value)
|
||||
}
|
||||
|
||||
// Sign and push the message
|
||||
return a.MessageSigner.SignMessage(ctx, msg, func(smsg *types.SignedMessage) error {
|
||||
if _, err := a.Mpool.Push(smsg); err != nil {
|
||||
return xerrors.Errorf("mpool push: failed to push message: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (a *MpoolAPI) MpoolGetNonce(ctx context.Context, addr address.Address) (uint64, error) {
|
||||
|
||||
+79
-118
@@ -3,19 +3,19 @@ package full
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/abi/big"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/multisig"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
|
||||
samsig "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
|
||||
|
||||
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
multisig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/minio/blake2b-simd"
|
||||
"go.uber.org/fx"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
@@ -28,57 +28,31 @@ type MsigAPI struct {
|
||||
MpoolAPI MpoolAPI
|
||||
}
|
||||
|
||||
func (a *MsigAPI) messageBuilder(ctx context.Context, from address.Address) (multisig.MessageBuilder, error) {
|
||||
nver, err := a.StateAPI.StateNetworkVersion(ctx, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return multisig.Message(actors.VersionForNetwork(nver), from), nil
|
||||
}
|
||||
|
||||
// TODO: remove gp (gasPrice) from arguments
|
||||
// TODO: Add "vesting start" to arguments.
|
||||
func (a *MsigAPI) MsigCreate(ctx context.Context, req uint64, addrs []address.Address, duration abi.ChainEpoch, val types.BigInt, src address.Address, gp types.BigInt) (cid.Cid, error) {
|
||||
|
||||
lenAddrs := uint64(len(addrs))
|
||||
|
||||
if lenAddrs < req {
|
||||
return cid.Undef, xerrors.Errorf("cannot require signing of more addresses than provided for multisig")
|
||||
mb, err := a.messageBuilder(ctx, src)
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
if req == 0 {
|
||||
req = lenAddrs
|
||||
}
|
||||
|
||||
if src == address.Undef {
|
||||
return cid.Undef, xerrors.Errorf("must provide source address")
|
||||
}
|
||||
|
||||
// Set up constructor parameters for multisig
|
||||
msigParams := &samsig.ConstructorParams{
|
||||
Signers: addrs,
|
||||
NumApprovalsThreshold: req,
|
||||
UnlockDuration: duration,
|
||||
}
|
||||
|
||||
enc, actErr := actors.SerializeParams(msigParams)
|
||||
if actErr != nil {
|
||||
return cid.Undef, actErr
|
||||
}
|
||||
|
||||
// new actors are created by invoking 'exec' on the init actor with the constructor params
|
||||
execParams := &init_.ExecParams{
|
||||
CodeCID: builtin.MultisigActorCodeID,
|
||||
ConstructorParams: enc,
|
||||
}
|
||||
|
||||
enc, actErr = actors.SerializeParams(execParams)
|
||||
if actErr != nil {
|
||||
return cid.Undef, actErr
|
||||
}
|
||||
|
||||
// now we create the message to send this with
|
||||
msg := types.Message{
|
||||
To: builtin.InitActorAddr,
|
||||
From: src,
|
||||
Method: builtin.MethodsInit.Exec,
|
||||
Params: enc,
|
||||
Value: val,
|
||||
msg, err := mb.Create(addrs, req, 0, duration, val)
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
// send the message out to the network
|
||||
smsg, err := a.MpoolAPI.MpoolPushMessage(ctx, &msg, nil)
|
||||
smsg, err := a.MpoolAPI.MpoolPushMessage(ctx, msg, nil)
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
@@ -88,38 +62,14 @@ func (a *MsigAPI) MsigCreate(ctx context.Context, req uint64, addrs []address.Ad
|
||||
|
||||
func (a *MsigAPI) MsigPropose(ctx context.Context, msig address.Address, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (cid.Cid, error) {
|
||||
|
||||
if msig == address.Undef {
|
||||
return cid.Undef, xerrors.Errorf("must provide a multisig address for proposal")
|
||||
mb, err := a.messageBuilder(ctx, src)
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
if to == address.Undef {
|
||||
return cid.Undef, xerrors.Errorf("must provide a target address for proposal")
|
||||
}
|
||||
|
||||
if amt.Sign() == -1 {
|
||||
return cid.Undef, xerrors.Errorf("must provide a positive amount for proposed send")
|
||||
}
|
||||
|
||||
if src == address.Undef {
|
||||
return cid.Undef, xerrors.Errorf("must provide source address")
|
||||
}
|
||||
|
||||
enc, actErr := actors.SerializeParams(&samsig.ProposeParams{
|
||||
To: to,
|
||||
Value: amt,
|
||||
Method: abi.MethodNum(method),
|
||||
Params: params,
|
||||
})
|
||||
if actErr != nil {
|
||||
return cid.Undef, xerrors.Errorf("failed to serialize parameters: %w", actErr)
|
||||
}
|
||||
|
||||
msg := &types.Message{
|
||||
To: msig,
|
||||
From: src,
|
||||
Value: types.NewInt(0),
|
||||
Method: builtin.MethodsMultisig.Propose,
|
||||
Params: enc,
|
||||
msg, err := mb.Propose(msig, to, amt, abi.MethodNum(method), params)
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("failed to create proposal: %w", err)
|
||||
}
|
||||
|
||||
smsg, err := a.MpoolAPI.MpoolPushMessage(ctx, msg, nil)
|
||||
@@ -130,13 +80,40 @@ func (a *MsigAPI) MsigPropose(ctx context.Context, msig address.Address, to addr
|
||||
return smsg.Cid(), nil
|
||||
}
|
||||
|
||||
func (a *MsigAPI) MsigAddPropose(ctx context.Context, msig address.Address, src address.Address, newAdd address.Address, inc bool) (cid.Cid, error) {
|
||||
enc, actErr := serializeAddParams(newAdd, inc)
|
||||
if actErr != nil {
|
||||
return cid.Undef, actErr
|
||||
}
|
||||
|
||||
return a.MsigPropose(ctx, msig, msig, big.Zero(), src, uint64(builtin0.MethodsMultisig.AddSigner), enc)
|
||||
}
|
||||
|
||||
func (a *MsigAPI) MsigAddApprove(ctx context.Context, msig address.Address, src address.Address, txID uint64, proposer address.Address, newAdd address.Address, inc bool) (cid.Cid, error) {
|
||||
enc, actErr := serializeAddParams(newAdd, inc)
|
||||
if actErr != nil {
|
||||
return cid.Undef, actErr
|
||||
}
|
||||
|
||||
return a.MsigApprove(ctx, msig, txID, proposer, msig, big.Zero(), src, uint64(builtin0.MethodsMultisig.AddSigner), enc)
|
||||
}
|
||||
|
||||
func (a *MsigAPI) MsigAddCancel(ctx context.Context, msig address.Address, src address.Address, txID uint64, newAdd address.Address, inc bool) (cid.Cid, error) {
|
||||
enc, actErr := serializeAddParams(newAdd, inc)
|
||||
if actErr != nil {
|
||||
return cid.Undef, actErr
|
||||
}
|
||||
|
||||
return a.MsigCancel(ctx, msig, txID, msig, big.Zero(), src, uint64(builtin0.MethodsMultisig.AddSigner), enc)
|
||||
}
|
||||
|
||||
func (a *MsigAPI) MsigSwapPropose(ctx context.Context, msig address.Address, src address.Address, oldAdd address.Address, newAdd address.Address) (cid.Cid, error) {
|
||||
enc, actErr := serializeSwapParams(oldAdd, newAdd)
|
||||
if actErr != nil {
|
||||
return cid.Undef, actErr
|
||||
}
|
||||
|
||||
return a.MsigPropose(ctx, msig, msig, big.Zero(), src, uint64(builtin.MethodsMultisig.SwapSigner), enc)
|
||||
return a.MsigPropose(ctx, msig, msig, big.Zero(), src, uint64(builtin0.MethodsMultisig.SwapSigner), enc)
|
||||
}
|
||||
|
||||
func (a *MsigAPI) MsigSwapApprove(ctx context.Context, msig address.Address, src address.Address, txID uint64, proposer address.Address, oldAdd address.Address, newAdd address.Address) (cid.Cid, error) {
|
||||
@@ -145,7 +122,7 @@ func (a *MsigAPI) MsigSwapApprove(ctx context.Context, msig address.Address, src
|
||||
return cid.Undef, actErr
|
||||
}
|
||||
|
||||
return a.MsigApprove(ctx, msig, txID, proposer, msig, big.Zero(), src, uint64(builtin.MethodsMultisig.SwapSigner), enc)
|
||||
return a.MsigApprove(ctx, msig, txID, proposer, msig, big.Zero(), src, uint64(builtin0.MethodsMultisig.SwapSigner), enc)
|
||||
}
|
||||
|
||||
func (a *MsigAPI) MsigSwapCancel(ctx context.Context, msig address.Address, src address.Address, txID uint64, oldAdd address.Address, newAdd address.Address) (cid.Cid, error) {
|
||||
@@ -154,7 +131,7 @@ func (a *MsigAPI) MsigSwapCancel(ctx context.Context, msig address.Address, src
|
||||
return cid.Undef, actErr
|
||||
}
|
||||
|
||||
return a.MsigCancel(ctx, msig, txID, msig, big.Zero(), src, uint64(builtin.MethodsMultisig.SwapSigner), enc)
|
||||
return a.MsigCancel(ctx, msig, txID, msig, big.Zero(), src, uint64(builtin0.MethodsMultisig.SwapSigner), enc)
|
||||
}
|
||||
|
||||
func (a *MsigAPI) MsigApprove(ctx context.Context, msig address.Address, txID uint64, proposer address.Address, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (cid.Cid, error) {
|
||||
@@ -170,14 +147,6 @@ func (a *MsigAPI) msigApproveOrCancel(ctx context.Context, operation api.MsigPro
|
||||
return cid.Undef, xerrors.Errorf("must provide multisig address")
|
||||
}
|
||||
|
||||
if to == address.Undef {
|
||||
return cid.Undef, xerrors.Errorf("must provide proposed target address")
|
||||
}
|
||||
|
||||
if amt.Sign() == -1 {
|
||||
return cid.Undef, xerrors.Errorf("must provide the positive amount that was proposed")
|
||||
}
|
||||
|
||||
if src == address.Undef {
|
||||
return cid.Undef, xerrors.Errorf("must provide source address")
|
||||
}
|
||||
@@ -190,7 +159,7 @@ func (a *MsigAPI) msigApproveOrCancel(ctx context.Context, operation api.MsigPro
|
||||
proposer = proposerID
|
||||
}
|
||||
|
||||
p := samsig.ProposalHashData{
|
||||
p := multisig.ProposalHashData{
|
||||
Requester: proposer,
|
||||
To: to,
|
||||
Value: amt,
|
||||
@@ -198,42 +167,22 @@ func (a *MsigAPI) msigApproveOrCancel(ctx context.Context, operation api.MsigPro
|
||||
Params: params,
|
||||
}
|
||||
|
||||
pser, err := p.Serialize()
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
phash := blake2b.Sum256(pser)
|
||||
|
||||
enc, err := actors.SerializeParams(&samsig.TxnIDParams{
|
||||
ID: samsig.TxnID(txID),
|
||||
ProposalHash: phash[:],
|
||||
})
|
||||
|
||||
mb, err := a.messageBuilder(ctx, src)
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
var msigResponseMethod abi.MethodNum
|
||||
|
||||
/*
|
||||
We pass in a MsigProposeResponse instead of MethodNum to
|
||||
tighten the possible inputs to just Approve and Cancel.
|
||||
*/
|
||||
var msg *types.Message
|
||||
switch operation {
|
||||
case api.MsigApprove:
|
||||
msigResponseMethod = builtin.MethodsMultisig.Approve
|
||||
msg, err = mb.Approve(msig, txID, &p)
|
||||
case api.MsigCancel:
|
||||
msigResponseMethod = builtin.MethodsMultisig.Cancel
|
||||
msg, err = mb.Cancel(msig, txID, &p)
|
||||
default:
|
||||
return cid.Undef, xerrors.Errorf("Invalid operation for msigApproveOrCancel")
|
||||
}
|
||||
|
||||
msg := &types.Message{
|
||||
To: msig,
|
||||
From: src,
|
||||
Value: types.NewInt(0),
|
||||
Method: msigResponseMethod,
|
||||
Params: enc,
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
smsg, err := a.MpoolAPI.MpoolPushMessage(ctx, msg, nil)
|
||||
@@ -244,8 +193,20 @@ func (a *MsigAPI) msigApproveOrCancel(ctx context.Context, operation api.MsigPro
|
||||
return smsg.Cid(), nil
|
||||
}
|
||||
|
||||
func serializeAddParams(new address.Address, inc bool) ([]byte, error) {
|
||||
enc, actErr := actors.SerializeParams(&multisig0.AddSignerParams{
|
||||
Signer: new,
|
||||
Increase: inc,
|
||||
})
|
||||
if actErr != nil {
|
||||
return nil, actErr
|
||||
}
|
||||
|
||||
return enc, nil
|
||||
}
|
||||
|
||||
func serializeSwapParams(old address.Address, new address.Address) ([]byte, error) {
|
||||
enc, actErr := actors.SerializeParams(&samsig.SwapSignerParams{
|
||||
enc, actErr := actors.SerializeParams(&multisig0.SwapSignerParams{
|
||||
From: old,
|
||||
To: new,
|
||||
})
|
||||
|
||||
+607
-511
File diff suppressed because it is too large
Load Diff
+35
-1
@@ -2,6 +2,7 @@ package full
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync/atomic"
|
||||
|
||||
cid "github.com/ipfs/go-cid"
|
||||
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
||||
@@ -13,6 +14,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain"
|
||||
"github.com/filecoin-project/lotus/chain/gen/slashfilter"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||
)
|
||||
|
||||
@@ -28,7 +30,9 @@ type SyncAPI struct {
|
||||
func (a *SyncAPI) SyncState(ctx context.Context) (*api.SyncState, error) {
|
||||
states := a.Syncer.State()
|
||||
|
||||
out := &api.SyncState{}
|
||||
out := &api.SyncState{
|
||||
VMApplied: atomic.LoadUint64(&vm.StatApplied),
|
||||
}
|
||||
|
||||
for i := range states {
|
||||
ss := &states[i]
|
||||
@@ -97,12 +101,23 @@ func (a *SyncAPI) SyncIncomingBlocks(ctx context.Context) (<-chan *types.BlockHe
|
||||
return a.Syncer.IncomingBlocks(ctx)
|
||||
}
|
||||
|
||||
func (a *SyncAPI) SyncCheckpoint(ctx context.Context, tsk types.TipSetKey) error {
|
||||
log.Warnf("Marking tipset %s as checkpoint", tsk)
|
||||
return a.Syncer.SetCheckpoint(tsk)
|
||||
}
|
||||
|
||||
func (a *SyncAPI) SyncMarkBad(ctx context.Context, bcid cid.Cid) error {
|
||||
log.Warnf("Marking block %s as bad", bcid)
|
||||
a.Syncer.MarkBad(bcid)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *SyncAPI) SyncUnmarkBad(ctx context.Context, bcid cid.Cid) error {
|
||||
log.Warnf("Unmarking block %s as bad", bcid)
|
||||
a.Syncer.UnmarkBad(bcid)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *SyncAPI) SyncCheckBad(ctx context.Context, bcid cid.Cid) (string, error) {
|
||||
reason, ok := a.Syncer.CheckBadBlockCache(bcid)
|
||||
if !ok {
|
||||
@@ -111,3 +126,22 @@ func (a *SyncAPI) SyncCheckBad(ctx context.Context, bcid cid.Cid) (string, error
|
||||
|
||||
return reason, nil
|
||||
}
|
||||
|
||||
func (a *SyncAPI) SyncValidateTipset(ctx context.Context, tsk types.TipSetKey) (bool, error) {
|
||||
ts, err := a.Syncer.ChainStore().LoadTipSet(tsk)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
fts, err := a.Syncer.ChainStore().TryFillTipSet(ts)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
err = a.Syncer.ValidateTipSet(ctx, fts, false)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
+12
-11
@@ -7,8 +7,8 @@ import (
|
||||
"go.uber.org/fx"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/abi/big"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||
@@ -26,16 +26,13 @@ type WalletAPI struct {
|
||||
}
|
||||
|
||||
func (a *WalletAPI) WalletBalance(ctx context.Context, addr address.Address) (types.BigInt, error) {
|
||||
var bal types.BigInt
|
||||
err := a.StateManager.WithParentStateTsk(types.EmptyTSK, a.StateManager.WithActor(addr, func(act *types.Actor) error {
|
||||
bal = act.Balance
|
||||
return nil
|
||||
}))
|
||||
|
||||
act, err := a.StateManager.LoadActorTsk(ctx, addr, types.EmptyTSK)
|
||||
if xerrors.Is(err, types.ErrActorNotFound) {
|
||||
return big.Zero(), nil
|
||||
} else if err != nil {
|
||||
return big.Zero(), err
|
||||
}
|
||||
return bal, err
|
||||
return act.Balance, nil
|
||||
}
|
||||
|
||||
func (a *WalletAPI) WalletSign(ctx context.Context, k address.Address, msg []byte) (*crypto.Signature, error) {
|
||||
@@ -54,8 +51,8 @@ func (a *WalletAPI) WalletSignMessage(ctx context.Context, k address.Address, ms
|
||||
return a.WalletAPI.WalletSignMessage(ctx, keyAddr, msg)
|
||||
}
|
||||
|
||||
func (a *WalletAPI) WalletVerify(ctx context.Context, k address.Address, msg []byte, sig *crypto.Signature) bool {
|
||||
return sigs.Verify(sig, k, msg) == nil
|
||||
func (a *WalletAPI) WalletVerify(ctx context.Context, k address.Address, msg []byte, sig *crypto.Signature) (bool, error) {
|
||||
return sigs.Verify(sig, k, msg) == nil, nil
|
||||
}
|
||||
|
||||
func (a *WalletAPI) WalletDefaultAddress(ctx context.Context) (address.Address, error) {
|
||||
@@ -65,3 +62,7 @@ func (a *WalletAPI) WalletDefaultAddress(ctx context.Context) (address.Address,
|
||||
func (a *WalletAPI) WalletSetDefault(ctx context.Context, addr address.Address) error {
|
||||
return a.Default.SetDefault(addr)
|
||||
}
|
||||
|
||||
func (a *WalletAPI) WalletValidateAddress(ctx context.Context, str string) (address.Address, error) {
|
||||
return address.NewFromString(str)
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@ import (
|
||||
"go.uber.org/fx"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
full "github.com/filecoin-project/lotus/node/impl/full"
|
||||
"github.com/filecoin-project/lotus/paychmgr"
|
||||
@@ -39,8 +39,12 @@ func (a *PaychAPI) PaychGet(ctx context.Context, from, to address.Address, amt t
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *PaychAPI) PaychAvailableFunds(from, to address.Address) (*api.ChannelAvailableFunds, error) {
|
||||
return a.PaychMgr.AvailableFunds(from, to)
|
||||
func (a *PaychAPI) PaychAvailableFunds(ctx context.Context, ch address.Address) (*api.ChannelAvailableFunds, error) {
|
||||
return a.PaychMgr.AvailableFunds(ch)
|
||||
}
|
||||
|
||||
func (a *PaychAPI) PaychAvailableFundsByFromTo(ctx context.Context, from, to address.Address) (*api.ChannelAvailableFunds, error) {
|
||||
return a.PaychMgr.AvailableFundsByFromTo(from, to)
|
||||
}
|
||||
|
||||
func (a *PaychAPI) PaychGetWaitReady(ctx context.Context, sentinel cid.Cid) (address.Address, error) {
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/filecoin-project/go-jsonrpc"
|
||||
"github.com/filecoin-project/go-jsonrpc/auth"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/api/client"
|
||||
|
||||
+35
-7
@@ -8,18 +8,18 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
datatransfer "github.com/filecoin-project/go-data-transfer"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi/big"
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/libp2p/go-libp2p-core/host"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
datatransfer "github.com/filecoin-project/go-data-transfer"
|
||||
"github.com/filecoin-project/go-fil-markets/piecestore"
|
||||
retrievalmarket "github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
||||
storagemarket "github.com/filecoin-project/go-fil-markets/storagemarket"
|
||||
"github.com/filecoin-project/go-jsonrpc/auth"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
|
||||
sectorstorage "github.com/filecoin-project/lotus/extern/sector-storage"
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
|
||||
@@ -56,6 +56,8 @@ type StorageMinerAPI struct {
|
||||
DataTransfer dtypes.ProviderDataTransfer
|
||||
Host host.Host
|
||||
|
||||
DS dtypes.MetadataDS
|
||||
|
||||
ConsiderOnlineStorageDealsConfigFunc dtypes.ConsiderOnlineStorageDealsConfigFunc
|
||||
SetConsiderOnlineStorageDealsConfigFunc dtypes.SetConsiderOnlineStorageDealsConfigFunc
|
||||
ConsiderOnlineRetrievalDealsConfigFunc dtypes.ConsiderOnlineRetrievalDealsConfigFunc
|
||||
@@ -305,8 +307,30 @@ func (sm *StorageMinerAPI) MarketImportDealData(ctx context.Context, propCid cid
|
||||
return sm.StorageProvider.ImportDataForDeal(ctx, propCid, fi)
|
||||
}
|
||||
|
||||
func (sm *StorageMinerAPI) MarketListDeals(ctx context.Context) ([]storagemarket.StorageDeal, error) {
|
||||
return sm.StorageProvider.ListDeals(ctx)
|
||||
func (sm *StorageMinerAPI) listDeals(ctx context.Context) ([]api.MarketDeal, error) {
|
||||
ts, err := sm.Full.ChainHead(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tsk := ts.Key()
|
||||
allDeals, err := sm.Full.StateMarketDeals(ctx, tsk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var out []api.MarketDeal
|
||||
|
||||
for _, deal := range allDeals {
|
||||
if deal.Proposal.Provider == sm.Miner.Address() {
|
||||
out = append(out, deal)
|
||||
}
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (sm *StorageMinerAPI) MarketListDeals(ctx context.Context) ([]api.MarketDeal, error) {
|
||||
return sm.listDeals(ctx)
|
||||
}
|
||||
|
||||
func (sm *StorageMinerAPI) MarketListRetrievalDeals(ctx context.Context) ([]retrievalmarket.ProviderDealState, error) {
|
||||
@@ -395,8 +419,8 @@ func (sm *StorageMinerAPI) MarketDataTransferUpdates(ctx context.Context) (<-cha
|
||||
return channels, nil
|
||||
}
|
||||
|
||||
func (sm *StorageMinerAPI) DealsList(ctx context.Context) ([]storagemarket.StorageDeal, error) {
|
||||
return sm.StorageProvider.ListDeals(ctx)
|
||||
func (sm *StorageMinerAPI) DealsList(ctx context.Context) ([]api.MarketDeal, error) {
|
||||
return sm.listDeals(ctx)
|
||||
}
|
||||
|
||||
func (sm *StorageMinerAPI) RetrievalDealsList(ctx context.Context) (map[retrievalmarket.ProviderDealIdentifier]retrievalmarket.ProviderDealState, error) {
|
||||
@@ -494,4 +518,8 @@ func (sm *StorageMinerAPI) PiecesGetCIDInfo(ctx context.Context, payloadCid cid.
|
||||
return &ci, nil
|
||||
}
|
||||
|
||||
func (sm *StorageMinerAPI) CreateBackup(ctx context.Context, fpath string) error {
|
||||
return backup(sm.DS, fpath)
|
||||
}
|
||||
|
||||
var _ api.StorageMiner = &StorageMinerAPI{}
|
||||
|
||||
Reference in New Issue
Block a user