This commit is contained in:
Sami Mäkelä 2020-07-24 12:34:48 +03:00
commit 15481e63dd
89 changed files with 2041 additions and 639 deletions

View File

@ -19,7 +19,7 @@ All work is tracked via issues. An attempt at keeping an up-to-date view on rema
The main branches under development at the moment are: The main branches under development at the moment are:
* [`master`](https://github.com/filecoin-project/lotus): current testnet. * [`master`](https://github.com/filecoin-project/lotus): current testnet.
* [`next`](https://github.com/filecoin-project/lotus/tree/next): working branch with chain-breaking changes. * [`next`](https://github.com/filecoin-project/lotus/tree/next): working branch with chain-breaking changes.
* [`interopnet`](https://github.com/filecoin-project/lotus/tree/interopnet): devnet running one of `next` commits. * [`ntwk-calibration`](https://github.com/filecoin-project/lotus/tree/ntwk-calibration): devnet running one of `next` commits.
## License ## License

View File

@ -367,7 +367,8 @@ type FullNode interface {
PaychGet(ctx context.Context, from, to address.Address, ensureFunds types.BigInt) (*ChannelInfo, error) PaychGet(ctx context.Context, from, to address.Address, ensureFunds types.BigInt) (*ChannelInfo, error)
PaychList(context.Context) ([]address.Address, error) PaychList(context.Context) ([]address.Address, error)
PaychStatus(context.Context, address.Address) (*PaychStatus, error) PaychStatus(context.Context, address.Address) (*PaychStatus, error)
PaychClose(context.Context, address.Address) (cid.Cid, error) PaychSettle(context.Context, address.Address) (cid.Cid, error)
PaychCollect(context.Context, address.Address) (cid.Cid, error)
PaychAllocateLane(ctx context.Context, ch address.Address) (uint64, error) PaychAllocateLane(ctx context.Context, ch address.Address) (uint64, error)
PaychNewPayment(ctx context.Context, from, to address.Address, vouchers []VoucherSpec) (*PaymentInfo, error) PaychNewPayment(ctx context.Context, from, to address.Address, vouchers []VoucherSpec) (*PaymentInfo, error)
PaychVoucherCheckValid(context.Context, address.Address, *paych.SignedVoucher) error PaychVoucherCheckValid(context.Context, address.Address, *paych.SignedVoucher) error
@ -506,6 +507,7 @@ type QueryOffer struct {
Size uint64 Size uint64
MinPrice types.BigInt MinPrice types.BigInt
UnsealPrice types.BigInt
PaymentInterval uint64 PaymentInterval uint64
PaymentIntervalIncrease uint64 PaymentIntervalIncrease uint64
Miner address.Address Miner address.Address
@ -518,6 +520,7 @@ func (o *QueryOffer) Order(client address.Address) RetrievalOrder {
Piece: o.Piece, Piece: o.Piece,
Size: o.Size, Size: o.Size,
Total: o.MinPrice, Total: o.MinPrice,
UnsealPrice: o.UnsealPrice,
PaymentInterval: o.PaymentInterval, PaymentInterval: o.PaymentInterval,
PaymentIntervalIncrease: o.PaymentIntervalIncrease, PaymentIntervalIncrease: o.PaymentIntervalIncrease,
Client: client, Client: client,
@ -544,6 +547,7 @@ type RetrievalOrder struct {
Size uint64 Size uint64
// TODO: support offset // TODO: support offset
Total types.BigInt Total types.BigInt
UnsealPrice types.BigInt
PaymentInterval uint64 PaymentInterval uint64
PaymentIntervalIncrease uint64 PaymentIntervalIncrease uint64
Client address.Address Client address.Address

View File

@ -61,6 +61,7 @@ type StorageMiner interface {
// WorkerConnect tells the node to connect to workers RPC // WorkerConnect tells the node to connect to workers RPC
WorkerConnect(context.Context, string) error WorkerConnect(context.Context, string) error
WorkerStats(context.Context) (map[uint64]storiface.WorkerStats, error) WorkerStats(context.Context) (map[uint64]storiface.WorkerStats, error)
WorkerJobs(context.Context) (map[uint64][]storiface.WorkerJob, error)
stores.SectorIndex stores.SectorIndex

View File

@ -180,7 +180,8 @@ type FullNodeStruct struct {
PaychGet func(ctx context.Context, from, to address.Address, ensureFunds types.BigInt) (*api.ChannelInfo, error) `perm:"sign"` PaychGet func(ctx context.Context, from, to address.Address, ensureFunds types.BigInt) (*api.ChannelInfo, error) `perm:"sign"`
PaychList func(context.Context) ([]address.Address, error) `perm:"read"` PaychList func(context.Context) ([]address.Address, error) `perm:"read"`
PaychStatus func(context.Context, address.Address) (*api.PaychStatus, error) `perm:"read"` PaychStatus func(context.Context, address.Address) (*api.PaychStatus, error) `perm:"read"`
PaychClose func(context.Context, address.Address) (cid.Cid, error) `perm:"sign"` PaychSettle func(context.Context, address.Address) (cid.Cid, error) `perm:"sign"`
PaychCollect func(context.Context, address.Address) (cid.Cid, error) `perm:"sign"`
PaychAllocateLane func(context.Context, address.Address) (uint64, error) `perm:"sign"` PaychAllocateLane func(context.Context, address.Address) (uint64, error) `perm:"sign"`
PaychNewPayment func(ctx context.Context, from, to address.Address, vouchers []api.VoucherSpec) (*api.PaymentInfo, error) `perm:"sign"` PaychNewPayment func(ctx context.Context, from, to address.Address, vouchers []api.VoucherSpec) (*api.PaymentInfo, error) `perm:"sign"`
PaychVoucherCheck func(context.Context, *paych.SignedVoucher) error `perm:"read"` PaychVoucherCheck func(context.Context, *paych.SignedVoucher) error `perm:"read"`
@ -228,6 +229,7 @@ type StorageMinerStruct struct {
WorkerConnect func(context.Context, string) error `perm:"admin"` // TODO: worker perm WorkerConnect func(context.Context, string) error `perm:"admin"` // TODO: worker perm
WorkerStats func(context.Context) (map[uint64]storiface.WorkerStats, error) `perm:"admin"` WorkerStats func(context.Context) (map[uint64]storiface.WorkerStats, error) `perm:"admin"`
WorkerJobs func(context.Context) (map[uint64][]storiface.WorkerJob, error) `perm:"admin"`
StorageList func(context.Context) (map[stores.ID][]stores.Decl, error) `perm:"admin"` StorageList func(context.Context) (map[stores.ID][]stores.Decl, error) `perm:"admin"`
StorageLocal func(context.Context) (map[stores.ID]string, error) `perm:"admin"` StorageLocal func(context.Context) (map[stores.ID]string, error) `perm:"admin"`
@ -804,8 +806,12 @@ func (c *FullNodeStruct) PaychVoucherList(ctx context.Context, pch address.Addre
return c.Internal.PaychVoucherList(ctx, pch) return c.Internal.PaychVoucherList(ctx, pch)
} }
func (c *FullNodeStruct) PaychClose(ctx context.Context, a address.Address) (cid.Cid, error) { func (c *FullNodeStruct) PaychSettle(ctx context.Context, a address.Address) (cid.Cid, error) {
return c.Internal.PaychClose(ctx, a) return c.Internal.PaychSettle(ctx, a)
}
func (c *FullNodeStruct) PaychCollect(ctx context.Context, a address.Address) (cid.Cid, error) {
return c.Internal.PaychCollect(ctx, a)
} }
func (c *FullNodeStruct) PaychAllocateLane(ctx context.Context, ch address.Address) (uint64, error) { func (c *FullNodeStruct) PaychAllocateLane(ctx context.Context, ch address.Address) (uint64, error) {
@ -892,6 +898,10 @@ func (c *StorageMinerStruct) WorkerStats(ctx context.Context) (map[uint64]storif
return c.Internal.WorkerStats(ctx) return c.Internal.WorkerStats(ctx)
} }
func (c *StorageMinerStruct) WorkerJobs(ctx context.Context) (map[uint64][]storiface.WorkerJob, error) {
return c.Internal.WorkerJobs(ctx)
}
func (c *StorageMinerStruct) StorageAttach(ctx context.Context, si stores.StorageInfo, st fsutil.FsStat) error { func (c *StorageMinerStruct) StorageAttach(ctx context.Context, si stores.StorageInfo, st fsutil.FsStat) error {
return c.Internal.StorageAttach(ctx, si, st) return c.Internal.StorageAttach(ctx, si, st)
} }

286
api/test/paych.go Normal file
View File

@ -0,0 +1,286 @@
package test
import (
"bytes"
"context"
"fmt"
"os"
"sync/atomic"
"testing"
"time"
"github.com/filecoin-project/lotus/api"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/events"
"github.com/filecoin-project/lotus/chain/events/state"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/wallet"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/abi/big"
initactor "github.com/filecoin-project/specs-actors/actors/builtin/init"
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
)
func TestPaymentChannels(t *testing.T, b APIBuilder, blocktime time.Duration) {
_ = os.Setenv("BELLMAN_NO_GPU", "1")
ctx := context.Background()
n, sn := b(t, 2, oneMiner)
paymentCreator := n[0]
paymentReceiver := n[1]
miner := sn[0]
// get everyone connected
addrs, err := paymentCreator.NetAddrsListen(ctx)
if err != nil {
t.Fatal(err)
}
if err := paymentReceiver.NetConnect(ctx, addrs); err != nil {
t.Fatal(err)
}
if err := miner.NetConnect(ctx, addrs); err != nil {
t.Fatal(err)
}
// start mining blocks
bm := newBlockMiner(ctx, t, miner, blocktime)
bm.mineBlocks()
// send some funds to register the receiver
receiverAddr, err := paymentReceiver.WalletNew(ctx, wallet.ActSigType("secp256k1"))
if err != nil {
t.Fatal(err)
}
sendFunds(ctx, t, paymentCreator, receiverAddr, abi.NewTokenAmount(1e10))
// setup the payment channel
createrAddr, err := paymentCreator.WalletDefaultAddress(ctx)
if err != nil {
t.Fatal(err)
}
channelAmt := int64(100000)
channelInfo, err := paymentCreator.PaychGet(ctx, createrAddr, receiverAddr, abi.NewTokenAmount(channelAmt))
if err != nil {
t.Fatal(err)
}
res := waitForMessage(ctx, t, paymentCreator, channelInfo.ChannelMessage, time.Second, "channel create")
var params initactor.ExecReturn
err = params.UnmarshalCBOR(bytes.NewReader(res.Receipt.Return))
if err != nil {
t.Fatal(err)
}
channel := params.RobustAddress
// allocate three lanes
var lanes []uint64
for i := 0; i < 3; i++ {
lane, err := paymentCreator.PaychAllocateLane(ctx, channel)
if err != nil {
t.Fatal(err)
}
lanes = append(lanes, lane)
}
// Make two vouchers each for each lane, then save on the other side
// Note that the voucher with a value of 2000 has a higher nonce, so it
// supersedes the voucher with a value of 1000
for _, lane := range lanes {
vouch1, err := paymentCreator.PaychVoucherCreate(ctx, channel, abi.NewTokenAmount(1000), lane)
if err != nil {
t.Fatal(err)
}
vouch2, err := paymentCreator.PaychVoucherCreate(ctx, channel, abi.NewTokenAmount(2000), lane)
if err != nil {
t.Fatal(err)
}
delta1, err := paymentReceiver.PaychVoucherAdd(ctx, channel, vouch1, nil, abi.NewTokenAmount(1000))
if err != nil {
t.Fatal(err)
}
if !delta1.Equals(abi.NewTokenAmount(1000)) {
t.Fatal("voucher didn't have the right amount")
}
delta2, err := paymentReceiver.PaychVoucherAdd(ctx, channel, vouch2, nil, abi.NewTokenAmount(1000))
if err != nil {
t.Fatal(err)
}
if !delta2.Equals(abi.NewTokenAmount(1000)) {
t.Fatal("voucher didn't have the right amount")
}
}
// settle the payment channel
settleMsgCid, err := paymentCreator.PaychSettle(ctx, channel)
if err != nil {
t.Fatal(err)
}
res = waitForMessage(ctx, t, paymentCreator, settleMsgCid, time.Second*10, "settle")
if res.Receipt.ExitCode != 0 {
t.Fatal("Unable to settle payment channel")
}
creatorPreCollectBalance, err := paymentCreator.WalletBalance(ctx, createrAddr)
if err != nil {
t.Fatal(err)
}
// wait for the receiver to submit their vouchers
ev := events.NewEvents(ctx, paymentCreator)
preds := state.NewStatePredicates(paymentCreator)
finished := make(chan struct{})
err = ev.StateChanged(func(ts *types.TipSet) (done bool, more bool, err error) {
act, err := paymentCreator.StateReadState(ctx, channel, ts.Key())
if err != nil {
return false, false, err
}
state := act.State.(paych.State)
if state.ToSend.GreaterThanEqual(abi.NewTokenAmount(6000)) {
return true, false, nil
}
return false, true, nil
}, func(oldTs, newTs *types.TipSet, states events.StateChange, curH abi.ChainEpoch) (more bool, err error) {
toSendChange := states.(*state.PayChToSendChange)
if toSendChange.NewToSend.GreaterThanEqual(abi.NewTokenAmount(6000)) {
close(finished)
return false, nil
}
return true, nil
}, func(ctx context.Context, ts *types.TipSet) error {
return nil
}, int(build.MessageConfidence)+1, build.SealRandomnessLookbackLimit, func(oldTs, newTs *types.TipSet) (bool, events.StateChange, error) {
return preds.OnPaymentChannelActorChanged(channel, preds.OnToSendAmountChanges())(ctx, oldTs.Key(), newTs.Key())
})
select {
case <-finished:
case <-time.After(time.Second):
t.Fatal("Timed out waiting for receiver to submit vouchers")
}
// collect funds (from receiver, though either party can do it)
collectMsg, err := paymentReceiver.PaychCollect(ctx, channel)
if err != nil {
t.Fatal(err)
}
res, err = paymentReceiver.StateWaitMsg(ctx, collectMsg, 1)
if err != nil {
t.Fatal(err)
}
if res.Receipt.ExitCode != 0 {
t.Fatal("unable to collect on payment channel")
}
// Finally, check the balance for the creator
currentCreatorBalance, err := paymentCreator.WalletBalance(ctx, createrAddr)
if err != nil {
t.Fatal(err)
}
// The highest nonce voucher that the creator sent on each lane is 2000
totalVouchers := int64(len(lanes) * 2000)
// When receiver submits the tokens to the chain, creator should get a
// refund on the remaining balance, which is
// channel amount - total voucher value
expectedRefund := channelAmt - totalVouchers
delta := big.Sub(currentCreatorBalance, creatorPreCollectBalance)
if !delta.Equals(abi.NewTokenAmount(expectedRefund)) {
t.Fatalf("did not send correct funds from creator: expected %d, got %d", expectedRefund, delta)
}
// shut down mining
bm.stop()
}
func waitForMessage(ctx context.Context, t *testing.T, paymentCreator TestNode, msgCid cid.Cid, duration time.Duration, desc string) *api.MsgLookup {
ctx, cancel := context.WithTimeout(ctx, duration)
defer cancel()
fmt.Println("Waiting for", desc)
res, err := paymentCreator.StateWaitMsg(ctx, msgCid, 1)
if err != nil {
fmt.Println("Error waiting for", desc, err)
t.Fatal(err)
}
if res.Receipt.ExitCode != 0 {
t.Fatalf("did not successfully send %s", desc)
}
fmt.Println("Confirmed", desc)
return res
}
type blockMiner struct {
ctx context.Context
t *testing.T
miner TestStorageNode
blocktime time.Duration
mine int64
done chan struct{}
}
func newBlockMiner(ctx context.Context, t *testing.T, miner TestStorageNode, blocktime time.Duration) *blockMiner {
return &blockMiner{
ctx: ctx,
t: t,
miner: miner,
blocktime: blocktime,
mine: int64(1),
done: make(chan struct{}),
}
}
func (bm *blockMiner) mineBlocks() {
time.Sleep(time.Second)
go func() {
defer close(bm.done)
for atomic.LoadInt64(&bm.mine) == 1 {
time.Sleep(bm.blocktime)
if err := bm.miner.MineOne(bm.ctx, func(bool, error) {}); err != nil {
bm.t.Error(err)
}
}
}()
}
func (bm *blockMiner) stop() {
atomic.AddInt64(&bm.mine, -1)
fmt.Println("shutting down mining")
<-bm.done
}
func sendFunds(ctx context.Context, t *testing.T, sender TestNode, addr address.Address, amount abi.TokenAmount) {
senderAddr, err := sender.WalletDefaultAddress(ctx)
if err != nil {
t.Fatal(err)
}
msg := &types.Message{
From: senderAddr,
To: addr,
Value: amount,
GasLimit: 0,
GasPrice: abi.NewTokenAmount(0),
}
sm, err := sender.MpoolPushMessage(ctx, msg)
if err != nil {
t.Fatal(err)
}
res, err := sender.StateWaitMsg(ctx, sm.Cid(), 1)
if err != nil {
t.Fatal(err)
}
if res.Receipt.ExitCode != 0 {
t.Fatal("did not successfully send money")
}
}

View File

@ -175,7 +175,65 @@ func TestWindowPost(t *testing.T, b APIBuilder, blocktime time.Duration, nSector
require.Equal(t, p.MinerPower, p.TotalPower) require.Equal(t, p.MinerPower, p.TotalPower)
require.Equal(t, p.MinerPower.RawBytePower, types.NewInt(uint64(ssz)*uint64(nSectors+GenesisPreseals))) require.Equal(t, p.MinerPower.RawBytePower, types.NewInt(uint64(ssz)*uint64(nSectors+GenesisPreseals)))
// TODO: Inject faults here // Drop 2 sectors from deadline 2 partition 0 (full partition / deadline)
{
parts, err := client.StateMinerPartitions(ctx, maddr, 2, types.EmptyTSK)
require.NoError(t, err)
require.Greater(t, len(parts), 0)
n, err := parts[0].Sectors.Count()
require.NoError(t, err)
require.Equal(t, uint64(2), n)
// Drop the partition
err = parts[0].Sectors.ForEach(func(sid uint64) error {
return miner.SectorRemove(ctx, abi.SectorNumber(sid))
})
require.NoError(t, err)
}
// Drop 1 sectors from deadline 3 partition 0
{
parts, err := client.StateMinerPartitions(ctx, maddr, 3, types.EmptyTSK)
require.NoError(t, err)
require.Greater(t, len(parts), 0)
n, err := parts[0].Sectors.Count()
require.NoError(t, err)
require.Equal(t, uint64(2), n)
// Drop the sector
s, err := parts[0].Sectors.First()
require.NoError(t, err)
err = miner.SectorRemove(ctx, abi.SectorNumber(s))
require.NoError(t, err)
}
di, err = client.StateMinerProvingDeadline(ctx, maddr, types.EmptyTSK)
require.NoError(t, err)
for {
head, err := client.ChainHead(ctx)
require.NoError(t, err)
if head.Height() > di.PeriodStart+(miner2.WPoStProvingPeriod)+2 {
break
}
if head.Height()%100 == 0 {
fmt.Printf("@%d\n", head.Height())
}
build.Clock.Sleep(blocktime)
}
p, err = client.StateMinerPower(ctx, maddr, types.EmptyTSK)
require.NoError(t, err)
require.Equal(t, p.MinerPower, p.TotalPower)
sectors := p.MinerPower.RawBytePower.Uint64() / uint64(ssz)
require.Equal(t, nSectors+GenesisPreseals - 3, int(sectors)) // -3 just removed sectors
mine = false mine = false
<-done <-done

View File

@ -38,12 +38,3 @@ func BuiltinBootstrap() ([]peer.AddrInfo, error) {
}) })
return out, err return out, err
} }
func DrandBootstrap() ([]peer.AddrInfo, error) {
addrs := []string{
"/dnsaddr/pl-eu.testnet.drand.sh/",
"/dnsaddr/pl-us.testnet.drand.sh/",
"/dnsaddr/pl-sin.testnet.drand.sh/",
}
return addrutil.ParseAddresses(context.TODO(), addrs)
}

58
build/drand.go Normal file
View File

@ -0,0 +1,58 @@
package build
import "github.com/filecoin-project/lotus/node/modules/dtypes"
var DrandNetwork = DrandTestnet
func DrandConfig() dtypes.DrandConfig {
return DrandConfigs[DrandNetwork]
}
type DrandEnum int
const (
DrandMainnet DrandEnum = iota + 1
DrandTestnet
DrandDevnet
DrandLocalnet
)
var DrandConfigs = map[DrandEnum]dtypes.DrandConfig{
DrandMainnet: {
Servers: []string{
"https://api.drand.sh",
"https://api2.drand.sh",
"https://api3.drand.sh",
},
Relays: []string{
"/dnsaddr/api.drand.sh/",
"/dnsaddr/api2.drand.sh/",
"/dnsaddr/api3.drand.sh/",
},
ChainInfoJSON: `{"public_key":"868f005eb8e6e4ca0a47c8a77ceaa5309a47978a7c71bc5cce96366b5d7a569937c529eeda66c7293784a9402801af31","period":30,"genesis_time":1595431050,"hash":"8990e7a9aaed2ffed73dbd7092123d6f289930540d7651336225dc172e51b2ce","groupHash":"176f93498eac9ca337150b46d21dd58673ea4e3581185f869672e59fa4cb390a"}`,
},
DrandTestnet: {
Servers: []string{
"https://pl-eu.testnet.drand.sh",
"https://pl-us.testnet.drand.sh",
"https://pl-sin.testnet.drand.sh",
},
Relays: []string{
"/dnsaddr/pl-eu.testnet.drand.sh/",
"/dnsaddr/pl-us.testnet.drand.sh/",
"/dnsaddr/pl-sin.testnet.drand.sh/",
},
ChainInfoJSON: `{"public_key":"922a2e93828ff83345bae533f5172669a26c02dc76d6bf59c80892e12ab1455c229211886f35bb56af6d5bea981024df","period":25,"genesis_time":1590445175,"hash":"84b2234fb34e835dccd048255d7ad3194b81af7d978c3bf157e3469592ae4e02","groupHash":"4dd408e5fdff9323c76a9b6f087ba8fdc5a6da907bd9217d9d10f2287d081957"}`,
},
DrandDevnet: {
Servers: []string{
"https://dev1.drand.sh",
"https://dev2.drand.sh",
},
Relays: []string{
"/dnsaddr/dev1.drand.sh/",
"/dnsaddr/dev2.drand.sh/",
},
ChainInfoJSON: `{"public_key":"8cda589f88914aa728fd183f383980b35789ce81b274e5daee1f338b77d02566ef4d3fb0098af1f844f10f9c803c1827","period":25,"genesis_time":1595348225,"hash":"e73b7dc3c4f6a236378220c0dd6aa110eb16eed26c11259606e07ee122838d4f","groupHash":"567d4785122a5a3e75a9bc9911d7ea807dd85ff76b78dc4ff06b075712898607"}`,
},
}

View File

@ -8,8 +8,6 @@ import (
"github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/miner" "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/lotus/node/modules/dtypes"
) )
// ///// // /////
@ -92,12 +90,3 @@ const VerifSigCacheSize = 32000
// TODO: If this is gonna stay, it should move to specs-actors // TODO: If this is gonna stay, it should move to specs-actors
const BlockMessageLimit = 512 const BlockMessageLimit = 512
const BlockGasLimit = 7_500_000_000 const BlockGasLimit = 7_500_000_000
var DrandConfig = dtypes.DrandConfig{
Servers: []string{
"https://pl-eu.testnet.drand.sh",
"https://pl-us.testnet.drand.sh",
"https://pl-sin.testnet.drand.sh",
},
ChainInfoJSON: `{"public_key":"922a2e93828ff83345bae533f5172669a26c02dc76d6bf59c80892e12ab1455c229211886f35bb56af6d5bea981024df","period":25,"genesis_time":1590445175,"hash":"84b2234fb34e835dccd048255d7ad3194b81af7d978c3bf157e3469592ae4e02","groupHash":"4dd408e5fdff9323c76a9b6f087ba8fdc5a6da907bd9217d9d10f2287d081957"}`,
}

View File

@ -10,8 +10,6 @@ package build
import ( import (
"math/big" "math/big"
"github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/miner" "github.com/filecoin-project/specs-actors/actors/builtin/miner"
@ -61,13 +59,4 @@ var (
v = v.Mul(v, big.NewInt(int64(FilecoinPrecision))) v = v.Mul(v, big.NewInt(int64(FilecoinPrecision)))
return v return v
}() }()
DrandConfig = dtypes.DrandConfig{
Servers: []string{
"https://pl-eu.testnet.drand.sh",
"https://pl-us.testnet.drand.sh",
"https://pl-sin.testnet.drand.sh",
},
ChainInfoJSON: `{"public_key":"922a2e93828ff83345bae533f5172669a26c02dc76d6bf59c80892e12ab1455c229211886f35bb56af6d5bea981024df","period":25,"genesis_time":1590445175,"hash":"138a324aa6540f93d0dad002aa89454b1bec2b6e948682cde6bd4db40f4b7c9b"}`,
}
) )

View File

@ -12,7 +12,7 @@ import (
) )
func TestPrintGroupInfo(t *testing.T) { func TestPrintGroupInfo(t *testing.T) {
server := build.DrandConfig.Servers[0] server := build.DrandConfig().Servers[0]
c, err := hclient.New(server, nil, nil) c, err := hclient.New(server, nil, nil)
assert.NoError(t, err) assert.NoError(t, err)
cg := c.(interface { cg := c.(interface {

View File

@ -3,6 +3,7 @@ package state
import ( import (
"bytes" "bytes"
"context" "context"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
@ -12,6 +13,7 @@ import (
"github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/market" "github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/builtin/miner" "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
"github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/api/apibstore" "github.com/filecoin-project/lotus/api/apibstore"
@ -493,3 +495,40 @@ func (sp *StatePredicates) OnMinerPreCommitChange() DiffMinerActorStateFunc {
return true, precommitChanges, nil return true, precommitChanges, nil
} }
} }
// DiffPaymentChannelStateFunc is function that compares two states for the payment channel
type DiffPaymentChannelStateFunc func(ctx context.Context, oldState *paych.State, newState *paych.State) (changed bool, user UserData, err error)
// OnPaymentChannelActorChanged calls diffPaymentChannelState when the state changes for the the payment channel actor
func (sp *StatePredicates) OnPaymentChannelActorChanged(paychAddr address.Address, diffPaymentChannelState DiffPaymentChannelStateFunc) DiffTipSetKeyFunc {
return sp.OnActorStateChanged(paychAddr, func(ctx context.Context, oldActorStateHead, newActorStateHead cid.Cid) (changed bool, user UserData, err error) {
var oldState paych.State
if err := sp.cst.Get(ctx, oldActorStateHead, &oldState); err != nil {
return false, nil, err
}
var newState paych.State
if err := sp.cst.Get(ctx, newActorStateHead, &newState); err != nil {
return false, nil, err
}
return diffPaymentChannelState(ctx, &oldState, &newState)
})
}
// PayChToSendChange is a difference in the amount to send on a payment channel when the money is collected
type PayChToSendChange struct {
OldToSend abi.TokenAmount
NewToSend abi.TokenAmount
}
// OnToSendAmountChanges monitors changes on the total amount to send from one party to the other on a payment channel
func (sp *StatePredicates) OnToSendAmountChanges() DiffPaymentChannelStateFunc {
return func(ctx context.Context, oldState *paych.State, newState *paych.State) (changed bool, user UserData, err error) {
if oldState.ToSend.Equals(newState.ToSend) {
return false, nil, nil
}
return true, &PayChToSendChange{
OldToSend: oldState.ToSend,
NewToSend: newState.ToSend,
}, nil
}
}

View File

@ -10,12 +10,10 @@ import (
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
ds "github.com/ipfs/go-datastore" ds "github.com/ipfs/go-datastore"
ds_sync "github.com/ipfs/go-datastore/sync" ds_sync "github.com/ipfs/go-datastore/sync"
"github.com/ipfs/go-hamt-ipld"
bstore "github.com/ipfs/go-ipfs-blockstore" bstore "github.com/ipfs/go-ipfs-blockstore"
cbornode "github.com/ipfs/go-ipld-cbor" cbornode "github.com/ipfs/go-ipld-cbor"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-amt-ipld/v2"
"github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/abi/big" "github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/specs-actors/actors/builtin/market" "github.com/filecoin-project/specs-actors/actors/builtin/market"
@ -69,7 +67,7 @@ func (m mockAPI) setActor(tsk types.TipSetKey, act *types.Actor) {
func TestMarketPredicates(t *testing.T) { func TestMarketPredicates(t *testing.T) {
ctx := context.Background() ctx := context.Background()
bs := bstore.NewBlockstore(ds_sync.MutexWrap(ds.NewMapDatastore())) bs := bstore.NewBlockstore(ds_sync.MutexWrap(ds.NewMapDatastore()))
store := cbornode.NewCborStore(bs) store := adt.WrapStore(ctx, cbornode.NewCborStore(bs))
oldDeal1 := &market.DealState{ oldDeal1 := &market.DealState{
SectorStartEpoch: 1, SectorStartEpoch: 1,
@ -284,7 +282,7 @@ func TestMarketPredicates(t *testing.T) {
func TestMinerSectorChange(t *testing.T) { func TestMinerSectorChange(t *testing.T) {
ctx := context.Background() ctx := context.Background()
bs := bstore.NewBlockstore(ds_sync.MutexWrap(ds.NewMapDatastore())) bs := bstore.NewBlockstore(ds_sync.MutexWrap(ds.NewMapDatastore()))
store := cbornode.NewCborStore(bs) store := adt.WrapStore(ctx, cbornode.NewCborStore(bs))
nextID := uint64(0) nextID := uint64(0)
nextIDAddrF := func() address.Address { nextIDAddrF := func() address.Address {
@ -376,7 +374,7 @@ func mockTipset(minerAddr address.Address, timestamp uint64) (*types.TipSet, err
}}) }})
} }
func createMarketState(ctx context.Context, t *testing.T, store *cbornode.BasicIpldStore, deals map[abi.DealID]*market.DealState, props map[abi.DealID]*market.DealProposal) cid.Cid { func createMarketState(ctx context.Context, t *testing.T, store adt.Store, deals map[abi.DealID]*market.DealState, props map[abi.DealID]*market.DealProposal) cid.Cid {
dealRootCid := createDealAMT(ctx, t, store, deals) dealRootCid := createDealAMT(ctx, t, store, deals)
propRootCid := createProposalAMT(ctx, t, store, props) propRootCid := createProposalAMT(ctx, t, store, props)
@ -389,37 +387,37 @@ func createMarketState(ctx context.Context, t *testing.T, store *cbornode.BasicI
return stateC return stateC
} }
func createEmptyMarketState(t *testing.T, store *cbornode.BasicIpldStore) *market.State { func createEmptyMarketState(t *testing.T, store adt.Store) *market.State {
emptyArrayCid, err := amt.NewAMT(store).Flush(context.TODO()) emptyArrayCid, err := adt.MakeEmptyArray(store).Root()
require.NoError(t, err) require.NoError(t, err)
emptyMap, err := store.Put(context.TODO(), hamt.NewNode(store, hamt.UseTreeBitWidth(5))) emptyMap, err := adt.MakeEmptyMap(store).Root()
require.NoError(t, err) require.NoError(t, err)
return market.ConstructState(emptyArrayCid, emptyMap, emptyMap) return market.ConstructState(emptyArrayCid, emptyMap, emptyMap)
} }
func createDealAMT(ctx context.Context, t *testing.T, store *cbornode.BasicIpldStore, deals map[abi.DealID]*market.DealState) cid.Cid { func createDealAMT(ctx context.Context, t *testing.T, store adt.Store, deals map[abi.DealID]*market.DealState) cid.Cid {
root := amt.NewAMT(store) root := adt.MakeEmptyArray(store)
for dealID, dealState := range deals { for dealID, dealState := range deals {
err := root.Set(ctx, uint64(dealID), dealState) err := root.Set(uint64(dealID), dealState)
require.NoError(t, err) require.NoError(t, err)
} }
rootCid, err := root.Flush(ctx) rootCid, err := root.Root()
require.NoError(t, err) require.NoError(t, err)
return rootCid return rootCid
} }
func createProposalAMT(ctx context.Context, t *testing.T, store *cbornode.BasicIpldStore, props map[abi.DealID]*market.DealProposal) cid.Cid { func createProposalAMT(ctx context.Context, t *testing.T, store adt.Store, props map[abi.DealID]*market.DealProposal) cid.Cid {
root := amt.NewAMT(store) root := adt.MakeEmptyArray(store)
for dealID, prop := range props { for dealID, prop := range props {
err := root.Set(ctx, uint64(dealID), prop) err := root.Set(uint64(dealID), prop)
require.NoError(t, err) require.NoError(t, err)
} }
rootCid, err := root.Flush(ctx) rootCid, err := root.Root()
require.NoError(t, err) require.NoError(t, err)
return rootCid return rootCid
} }
func createMinerState(ctx context.Context, t *testing.T, store *cbornode.BasicIpldStore, owner, worker address.Address, sectors []miner.SectorOnChainInfo) cid.Cid { func createMinerState(ctx context.Context, t *testing.T, store adt.Store, owner, worker address.Address, sectors []miner.SectorOnChainInfo) cid.Cid {
rootCid := createSectorsAMT(ctx, t, store, sectors) rootCid := createSectorsAMT(ctx, t, store, sectors)
state := createEmptyMinerState(ctx, t, store, owner, worker) state := createEmptyMinerState(ctx, t, store, owner, worker)
@ -430,10 +428,10 @@ func createMinerState(ctx context.Context, t *testing.T, store *cbornode.BasicIp
return stateC return stateC
} }
func createEmptyMinerState(ctx context.Context, t *testing.T, store *cbornode.BasicIpldStore, owner, worker address.Address) *miner.State { func createEmptyMinerState(ctx context.Context, t *testing.T, store adt.Store, owner, worker address.Address) *miner.State {
emptyArrayCid, err := amt.NewAMT(store).Flush(context.TODO()) emptyArrayCid, err := adt.MakeEmptyArray(store).Root()
require.NoError(t, err) require.NoError(t, err)
emptyMap, err := store.Put(context.TODO(), hamt.NewNode(store, hamt.UseTreeBitWidth(5))) emptyMap, err := adt.MakeEmptyMap(store).Root()
require.NoError(t, err) require.NoError(t, err)
emptyDeadline, err := store.Put(context.TODO(), &miner.Deadline{ emptyDeadline, err := store.Put(context.TODO(), &miner.Deadline{
@ -457,14 +455,14 @@ func createEmptyMinerState(ctx context.Context, t *testing.T, store *cbornode.Ba
} }
func createSectorsAMT(ctx context.Context, t *testing.T, store *cbornode.BasicIpldStore, sectors []miner.SectorOnChainInfo) cid.Cid { func createSectorsAMT(ctx context.Context, t *testing.T, store adt.Store, sectors []miner.SectorOnChainInfo) cid.Cid {
root := amt.NewAMT(store) root := adt.MakeEmptyArray(store)
for _, sector := range sectors { for _, sector := range sectors {
sector := sector sector := sector
err := root.Set(ctx, uint64(sector.SectorNumber), &sector) err := root.Set(uint64(sector.SectorNumber), &sector)
require.NoError(t, err) require.NoError(t, err)
} }
rootCid, err := root.Flush(ctx) rootCid, err := root.Root()
require.NoError(t, err) require.NoError(t, err)
return rootCid return rootCid
} }

View File

@ -378,6 +378,10 @@ func (cg *ChainGen) NextTipSet() (*MinedTipSet, error) {
return mts, nil return mts, nil
} }
func (cg *ChainGen) SetWinningPoStProver(m address.Address, wpp WinningPoStProver) {
cg.eppProvs[m] = wpp
}
func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Address) (*MinedTipSet, error) { func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Address) (*MinedTipSet, error) {
var blks []*types.FullBlock var blks []*types.FullBlock

View File

@ -4,15 +4,6 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"github.com/filecoin-project/go-amt-ipld/v2"
"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/builtin/account"
"github.com/filecoin-project/specs-actors/actors/builtin/multisig"
"github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore"
bstore "github.com/ipfs/go-ipfs-blockstore" bstore "github.com/ipfs/go-ipfs-blockstore"
@ -22,11 +13,21 @@ import (
"github.com/filecoin-project/go-address" "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/builtin/account"
"github.com/filecoin-project/specs-actors/actors/builtin/multisig"
"github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
"github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/genesis" "github.com/filecoin-project/lotus/genesis"
"github.com/filecoin-project/lotus/lib/sigs"
) )
const AccountStart = 100 const AccountStart = 100
@ -224,6 +225,43 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge
return nil, err return nil, err
} }
// Setup the first verifier as ID-address 81
// TODO: remove this
skBytes, err := sigs.Generate(crypto.SigTypeBLS)
if err != nil {
return nil, xerrors.Errorf("creating random verifier secret key: %w", err)
}
verifierPk, err := sigs.ToPublic(crypto.SigTypeBLS, skBytes)
if err != nil {
return nil, xerrors.Errorf("creating random verifier public key: %w", err)
}
verifierAd, err := address.NewBLSAddress(verifierPk)
if err != nil {
return nil, xerrors.Errorf("creating random verifier address: %w", err)
}
verifierId, err := address.NewIDAddress(81)
if err != nil {
return nil, err
}
verifierState, err := cst.Put(ctx, &account.State{Address: verifierAd})
if err != nil {
return nil, err
}
err = state.SetActor(verifierId, &types.Actor{
Code: builtin.AccountActorCodeID,
Balance: types.NewInt(0),
Head: verifierState,
})
if err != nil {
return nil, xerrors.Errorf("setting account from actmap: %w", err)
}
return state, nil return state, nil
} }
@ -290,17 +328,22 @@ func VerifyPreSealedData(ctx context.Context, cs *store.ChainStore, stateroot ci
} }
} }
verifier, err := address.NewIDAddress(80) verifregRoot, err := address.NewIDAddress(80)
if err != nil { if err != nil {
return cid.Undef, err return cid.Undef, err
} }
vm, err := vm.NewVM(stateroot, 0, &fakeRand{}, cs.Blockstore(), &fakedSigSyscalls{cs.VMSys()}) verifier, err := address.NewIDAddress(81)
if err != nil {
return cid.Undef, err
}
vm, err := vm.NewVM(stateroot, 0, &fakeRand{}, cs.Blockstore(), mkFakedSigSyscalls(cs.VMSys()))
if err != nil { if err != nil {
return cid.Undef, xerrors.Errorf("failed to create NewVM: %w", err) return cid.Undef, xerrors.Errorf("failed to create NewVM: %w", err)
} }
_, err = doExecValue(ctx, vm, builtin.VerifiedRegistryActorAddr, verifier, types.NewInt(0), builtin.MethodsVerifiedRegistry.AddVerifier, mustEnc(&verifreg.AddVerifierParams{ _, err = doExecValue(ctx, vm, builtin.VerifiedRegistryActorAddr, verifregRoot, types.NewInt(0), builtin.MethodsVerifiedRegistry.AddVerifier, mustEnc(&verifreg.AddVerifierParams{
Address: verifier, Address: verifier,
Allowance: abi.NewStoragePower(int64(sum)), // eh, close enough Allowance: abi.NewStoragePower(int64(sum)), // eh, close enough
@ -327,7 +370,7 @@ func VerifyPreSealedData(ctx context.Context, cs *store.ChainStore, stateroot ci
return st, nil return st, nil
} }
func MakeGenesisBlock(ctx context.Context, bs bstore.Blockstore, sys runtime.Syscalls, template genesis.Template) (*GenesisBootstrap, error) { func MakeGenesisBlock(ctx context.Context, bs bstore.Blockstore, sys vm.SyscallBuilder, template genesis.Template) (*GenesisBootstrap, error) {
st, err := MakeInitialStateTree(ctx, bs, template) st, err := MakeInitialStateTree(ctx, bs, template)
if err != nil { if err != nil {
return nil, xerrors.Errorf("make initial state tree failed: %w", err) return nil, xerrors.Errorf("make initial state tree failed: %w", err)
@ -352,9 +395,8 @@ func MakeGenesisBlock(ctx context.Context, bs bstore.Blockstore, sys runtime.Sys
return nil, xerrors.Errorf("setup miners failed: %w", err) return nil, xerrors.Errorf("setup miners failed: %w", err)
} }
cst := cbor.NewCborStore(bs) store := adt.WrapStore(ctx, cbor.NewCborStore(bs))
emptyroot, err := adt.MakeEmptyArray(store).Root()
emptyroot, err := amt.FromArray(ctx, cst, nil)
if err != nil { if err != nil {
return nil, xerrors.Errorf("amt build failed: %w", err) return nil, xerrors.Errorf("amt build failed: %w", err)
} }

View File

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"context" "context"
"fmt" "fmt"
"github.com/filecoin-project/lotus/chain/state"
"math/rand" "math/rand"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
@ -46,8 +47,16 @@ func (fss *fakedSigSyscalls) VerifySignature(signature crypto.Signature, signer
return nil return nil
} }
func mkFakedSigSyscalls(base vm.SyscallBuilder) vm.SyscallBuilder {
return func(ctx context.Context, cstate *state.StateTree, cst cbor.IpldStore) runtime.Syscalls {
return &fakedSigSyscalls{
base(ctx, cstate, cst),
}
}
}
func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid, miners []genesis.Miner) (cid.Cid, error) { func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid, miners []genesis.Miner) (cid.Cid, error) {
vm, err := vm.NewVM(sroot, 0, &fakeRand{}, cs.Blockstore(), &fakedSigSyscalls{cs.VMSys()}) vm, err := vm.NewVM(sroot, 0, &fakeRand{}, cs.Blockstore(), mkFakedSigSyscalls(cs.VMSys()))
if err != nil { if err != nil {
return cid.Undef, xerrors.Errorf("failed to create NewVM: %w", err) return cid.Undef, xerrors.Errorf("failed to create NewVM: %w", err)
} }

View File

@ -6,11 +6,12 @@ import (
"fmt" "fmt"
"github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/util/adt"
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init" init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
"github.com/ipfs/go-hamt-ipld"
bstore "github.com/ipfs/go-ipfs-blockstore" bstore "github.com/ipfs/go-ipfs-blockstore"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
@ -26,8 +27,8 @@ func SetupInitActor(bs bstore.Blockstore, netname string, initialActors []genesi
ias.NextID = MinerStart ias.NextID = MinerStart
ias.NetworkName = netname ias.NetworkName = netname
cst := cbor.NewCborStore(bs) store := adt.WrapStore(context.TODO(), cbor.NewCborStore(bs))
amap := hamt.NewNode(cst, hamt.UseTreeBitWidth(5)) // TODO: use spec adt map amap := adt.MakeEmptyMap(store)
for i, a := range initialActors { for i, a := range initialActors {
if a.Type == genesis.TMultisig { if a.Type == genesis.TMultisig {
@ -43,9 +44,10 @@ func SetupInitActor(bs bstore.Blockstore, netname string, initialActors []genesi
return nil, xerrors.Errorf("unmarshaling account meta: %w", err) return nil, xerrors.Errorf("unmarshaling account meta: %w", err)
} }
fmt.Printf("init set %s t0%d\n", ainfo.Owner, AccountStart+uint64(i)) fmt.Printf("init set %s t0%d\n", ainfo.Owner, AccountStart+int64(i))
if err := amap.Set(context.TODO(), string(ainfo.Owner.Bytes()), AccountStart+uint64(i)); err != nil { value := cbg.CborInt(AccountStart + int64(i))
if err := amap.Put(adt.AddrKey(ainfo.Owner), &value); err != nil {
return nil, err return nil, err
} }
} }
@ -55,22 +57,19 @@ func SetupInitActor(bs bstore.Blockstore, netname string, initialActors []genesi
if err := json.Unmarshal(rootVerifier.Meta, &ainfo); err != nil { if err := json.Unmarshal(rootVerifier.Meta, &ainfo); err != nil {
return nil, xerrors.Errorf("unmarshaling account meta: %w", err) return nil, xerrors.Errorf("unmarshaling account meta: %w", err)
} }
if err := amap.Set(context.TODO(), string(ainfo.Owner.Bytes()), 80); err != nil { value := cbg.CborInt(80)
if err := amap.Put(adt.AddrKey(ainfo.Owner), &value); err != nil {
return nil, err return nil, err
} }
} }
if err := amap.Flush(context.TODO()); err != nil { amapaddr, err := amap.Root()
return nil, err
}
amapcid, err := cst.Put(context.TODO(), amap)
if err != nil { if err != nil {
return nil, err return nil, err
} }
ias.AddressMap = amapaddr
ias.AddressMap = amapcid statecid, err := store.Put(store.Context(), &ias)
statecid, err := cst.Put(context.TODO(), &ias)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -2,11 +2,12 @@ package genesis
import ( import (
"context" "context"
"github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/specs-actors/actors/abi/big" "github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/specs-actors/actors/builtin/power" "github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/ipfs/go-hamt-ipld"
bstore "github.com/ipfs/go-ipfs-blockstore" bstore "github.com/ipfs/go-ipfs-blockstore"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
@ -14,10 +15,8 @@ import (
) )
func SetupStoragePowerActor(bs bstore.Blockstore) (*types.Actor, error) { func SetupStoragePowerActor(bs bstore.Blockstore) (*types.Actor, error) {
ctx := context.TODO() store := adt.WrapStore(context.TODO(), cbor.NewCborStore(bs))
cst := cbor.NewCborStore(bs) emptyhamt, err := adt.MakeEmptyMap(store).Root()
nd := hamt.NewNode(cst, hamt.UseTreeBitWidth(5))
emptyhamt, err := cst.Put(ctx, nd)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -36,7 +35,7 @@ func SetupStoragePowerActor(bs bstore.Blockstore) (*types.Actor, error) {
ProofValidationBatch: nil, ProofValidationBatch: nil,
} }
stcid, err := cst.Put(ctx, sms) stcid, err := store.Put(store.Context(), sms)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -2,11 +2,10 @@ package genesis
import ( import (
"context" "context"
"github.com/ipfs/go-hamt-ipld"
"github.com/filecoin-project/go-amt-ipld/v2"
"github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/market" "github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/util/adt"
bstore "github.com/ipfs/go-ipfs-blockstore" bstore "github.com/ipfs/go-ipfs-blockstore"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
@ -14,20 +13,20 @@ import (
) )
func SetupStorageMarketActor(bs bstore.Blockstore) (*types.Actor, error) { func SetupStorageMarketActor(bs bstore.Blockstore) (*types.Actor, error) {
cst := cbor.NewCborStore(bs) store := adt.WrapStore(context.TODO(), cbor.NewCborStore(bs))
a, err := amt.NewAMT(cst).Flush(context.TODO()) a, err := adt.MakeEmptyArray(store).Root()
if err != nil { if err != nil {
return nil, err return nil, err
} }
h, err := cst.Put(context.TODO(), hamt.NewNode(cst, hamt.UseTreeBitWidth(5))) h, err := adt.MakeEmptyMap(store).Root()
if err != nil { if err != nil {
return nil, err return nil, err
} }
sms := market.ConstructState(a, h, h) sms := market.ConstructState(a, h, h)
stcid, err := cst.Put(context.TODO(), sms) stcid, err := store.Put(store.Context(), sms)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -4,12 +4,12 @@ import (
"context" "context"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/ipfs/go-hamt-ipld"
bstore "github.com/ipfs/go-ipfs-blockstore" bstore "github.com/ipfs/go-ipfs-blockstore"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
"github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/verifreg" "github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
) )
@ -27,16 +27,16 @@ func init() {
} }
func SetupVerifiedRegistryActor(bs bstore.Blockstore) (*types.Actor, error) { func SetupVerifiedRegistryActor(bs bstore.Blockstore) (*types.Actor, error) {
cst := cbor.NewCborStore(bs) store := adt.WrapStore(context.TODO(), cbor.NewCborStore(bs))
h, err := cst.Put(context.TODO(), hamt.NewNode(cst, hamt.UseTreeBitWidth(5))) h, err := adt.MakeEmptyMap(store).Root()
if err != nil { if err != nil {
return nil, err return nil, err
} }
sms := verifreg.ConstructState(h, RootVerifierID) sms := verifreg.ConstructState(h, RootVerifierID)
stcid, err := cst.Put(context.TODO(), sms) stcid, err := store.Put(store.Context(), sms)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -4,8 +4,8 @@ import (
"context" "context"
bls "github.com/filecoin-project/filecoin-ffi" bls "github.com/filecoin-project/filecoin-ffi"
amt "github.com/filecoin-project/go-amt-ipld/v2"
"github.com/filecoin-project/specs-actors/actors/crypto" "github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/filecoin-project/specs-actors/actors/util/adt"
cid "github.com/ipfs/go-cid" cid "github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
@ -78,17 +78,17 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wal
} }
} }
bs := cbor.NewCborStore(sm.ChainStore().Blockstore()) store := sm.ChainStore().Store(ctx)
blsmsgroot, err := amt.FromArray(ctx, bs, toIfArr(blsMsgCids)) blsmsgroot, err := toArray(store, blsMsgCids)
if err != nil { if err != nil {
return nil, xerrors.Errorf("building bls amt: %w", err) return nil, xerrors.Errorf("building bls amt: %w", err)
} }
secpkmsgroot, err := amt.FromArray(ctx, bs, toIfArr(secpkMsgCids)) secpkmsgroot, err := toArray(store, secpkMsgCids)
if err != nil { if err != nil {
return nil, xerrors.Errorf("building secpk amt: %w", err) return nil, xerrors.Errorf("building secpk amt: %w", err)
} }
mmcid, err := bs.Put(ctx, &types.MsgMeta{ mmcid, err := store.Put(store.Context(), &types.MsgMeta{
BlsMessages: blsmsgroot, BlsMessages: blsmsgroot,
SecpkMessages: secpkmsgroot, SecpkMessages: secpkmsgroot,
}) })
@ -167,11 +167,13 @@ func aggregateSignatures(sigs []crypto.Signature) (*crypto.Signature, error) {
}, nil }, nil
} }
func toIfArr(cids []cid.Cid) []cbg.CBORMarshaler { func toArray(store adt.Store, cids []cid.Cid) (cid.Cid, error) {
out := make([]cbg.CBORMarshaler, 0, len(cids)) arr := adt.MakeEmptyArray(store)
for _, c := range cids { for i, c := range cids {
oc := cbg.CborCid(c) oc := cbg.CborCid(c)
out = append(out, &oc) if err := arr.Set(uint64(i), &oc); err != nil {
return cid.Undef, err
} }
return out }
return arr.Root()
} }

View File

@ -117,12 +117,14 @@ func (ms *msgSet) add(m *types.SignedMessage) error {
minPrice := exms.Message.GasPrice minPrice := exms.Message.GasPrice
minPrice = types.BigAdd(minPrice, types.BigDiv(types.BigMul(minPrice, rbfNum), rbfDenom)) minPrice = types.BigAdd(minPrice, types.BigDiv(types.BigMul(minPrice, rbfNum), rbfDenom))
minPrice = types.BigAdd(minPrice, types.NewInt(1)) minPrice = types.BigAdd(minPrice, types.NewInt(1))
if types.BigCmp(m.Message.GasPrice, minPrice) > 0 { if types.BigCmp(m.Message.GasPrice, minPrice) >= 0 {
log.Infow("add with RBF", "oldprice", exms.Message.GasPrice, log.Infow("add with RBF", "oldprice", exms.Message.GasPrice,
"newprice", m.Message.GasPrice, "addr", m.Message.From, "nonce", m.Message.Nonce) "newprice", m.Message.GasPrice, "addr", m.Message.From, "nonce", m.Message.Nonce)
} else { } else {
log.Info("add with duplicate nonce") log.Info("add with duplicate nonce")
return xerrors.Errorf("message to %s with nonce %d already in mpool", m.Message.To, m.Message.Nonce) return xerrors.Errorf("message from %s with nonce %d already in mpool,"+
" increase GasPrice to %s from %s to trigger replace by fee",
m.Message.From, m.Message.Nonce, minPrice, m.Message.GasPrice)
} }
} }
} }
@ -617,6 +619,14 @@ func (mp *MessagePool) Pending() ([]*types.SignedMessage, *types.TipSet) {
return out, mp.curTs return out, mp.curTs
} }
func (mp *MessagePool) PendingFor(a address.Address) ([]*types.SignedMessage, *types.TipSet) {
mp.curTsLk.Lock()
defer mp.curTsLk.Unlock()
mp.lk.Lock()
defer mp.lk.Unlock()
return mp.pendingFor(a), mp.curTs
}
func (mp *MessagePool) pendingFor(a address.Address) []*types.SignedMessage { func (mp *MessagePool) pendingFor(a address.Address) []*types.SignedMessage {
mset := mp.pending[a] mset := mp.pending[a]

View File

@ -9,7 +9,6 @@ import (
"github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
hamt "github.com/ipfs/go-hamt-ipld"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
logging "github.com/ipfs/go-log/v2" logging "github.com/ipfs/go-log/v2"
"go.opencensus.io/trace" "go.opencensus.io/trace"
@ -23,7 +22,7 @@ var log = logging.Logger("statetree")
// StateTree stores actors state by their ID. // StateTree stores actors state by their ID.
type StateTree struct { type StateTree struct {
root *hamt.Node root *adt.Map
Store cbor.IpldStore Store cbor.IpldStore
snaps *stateSnaps snaps *stateSnaps
@ -117,15 +116,16 @@ func (ss *stateSnaps) deleteActor(addr address.Address) {
} }
func NewStateTree(cst cbor.IpldStore) (*StateTree, error) { func NewStateTree(cst cbor.IpldStore) (*StateTree, error) {
return &StateTree{ return &StateTree{
root: hamt.NewNode(cst, hamt.UseTreeBitWidth(5)), root: adt.MakeEmptyMap(adt.WrapStore(context.TODO(), cst)),
Store: cst, Store: cst,
snaps: newStateSnaps(), snaps: newStateSnaps(),
}, nil }, nil
} }
func LoadStateTree(cst cbor.IpldStore, c cid.Cid) (*StateTree, error) { func LoadStateTree(cst cbor.IpldStore, c cid.Cid) (*StateTree, error) {
nd, err := hamt.LoadNode(context.Background(), cst, c, hamt.UseTreeBitWidth(5)) nd, err := adt.AsMap(adt.WrapStore(context.TODO(), cst), c)
if err != nil { if err != nil {
log.Errorf("loading hamt node %s failed: %s", c, err) log.Errorf("loading hamt node %s failed: %s", c, err)
return nil, err return nil, err
@ -206,12 +206,10 @@ func (st *StateTree) GetActor(addr address.Address) (*types.Actor, error) {
} }
var act types.Actor var act types.Actor
err = st.root.Find(context.TODO(), string(addr.Bytes()), &act) if found, err := st.root.Get(adt.AddrKey(addr), &act); err != nil {
if err != nil {
if err == hamt.ErrNotFound {
return nil, types.ErrActorNotFound
}
return nil, xerrors.Errorf("hamt find failed: %w", err) return nil, xerrors.Errorf("hamt find failed: %w", err)
} else if !found {
return nil, types.ErrActorNotFound
} }
st.snaps.setActor(addr, &act) st.snaps.setActor(addr, &act)
@ -253,21 +251,17 @@ func (st *StateTree) Flush(ctx context.Context) (cid.Cid, error) {
for addr, sto := range st.snaps.layers[0].actors { for addr, sto := range st.snaps.layers[0].actors {
if sto.Delete { if sto.Delete {
if err := st.root.Delete(ctx, string(addr.Bytes())); err != nil { if err := st.root.Delete(adt.AddrKey(addr)); err != nil {
return cid.Undef, err return cid.Undef, err
} }
} else { } else {
if err := st.root.Set(ctx, string(addr.Bytes()), &sto.Act); err != nil { if err := st.root.Put(adt.AddrKey(addr), &sto.Act); err != nil {
return cid.Undef, err return cid.Undef, err
} }
} }
} }
if err := st.root.Flush(ctx); err != nil { return st.root.Root()
return cid.Undef, err
}
return st.Store.Put(ctx, st.root)
} }
func (st *StateTree) Snapshot(ctx context.Context) error { func (st *StateTree) Snapshot(ctx context.Context) error {

View File

@ -272,7 +272,7 @@ func TestStateTreeConsistency(t *testing.T) {
} }
fmt.Println("root is: ", root) fmt.Println("root is: ", root)
if root.String() != "bafy2bzaceadyjnrv3sbjvowfl3jr4pdn5p2bf3exjjie2f3shg4oy5sub7h34" { if root.String() != "bafy2bzaceb2bhqw75pqp44efoxvlnm73lnctq6djair56bfn5x3gw56epcxbi" {
t.Fatal("MISMATCH!") t.Fatal("MISMATCH!")
} }
} }

View File

@ -86,7 +86,7 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types.
return sm.CallRaw(ctx, msg, state, r, ts.Height()) return sm.CallRaw(ctx, msg, state, r, ts.Height())
} }
func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, ts *types.TipSet) (*api.InvocResult, error) { func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, priorMsgs []types.ChainMsg, ts *types.TipSet) (*api.InvocResult, error) {
ctx, span := trace.StartSpan(ctx, "statemanager.CallWithGas") ctx, span := trace.StartSpan(ctx, "statemanager.CallWithGas")
defer span.End() defer span.End()
@ -110,6 +110,13 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, ts
if err != nil { if err != nil {
return nil, xerrors.Errorf("failed to set up vm: %w", err) return nil, xerrors.Errorf("failed to set up vm: %w", err)
} }
for i, m := range priorMsgs {
_, err := vmi.ApplyMessage(ctx, m)
if err != nil {
return nil, xerrors.Errorf("applying prior message (%d, %s): %w", i, m.Cid(), err)
}
}
fromActor, err := vmi.StateTree().GetActor(msg.From) fromActor, err := vmi.StateTree().GetActor(msg.From)
if err != nil { if err != nil {
return nil, xerrors.Errorf("call raw get actor: %s", err) return nil, xerrors.Errorf("call raw get actor: %s", err)

View File

@ -156,7 +156,7 @@ func TestForkHeightTriggers(t *testing.T) {
} }
inv.Register(builtin.PaymentChannelActorCodeID, &testActor{}, &testActorState{}) inv.Register(builtin.PaymentChannelActorCodeID, &testActor{}, &testActorState{})
sm.SetVMConstructor(func(c cid.Cid, h abi.ChainEpoch, r vm.Rand, b blockstore.Blockstore, s runtime.Syscalls) (*vm.VM, error) { sm.SetVMConstructor(func(c cid.Cid, h abi.ChainEpoch, r vm.Rand, b blockstore.Blockstore, s vm.SyscallBuilder) (*vm.VM, error) {
nvm, err := vm.NewVM(c, h, r, b, s) nvm, err := vm.NewVM(c, h, r, b, s)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -6,7 +6,6 @@ import (
"sync" "sync"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
amt "github.com/filecoin-project/go-amt-ipld/v2"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors"
@ -19,14 +18,12 @@ import (
"github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/market" "github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/builtin/reward" "github.com/filecoin-project/specs-actors/actors/builtin/reward"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/filecoin-project/specs-actors/actors/util/adt"
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors" "golang.org/x/xerrors"
bls "github.com/filecoin-project/filecoin-ffi" bls "github.com/filecoin-project/filecoin-ffi"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
hamt "github.com/ipfs/go-hamt-ipld"
blockstore "github.com/ipfs/go-ipfs-blockstore" blockstore "github.com/ipfs/go-ipfs-blockstore"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
logging "github.com/ipfs/go-log/v2" logging "github.com/ipfs/go-log/v2"
@ -41,7 +38,7 @@ type StateManager struct {
stCache map[string][]cid.Cid stCache map[string][]cid.Cid
compWait map[string]chan struct{} compWait map[string]chan struct{}
stlk sync.Mutex stlk sync.Mutex
newVM func(cid.Cid, abi.ChainEpoch, vm.Rand, blockstore.Blockstore, runtime.Syscalls) (*vm.VM, error) newVM func(cid.Cid, abi.ChainEpoch, vm.Rand, blockstore.Blockstore, vm.SyscallBuilder) (*vm.VM, error)
} }
func NewStateManager(cs *store.ChainStore) *StateManager { func NewStateManager(cs *store.ChainStore) *StateManager {
@ -254,8 +251,13 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, pstate cid.Cid, bms []B
return cid.Undef, cid.Undef, xerrors.Errorf("CheckProofSubmissions exit was non-zero: %d", ret.ExitCode) return cid.Undef, cid.Undef, xerrors.Errorf("CheckProofSubmissions exit was non-zero: %d", ret.ExitCode)
} }
bs := cbor.NewCborStore(sm.cs.Blockstore()) rectarr := adt.MakeEmptyArray(sm.cs.Store(ctx))
rectroot, err := amt.FromArray(ctx, bs, receipts) for i, receipt := range receipts {
if err := rectarr.Set(uint64(i), receipt); err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("failed to build receipts amt: %w", err)
}
}
rectroot, err := rectarr.Root()
if err != nil { if err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("failed to build receipts amt: %w", err) return cid.Undef, cid.Undef, xerrors.Errorf("failed to build receipts amt: %w", err)
} }
@ -652,14 +654,13 @@ func (sm *StateManager) ListAllActors(ctx context.Context, ts *types.TipSet) ([]
return nil, err return nil, err
} }
cst := cbor.NewCborStore(sm.cs.Blockstore()) r, err := adt.AsMap(sm.cs.Store(ctx), st)
r, err := hamt.LoadNode(ctx, cst, st, hamt.UseTreeBitWidth(5))
if err != nil { if err != nil {
return nil, err return nil, err
} }
var out []address.Address var out []address.Address
err = r.ForEach(ctx, func(k string, val interface{}) error { err = r.ForEach(nil, func(k string) error {
addr, err := address.NewFromBytes([]byte(k)) addr, err := address.NewFromBytes([]byte(k))
if err != nil { if err != nil {
return xerrors.Errorf("address in state tree was not valid: %w", err) return xerrors.Errorf("address in state tree was not valid: %w", err)
@ -754,6 +755,6 @@ func (sm *StateManager) ValidateChain(ctx context.Context, ts *types.TipSet) err
return nil return nil
} }
func (sm *StateManager) SetVMConstructor(nvm func(cid.Cid, abi.ChainEpoch, vm.Rand, blockstore.Blockstore, runtime.Syscalls) (*vm.VM, error)) { func (sm *StateManager) SetVMConstructor(nvm func(cid.Cid, abi.ChainEpoch, vm.Rand, blockstore.Blockstore, vm.SyscallBuilder) (*vm.VM, error)) {
sm.newVM = nvm sm.newVM = nvm
} }

View File

@ -13,7 +13,6 @@ import (
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
amt "github.com/filecoin-project/go-amt-ipld/v2"
"github.com/filecoin-project/go-bitfield" "github.com/filecoin-project/go-bitfield"
"github.com/filecoin-project/sector-storage/ffiwrapper" "github.com/filecoin-project/sector-storage/ffiwrapper"
"github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/abi"
@ -258,7 +257,7 @@ func GetSectorsForWinningPoSt(ctx context.Context, pv ffiwrapper.Verifier, sm *S
return nil, xerrors.Errorf("failed to enumerate all sector IDs: %w", err) return nil, xerrors.Errorf("failed to enumerate all sector IDs: %w", err)
} }
sectorAmt, err := amt.LoadAMT(ctx, sm.cs.Store(ctx), mas.Sectors) sectorAmt, err := adt.AsArray(sm.cs.Store(ctx), mas.Sectors)
if err != nil { if err != nil {
return nil, xerrors.Errorf("failed to load sectors amt: %w", err) return nil, xerrors.Errorf("failed to load sectors amt: %w", err)
} }
@ -268,8 +267,10 @@ func GetSectorsForWinningPoSt(ctx context.Context, pv ffiwrapper.Verifier, sm *S
sid := sectors[n] sid := sectors[n]
var sinfo miner.SectorOnChainInfo var sinfo miner.SectorOnChainInfo
if err := sectorAmt.Get(ctx, sid, &sinfo); err != nil { if found, err := sectorAmt.Get(sid, &sinfo); err != nil {
return nil, xerrors.Errorf("failed to get sector %d: %w", sid, err) return nil, xerrors.Errorf("failed to get sector %d: %w", sid, err)
} else if !found {
return nil, xerrors.Errorf("failed to find sector %d", sid)
} }
out[i] = abi.SectorInfo{ out[i] = abi.SectorInfo{
@ -328,18 +329,21 @@ func GetStorageDeal(ctx context.Context, sm *StateManager, dealID abi.DealID, ts
if _, err := sm.LoadActorState(ctx, builtin.StorageMarketActorAddr, &state, ts); err != nil { if _, err := sm.LoadActorState(ctx, builtin.StorageMarketActorAddr, &state, ts); err != nil {
return nil, err return nil, err
} }
store := sm.ChainStore().Store(ctx)
da, err := amt.LoadAMT(ctx, cbor.NewCborStore(sm.ChainStore().Blockstore()), state.Proposals) da, err := adt.AsArray(store, state.Proposals)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var dp market.DealProposal var dp market.DealProposal
if err := da.Get(ctx, uint64(dealID), &dp); err != nil { if found, err := da.Get(uint64(dealID), &dp); err != nil {
return nil, err return nil, err
} else if !found {
return nil, xerrors.Errorf("deal %d not found", dealID)
} }
sa, err := market.AsDealStateArray(sm.ChainStore().Store(ctx), state.States) sa, err := market.AsDealStateArray(store, state.States)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -391,15 +395,16 @@ func ListMinerActors(ctx context.Context, sm *StateManager, ts *types.TipSet) ([
} }
func LoadSectorsFromSet(ctx context.Context, bs blockstore.Blockstore, ssc cid.Cid, filter *abi.BitField, filterOut bool) ([]*api.ChainSectorInfo, error) { func LoadSectorsFromSet(ctx context.Context, bs blockstore.Blockstore, ssc cid.Cid, filter *abi.BitField, filterOut bool) ([]*api.ChainSectorInfo, error) {
a, err := amt.LoadAMT(ctx, cbor.NewCborStore(bs), ssc) a, err := adt.AsArray(store.ActorStore(ctx, bs), ssc)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var sset []*api.ChainSectorInfo var sset []*api.ChainSectorInfo
if err := a.ForEach(ctx, func(i uint64, v *cbg.Deferred) error { var v cbg.Deferred
if err := a.ForEach(&v, func(i int64) error {
if filter != nil { if filter != nil {
set, err := filter.IsSet(i) set, err := filter.IsSet(uint64(i))
if err != nil { if err != nil {
return xerrors.Errorf("filter check error: %w", err) return xerrors.Errorf("filter check error: %w", err)
} }

View File

@ -9,14 +9,11 @@ import (
"os" "os"
"sync" "sync"
"github.com/filecoin-project/lotus/lib/adtutil"
"github.com/filecoin-project/specs-actors/actors/crypto" "github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/minio/blake2b-simd" "github.com/minio/blake2b-simd"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
@ -28,8 +25,6 @@ import (
"go.opencensus.io/trace" "go.opencensus.io/trace"
"go.uber.org/multierr" "go.uber.org/multierr"
amt "github.com/filecoin-project/go-amt-ipld/v2"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
lru "github.com/hashicorp/golang-lru" lru "github.com/hashicorp/golang-lru"
@ -85,10 +80,10 @@ type ChainStore struct {
mmCache *lru.ARCCache mmCache *lru.ARCCache
tsCache *lru.ARCCache tsCache *lru.ARCCache
vmcalls runtime.Syscalls vmcalls vm.SyscallBuilder
} }
func NewChainStore(bs bstore.Blockstore, ds dstore.Batching, vmcalls runtime.Syscalls) *ChainStore { func NewChainStore(bs bstore.Blockstore, ds dstore.Batching, vmcalls vm.SyscallBuilder) *ChainStore {
c, _ := lru.NewARC(2048) c, _ := lru.NewARC(2048)
tsc, _ := lru.NewARC(4096) tsc, _ := lru.NewARC(4096)
cs := &ChainStore{ cs := &ChainStore{
@ -688,20 +683,25 @@ func (cs *ChainStore) GetSignedMessage(c cid.Cid) (*types.SignedMessage, error)
func (cs *ChainStore) readAMTCids(root cid.Cid) ([]cid.Cid, error) { func (cs *ChainStore) readAMTCids(root cid.Cid) ([]cid.Cid, error) {
ctx := context.TODO() ctx := context.TODO()
bs := cbor.NewCborStore(cs.bs) a, err := adt.AsArray(cs.Store(ctx), root)
a, err := amt.LoadAMT(ctx, bs, root)
if err != nil { if err != nil {
return nil, xerrors.Errorf("amt load: %w", err) return nil, xerrors.Errorf("amt load: %w", err)
} }
var cids []cid.Cid var (
for i := uint64(0); i < a.Count; i++ { cids []cid.Cid
var c cbg.CborCid cborCid cbg.CborCid
if err := a.Get(ctx, i, &c); err != nil { )
return nil, xerrors.Errorf("failed to load cid from amt: %w", err) if err := a.ForEach(&cborCid, func(i int64) error {
c := cid.Cid(cborCid)
cids = append(cids, c)
return nil
}); err != nil {
return nil, xerrors.Errorf("failed to traverse amt: %w", err)
} }
cids = append(cids, cid.Cid(c)) if uint64(len(cids)) != a.Length() {
return nil, xerrors.Errorf("found %d cids, expected %d", len(cids), a.Length())
} }
return cids, nil return cids, nil
@ -849,15 +849,16 @@ func (cs *ChainStore) MessagesForBlock(b *types.BlockHeader) ([]*types.Message,
func (cs *ChainStore) GetParentReceipt(b *types.BlockHeader, i int) (*types.MessageReceipt, error) { func (cs *ChainStore) GetParentReceipt(b *types.BlockHeader, i int) (*types.MessageReceipt, error) {
ctx := context.TODO() ctx := context.TODO()
bs := cbor.NewCborStore(cs.bs) a, err := adt.AsArray(cs.Store(ctx), b.ParentMessageReceipts)
a, err := amt.LoadAMT(ctx, bs, b.ParentMessageReceipts)
if err != nil { if err != nil {
return nil, xerrors.Errorf("amt load: %w", err) return nil, xerrors.Errorf("amt load: %w", err)
} }
var r types.MessageReceipt var r types.MessageReceipt
if err := a.Get(ctx, uint64(i), &r); err != nil { if found, err := a.Get(uint64(i), &r); err != nil {
return nil, err return nil, err
} else if !found {
return nil, xerrors.Errorf("failed to find receipt %d", i)
} }
return &r, nil return &r, nil
@ -896,14 +897,14 @@ func (cs *ChainStore) Blockstore() bstore.Blockstore {
} }
func ActorStore(ctx context.Context, bs blockstore.Blockstore) adt.Store { func ActorStore(ctx context.Context, bs blockstore.Blockstore) adt.Store {
return adtutil.NewStore(ctx, cbor.NewCborStore(bs)) return adt.WrapStore(ctx, cbor.NewCborStore(bs))
} }
func (cs *ChainStore) Store(ctx context.Context) adt.Store { func (cs *ChainStore) Store(ctx context.Context) adt.Store {
return ActorStore(ctx, cs.bs) return ActorStore(ctx, cs.bs)
} }
func (cs *ChainStore) VMSys() runtime.Syscalls { func (cs *ChainStore) VMSys() vm.SyscallBuilder {
return cs.vmcalls return cs.vmcalls
} }

View File

@ -4,15 +4,14 @@ import (
"bytes" "bytes"
"context" "context"
"fmt" "fmt"
"github.com/filecoin-project/lotus/lib/adtutil"
"sync" "sync"
"time" "time"
"golang.org/x/xerrors" "golang.org/x/xerrors"
address "github.com/filecoin-project/go-address" address "github.com/filecoin-project/go-address"
amt "github.com/filecoin-project/go-amt-ipld/v2"
miner "github.com/filecoin-project/specs-actors/actors/builtin/miner" miner "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/util/adt"
lru "github.com/hashicorp/golang-lru" lru "github.com/hashicorp/golang-lru"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
dstore "github.com/ipfs/go-datastore" dstore "github.com/ipfs/go-datastore"
@ -239,31 +238,36 @@ func (bv *BlockValidator) isChainNearSynced() bool {
} }
func (bv *BlockValidator) validateMsgMeta(ctx context.Context, msg *types.BlockMsg) error { func (bv *BlockValidator) validateMsgMeta(ctx context.Context, msg *types.BlockMsg) error {
var bcids, scids []cbg.CBORMarshaler
for _, m := range msg.BlsMessages {
c := cbg.CborCid(m)
bcids = append(bcids, &c)
}
for _, m := range msg.SecpkMessages {
c := cbg.CborCid(m)
scids = append(scids, &c)
}
// TODO there has to be a simpler way to do this without the blockstore dance // TODO there has to be a simpler way to do this without the blockstore dance
bs := cbor.NewCborStore(bstore.NewBlockstore(dstore.NewMapDatastore())) store := adt.WrapStore(ctx, cbor.NewCborStore(bstore.NewBlockstore(dstore.NewMapDatastore())))
bmArr := adt.MakeEmptyArray(store)
smArr := adt.MakeEmptyArray(store)
bmroot, err := amt.FromArray(ctx, bs, bcids) for i, m := range msg.BlsMessages {
c := cbg.CborCid(m)
if err := bmArr.Set(uint64(i), &c); err != nil {
return err
}
}
for i, m := range msg.SecpkMessages {
c := cbg.CborCid(m)
if err := smArr.Set(uint64(i), &c); err != nil {
return err
}
}
bmroot, err := bmArr.Root()
if err != nil { if err != nil {
return err return err
} }
smroot, err := amt.FromArray(ctx, bs, scids) smroot, err := smArr.Root()
if err != nil { if err != nil {
return err return err
} }
mrcid, err := bs.Put(ctx, &types.MsgMeta{ mrcid, err := store.Put(store.Context(), &types.MsgMeta{
BlsMessages: bmroot, BlsMessages: bmroot,
SecpkMessages: smroot, SecpkMessages: smroot,
}) })
@ -318,7 +322,7 @@ func (bv *BlockValidator) getMinerWorkerKey(ctx context.Context, msg *types.Bloc
return address.Undef, err return address.Undef, err
} }
info, err := mst.GetInfo(adtutil.NewStore(ctx, cst)) info, err := mst.GetInfo(adt.WrapStore(ctx, cst))
if err != nil { if err != nil {
return address.Undef, err return address.Undef, err
} }

View File

@ -27,7 +27,6 @@ import (
bls "github.com/filecoin-project/filecoin-ffi" bls "github.com/filecoin-project/filecoin-ffi"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
amt "github.com/filecoin-project/go-amt-ipld/v2"
"github.com/filecoin-project/sector-storage/ffiwrapper" "github.com/filecoin-project/sector-storage/ffiwrapper"
"github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin"
@ -256,15 +255,13 @@ func (syncer *Syncer) ValidateMsgMeta(fblk *types.FullBlock) error {
} }
// Collect the CIDs of both types of messages separately: BLS and Secpk. // Collect the CIDs of both types of messages separately: BLS and Secpk.
var bcids, scids []cbg.CBORMarshaler var bcids, scids []cid.Cid
for _, m := range fblk.BlsMessages { for _, m := range fblk.BlsMessages {
c := cbg.CborCid(m.Cid()) bcids = append(bcids, m.Cid())
bcids = append(bcids, &c)
} }
for _, m := range fblk.SecpkMessages { for _, m := range fblk.SecpkMessages {
c := cbg.CborCid(m.Cid()) scids = append(scids, m.Cid())
scids = append(scids, &c)
} }
// TODO: IMPORTANT(GARBAGE). These message puts and the msgmeta // TODO: IMPORTANT(GARBAGE). These message puts and the msgmeta
@ -354,19 +351,17 @@ func zipTipSetAndMessages(bs cbor.IpldStore, ts *types.TipSet, allbmsgs []*types
} }
var smsgs []*types.SignedMessage var smsgs []*types.SignedMessage
var smsgCids []cbg.CBORMarshaler var smsgCids []cid.Cid
for _, m := range smi[bi] { for _, m := range smi[bi] {
smsgs = append(smsgs, allsmsgs[m]) smsgs = append(smsgs, allsmsgs[m])
c := cbg.CborCid(allsmsgs[m].Cid()) smsgCids = append(smsgCids, allsmsgs[m].Cid())
smsgCids = append(smsgCids, &c)
} }
var bmsgs []*types.Message var bmsgs []*types.Message
var bmsgCids []cbg.CBORMarshaler var bmsgCids []cid.Cid
for _, m := range bmi[bi] { for _, m := range bmi[bi] {
bmsgs = append(bmsgs, allbmsgs[m]) bmsgs = append(bmsgs, allbmsgs[m])
c := cbg.CborCid(allbmsgs[m].Cid()) bmsgCids = append(bmsgCids, allbmsgs[m].Cid())
bmsgCids = append(bmsgCids, &c)
} }
mrcid, err := computeMsgMeta(bs, bmsgCids, smsgCids) mrcid, err := computeMsgMeta(bs, bmsgCids, smsgCids)
@ -392,19 +387,36 @@ func zipTipSetAndMessages(bs cbor.IpldStore, ts *types.TipSet, allbmsgs []*types
// computeMsgMeta computes the root CID of the combined arrays of message CIDs // computeMsgMeta computes the root CID of the combined arrays of message CIDs
// of both types (BLS and Secpk). // of both types (BLS and Secpk).
func computeMsgMeta(bs cbor.IpldStore, bmsgCids, smsgCids []cbg.CBORMarshaler) (cid.Cid, error) { func computeMsgMeta(bs cbor.IpldStore, bmsgCids, smsgCids []cid.Cid) (cid.Cid, error) {
ctx := context.TODO() store := adt.WrapStore(context.TODO(), bs)
bmroot, err := amt.FromArray(ctx, bs, bmsgCids) bmArr := adt.MakeEmptyArray(store)
smArr := adt.MakeEmptyArray(store)
for i, m := range bmsgCids {
c := cbg.CborCid(m)
if err := bmArr.Set(uint64(i), &c); err != nil {
return cid.Undef, err
}
}
for i, m := range smsgCids {
c := cbg.CborCid(m)
if err := smArr.Set(uint64(i), &c); err != nil {
return cid.Undef, err
}
}
bmroot, err := bmArr.Root()
if err != nil { if err != nil {
return cid.Undef, err return cid.Undef, err
} }
smroot, err := amt.FromArray(ctx, bs, smsgCids) smroot, err := smArr.Root()
if err != nil { if err != nil {
return cid.Undef, err return cid.Undef, err
} }
mrcid, err := bs.Put(ctx, &types.MsgMeta{ mrcid, err := store.Put(store.Context(), &types.MsgMeta{
BlsMessages: bmroot, BlsMessages: bmroot,
SecpkMessages: smroot, SecpkMessages: smroot,
}) })
@ -851,6 +863,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) (er
"%d errors occurred:\n\t%s\n\n", "%d errors occurred:\n\t%s\n\n",
len(es), strings.Join(points, "\n\t")) len(es), strings.Join(points, "\n\t"))
} }
return mulErr
} }
if err := syncer.store.MarkBlockAsValidated(ctx, b.Cid()); err != nil { if err := syncer.store.MarkBlockAsValidated(ctx, b.Cid()); err != nil {
@ -908,7 +921,7 @@ func (syncer *Syncer) VerifyWinningPoStProof(ctx context.Context, h *types.Block
} }
if !ok { if !ok {
log.Errorf("invalid winning post (%x; %v)", rand, sectors) log.Errorf("invalid winning post (block: %s, %x; %v)", h.Cid(), rand, sectors)
return xerrors.Errorf("winning post was invalid") return xerrors.Errorf("winning post was invalid")
} }
@ -992,18 +1005,21 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock
return nil return nil
} }
var blsCids []cbg.CBORMarshaler store := adt.WrapStore(ctx, cst)
bmArr := adt.MakeEmptyArray(store)
for i, m := range b.BlsMessages { for i, m := range b.BlsMessages {
if err := checkMsg(m); err != nil { if err := checkMsg(m); err != nil {
return xerrors.Errorf("block had invalid bls message at index %d: %w", i, err) return xerrors.Errorf("block had invalid bls message at index %d: %w", i, err)
} }
c := cbg.CborCid(m.Cid()) c := cbg.CborCid(m.Cid())
blsCids = append(blsCids, &c) if err := bmArr.Set(uint64(i), &c); err != nil {
return xerrors.Errorf("failed to put bls message at index %d: %w", i, err)
}
} }
var secpkCids []cbg.CBORMarshaler smArr := adt.MakeEmptyArray(store)
for i, m := range b.SecpkMessages { for i, m := range b.SecpkMessages {
if err := checkMsg(m); err != nil { if err := checkMsg(m); err != nil {
return xerrors.Errorf("block had invalid secpk message at index %d: %w", i, err) return xerrors.Errorf("block had invalid secpk message at index %d: %w", i, err)
@ -1021,17 +1037,19 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock
} }
c := cbg.CborCid(m.Cid()) c := cbg.CborCid(m.Cid())
secpkCids = append(secpkCids, &c) if err := smArr.Set(uint64(i), &c); err != nil {
return xerrors.Errorf("failed to put secpk message at index %d: %w", i, err)
}
} }
bmroot, err := amt.FromArray(ctx, cst, blsCids) bmroot, err := bmArr.Root()
if err != nil { if err != nil {
return xerrors.Errorf("failed to build amt from bls msg cids: %w", err) return err
} }
smroot, err := amt.FromArray(ctx, cst, secpkCids) smroot, err := smArr.Root()
if err != nil { if err != nil {
return xerrors.Errorf("failed to build amt from bls msg cids: %w", err) return err
} }
mrcid, err := cst.Put(ctx, &types.MsgMeta{ mrcid, err := cst.Put(ctx, &types.MsgMeta{
@ -1056,6 +1074,10 @@ func (syncer *Syncer) verifyBlsAggregate(ctx context.Context, sig *crypto.Signat
trace.Int64Attribute("msgCount", int64(len(msgs))), trace.Int64Attribute("msgCount", int64(len(msgs))),
) )
if len(msgs) == 0 {
return nil
}
bmsgs := make([]bls.Message, len(msgs)) bmsgs := make([]bls.Message, len(msgs))
for i, m := range msgs { for i, m := range msgs {
bmsgs[i] = m.Bytes() bmsgs[i] = m.Bytes()

View File

@ -170,7 +170,7 @@ func (tu *syncTestUtil) pushTsExpectErr(to int, fts *store.FullTipSet, experr bo
} }
} }
func (tu *syncTestUtil) mineOnBlock(blk *store.FullTipSet, src int, miners []int, wait, fail bool) *store.FullTipSet { func (tu *syncTestUtil) mineOnBlock(blk *store.FullTipSet, to int, miners []int, wait, fail bool) *store.FullTipSet {
if miners == nil { if miners == nil {
for i := range tu.g.Miners { for i := range tu.g.Miners {
miners = append(miners, i) miners = append(miners, i)
@ -188,9 +188,9 @@ func (tu *syncTestUtil) mineOnBlock(blk *store.FullTipSet, src int, miners []int
require.NoError(tu.t, err) require.NoError(tu.t, err)
if fail { if fail {
tu.pushTsExpectErr(src, mts.TipSet, true) tu.pushTsExpectErr(to, mts.TipSet, true)
} else { } else {
tu.pushFtsAndWait(src, mts.TipSet, wait) tu.pushFtsAndWait(to, mts.TipSet, wait)
} }
return mts.TipSet return mts.TipSet
@ -433,6 +433,41 @@ func TestSyncBadTimestamp(t *testing.T) {
} }
} }
type badWpp struct{}
func (wpp badWpp) GenerateCandidates(context.Context, abi.PoStRandomness, uint64) ([]uint64, error) {
return []uint64{1}, nil
}
func (wpp badWpp) ComputeProof(context.Context, []abi.SectorInfo, abi.PoStRandomness) ([]abi.PoStProof, error) {
return []abi.PoStProof{
abi.PoStProof{
PoStProof: abi.RegisteredPoStProof_StackedDrgWinning2KiBV1,
ProofBytes: []byte("evil"),
},
}, nil
}
func TestSyncBadWinningPoSt(t *testing.T) {
H := 15
tu := prepSyncTest(t, H)
client := tu.addClientNode()
require.NoError(t, tu.mn.LinkAll())
tu.connect(client, 0)
tu.waitUntilSync(0, client)
base := tu.g.CurTipset
// both miners now produce invalid winning posts
tu.g.SetWinningPoStProver(tu.g.Miners[0], &badWpp{})
tu.g.SetWinningPoStProver(tu.g.Miners[1], &badWpp{})
// now ensure that new blocks are not accepted
tu.mineOnBlock(base, client, nil, false, true)
}
func (tu *syncTestUtil) loadChainToNode(to int) { func (tu *syncTestUtil) loadChainToNode(to int) {
// utility to simulate incoming blocks without miner process // utility to simulate incoming blocks without miner process
// TODO: should call syncer directly, this won't work correctly in all cases // TODO: should call syncer directly, this won't work correctly in all cases

View File

@ -10,7 +10,6 @@ import (
"github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/crypto" "github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/filecoin-project/specs-actors/actors/puppet" "github.com/filecoin-project/specs-actors/actors/puppet"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
vtypes "github.com/filecoin-project/chain-validation/chain/types" vtypes "github.com/filecoin-project/chain-validation/chain/types"
@ -25,12 +24,12 @@ import (
// Applier applies messages to state trees and storage. // Applier applies messages to state trees and storage.
type Applier struct { type Applier struct {
stateWrapper *StateWrapper stateWrapper *StateWrapper
syscalls runtime.Syscalls syscalls vm.SyscallBuilder
} }
var _ vstate.Applier = &Applier{} var _ vstate.Applier = &Applier{}
func NewApplier(sw *StateWrapper, syscalls runtime.Syscalls) *Applier { func NewApplier(sw *StateWrapper, syscalls vm.SyscallBuilder) *Applier {
return &Applier{sw, syscalls} return &Applier{sw, syscalls}
} }

View File

@ -1,7 +1,10 @@
package validation package validation
import ( import (
"context"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/specs-actors/actors/runtime" "github.com/filecoin-project/specs-actors/actors/runtime"
cbor "github.com/ipfs/go-ipld-cbor"
vstate "github.com/filecoin-project/chain-validation/state" vstate "github.com/filecoin-project/chain-validation/state"
) )
@ -18,7 +21,9 @@ func NewFactories() *Factories {
func (f *Factories) NewStateAndApplier(syscalls runtime.Syscalls) (vstate.VMWrapper, vstate.Applier) { func (f *Factories) NewStateAndApplier(syscalls runtime.Syscalls) (vstate.VMWrapper, vstate.Applier) {
st := NewState() st := NewState()
return st, NewApplier(st, syscalls) return st, NewApplier(st, func(ctx context.Context, cstate *state.StateTree, cst cbor.IpldStore) runtime.Syscalls {
return syscalls
})
} }
func (f *Factories) NewKeyManager() vstate.KeyManager { func (f *Factories) NewKeyManager() vstate.KeyManager {

View File

@ -18,6 +18,7 @@ func LoadVector(t *testing.T, f string, out interface{}) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
defer fi.Close()
if err := json.NewDecoder(fi).Decode(out); err != nil { if err := json.NewDecoder(fi).Decode(out); err != nil {
t.Fatal(err) t.Fatal(err)

View File

@ -13,7 +13,7 @@ import (
) )
const ( const (
GasStorageMulti = 1 GasStorageMulti = 1000
GasComputeMulti = 1 GasComputeMulti = 1
) )
@ -85,10 +85,10 @@ type Pricelist interface {
var prices = map[abi.ChainEpoch]Pricelist{ var prices = map[abi.ChainEpoch]Pricelist{
abi.ChainEpoch(0): &pricelistV0{ abi.ChainEpoch(0): &pricelistV0{
onChainMessageComputeBase: 137137, onChainMessageComputeBase: 137137,
onChainMessageStorageBase: 0, // TODO gas onChainMessageStorageBase: 36,
onChainMessageStoragePerByte: 2, // TODO gas onChainMessageStoragePerByte: 1,
onChainReturnValuePerByte: 8, // TODO gas onChainReturnValuePerByte: 1,
sendBase: 97236, sendBase: 97236,
sendTransferFunds: 96812, sendTransferFunds: 96812,
@ -97,11 +97,11 @@ var prices = map[abi.ChainEpoch]Pricelist{
ipldGetBase: 417230, ipldGetBase: 417230,
ipldPutBase: 396100, ipldPutBase: 396100,
ipldPutPerByte: 2, // TODO gas ipldPutPerByte: 1,
createActorCompute: 750011, createActorCompute: 750011,
createActorStorage: 500, // TODO gas createActorStorage: 36 + 40,
deleteActor: -500, // -createActorStorage deleteActor: -(36 + 40), // -createActorStorage
verifySignature: map[crypto.SigType]int64{ verifySignature: map[crypto.SigType]int64{
crypto.SigTypeBLS: 219946580, crypto.SigTypeBLS: 219946580,

View File

@ -20,7 +20,6 @@ import (
"github.com/filecoin-project/specs-actors/actors/runtime/exitcode" "github.com/filecoin-project/specs-actors/actors/runtime/exitcode"
"github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
hamt "github.com/ipfs/go-hamt-ipld"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
"go.opencensus.io/trace" "go.opencensus.io/trace"
@ -464,7 +463,7 @@ func (rt *Runtime) GetBalance(a address.Address) (types.BigInt, aerrors.ActorErr
switch err { switch err {
default: default:
return types.EmptyInt, aerrors.Escalate(err, "failed to look up actor balance") return types.EmptyInt, aerrors.Escalate(err, "failed to look up actor balance")
case hamt.ErrNotFound: case types.ErrActorNotFound:
return types.NewInt(0), nil return types.NewInt(0), nil
case nil: case nil:
return act.Balance, nil return act.Balance, nil
@ -582,12 +581,12 @@ func (rt *Runtime) abortIfAlreadyValidated() {
func (rt *Runtime) Log(level vmr.LogLevel, msg string, args ...interface{}) { func (rt *Runtime) Log(level vmr.LogLevel, msg string, args ...interface{}) {
switch level { switch level {
case vmr.DEBUG: case vmr.DEBUG:
actorLog.Debugf(msg, args) actorLog.Debugf(msg, args...)
case vmr.INFO: case vmr.INFO:
actorLog.Infof(msg, args) actorLog.Infof(msg, args...)
case vmr.WARN: case vmr.WARN:
actorLog.Warnf(msg, args) actorLog.Warnf(msg, args...)
case vmr.ERROR: case vmr.ERROR:
actorLog.Errorf(msg, args) actorLog.Errorf(msg, args...)
} }
} }

View File

@ -16,12 +16,12 @@ import (
"github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/adtutil"
"github.com/filecoin-project/lotus/lib/sigs" "github.com/filecoin-project/lotus/lib/sigs"
"github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin/miner" "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/crypto" "github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/filecoin-project/specs-actors/actors/runtime" "github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/sector-storage/ffiwrapper" "github.com/filecoin-project/sector-storage/ffiwrapper"
) )
@ -32,15 +32,26 @@ func init() {
// Actual type is defined in chain/types/vmcontext.go because the VMContext interface is there // Actual type is defined in chain/types/vmcontext.go because the VMContext interface is there
func Syscalls(verifier ffiwrapper.Verifier) runtime.Syscalls { type SyscallBuilder func(ctx context.Context, cstate *state.StateTree, cst cbor.IpldStore) runtime.Syscalls
return &syscallShim{verifier: verifier}
func Syscalls(verifier ffiwrapper.Verifier) SyscallBuilder {
return func(ctx context.Context, cstate *state.StateTree, cst cbor.IpldStore) runtime.Syscalls {
return &syscallShim{
ctx: ctx,
cstate: cstate,
cst: cst,
verifier: verifier,
}
}
} }
type syscallShim struct { type syscallShim struct {
ctx context.Context ctx context.Context
cstate *state.StateTree cstate *state.StateTree
cst *cbor.BasicIpldStore cst cbor.IpldStore
verifier ffiwrapper.Verifier verifier ffiwrapper.Verifier
} }
@ -180,7 +191,7 @@ func (ss *syscallShim) VerifyBlockSig(blk *types.BlockHeader) error {
return err return err
} }
info, err := mas.GetInfo(adtutil.NewStore(ss.ctx, ss.cst)) info, err := mas.GetInfo(adt.WrapStore(ss.ctx, ss.cst))
if err != nil { if err != nil {
return err return err
} }

View File

@ -24,7 +24,6 @@ import (
"github.com/filecoin-project/specs-actors/actors/builtin/account" "github.com/filecoin-project/specs-actors/actors/builtin/account"
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init" init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
"github.com/filecoin-project/specs-actors/actors/crypto" "github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/specs-actors/actors/runtime/exitcode" "github.com/filecoin-project/specs-actors/actors/runtime/exitcode"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
@ -115,7 +114,7 @@ func (vm *VM) makeRuntime(ctx context.Context, msg *types.Message, origin addres
Atlas: vm.cst.Atlas, Atlas: vm.cst.Atlas,
} }
rt.sys = pricedSyscalls{ rt.sys = pricedSyscalls{
under: vm.Syscalls, under: vm.Syscalls(ctx, vm.cstate, rt.cst),
chargeGas: rt.chargeGasFunc(1), chargeGas: rt.chargeGasFunc(1),
pl: rt.pricelist, pl: rt.pricelist,
} }
@ -148,10 +147,10 @@ type VM struct {
inv *Invoker inv *Invoker
rand Rand rand Rand
Syscalls runtime.Syscalls Syscalls SyscallBuilder
} }
func NewVM(base cid.Cid, height abi.ChainEpoch, r Rand, cbs blockstore.Blockstore, syscalls runtime.Syscalls) (*VM, error) { func NewVM(base cid.Cid, height abi.ChainEpoch, r Rand, cbs blockstore.Blockstore, syscalls SyscallBuilder) (*VM, error) {
buf := bufbstore.NewBufferedBstore(cbs) buf := bufbstore.NewBufferedBstore(cbs)
cst := cbor.NewCborStore(buf) cst := cbor.NewCborStore(buf)
state, err := state.LoadStateTree(cst, base) state, err := state.LoadStateTree(cst, base)
@ -347,6 +346,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
ExitCode: exitcode.SysErrSenderInvalid, ExitCode: exitcode.SysErrSenderInvalid,
GasUsed: 0, GasUsed: 0,
}, },
ActorErr: aerrors.Newf(exitcode.SysErrSenderInvalid, "actor not found: %s", msg.From),
Penalty: minerPenaltyAmount, Penalty: minerPenaltyAmount,
Duration: time.Since(start), Duration: time.Since(start),
}, nil }, nil
@ -361,6 +361,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
ExitCode: exitcode.SysErrSenderInvalid, ExitCode: exitcode.SysErrSenderInvalid,
GasUsed: 0, GasUsed: 0,
}, },
ActorErr: aerrors.Newf(exitcode.SysErrSenderInvalid, "send from not account actor: %s", fromActor.Code),
Penalty: minerPenaltyAmount, Penalty: minerPenaltyAmount,
Duration: time.Since(start), Duration: time.Since(start),
}, nil }, nil
@ -373,6 +374,8 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
ExitCode: exitcode.SysErrSenderStateInvalid, ExitCode: exitcode.SysErrSenderStateInvalid,
GasUsed: 0, GasUsed: 0,
}, },
ActorErr: aerrors.Newf(exitcode.SysErrSenderStateInvalid,
"actor nonce invalid: msg:%d != state:%d", msg.Nonce, fromActor.Nonce),
Penalty: minerPenaltyAmount, Penalty: minerPenaltyAmount,
Duration: time.Since(start), Duration: time.Since(start),
}, nil }, nil
@ -386,6 +389,8 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
ExitCode: exitcode.SysErrSenderStateInvalid, ExitCode: exitcode.SysErrSenderStateInvalid,
GasUsed: 0, GasUsed: 0,
}, },
ActorErr: aerrors.Newf(exitcode.SysErrSenderStateInvalid,
"actor balance less than needed: %s < %s", types.FIL(fromActor.Balance), types.FIL(totalCost)),
Penalty: minerPenaltyAmount, Penalty: minerPenaltyAmount,
Duration: time.Since(start), Duration: time.Since(start),
}, nil }, nil

View File

@ -242,24 +242,24 @@ var CommonCommands = []*cli.Command{
} }
var Commands = []*cli.Command{ var Commands = []*cli.Command{
withCategory("basic", sendCmd), WithCategory("basic", sendCmd),
withCategory("basic", walletCmd), WithCategory("basic", walletCmd),
withCategory("basic", clientCmd), WithCategory("basic", clientCmd),
withCategory("basic", multisigCmd), WithCategory("basic", multisigCmd),
withCategory("basic", paychCmd), WithCategory("basic", paychCmd),
withCategory("developer", authCmd), WithCategory("developer", authCmd),
withCategory("developer", mpoolCmd), WithCategory("developer", mpoolCmd),
withCategory("developer", stateCmd), WithCategory("developer", stateCmd),
withCategory("developer", chainCmd), WithCategory("developer", chainCmd),
withCategory("developer", logCmd), WithCategory("developer", logCmd),
withCategory("developer", waitApiCmd), WithCategory("developer", waitApiCmd),
withCategory("developer", fetchParamCmd), WithCategory("developer", fetchParamCmd),
withCategory("network", netCmd), WithCategory("network", netCmd),
withCategory("network", syncCmd), WithCategory("network", syncCmd),
versionCmd, versionCmd,
} }
func withCategory(cat string, cmd *cli.Command) *cli.Command { func WithCategory(cat string, cmd *cli.Command) *cli.Command {
cmd.Category = cat cmd.Category = cat
return cmd return cmd
} }

46
cli/helper.go Normal file
View File

@ -0,0 +1,46 @@
package cli
import (
"fmt"
"os"
"github.com/urfave/cli/v2"
"golang.org/x/xerrors"
)
type PrintHelpErr struct {
Err error
Ctx *cli.Context
}
func (e *PrintHelpErr) Error() string {
return e.Err.Error()
}
func (e *PrintHelpErr) Unwrap() error {
return e.Err
}
func (e *PrintHelpErr) Is(o error) bool {
_, ok := o.(*PrintHelpErr)
return ok
}
func ShowHelp(cctx *cli.Context, err error) error {
return &PrintHelpErr{Err: err, Ctx: cctx}
}
func RunApp(app *cli.App) {
if err := app.Run(os.Args); err != nil {
if os.Getenv("LOTUS_DEV") != "" {
log.Warnf("%+v", err)
} else {
fmt.Printf("ERROR: %s\n\n", err)
}
var phe *PrintHelpErr
if xerrors.As(err, &phe) {
cli.ShowCommandHelp(phe.Ctx, phe.Ctx.Command.Name)
}
os.Exit(1)
}
}

View File

@ -4,11 +4,13 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"sort" "sort"
"strconv"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
) )
@ -20,6 +22,8 @@ var mpoolCmd = &cli.Command{
mpoolPending, mpoolPending,
mpoolSub, mpoolSub,
mpoolStat, mpoolStat,
mpoolReplaceCmd,
mpoolFindCmd,
}, },
} }
@ -228,3 +232,165 @@ var mpoolStat = &cli.Command{
return nil return nil
}, },
} }
var mpoolReplaceCmd = &cli.Command{
Name: "replace",
Usage: "replace a message in the mempool",
Flags: []cli.Flag{
&cli.Int64Flag{
Name: "gas-price",
Usage: "gas price for new message",
},
&cli.Int64Flag{
Name: "gas-limit",
Usage: "gas price for new message",
},
},
ArgsUsage: "[from] [nonce]",
Action: func(cctx *cli.Context) error {
if cctx.Args().Len() < 2 {
return cli.ShowCommandHelp(cctx, cctx.Command.Name)
}
from, err := address.NewFromString(cctx.Args().Get(0))
if err != nil {
return err
}
nonce, err := strconv.ParseUint(cctx.Args().Get(1), 10, 64)
if err != nil {
return err
}
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
ts, err := api.ChainHead(ctx)
if err != nil {
return xerrors.Errorf("getting chain head: %w", err)
}
pending, err := api.MpoolPending(ctx, ts.Key())
if err != nil {
return err
}
var found *types.SignedMessage
for _, p := range pending {
if p.Message.From == from && p.Message.Nonce == nonce {
found = p
break
}
}
if found == nil {
return fmt.Errorf("no pending message found from %s with nonce %d", from, nonce)
}
msg := found.Message
msg.GasLimit = cctx.Int64("gas-limit")
msg.GasPrice = types.NewInt(uint64(cctx.Int64("gas-price")))
smsg, err := api.WalletSignMessage(ctx, msg.From, &msg)
if err != nil {
return fmt.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)
}
fmt.Println("new message cid: ", cid)
return nil
},
}
var mpoolFindCmd = &cli.Command{
Name: "find",
Usage: "find a message in the mempool",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "from",
Usage: "search for messages with given 'from' address",
},
&cli.StringFlag{
Name: "to",
Usage: "search for messages with given 'to' address",
},
&cli.Int64Flag{
Name: "method",
Usage: "search for messages with given method",
},
},
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
pending, err := api.MpoolPending(ctx, types.EmptyTSK)
if err != nil {
return err
}
var toFilter, fromFilter address.Address
if cctx.IsSet("to") {
a, err := address.NewFromString(cctx.String("to"))
if err != nil {
return fmt.Errorf("'to' address was invalid: %w", err)
}
toFilter = a
}
if cctx.IsSet("from") {
a, err := address.NewFromString(cctx.String("from"))
if err != nil {
return fmt.Errorf("'from' address was invalid: %w", err)
}
fromFilter = a
}
var methodFilter *abi.MethodNum
if cctx.IsSet("method") {
m := abi.MethodNum(cctx.Int64("method"))
methodFilter = &m
}
var out []*types.SignedMessage
for _, m := range pending {
if toFilter != address.Undef && m.Message.To != toFilter {
continue
}
if fromFilter != address.Undef && m.Message.From != fromFilter {
continue
}
if methodFilter != nil && *methodFilter != m.Message.Method {
continue
}
out = append(out, m)
}
b, err := json.MarshalIndent(out, "", " ")
if err != nil {
return err
}
fmt.Println(string(b))
return nil
},
}

View File

@ -12,15 +12,14 @@ import (
"text/tabwriter" "text/tabwriter"
"github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init" init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
samsig "github.com/filecoin-project/specs-actors/actors/builtin/multisig" samsig "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
cid "github.com/ipfs/go-cid" cid "github.com/ipfs/go-cid"
"github.com/ipfs/go-hamt-ipld"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
@ -68,6 +67,10 @@ var msigCreateCmd = &cli.Command{
}, },
}, },
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
if cctx.Args().Len() < 1 {
return ShowHelp(cctx, fmt.Errorf("multisigs must have at least one signer"))
}
api, closer, err := GetFullNodeAPI(cctx) api, closer, err := GetFullNodeAPI(cctx)
if err != nil { if err != nil {
return err return err
@ -75,10 +78,6 @@ var msigCreateCmd = &cli.Command{
defer closer() defer closer()
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
if cctx.Args().Len() < 1 {
return fmt.Errorf("multisigs must have at least one signer")
}
var addrs []address.Address var addrs []address.Address
for _, a := range cctx.Args().Slice() { for _, a := range cctx.Args().Slice() {
addr, err := address.NewFromString(a) addr, err := address.NewFromString(a)
@ -159,6 +158,10 @@ var msigInspectCmd = &cli.Command{
ArgsUsage: "[address]", ArgsUsage: "[address]",
Flags: []cli.Flag{}, Flags: []cli.Flag{},
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
if !cctx.Args().Present() {
return ShowHelp(cctx, fmt.Errorf("must specify address of multisig to inspect"))
}
api, closer, err := GetFullNodeAPI(cctx) api, closer, err := GetFullNodeAPI(cctx)
if err != nil { if err != nil {
return err return err
@ -166,10 +169,6 @@ var msigInspectCmd = &cli.Command{
defer closer() defer closer()
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
if !cctx.Args().Present() {
return fmt.Errorf("must specify address of multisig to inspect")
}
maddr, err := address.NewFromString(cctx.Args().First()) maddr, err := address.NewFromString(cctx.Args().First())
if err != nil { if err != nil {
return err return err
@ -237,24 +236,20 @@ var msigInspectCmd = &cli.Command{
func GetMultisigPending(ctx context.Context, lapi api.FullNode, hroot cid.Cid) (map[int64]*samsig.Transaction, error) { func GetMultisigPending(ctx context.Context, lapi api.FullNode, hroot cid.Cid) (map[int64]*samsig.Transaction, error) {
bs := apibstore.NewAPIBlockstore(lapi) bs := apibstore.NewAPIBlockstore(lapi)
cst := cbor.NewCborStore(bs) store := adt.WrapStore(ctx, cbor.NewCborStore(bs))
nd, err := hamt.LoadNode(ctx, cst, hroot, hamt.UseTreeBitWidth(5)) nd, err := adt.AsMap(store, hroot)
if err != nil { if err != nil {
return nil, err return nil, err
} }
txs := make(map[int64]*samsig.Transaction) txs := make(map[int64]*samsig.Transaction)
err = nd.ForEach(ctx, func(k string, val interface{}) error {
d := val.(*cbg.Deferred)
var tx samsig.Transaction var tx samsig.Transaction
if err := tx.UnmarshalCBOR(bytes.NewReader(d.Raw)); err != nil { err = nd.ForEach(&tx, func(k string) error {
return err
}
txid, _ := binary.Varint([]byte(k)) txid, _ := binary.Varint([]byte(k))
txs[txid] = &tx cpy := tx // copy so we don't clobber on future iterations.
txs[txid] = &cpy
return nil return nil
}) })
if err != nil { if err != nil {
@ -287,6 +282,14 @@ var msigProposeCmd = &cli.Command{
}, },
}, },
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
if cctx.Args().Len() < 3 {
return ShowHelp(cctx, fmt.Errorf("must pass at least multisig address, destination, and value"))
}
if cctx.Args().Len() > 3 && cctx.Args().Len() != 5 {
return ShowHelp(cctx, fmt.Errorf("must either pass three or five arguments"))
}
api, closer, err := GetFullNodeAPI(cctx) api, closer, err := GetFullNodeAPI(cctx)
if err != nil { if err != nil {
return err return err
@ -294,14 +297,6 @@ var msigProposeCmd = &cli.Command{
defer closer() defer closer()
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
if cctx.Args().Len() < 3 {
return fmt.Errorf("must pass multisig address, destination, and value")
}
if cctx.Args().Len() > 3 && cctx.Args().Len() != 5 {
return fmt.Errorf("usage: msig propose <msig addr> <desination> <value> [ <method> <params> ]")
}
msig, err := address.NewFromString(cctx.Args().Get(0)) msig, err := address.NewFromString(cctx.Args().Get(0))
if err != nil { if err != nil {
return err return err
@ -391,6 +386,14 @@ var msigApproveCmd = &cli.Command{
}, },
}, },
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
if cctx.Args().Len() < 5 {
return ShowHelp(cctx, fmt.Errorf("must pass multisig address, message ID, proposer address, destination, and value"))
}
if cctx.Args().Len() > 5 && cctx.Args().Len() != 7 {
return ShowHelp(cctx, fmt.Errorf("usage: msig approve <msig addr> <message ID> <proposer address> <desination> <value> [ <method> <params> ]"))
}
api, closer, err := GetFullNodeAPI(cctx) api, closer, err := GetFullNodeAPI(cctx)
if err != nil { if err != nil {
return err return err
@ -398,14 +401,6 @@ var msigApproveCmd = &cli.Command{
defer closer() defer closer()
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
if cctx.Args().Len() < 5 {
return fmt.Errorf("must pass multisig address, message ID, proposer address, destination, and value")
}
if cctx.Args().Len() > 5 && cctx.Args().Len() != 7 {
return fmt.Errorf("usage: msig approve <msig addr> <message ID> <proposer address> <desination> <value> [ <method> <params> ]")
}
msig, err := address.NewFromString(cctx.Args().Get(0)) msig, err := address.NewFromString(cctx.Args().Get(0))
if err != nil { if err != nil {
return err return err
@ -500,6 +495,10 @@ var msigSwapProposeCmd = &cli.Command{
}, },
}, },
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
if cctx.Args().Len() != 3 {
return ShowHelp(cctx, fmt.Errorf("must pass multisig address, old signer address, new signer address"))
}
api, closer, err := GetFullNodeAPI(cctx) api, closer, err := GetFullNodeAPI(cctx)
if err != nil { if err != nil {
return err return err
@ -507,10 +506,6 @@ var msigSwapProposeCmd = &cli.Command{
defer closer() defer closer()
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
if cctx.Args().Len() != 3 {
return fmt.Errorf("must pass multisig address, old signer address, new signer address")
}
msig, err := address.NewFromString(cctx.Args().Get(0)) msig, err := address.NewFromString(cctx.Args().Get(0))
if err != nil { if err != nil {
return err return err
@ -572,6 +567,10 @@ var msigSwapApproveCmd = &cli.Command{
}, },
}, },
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
if cctx.Args().Len() != 5 {
return ShowHelp(cctx, fmt.Errorf("must pass multisig address, proposer address, transaction id, old signer address, new signer address"))
}
api, closer, err := GetFullNodeAPI(cctx) api, closer, err := GetFullNodeAPI(cctx)
if err != nil { if err != nil {
return err return err
@ -579,10 +578,6 @@ var msigSwapApproveCmd = &cli.Command{
defer closer() defer closer()
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
if cctx.Args().Len() != 5 {
return fmt.Errorf("must pass multisig address, proposer address, transaction id, old signer address, new signer address")
}
msig, err := address.NewFromString(cctx.Args().Get(0)) msig, err := address.NewFromString(cctx.Args().Get(0))
if err != nil { if err != nil {
return err return err
@ -654,6 +649,10 @@ var msigSwapCancelCmd = &cli.Command{
}, },
}, },
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
if cctx.Args().Len() != 4 {
return ShowHelp(cctx, fmt.Errorf("must pass multisig address, transaction id, old signer address, new signer address"))
}
api, closer, err := GetFullNodeAPI(cctx) api, closer, err := GetFullNodeAPI(cctx)
if err != nil { if err != nil {
return err return err
@ -661,10 +660,6 @@ var msigSwapCancelCmd = &cli.Command{
defer closer() defer closer()
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
if cctx.Args().Len() != 4 {
return fmt.Errorf("must pass multisig address, transaction id, old signer address, new signer address")
}
msig, err := address.NewFromString(cctx.Args().Get(0)) msig, err := address.NewFromString(cctx.Args().Get(0))
if err != nil { if err != nil {
return err return err

View File

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
@ -20,6 +21,8 @@ var paychCmd = &cli.Command{
paychGetCmd, paychGetCmd,
paychListCmd, paychListCmd,
paychVoucherCmd, paychVoucherCmd,
paychSettleCmd,
paychCloseCmd,
}, },
} }
@ -29,22 +32,22 @@ var paychGetCmd = &cli.Command{
ArgsUsage: "[fromAddress toAddress amount]", ArgsUsage: "[fromAddress toAddress amount]",
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
if cctx.Args().Len() != 3 { if cctx.Args().Len() != 3 {
return fmt.Errorf("must pass three arguments: <from> <to> <available funds>") return ShowHelp(cctx, fmt.Errorf("must pass three arguments: <from> <to> <available funds>"))
} }
from, err := address.NewFromString(cctx.Args().Get(0)) from, err := address.NewFromString(cctx.Args().Get(0))
if err != nil { if err != nil {
return fmt.Errorf("failed to parse from address: %s", err) return ShowHelp(cctx, fmt.Errorf("failed to parse from address: %s", err))
} }
to, err := address.NewFromString(cctx.Args().Get(1)) to, err := address.NewFromString(cctx.Args().Get(1))
if err != nil { if err != nil {
return fmt.Errorf("failed to parse to address: %s", err) return ShowHelp(cctx, fmt.Errorf("failed to parse to address: %s", err))
} }
amt, err := types.BigFromString(cctx.Args().Get(2)) amt, err := types.BigFromString(cctx.Args().Get(2))
if err != nil { if err != nil {
return fmt.Errorf("parsing amount failed: %s", err) return ShowHelp(cctx, fmt.Errorf("parsing amount failed: %s", err))
} }
api, closer, err := GetFullNodeAPI(cctx) api, closer, err := GetFullNodeAPI(cctx)
@ -89,6 +92,86 @@ var paychListCmd = &cli.Command{
}, },
} }
var paychSettleCmd = &cli.Command{
Name: "settle",
Usage: "Settle a payment channel",
ArgsUsage: "[channelAddress]",
Action: func(cctx *cli.Context) error {
if cctx.Args().Len() != 1 {
return fmt.Errorf("must pass payment channel address")
}
ch, err := address.NewFromString(cctx.Args().Get(0))
if err != nil {
return fmt.Errorf("failed to parse payment channel address: %s", err)
}
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
mcid, err := api.PaychSettle(ctx, ch)
if err != nil {
return err
}
mwait, err := api.StateWaitMsg(ctx, mcid, build.MessageConfidence)
if err != nil {
return nil
}
if mwait.Receipt.ExitCode != 0 {
return fmt.Errorf("settle message execution failed (exit code %d)", mwait.Receipt.ExitCode)
}
fmt.Printf("Settled channel %s\n", ch)
return nil
},
}
var paychCloseCmd = &cli.Command{
Name: "collect",
Usage: "Collect funds for a payment channel",
ArgsUsage: "[channelAddress]",
Action: func(cctx *cli.Context) error {
if cctx.Args().Len() != 1 {
return fmt.Errorf("must pass payment channel address")
}
ch, err := address.NewFromString(cctx.Args().Get(0))
if err != nil {
return fmt.Errorf("failed to parse payment channel address: %s", err)
}
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
mcid, err := api.PaychCollect(ctx, ch)
if err != nil {
return err
}
mwait, err := api.StateWaitMsg(ctx, mcid, build.MessageConfidence)
if err != nil {
return nil
}
if mwait.Receipt.ExitCode != 0 {
return fmt.Errorf("collect message execution failed (exit code %d)", mwait.Receipt.ExitCode)
}
fmt.Printf("Collected funds for channel %s\n", ch)
return nil
},
}
var paychVoucherCmd = &cli.Command{ var paychVoucherCmd = &cli.Command{
Name: "voucher", Name: "voucher",
Usage: "Interact with payment channel vouchers", Usage: "Interact with payment channel vouchers",
@ -115,7 +198,7 @@ var paychVoucherCreateCmd = &cli.Command{
}, },
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
if cctx.Args().Len() != 2 { if cctx.Args().Len() != 2 {
return fmt.Errorf("must pass two arguments: <channel> <amount>") return ShowHelp(cctx, fmt.Errorf("must pass two arguments: <channel> <amount>"))
} }
ch, err := address.NewFromString(cctx.Args().Get(0)) ch, err := address.NewFromString(cctx.Args().Get(0))
@ -159,7 +242,7 @@ var paychVoucherCheckCmd = &cli.Command{
ArgsUsage: "[channelAddress voucher]", ArgsUsage: "[channelAddress voucher]",
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
if cctx.Args().Len() != 2 { if cctx.Args().Len() != 2 {
return fmt.Errorf("must pass payment channel address and voucher to validate") return ShowHelp(cctx, fmt.Errorf("must pass payment channel address and voucher to validate"))
} }
ch, err := address.NewFromString(cctx.Args().Get(0)) ch, err := address.NewFromString(cctx.Args().Get(0))
@ -195,7 +278,7 @@ var paychVoucherAddCmd = &cli.Command{
ArgsUsage: "[channelAddress voucher]", ArgsUsage: "[channelAddress voucher]",
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
if cctx.Args().Len() != 2 { if cctx.Args().Len() != 2 {
return fmt.Errorf("must pass payment channel address and voucher") return ShowHelp(cctx, fmt.Errorf("must pass payment channel address and voucher"))
} }
ch, err := address.NewFromString(cctx.Args().Get(0)) ch, err := address.NewFromString(cctx.Args().Get(0))
@ -237,7 +320,7 @@ var paychVoucherListCmd = &cli.Command{
}, },
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
if cctx.Args().Len() != 1 { if cctx.Args().Len() != 1 {
return fmt.Errorf("must pass payment channel address") return ShowHelp(cctx, fmt.Errorf("must pass payment channel address"))
} }
ch, err := address.NewFromString(cctx.Args().Get(0)) ch, err := address.NewFromString(cctx.Args().Get(0))
@ -281,7 +364,7 @@ var paychVoucherBestSpendableCmd = &cli.Command{
ArgsUsage: "[channelAddress]", ArgsUsage: "[channelAddress]",
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
if cctx.Args().Len() != 1 { if cctx.Args().Len() != 1 {
return fmt.Errorf("must pass payment channel address") return ShowHelp(cctx, fmt.Errorf("must pass payment channel address"))
} }
ch, err := address.NewFromString(cctx.Args().Get(0)) ch, err := address.NewFromString(cctx.Args().Get(0))
@ -336,7 +419,7 @@ var paychVoucherSubmitCmd = &cli.Command{
ArgsUsage: "[channelAddress voucher]", ArgsUsage: "[channelAddress voucher]",
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
if cctx.Args().Len() != 2 { if cctx.Args().Len() != 2 {
return fmt.Errorf("must pass payment channel address and voucher") return ShowHelp(cctx, fmt.Errorf("must pass payment channel address and voucher"))
} }
ch, err := address.NewFromString(cctx.Args().Get(0)) ch, err := address.NewFromString(cctx.Args().Get(0))

View File

@ -1,11 +1,20 @@
package cli package cli
import ( import (
"bytes"
"context"
"encoding/hex"
"encoding/json"
"fmt" "fmt"
"reflect"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
cbg "github.com/whyrusleeping/cbor-gen"
) )
var sendCmd = &cli.Command{ var sendCmd = &cli.Command{
@ -22,13 +31,35 @@ var sendCmd = &cli.Command{
Usage: "specify gas price to use in AttoFIL", Usage: "specify gas price to use in AttoFIL",
Value: "0", Value: "0",
}, },
&cli.Int64Flag{
Name: "gas-limit",
Usage: "specify gas limit",
Value: 0,
},
&cli.Int64Flag{ &cli.Int64Flag{
Name: "nonce", Name: "nonce",
Usage: "specify the nonce to use", Usage: "specify the nonce to use",
Value: -1, Value: -1,
}, },
&cli.Uint64Flag{
Name: "method",
Usage: "specify method to invoke",
Value: 0,
},
&cli.StringFlag{
Name: "params-json",
Usage: "specify invocation parameters in json",
},
&cli.StringFlag{
Name: "params-hex",
Usage: "specify invocation parameters in hex",
},
}, },
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
if cctx.Args().Len() != 2 {
return ShowHelp(cctx, fmt.Errorf("'send' expects two arguments, target and amount"))
}
api, closer, err := GetFullNodeAPI(cctx) api, closer, err := GetFullNodeAPI(cctx)
if err != nil { if err != nil {
return err return err
@ -37,18 +68,14 @@ var sendCmd = &cli.Command{
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
if cctx.Args().Len() != 2 {
return fmt.Errorf("'send' expects two arguments, target and amount")
}
toAddr, err := address.NewFromString(cctx.Args().Get(0)) toAddr, err := address.NewFromString(cctx.Args().Get(0))
if err != nil { if err != nil {
return err return ShowHelp(cctx, fmt.Errorf("failed to parse target address: %w", err))
} }
val, err := types.ParseFIL(cctx.Args().Get(1)) val, err := types.ParseFIL(cctx.Args().Get(1))
if err != nil { if err != nil {
return err return ShowHelp(cctx, fmt.Errorf("failed to parse amount: %w", err))
} }
var fromAddr address.Address var fromAddr address.Address
@ -73,11 +100,35 @@ var sendCmd = &cli.Command{
return err return err
} }
method := abi.MethodNum(cctx.Uint64("method"))
var params []byte
if cctx.IsSet("params-json") {
decparams, err := decodeTypedParams(ctx, api, toAddr, method, cctx.String("params-json"))
if err != nil {
return fmt.Errorf("failed to decode json params: %w", err)
}
params = decparams
}
if cctx.IsSet("params-hex") {
if params != nil {
return fmt.Errorf("can only specify one of 'params-json' and 'params-hex'")
}
decparams, err := hex.DecodeString(cctx.String("params-hex"))
if err != nil {
return fmt.Errorf("failed to decode hex params: %w", err)
}
params = decparams
}
msg := &types.Message{ msg := &types.Message{
From: fromAddr, From: fromAddr,
To: toAddr, To: toAddr,
Value: types.BigInt(val), Value: types.BigInt(val),
GasPrice: gp, GasPrice: gp,
GasLimit: cctx.Int64("gas-limit"),
Method: method,
Params: params,
} }
if cctx.Int64("nonce") > 0 { if cctx.Int64("nonce") > 0 {
@ -103,3 +154,22 @@ var sendCmd = &cli.Command{
return nil return nil
}, },
} }
func decodeTypedParams(ctx context.Context, fapi api.FullNode, to address.Address, method abi.MethodNum, paramstr string) ([]byte, error) {
act, err := fapi.StateGetActor(ctx, to, types.EmptyTSK)
if err != nil {
return nil, err
}
p := reflect.New(stmgr.MethodsMap[act.Code][method].Params.Elem()).Interface().(cbg.CBORMarshaler)
if err := json.Unmarshal([]byte(paramstr), p); err != nil {
return nil, fmt.Errorf("unmarshaling input into params type: %w", err)
}
buf := new(bytes.Buffer)
if err := p.MarshalCBOR(buf); err != nil {
return nil, err
}
return buf.Bytes(), nil
}

View File

@ -466,6 +466,7 @@ var importAnalyzeCmd = &cli.Command{
if err != nil { if err != nil {
return err return err
} }
defer fi.Close() //nolint:errcheck
const nWorkers = 16 const nWorkers = 16
jsonIn := make(chan []byte, 2*nWorkers) jsonIn := make(chan []byte, 2*nWorkers)

View File

@ -1,7 +1,6 @@
package main package main
import ( import (
_ "net/http/pprof"
"os" "os"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"

View File

@ -207,7 +207,8 @@ create temp table iam (like id_address_map excluding constraints) on commit drop
return err return err
} }
if _, err := tx.Exec(`insert into id_address_map select * from iam on conflict do nothing `); err != nil { // HACK until chain watch can handle reorgs we need to update this table when ID -> PubKey mappings change
if _, err := tx.Exec(`insert into id_address_map select * from iam on conflict (id) do update set address = EXCLUDED.address`); err != nil {
return xerrors.Errorf("actor put: %w", err) return xerrors.Errorf("actor put: %w", err)
} }

View File

@ -2,6 +2,8 @@ package main
import ( import (
"database/sql" "database/sql"
"net/http"
_ "net/http/pprof"
"os" "os"
_ "github.com/lib/pq" _ "github.com/lib/pq"
@ -12,6 +14,7 @@ import (
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/lotus/cmd/lotus-chainwatch/processor" "github.com/filecoin-project/lotus/cmd/lotus-chainwatch/processor"
"github.com/filecoin-project/lotus/cmd/lotus-chainwatch/scheduler"
"github.com/filecoin-project/lotus/cmd/lotus-chainwatch/syncer" "github.com/filecoin-project/lotus/cmd/lotus-chainwatch/syncer"
) )
@ -25,6 +28,9 @@ var runCmd = &cli.Command{
}, },
}, },
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
go func() {
http.ListenAndServe(":6060", nil)
}()
ll := cctx.String("log-level") ll := cctx.String("log-level")
if err := logging.SetLogLevel("*", ll); err != nil { if err := logging.SetLogLevel("*", ll); err != nil {
return err return err
@ -70,6 +76,9 @@ var runCmd = &cli.Command{
proc := processor.NewProcessor(db, api, maxBatch) proc := processor.NewProcessor(db, api, maxBatch)
proc.Start(ctx) proc.Start(ctx)
sched := scheduler.PrepareScheduler(db)
sched.Start(ctx)
<-ctx.Done() <-ctx.Done()
os.Exit(0) os.Exit(0)
return nil return nil

View File

@ -0,0 +1,29 @@
package scheduler
import (
"context"
"database/sql"
"time"
"golang.org/x/xerrors"
)
func refreshTopMinerByBaseReward(ctx context.Context, db *sql.DB) error {
select {
case <-ctx.Done():
return nil
default:
}
t := time.Now()
defer func() {
log.Debugw("refresh top_miners_by_base_reward", "duration", time.Since(t).String())
}()
_, err := db.Exec("REFRESH MATERIALIZED VIEW top_miners_by_base_reward;")
if err != nil {
return xerrors.Errorf("refresh top_miners_by_base_reward: %w", err)
}
return nil
}

View File

@ -0,0 +1,47 @@
package scheduler
import (
"context"
"database/sql"
"time"
logging "github.com/ipfs/go-log/v2"
)
var log = logging.Logger("scheduler")
// Scheduler manages the execution of jobs triggered
// by tickers. Not externally configuable at runtime.
type Scheduler struct {
db *sql.DB
}
// PrepareScheduler returns a ready-to-run Scheduler
func PrepareScheduler(db *sql.DB) *Scheduler {
return &Scheduler{db}
}
// Start the scheduler jobs at the defined intervals
func (s *Scheduler) Start(ctx context.Context) {
log.Debug("Starting Scheduler")
go func() {
// run once on start after schema has initialized
time.Sleep(5 * time.Second)
if err := refreshTopMinerByBaseReward(ctx, s.db); err != nil {
log.Errorf(err.Error())
}
refreshTopMinerCh := time.NewTicker(6 * time.Hour)
defer refreshTopMinerCh.Stop()
for {
select {
case <-refreshTopMinerCh.C:
if err := refreshTopMinerByBaseReward(ctx, s.db); err != nil {
log.Errorf(err.Error())
}
case <-ctx.Done():
return
}
}
}()
}

View File

@ -9,6 +9,7 @@ import (
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"syscall" "syscall"
"time" "time"
@ -93,7 +94,8 @@ var runCmd = &cli.Command{
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.StringFlag{ &cli.StringFlag{
Name: "address", Name: "address",
Usage: "Locally reachable address", Usage: "locally reachable address",
Value: "0.0.0.0",
}, },
&cli.BoolFlag{ &cli.BoolFlag{
Name: "no-local-storage", Name: "no-local-storage",
@ -114,6 +116,11 @@ var runCmd = &cli.Command{
Usage: "enable commit (32G sectors: all cores or GPUs, 128GiB Memory + 64GiB swap)", Usage: "enable commit (32G sectors: all cores or GPUs, 128GiB Memory + 64GiB swap)",
Value: true, Value: true,
}, },
&cli.StringFlag{
Name: "timeout",
Usage: "used when address is unspecified. must be a valid duration recognized by golang's time.ParseDuration function",
Value: "30m",
},
}, },
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
if !cctx.Bool("enable-gpu-proving") { if !cctx.Bool("enable-gpu-proving") {
@ -122,10 +129,6 @@ var runCmd = &cli.Command{
} }
} }
if cctx.String("address") == "" {
return xerrors.Errorf("--address flag is required")
}
// Connect to storage-miner // Connect to storage-miner
var nodeApi api.StorageMiner var nodeApi api.StorageMiner
var closer func() var closer func()
@ -259,8 +262,24 @@ var runCmd = &cli.Command{
} }
log.Info("Opening local storage; connecting to master") log.Info("Opening local storage; connecting to master")
const unspecifiedAddress = "0.0.0.0"
address := cctx.String("address")
addressSlice := strings.Split(address, ":")
if ip := net.ParseIP(addressSlice[0]); ip != nil {
if ip.String() == unspecifiedAddress {
timeout, err := time.ParseDuration(cctx.String("timeout"))
if err != nil {
return err
}
rip, err := extractRoutableIP(timeout)
if err != nil {
return err
}
address = rip + ":" + addressSlice[1]
}
}
localStore, err := stores.NewLocal(ctx, lr, nodeApi, []string{"http://" + cctx.String("address") + "/remote"}) localStore, err := stores.NewLocal(ctx, lr, nodeApi, []string{"http://" + address + "/remote"})
if err != nil { if err != nil {
return err return err
} }
@ -289,7 +308,7 @@ var runCmd = &cli.Command{
mux := mux.NewRouter() mux := mux.NewRouter()
log.Info("Setting up control endpoint at " + cctx.String("address")) log.Info("Setting up control endpoint at " + address)
rpcServer := jsonrpc.NewServer() rpcServer := jsonrpc.NewServer()
rpcServer.Register("Filecoin", apistruct.PermissionedWorkerAPI(workerApi)) rpcServer.Register("Filecoin", apistruct.PermissionedWorkerAPI(workerApi))
@ -319,7 +338,7 @@ var runCmd = &cli.Command{
log.Warn("Graceful shutdown successful") log.Warn("Graceful shutdown successful")
}() }()
nl, err := net.Listen("tcp", cctx.String("address")) nl, err := net.Listen("tcp", address)
if err != nil { if err != nil {
return err return err
} }
@ -327,7 +346,7 @@ var runCmd = &cli.Command{
log.Info("Waiting for tasks") log.Info("Waiting for tasks")
go func() { go func() {
if err := nodeApi.WorkerConnect(ctx, "ws://"+cctx.String("address")+"/rpc/v0"); err != nil { if err := nodeApi.WorkerConnect(ctx, "ws://"+address+"/rpc/v0"); err != nil {
log.Errorf("Registering worker failed: %+v", err) log.Errorf("Registering worker failed: %+v", err)
cancel() cancel()
return return
@ -376,3 +395,27 @@ func watchMinerConn(ctx context.Context, cctx *cli.Context, nodeApi api.StorageM
} }
}() }()
} }
func extractRoutableIP(timeout time.Duration) (string, error) {
minerMultiAddrKey := "MINER_API_INFO"
deprecatedMinerMultiAddrKey := "STORAGE_API_INFO"
env, ok := os.LookupEnv(minerMultiAddrKey)
if !ok {
// TODO remove after deprecation period
env, ok = os.LookupEnv(deprecatedMinerMultiAddrKey)
if ok {
log.Warnf("Using a deprecated env(%s) value, please use env(%s) instead.", deprecatedMinerMultiAddrKey, minerMultiAddrKey)
}
return "", xerrors.New("MINER_API_INFO environment variable required to extract IP")
}
minerAddr := strings.Split(env, "/")
conn, err := net.DialTimeout("tcp", minerAddr[2]+":"+minerAddr[4], timeout)
if err != nil {
return "", err
}
defer conn.Close()
localAddr := conn.LocalAddr().(*net.TCPAddr)
return strings.Split(localAddr.IP.String(), ":")[0], nil
}

View File

@ -241,6 +241,7 @@ func parseMultisigCsv(csvf string) ([]GenAccountEntry, error) {
if err != nil { if err != nil {
return nil, xerrors.Errorf("read multisig csv: %w", err) return nil, xerrors.Errorf("read multisig csv: %w", err)
} }
defer fileReader.Close() //nolint:errcheck
r := csv.NewReader(fileReader) r := csv.NewReader(fileReader)
records, err := r.ReadAll() records, err := r.ReadAll()
if err != nil { if err != nil {

View File

@ -155,6 +155,9 @@ var aggregateManifestsCmd = &cli.Command{
} }
inputs = append(inputs, val) inputs = append(inputs, val)
if err := fi.Close(); err != nil {
return err
}
} }
output := make(map[string]genesis.Miner) output := make(map[string]genesis.Miner)

View File

@ -65,11 +65,17 @@ var importCarCmd = &cli.Command{
fmt.Println() fmt.Println()
return ds.Close() return ds.Close()
default: default:
if err := f.Close(); err != nil {
return err
}
fmt.Println() fmt.Println()
return err return err
case nil: case nil:
fmt.Printf("\r%s", blk.Cid()) fmt.Printf("\r%s", blk.Cid())
if err := bs.Put(blk); err != nil { if err := bs.Put(blk); err != nil {
if err := f.Close(); err != nil {
return err
}
return xerrors.Errorf("put %s: %w", blk.Cid(), err) return xerrors.Errorf("put %s: %w", blk.Cid(), err)
} }
} }

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"bufio"
"encoding/base64" "encoding/base64"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
@ -64,10 +65,12 @@ var keyinfoImportCmd = &cli.Command{
input = os.Stdin input = os.Stdin
} else { } else {
var err error var err error
input, err = os.Open(cctx.Args().First()) inputFile, err := os.Open(cctx.Args().First())
if err != nil { if err != nil {
return err return err
} }
defer inputFile.Close()
input = bufio.NewReader(inputFile)
} }
encoded, err := ioutil.ReadAll(input) encoded, err := ioutil.ReadAll(input)
@ -174,10 +177,12 @@ var keyinfoInfoCmd = &cli.Command{
input = os.Stdin input = os.Stdin
} else { } else {
var err error var err error
input, err = os.Open(cctx.Args().First()) inputFile, err := os.Open(cctx.Args().First())
if err != nil { if err != nil {
return err return err
} }
defer inputFile.Close()
input = bufio.NewReader(inputFile)
} }
encoded, err := ioutil.ReadAll(input) encoded, err := ioutil.ReadAll(input)

View File

@ -27,6 +27,8 @@ func main() {
fetchParamCmd, fetchParamCmd,
proofsCmd, proofsCmd,
verifRegCmd, verifRegCmd,
miscCmd,
mpoolCmd,
} }
app := &cli.App{ app := &cli.App{

39
cmd/lotus-shed/misc.go Normal file
View File

@ -0,0 +1,39 @@
package main
import (
"fmt"
"strconv"
"github.com/filecoin-project/go-fil-markets/storagemarket"
"github.com/urfave/cli/v2"
)
var miscCmd = &cli.Command{
Name: "misc",
Usage: "Assorted unsorted commands for various purposes",
Flags: []cli.Flag{},
Subcommands: []*cli.Command{
dealStateMappingCmd,
},
}
var dealStateMappingCmd = &cli.Command{
Name: "deal-state",
Action: func(cctx *cli.Context) error {
if !cctx.Args().Present() {
return cli.ShowCommandHelp(cctx, cctx.Command.Name)
}
num, err := strconv.Atoi(cctx.Args().First())
if err != nil {
return err
}
ststr, ok := storagemarket.DealStates[uint64(num)]
if !ok {
return fmt.Errorf("no such deal state %d", num)
}
fmt.Println(ststr)
return nil
},
}

50
cmd/lotus-shed/mpool.go Normal file
View File

@ -0,0 +1,50 @@
package main
import (
"fmt"
lcli "github.com/filecoin-project/lotus/cli"
"github.com/filecoin-project/lotus/miner"
"github.com/urfave/cli/v2"
)
var mpoolCmd = &cli.Command{
Name: "mpool",
Usage: "Tools for diagnosing mempool issues",
Flags: []cli.Flag{},
Subcommands: []*cli.Command{
minerSelectMsgsCmd,
},
}
var minerSelectMsgsCmd = &cli.Command{
Name: "miner-select-msgs",
Action: func(cctx *cli.Context) error {
api, closer, err := lcli.GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := lcli.ReqContext(cctx)
head, err := api.ChainHead(ctx)
if err != nil {
return err
}
msgs, err := api.MpoolPending(ctx, head.Key())
if err != nil {
return err
}
filtered, err := miner.SelectMessages(ctx, api.StateGetActor, head, msgs)
if err != nil {
return err
}
fmt.Println("mempool input messages: ", len(msgs))
fmt.Println("filtered messages: ", len(filtered))
return nil
},
}

View File

@ -1,7 +1,6 @@
package main package main
import ( import (
"bytes"
"fmt" "fmt"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
@ -16,10 +15,8 @@ import (
"github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/verifreg" "github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
"github.com/ipfs/go-hamt-ipld" "github.com/filecoin-project/specs-actors/actors/util/adt"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
cbg "github.com/whyrusleeping/cbor-gen"
) )
var verifRegCmd = &cli.Command{ var verifRegCmd = &cli.Command{
@ -193,27 +190,22 @@ var verifRegListVerifiersCmd = &cli.Command{
} }
apibs := apibstore.NewAPIBlockstore(api) apibs := apibstore.NewAPIBlockstore(api)
cst := cbor.NewCborStore(apibs) store := adt.WrapStore(ctx, cbor.NewCborStore(apibs))
var st verifreg.State var st verifreg.State
if err := cst.Get(ctx, act.Head, &st); err != nil { if err := store.Get(ctx, act.Head, &st); err != nil {
return err return err
} }
vh, err := hamt.LoadNode(ctx, cst, st.Verifiers, hamt.UseTreeBitWidth(5)) vh, err := adt.AsMap(store, st.Verifiers)
if err != nil {
return err
}
if err := vh.ForEach(ctx, func(k string, val interface{}) error {
addr, err := address.NewFromBytes([]byte(k))
if err != nil { if err != nil {
return err return err
} }
var dcap verifreg.DataCap var dcap verifreg.DataCap
if err := vh.ForEach(&dcap, func(k string) error {
if err := dcap.UnmarshalCBOR(bytes.NewReader(val.(*cbg.Deferred).Raw)); err != nil { addr, err := address.NewFromBytes([]byte(k))
if err != nil {
return err return err
} }
@ -245,27 +237,22 @@ var verifRegListClientsCmd = &cli.Command{
} }
apibs := apibstore.NewAPIBlockstore(api) apibs := apibstore.NewAPIBlockstore(api)
cst := cbor.NewCborStore(apibs) store := adt.WrapStore(ctx, cbor.NewCborStore(apibs))
var st verifreg.State var st verifreg.State
if err := cst.Get(ctx, act.Head, &st); err != nil { if err := store.Get(ctx, act.Head, &st); err != nil {
return err return err
} }
vh, err := hamt.LoadNode(ctx, cst, st.VerifiedClients, hamt.UseTreeBitWidth(5)) vh, err := adt.AsMap(store, st.VerifiedClients)
if err != nil {
return err
}
if err := vh.ForEach(ctx, func(k string, val interface{}) error {
addr, err := address.NewFromBytes([]byte(k))
if err != nil { if err != nil {
return err return err
} }
var dcap verifreg.DataCap var dcap verifreg.DataCap
if err := vh.ForEach(&dcap, func(k string) error {
if err := dcap.UnmarshalCBOR(bytes.NewReader(val.(*cbg.Deferred).Raw)); err != nil { addr, err := address.NewFromBytes([]byte(k))
if err != nil {
return err return err
} }
@ -340,21 +327,23 @@ var verifRegCheckVerifierCmd = &cli.Command{
} }
apibs := apibstore.NewAPIBlockstore(api) apibs := apibstore.NewAPIBlockstore(api)
cst := cbor.NewCborStore(apibs) store := adt.WrapStore(ctx, cbor.NewCborStore(apibs))
var st verifreg.State var st verifreg.State
if err := cst.Get(ctx, act.Head, &st); err != nil { if err := store.Get(ctx, act.Head, &st); err != nil {
return err return err
} }
vh, err := hamt.LoadNode(ctx, cst, st.Verifiers, hamt.UseTreeBitWidth(5)) vh, err := adt.AsMap(store, st.Verifiers)
if err != nil { if err != nil {
return err return err
} }
var dcap verifreg.DataCap var dcap verifreg.DataCap
if err := vh.Find(ctx, string(vaddr.Bytes()), &dcap); err != nil { if found, err := vh.Get(adt.AddrKey(vaddr), &dcap); err != nil {
return err return err
} else if !found {
return fmt.Errorf("not found")
} }
fmt.Println(dcap) fmt.Println(dcap)

View File

@ -3,7 +3,6 @@ package main
import ( import (
"context" "context"
"fmt" "fmt"
"os"
logging "github.com/ipfs/go-log/v2" logging "github.com/ipfs/go-log/v2"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
@ -30,18 +29,18 @@ func main() {
lotuslog.SetupLogLevels() lotuslog.SetupLogLevels()
local := []*cli.Command{ local := []*cli.Command{
actorCmd,
storageDealsCmd,
retrievalDealsCmd,
infoCmd,
initCmd, initCmd,
rewardsCmd,
runCmd, runCmd,
stopCmd, stopCmd,
sectorsCmd, lcli.WithCategory("chain", actorCmd),
storageCmd, lcli.WithCategory("chain", rewardsCmd),
workersCmd, lcli.WithCategory("chain", infoCmd),
provingCmd, lcli.WithCategory("market", storageDealsCmd),
lcli.WithCategory("market", retrievalDealsCmd),
lcli.WithCategory("storage", sectorsCmd),
lcli.WithCategory("storage", provingCmd),
lcli.WithCategory("storage", storageCmd),
lcli.WithCategory("storage", sealingCmd),
} }
jaeger := tracing.SetupJaegerTracing("lotus") jaeger := tracing.SetupJaegerTracing("lotus")
defer func() { defer func() {
@ -96,10 +95,7 @@ func main() {
app.Setup() app.Setup()
app.Metadata["repoType"] = repo.StorageMiner app.Metadata["repoType"] = repo.StorageMiner
if err := app.Run(os.Args); err != nil { lcli.RunApp(app)
log.Warnf("%+v", err)
os.Exit(1)
}
} }
func getActorAddress(ctx context.Context, nodeAPI api.StorageMiner, overrideMaddr string) (maddr address.Address, err error) { func getActorAddress(ctx context.Context, nodeAPI api.StorageMiner, overrideMaddr string) (maddr address.Address, err error) {

View File

@ -2,8 +2,12 @@ package main
import ( import (
"fmt" "fmt"
"golang.org/x/xerrors"
"os"
"sort" "sort"
"strings" "strings"
"text/tabwriter"
"time"
"github.com/fatih/color" "github.com/fatih/color"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
@ -14,16 +18,17 @@ import (
lcli "github.com/filecoin-project/lotus/cli" lcli "github.com/filecoin-project/lotus/cli"
) )
var workersCmd = &cli.Command{ var sealingCmd = &cli.Command{
Name: "workers", Name: "sealing",
Usage: "interact with workers", Usage: "interact with sealing pipeline",
Subcommands: []*cli.Command{ Subcommands: []*cli.Command{
workersListCmd, sealingJobsCmd,
sealingWorkersCmd,
}, },
} }
var workersListCmd = &cli.Command{ var sealingWorkersCmd = &cli.Command{
Name: "list", Name: "workers",
Usage: "list workers", Usage: "list workers",
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.BoolFlag{Name: "color"}, &cli.BoolFlag{Name: "color"},
@ -106,3 +111,68 @@ var workersListCmd = &cli.Command{
return nil return nil
}, },
} }
var sealingJobsCmd = &cli.Command{
Name: "jobs",
Usage: "list workers",
Flags: []cli.Flag{
&cli.BoolFlag{Name: "color"},
},
Action: func(cctx *cli.Context) error {
color.NoColor = !cctx.Bool("color")
nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := lcli.ReqContext(cctx)
jobs, err := nodeApi.WorkerJobs(ctx)
if err != nil {
return xerrors.Errorf("getting worker jobs: %w", err)
}
type line struct {
storiface.WorkerJob
wid uint64
}
lines := make([]line, 0)
for wid, jobs := range jobs {
for _, job := range jobs {
lines = append(lines, line{
WorkerJob: job,
wid: wid,
})
}
}
// oldest first
sort.Slice(lines, func(i, j int) bool {
return lines[i].Start.Before(lines[j].Start)
})
workerHostnames := map[uint64]string{}
wst, err := nodeApi.WorkerStats(ctx)
if err != nil {
return xerrors.Errorf("getting worker stats: %w", err)
}
for wid, st := range wst {
workerHostnames[wid] = st.Info.Hostname
}
tw := tabwriter.NewWriter(os.Stdout, 2, 4, 2, ' ', 0)
_, _ = fmt.Fprintf(tw, "ID\tSector\tWorker\tHostname\tTask\tTime\n")
for _, l := range lines {
_, _ = fmt.Fprintf(tw, "%d\t%d\t%d\t%s\t%s\t%s\n", l.ID, l.Sector.Number, l.wid, workerHostnames[l.wid], l.Task.Short(), time.Now().Sub(l.Start).Truncate(time.Millisecond*100))
}
return tw.Flush()
},
}

View File

@ -82,16 +82,16 @@ var sectorsStatusCmd = &cli.Command{
} }
fmt.Printf("SectorID:\t%d\n", status.SectorID) fmt.Printf("SectorID:\t%d\n", status.SectorID)
fmt.Printf("Status:\t%s\n", status.State) fmt.Printf("Status:\t\t%s\n", status.State)
fmt.Printf("CommD:\t\t%x\n", status.CommD) fmt.Printf("CIDcommD:\t%s\n", status.CommD)
fmt.Printf("CommR:\t\t%x\n", status.CommR) fmt.Printf("CIDcommR:\t%s\n", status.CommR)
fmt.Printf("Ticket:\t\t%x\n", status.Ticket.Value) fmt.Printf("Ticket:\t\t%x\n", status.Ticket.Value)
fmt.Printf("TicketH:\t\t%d\n", status.Ticket.Epoch) fmt.Printf("TicketH:\t%d\n", status.Ticket.Epoch)
fmt.Printf("Seed:\t\t%x\n", status.Seed.Value) fmt.Printf("Seed:\t\t%x\n", status.Seed.Value)
fmt.Printf("SeedH:\t\t%d\n", status.Seed.Epoch) fmt.Printf("SeedH:\t\t%d\n", status.Seed.Epoch)
fmt.Printf("Proof:\t\t%x\n", status.Proof) fmt.Printf("Proof:\t\t%x\n", status.Proof)
fmt.Printf("Deals:\t\t%v\n", status.Deals) fmt.Printf("Deals:\t\t%v\n", status.Deals)
fmt.Printf("Retries:\t\t%d\n", status.Retries) fmt.Printf("Retries:\t%d\n", status.Retries)
if status.LastErr != "" { if status.LastErr != "" {
fmt.Printf("Last Error:\t\t%s\n", status.LastErr) fmt.Printf("Last Error:\t\t%s\n", status.LastErr)
} }
@ -251,15 +251,16 @@ var sectorsMarkForUpgradeCmd = &cli.Command{
Usage: "Mark a committed capacity sector for replacement by a sector with deals", Usage: "Mark a committed capacity sector for replacement by a sector with deals",
ArgsUsage: "<sectorNum>", ArgsUsage: "<sectorNum>",
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
if cctx.Args().Len() != 1 {
return lcli.ShowHelp(cctx, xerrors.Errorf("must pass sector number"))
}
nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx) nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx)
if err != nil { if err != nil {
return err return err
} }
defer closer() defer closer()
ctx := lcli.ReqContext(cctx) ctx := lcli.ReqContext(cctx)
if cctx.Args().Len() != 1 {
return xerrors.Errorf("must pass sector number")
}
id, err := strconv.ParseUint(cctx.Args().Get(0), 10, 64) id, err := strconv.ParseUint(cctx.Args().Get(0), 10, 64)
if err != nil { if err != nil {

View File

@ -317,6 +317,7 @@ func ImportChain(r repo.Repo, fname string) error {
if err != nil { if err != nil {
return err return err
} }
defer fi.Close() //nolint:errcheck
lr, err := r.Lock(repo.FullNode) lr, err := r.Lock(repo.FullNode)
if err != nil { if err != nil {

View File

@ -2,7 +2,6 @@ package main
import ( import (
"context" "context"
"os"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"go.opencensus.io/trace" "go.opencensus.io/trace"
@ -69,17 +68,5 @@ func main() {
app.Metadata["traceContext"] = ctx app.Metadata["traceContext"] = ctx
app.Metadata["repoType"] = repo.FullNode app.Metadata["repoType"] = repo.FullNode
if err := app.Run(os.Args); err != nil { lcli.RunApp(app)
span.SetStatus(trace.Status{
Code: trace.StatusCodeFailedPrecondition,
Message: err.Error(),
})
_, ok := err.(*lcli.ErrCmdFailed)
if ok {
log.Debugf("%+v", err)
} else {
log.Warnf("%+v", err)
}
os.Exit(1)
}
} }

18
go.mod
View File

@ -15,22 +15,21 @@ require (
github.com/drand/drand v1.0.3-0.20200714175734-29705eaf09d4 github.com/drand/drand v1.0.3-0.20200714175734-29705eaf09d4
github.com/drand/kyber v1.1.1 github.com/drand/kyber v1.1.1
github.com/fatih/color v1.8.0 github.com/fatih/color v1.8.0
github.com/filecoin-project/chain-validation v0.0.6-0.20200720093255-843129967fdf github.com/filecoin-project/chain-validation v0.0.6-0.20200723211224-ffdcb7a20fe8
github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200716204036-cddc56607e1d github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200716204036-cddc56607e1d
github.com/filecoin-project/go-address v0.0.2-0.20200504173055-8b6f2fb2b3ef github.com/filecoin-project/go-address v0.0.2-0.20200504173055-8b6f2fb2b3ef
github.com/filecoin-project/go-amt-ipld/v2 v2.0.1-0.20200424220931-6263827e49f2 github.com/filecoin-project/go-bitfield v0.1.0
github.com/filecoin-project/go-bitfield v0.0.4-0.20200703174658-f4a5758051a1
github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2 github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03
github.com/filecoin-project/go-data-transfer v0.4.1-0.20200715144713-b3311844e1a5 github.com/filecoin-project/go-data-transfer v0.5.0
github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f
github.com/filecoin-project/go-fil-markets v0.4.1-0.20200715201050-c141144ea312 github.com/filecoin-project/go-fil-markets v0.5.1
github.com/filecoin-project/go-jsonrpc v0.1.1-0.20200602181149-522144ab4e24 github.com/filecoin-project/go-jsonrpc v0.1.1-0.20200602181149-522144ab4e24
github.com/filecoin-project/go-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261 github.com/filecoin-project/go-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261
github.com/filecoin-project/go-statestore v0.1.0 github.com/filecoin-project/go-statestore v0.1.0
github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b
github.com/filecoin-project/sector-storage v0.0.0-20200717213554-a109ef9cbeab github.com/filecoin-project/sector-storage v0.0.0-20200723200950-ed2e57dde6df
github.com/filecoin-project/specs-actors v0.8.1-0.20200720115956-cd051eabf328 github.com/filecoin-project/specs-actors v0.8.1-0.20200724015154-3c690d9b7e1d
github.com/filecoin-project/specs-storage v0.1.1-0.20200622113353-88a9704877ea github.com/filecoin-project/specs-storage v0.1.1-0.20200622113353-88a9704877ea
github.com/filecoin-project/storage-fsm v0.0.0-20200720190000-2cfe2fe3c334 github.com/filecoin-project/storage-fsm v0.0.0-20200720190000-2cfe2fe3c334
github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1 github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1
@ -53,8 +52,7 @@ require (
github.com/ipfs/go-ds-measure v0.1.0 github.com/ipfs/go-ds-measure v0.1.0
github.com/ipfs/go-filestore v1.0.0 github.com/ipfs/go-filestore v1.0.0
github.com/ipfs/go-fs-lock v0.0.1 github.com/ipfs/go-fs-lock v0.0.1
github.com/ipfs/go-graphsync v0.0.6-0.20200715142715-e2f27c4754e6 github.com/ipfs/go-graphsync v0.0.6-0.20200715204712-ef06b3d32e83
github.com/ipfs/go-hamt-ipld v0.1.1-0.20200605182717-0310ad2b0b1f
github.com/ipfs/go-ipfs-blockstore v1.0.0 github.com/ipfs/go-ipfs-blockstore v1.0.0
github.com/ipfs/go-ipfs-chunker v0.0.5 github.com/ipfs/go-ipfs-chunker v0.0.5
github.com/ipfs/go-ipfs-ds-help v1.0.0 github.com/ipfs/go-ipfs-ds-help v1.0.0
@ -109,7 +107,7 @@ require (
github.com/syndtr/goleveldb v1.0.0 github.com/syndtr/goleveldb v1.0.0
github.com/urfave/cli/v2 v2.2.0 github.com/urfave/cli/v2 v2.2.0
github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba
github.com/whyrusleeping/cbor-gen v0.0.0-20200715143311-227fab5a2377 github.com/whyrusleeping/cbor-gen v0.0.0-20200723182808-cb5de1c427f5
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7
github.com/whyrusleeping/pubsub v0.0.0-20131020042734-02de8aa2db3d github.com/whyrusleeping/pubsub v0.0.0-20131020042734-02de8aa2db3d
github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542 github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542

43
go.sum
View File

@ -216,8 +216,8 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv
github.com/fatih/color v1.8.0 h1:5bzFgL+oy7JITMTxUPJ00n7VxmYd/PdMp5mHFX40/RY= github.com/fatih/color v1.8.0 h1:5bzFgL+oy7JITMTxUPJ00n7VxmYd/PdMp5mHFX40/RY=
github.com/fatih/color v1.8.0/go.mod h1:3l45GVGkyrnYNl9HoIjnp2NnNWvh6hLAqD8yTfGjnw8= github.com/fatih/color v1.8.0/go.mod h1:3l45GVGkyrnYNl9HoIjnp2NnNWvh6hLAqD8yTfGjnw8=
github.com/fd/go-nat v1.0.0/go.mod h1:BTBu/CKvMmOMUPkKVef1pngt2WFH/lg7E6yQnulfp6E= github.com/fd/go-nat v1.0.0/go.mod h1:BTBu/CKvMmOMUPkKVef1pngt2WFH/lg7E6yQnulfp6E=
github.com/filecoin-project/chain-validation v0.0.6-0.20200720093255-843129967fdf h1:7SkS/gSZv4ljQaQeDu4SfnF9CcvQuT9QCEf3+Hn1jp8= github.com/filecoin-project/chain-validation v0.0.6-0.20200723211224-ffdcb7a20fe8 h1:WA2KU3u/FELAMVElQgiwEKTQe/QLUUsT52AnW4YjPjs=
github.com/filecoin-project/chain-validation v0.0.6-0.20200720093255-843129967fdf/go.mod h1:9xZvimiD8wsZbTNTUoACMPzXj4/fpIxeZBV2YjQcLhI= github.com/filecoin-project/chain-validation v0.0.6-0.20200723211224-ffdcb7a20fe8/go.mod h1:P4FhsyLtySqsVFbOPpPVFeEShVQ4j/iA5Dzo8D2p978=
github.com/filecoin-project/go-address v0.0.0-20200107215422-da8eea2842b5/go.mod h1:SAOwJoakQ8EPjwNIsiakIQKsoKdkcbx8U3IapgCg9R0= github.com/filecoin-project/go-address v0.0.0-20200107215422-da8eea2842b5/go.mod h1:SAOwJoakQ8EPjwNIsiakIQKsoKdkcbx8U3IapgCg9R0=
github.com/filecoin-project/go-address v0.0.2-0.20200218010043-eb9bb40ed5be/go.mod h1:SAOwJoakQ8EPjwNIsiakIQKsoKdkcbx8U3IapgCg9R0= github.com/filecoin-project/go-address v0.0.2-0.20200218010043-eb9bb40ed5be/go.mod h1:SAOwJoakQ8EPjwNIsiakIQKsoKdkcbx8U3IapgCg9R0=
github.com/filecoin-project/go-address v0.0.2-0.20200504173055-8b6f2fb2b3ef h1:Wi5E+P1QfHP8IF27eUiTx5vYfqQZwfPxzq3oFEq8w8U= github.com/filecoin-project/go-address v0.0.2-0.20200504173055-8b6f2fb2b3ef h1:Wi5E+P1QfHP8IF27eUiTx5vYfqQZwfPxzq3oFEq8w8U=
@ -225,23 +225,27 @@ github.com/filecoin-project/go-address v0.0.2-0.20200504173055-8b6f2fb2b3ef/go.m
github.com/filecoin-project/go-amt-ipld/v2 v2.0.1-0.20200131012142-05d80eeccc5e/go.mod h1:boRtQhzmxNocrMxOXo1NYn4oUc1NGvR8tEa79wApNXg= github.com/filecoin-project/go-amt-ipld/v2 v2.0.1-0.20200131012142-05d80eeccc5e/go.mod h1:boRtQhzmxNocrMxOXo1NYn4oUc1NGvR8tEa79wApNXg=
github.com/filecoin-project/go-amt-ipld/v2 v2.0.1-0.20200424220931-6263827e49f2 h1:jamfsxfK0Q9yCMHt8MPWx7Aa/O9k2Lve8eSc6FILYGQ= github.com/filecoin-project/go-amt-ipld/v2 v2.0.1-0.20200424220931-6263827e49f2 h1:jamfsxfK0Q9yCMHt8MPWx7Aa/O9k2Lve8eSc6FILYGQ=
github.com/filecoin-project/go-amt-ipld/v2 v2.0.1-0.20200424220931-6263827e49f2/go.mod h1:boRtQhzmxNocrMxOXo1NYn4oUc1NGvR8tEa79wApNXg= github.com/filecoin-project/go-amt-ipld/v2 v2.0.1-0.20200424220931-6263827e49f2/go.mod h1:boRtQhzmxNocrMxOXo1NYn4oUc1NGvR8tEa79wApNXg=
github.com/filecoin-project/go-amt-ipld/v2 v2.1.0 h1:t6qDiuGYYngDqaLc2ZUvdtAg4UNxPeOYaXhBWSNsVaM=
github.com/filecoin-project/go-amt-ipld/v2 v2.1.0/go.mod h1:nfFPoGyX0CU9SkXX8EoCcSuHN1XcbN0c6KBh7yvP5fs=
github.com/filecoin-project/go-bitfield v0.0.0-20200416002808-b3ee67ec9060/go.mod h1:iodsLxOFZnqKtjj2zkgqzoGNrv6vUqj69AT/J8DKXEw= github.com/filecoin-project/go-bitfield v0.0.0-20200416002808-b3ee67ec9060/go.mod h1:iodsLxOFZnqKtjj2zkgqzoGNrv6vUqj69AT/J8DKXEw=
github.com/filecoin-project/go-bitfield v0.0.1/go.mod h1:Ry9/iUlWSyjPUzlAvdnfy4Gtvrq4kWmWDztCU1yEgJY= github.com/filecoin-project/go-bitfield v0.0.1/go.mod h1:Ry9/iUlWSyjPUzlAvdnfy4Gtvrq4kWmWDztCU1yEgJY=
github.com/filecoin-project/go-bitfield v0.0.2-0.20200518150651-562fdb554b6e/go.mod h1:Ry9/iUlWSyjPUzlAvdnfy4Gtvrq4kWmWDztCU1yEgJY= github.com/filecoin-project/go-bitfield v0.0.2-0.20200518150651-562fdb554b6e/go.mod h1:Ry9/iUlWSyjPUzlAvdnfy4Gtvrq4kWmWDztCU1yEgJY=
github.com/filecoin-project/go-bitfield v0.0.3/go.mod h1:Ry9/iUlWSyjPUzlAvdnfy4Gtvrq4kWmWDztCU1yEgJY= github.com/filecoin-project/go-bitfield v0.0.3/go.mod h1:Ry9/iUlWSyjPUzlAvdnfy4Gtvrq4kWmWDztCU1yEgJY=
github.com/filecoin-project/go-bitfield v0.0.4-0.20200703174658-f4a5758051a1 h1:xuHlrdznafh7ul5t4xEncnA4qgpQvJZEw+mr98eqHXw= github.com/filecoin-project/go-bitfield v0.0.4-0.20200703174658-f4a5758051a1 h1:xuHlrdznafh7ul5t4xEncnA4qgpQvJZEw+mr98eqHXw=
github.com/filecoin-project/go-bitfield v0.0.4-0.20200703174658-f4a5758051a1/go.mod h1:Ry9/iUlWSyjPUzlAvdnfy4Gtvrq4kWmWDztCU1yEgJY= github.com/filecoin-project/go-bitfield v0.0.4-0.20200703174658-f4a5758051a1/go.mod h1:Ry9/iUlWSyjPUzlAvdnfy4Gtvrq4kWmWDztCU1yEgJY=
github.com/filecoin-project/go-bitfield v0.1.0 h1:ZDAQjvXuLzbrLnwfFruQFJP7IhImmXLuO+8i2qeAczM=
github.com/filecoin-project/go-bitfield v0.1.0/go.mod h1:CNl9WG8hgR5mttCnUErjcQjGvuiZjRqK9rHVBsQF4oM=
github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2 h1:av5fw6wmm58FYMgJeoB/lK9XXrgdugYiTqkdxjTy9k8= github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2 h1:av5fw6wmm58FYMgJeoB/lK9XXrgdugYiTqkdxjTy9k8=
github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2/go.mod h1:pqTiPHobNkOVM5thSRsHYjyQfq7O5QSCMhvuu9JoDlg= github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2/go.mod h1:pqTiPHobNkOVM5thSRsHYjyQfq7O5QSCMhvuu9JoDlg=
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 h1:2pMXdBnCiXjfCYx/hLqFxccPoqsSveQFxVLvNxy9bus= github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 h1:2pMXdBnCiXjfCYx/hLqFxccPoqsSveQFxVLvNxy9bus=
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ=
github.com/filecoin-project/go-data-transfer v0.4.1-0.20200715144713-b3311844e1a5 h1:/OZ+nr0x3uMZCPrreuUbS5EUOFm9DDo4ljgdav8rp/s= github.com/filecoin-project/go-data-transfer v0.5.0 h1:pvWlab69BD5dwheRHjjBjFB6m7CEqEZeI+aChtVqKVk=
github.com/filecoin-project/go-data-transfer v0.4.1-0.20200715144713-b3311844e1a5/go.mod h1:duGDSKvsOxiKl6Dueh8DNA6ZbiM30PWUWlSKjo9ac+o= github.com/filecoin-project/go-data-transfer v0.5.0/go.mod h1:7yckbsPPMGuN3O1+SYNE/lowwheaUn5woGILpjN52UI=
github.com/filecoin-project/go-fil-commcid v0.0.0-20200208005934-2b8bd03caca5/go.mod h1:JbkIgFF/Z9BDlvrJO1FuKkaWsH673/UdFaiVS6uIHlA= github.com/filecoin-project/go-fil-commcid v0.0.0-20200208005934-2b8bd03caca5/go.mod h1:JbkIgFF/Z9BDlvrJO1FuKkaWsH673/UdFaiVS6uIHlA=
github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f h1:GxJzR3oRIMTPtpZ0b7QF8FKPK6/iPAc7trhlL5k/g+s= github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f h1:GxJzR3oRIMTPtpZ0b7QF8FKPK6/iPAc7trhlL5k/g+s=
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-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ=
github.com/filecoin-project/go-fil-markets v0.4.1-0.20200715201050-c141144ea312 h1:oVZggNjDWZWEjomkxPl8U3jrOLURoS4QSZA6t4YU5BY= github.com/filecoin-project/go-fil-markets v0.5.1 h1:Y69glslNCuXnygfesCmyilTVhEEjcLK7CtAohKP9SL8=
github.com/filecoin-project/go-fil-markets v0.4.1-0.20200715201050-c141144ea312/go.mod h1:MvrpKOiETu39e9H167gdQzdzLNcvHsUp48UkXqPSdtU= github.com/filecoin-project/go-fil-markets v0.5.1/go.mod h1:GKGigsFNMvKmx/+Mcn7093TdZTiCDLc7YGxQ7d6fq2s=
github.com/filecoin-project/go-jsonrpc v0.1.1-0.20200602181149-522144ab4e24 h1:Jc7vkplmZYVuaEcSXGHDwefvZIdoyyaoGDLqSr8Svms= github.com/filecoin-project/go-jsonrpc v0.1.1-0.20200602181149-522144ab4e24 h1:Jc7vkplmZYVuaEcSXGHDwefvZIdoyyaoGDLqSr8Svms=
github.com/filecoin-project/go-jsonrpc v0.1.1-0.20200602181149-522144ab4e24/go.mod h1:j6zV//WXIIY5kky873Q3iIKt/ViOE8rcijovmpxrXzM= github.com/filecoin-project/go-jsonrpc v0.1.1-0.20200602181149-522144ab4e24/go.mod h1:j6zV//WXIIY5kky873Q3iIKt/ViOE8rcijovmpxrXzM=
github.com/filecoin-project/go-padreader v0.0.0-20200210211231-548257017ca6 h1:92PET+sx1Hb4W/8CgFwGuxaKbttwY+UNspYZTvXY0vs= github.com/filecoin-project/go-padreader v0.0.0-20200210211231-548257017ca6 h1:92PET+sx1Hb4W/8CgFwGuxaKbttwY+UNspYZTvXY0vs=
@ -260,19 +264,19 @@ github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b/
github.com/filecoin-project/sector-storage v0.0.0-20200615154852-728a47ab99d6/go.mod h1:M59QnAeA/oV+Z8oHFLoNpGMv0LZ8Rll+vHVXX7GirPM= github.com/filecoin-project/sector-storage v0.0.0-20200615154852-728a47ab99d6/go.mod h1:M59QnAeA/oV+Z8oHFLoNpGMv0LZ8Rll+vHVXX7GirPM=
github.com/filecoin-project/sector-storage v0.0.0-20200712023225-1d67dcfa3c15 h1:miw6hiusb/MkV1ryoqUKKWnvHhPW00AYtyeCj0L8pqo= github.com/filecoin-project/sector-storage v0.0.0-20200712023225-1d67dcfa3c15 h1:miw6hiusb/MkV1ryoqUKKWnvHhPW00AYtyeCj0L8pqo=
github.com/filecoin-project/sector-storage v0.0.0-20200712023225-1d67dcfa3c15/go.mod h1:salgVdX7qeXFo/xaiEQE29J4pPkjn71T0kt0n+VDBzo= github.com/filecoin-project/sector-storage v0.0.0-20200712023225-1d67dcfa3c15/go.mod h1:salgVdX7qeXFo/xaiEQE29J4pPkjn71T0kt0n+VDBzo=
github.com/filecoin-project/sector-storage v0.0.0-20200717213554-a109ef9cbeab h1:jEQtbWFyEKnCw3eAVCW3MSX/K7Nv03B3zzS/rfm2k+Q= github.com/filecoin-project/sector-storage v0.0.0-20200723200950-ed2e57dde6df h1:VDdWrCNUNx6qeHnGU9oAy+izuGM02it9V/5+MJyhZQw=
github.com/filecoin-project/sector-storage v0.0.0-20200717213554-a109ef9cbeab/go.mod h1:7EE+f7jM4kCy2MKHoiiwNDQGJSb+QQzZ+y+/17ugq4w= github.com/filecoin-project/sector-storage v0.0.0-20200723200950-ed2e57dde6df/go.mod h1:7EE+f7jM4kCy2MKHoiiwNDQGJSb+QQzZ+y+/17ugq4w=
github.com/filecoin-project/specs-actors v0.0.0-20200210130641-2d1fbd8672cf/go.mod h1:xtDZUB6pe4Pksa/bAJbJ693OilaC5Wbot9jMhLm3cZA= github.com/filecoin-project/specs-actors v0.0.0-20200210130641-2d1fbd8672cf/go.mod h1:xtDZUB6pe4Pksa/bAJbJ693OilaC5Wbot9jMhLm3cZA=
github.com/filecoin-project/specs-actors v0.3.0/go.mod h1:nQYnFbQ7Y0bHZyq6HDEuVlCPR+U3z5Q3wMOQ+2aiV+Y= github.com/filecoin-project/specs-actors v0.3.0/go.mod h1:nQYnFbQ7Y0bHZyq6HDEuVlCPR+U3z5Q3wMOQ+2aiV+Y=
github.com/filecoin-project/specs-actors v0.6.0/go.mod h1:dRdy3cURykh2R8O/DKqy8olScl70rmIS7GrB4hB1IDY= github.com/filecoin-project/specs-actors v0.6.0/go.mod h1:dRdy3cURykh2R8O/DKqy8olScl70rmIS7GrB4hB1IDY=
github.com/filecoin-project/specs-actors v0.6.1/go.mod h1:dRdy3cURykh2R8O/DKqy8olScl70rmIS7GrB4hB1IDY= github.com/filecoin-project/specs-actors v0.6.1/go.mod h1:dRdy3cURykh2R8O/DKqy8olScl70rmIS7GrB4hB1IDY=
github.com/filecoin-project/specs-actors v0.7.0/go.mod h1:+z0htZu/wLBDbOLcQTKKUEC2rkUTFzL2KJ/bRAVWkws=
github.com/filecoin-project/specs-actors v0.7.3-0.20200716231407-60a2ae96d2e6 h1:F+GcBdKPdW/wTv6bMJxG9Zj1dc0UGkO6uNOQmKP/g1o= github.com/filecoin-project/specs-actors v0.7.3-0.20200716231407-60a2ae96d2e6 h1:F+GcBdKPdW/wTv6bMJxG9Zj1dc0UGkO6uNOQmKP/g1o=
github.com/filecoin-project/specs-actors v0.7.3-0.20200716231407-60a2ae96d2e6/go.mod h1:JOMUa7EijvpOO4ofD1yeHNmqohkmmnhTvz/IpB6so4c= github.com/filecoin-project/specs-actors v0.7.3-0.20200716231407-60a2ae96d2e6/go.mod h1:JOMUa7EijvpOO4ofD1yeHNmqohkmmnhTvz/IpB6so4c=
github.com/filecoin-project/specs-actors v0.8.1-0.20200720061236-f4719fdd7d90 h1:E8M5FyB53tuRXHO5KAAi9DlksOl54ULImW57MrUfyDY=
github.com/filecoin-project/specs-actors v0.8.1-0.20200720061236-f4719fdd7d90/go.mod h1:JOMUa7EijvpOO4ofD1yeHNmqohkmmnhTvz/IpB6so4c=
github.com/filecoin-project/specs-actors v0.8.1-0.20200720115956-cd051eabf328 h1:jZwz1VxqzNCfINY5FDnsT+ZL03wjzLifi+JwdLkehuU=
github.com/filecoin-project/specs-actors v0.8.1-0.20200720115956-cd051eabf328/go.mod h1:0+CxQ5Jeii3522irTvhKRDpr4GG1bj5Erq3p/d38DzY= github.com/filecoin-project/specs-actors v0.8.1-0.20200720115956-cd051eabf328/go.mod h1:0+CxQ5Jeii3522irTvhKRDpr4GG1bj5Erq3p/d38DzY=
github.com/filecoin-project/specs-actors v0.8.1-0.20200723200253-a3c01bc62f99 h1:li6OZVhGNrQihzKhUy7x4vwKgUCExnpVSj746VMkq1I=
github.com/filecoin-project/specs-actors v0.8.1-0.20200723200253-a3c01bc62f99/go.mod h1:TLvIheTVl0EIuyncuKSTVXPULaj7gzhLup5CLZ/S+uM=
github.com/filecoin-project/specs-actors v0.8.1-0.20200724015154-3c690d9b7e1d h1:dti6ssgSFG7Tk851S3RdiDr1TNbOJ26ylc6DJ9Y2Le0=
github.com/filecoin-project/specs-actors v0.8.1-0.20200724015154-3c690d9b7e1d/go.mod h1:TLvIheTVl0EIuyncuKSTVXPULaj7gzhLup5CLZ/S+uM=
github.com/filecoin-project/specs-storage v0.1.0 h1:PkDgTOT5W5Ao7752onjDl4QSv+sgOVdJbvFjOnD5w94= github.com/filecoin-project/specs-storage v0.1.0 h1:PkDgTOT5W5Ao7752onjDl4QSv+sgOVdJbvFjOnD5w94=
github.com/filecoin-project/specs-storage v0.1.0/go.mod h1:Pr5ntAaxsh+sLG/LYiL4tKzvA83Vk5vLODYhfNwOg7k= github.com/filecoin-project/specs-storage v0.1.0/go.mod h1:Pr5ntAaxsh+sLG/LYiL4tKzvA83Vk5vLODYhfNwOg7k=
github.com/filecoin-project/specs-storage v0.1.1-0.20200622113353-88a9704877ea h1:iixjULRQFPn7Q9KlIqfwLJnlAXO10bbkI+xy5GKGdLY= github.com/filecoin-project/specs-storage v0.1.1-0.20200622113353-88a9704877ea h1:iixjULRQFPn7Q9KlIqfwLJnlAXO10bbkI+xy5GKGdLY=
@ -418,6 +422,8 @@ github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmv
github.com/gxed/pubsub v0.0.0-20180201040156-26ebdf44f824/go.mod h1:OiEWyHgK+CWrmOlVquHaIK1vhpUJydC9m0Je6mhaiNE= github.com/gxed/pubsub v0.0.0-20180201040156-26ebdf44f824/go.mod h1:OiEWyHgK+CWrmOlVquHaIK1vhpUJydC9m0Je6mhaiNE=
github.com/hannahhoward/cbor-gen-for v0.0.0-20191218204337-9ab7b1bcc099 h1:vQqOW42RRM5LoM/1K5dK940VipLqpH8lEVGrMz+mNjU= github.com/hannahhoward/cbor-gen-for v0.0.0-20191218204337-9ab7b1bcc099 h1:vQqOW42RRM5LoM/1K5dK940VipLqpH8lEVGrMz+mNjU=
github.com/hannahhoward/cbor-gen-for v0.0.0-20191218204337-9ab7b1bcc099/go.mod h1:WVPCl0HO/0RAL5+vBH2GMxBomlxBF70MAS78+Lu1//k= github.com/hannahhoward/cbor-gen-for v0.0.0-20191218204337-9ab7b1bcc099/go.mod h1:WVPCl0HO/0RAL5+vBH2GMxBomlxBF70MAS78+Lu1//k=
github.com/hannahhoward/cbor-gen-for v0.0.0-20200723175505-5892b522820a h1:wfqh5oiHXvn3Rk54xy8Cwqh+HnYihGnjMNzdNb3/ld0=
github.com/hannahhoward/cbor-gen-for v0.0.0-20200723175505-5892b522820a/go.mod h1:jvfsLIxk0fY/2BKSQ1xf2406AKA5dwMmKKv0ADcOfN8=
github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e h1:3YKHER4nmd7b5qy5t0GWDTwSn4OyRgfAXSmo6VnryBY= github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e h1:3YKHER4nmd7b5qy5t0GWDTwSn4OyRgfAXSmo6VnryBY=
github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e/go.mod h1:I8h3MITA53gN9OnWGCgaMa0JWVRdXthWw4M3CPM54OY= github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e/go.mod h1:I8h3MITA53gN9OnWGCgaMa0JWVRdXthWw4M3CPM54OY=
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
@ -520,13 +526,12 @@ github.com/ipfs/go-filestore v1.0.0 h1:QR7ekKH+q2AGiWDc7W2Q0qHuYSRZGUJqUn0GsegEP
github.com/ipfs/go-filestore v1.0.0/go.mod h1:/XOCuNtIe2f1YPbiXdYvD0BKLA0JR1MgPiFOdcuu9SM= github.com/ipfs/go-filestore v1.0.0/go.mod h1:/XOCuNtIe2f1YPbiXdYvD0BKLA0JR1MgPiFOdcuu9SM=
github.com/ipfs/go-fs-lock v0.0.1 h1:XHX8uW4jQBYWHj59XXcjg7BHlHxV9ZOYs6Y43yb7/l0= github.com/ipfs/go-fs-lock v0.0.1 h1:XHX8uW4jQBYWHj59XXcjg7BHlHxV9ZOYs6Y43yb7/l0=
github.com/ipfs/go-fs-lock v0.0.1/go.mod h1:DNBekbboPKcxs1aukPSaOtFA3QfSdi5C855v0i9XJ8Y= github.com/ipfs/go-fs-lock v0.0.1/go.mod h1:DNBekbboPKcxs1aukPSaOtFA3QfSdi5C855v0i9XJ8Y=
github.com/ipfs/go-graphsync v0.0.6-0.20200715142715-e2f27c4754e6 h1:+dQnaRkLV4za46Gfw6b1KNVOCcGDrdnEGZrjz3kF80k= github.com/ipfs/go-graphsync v0.0.6-0.20200715204712-ef06b3d32e83 h1:tkGDAwcZfzDFeBNyBWYOM02Qw0rGpA2UuCvq49T3K5o=
github.com/ipfs/go-graphsync v0.0.6-0.20200715142715-e2f27c4754e6/go.mod h1:jMXfqIEDFukLPZHqDPp8tJMbHO9Rmeb9CEGevngQbmE= github.com/ipfs/go-graphsync v0.0.6-0.20200715204712-ef06b3d32e83/go.mod h1:jMXfqIEDFukLPZHqDPp8tJMbHO9Rmeb9CEGevngQbmE=
github.com/ipfs/go-hamt-ipld v0.0.15-0.20200131012125-dd88a59d3f2e/go.mod h1:9aQJu/i/TaRDW6jqB5U217dLIDopn50wxLdHXM2CTfE= github.com/ipfs/go-hamt-ipld v0.0.15-0.20200131012125-dd88a59d3f2e/go.mod h1:9aQJu/i/TaRDW6jqB5U217dLIDopn50wxLdHXM2CTfE=
github.com/ipfs/go-hamt-ipld v0.0.15-0.20200204200533-99b8553ef242/go.mod h1:kq3Pi+UP3oHhAdKexE+kHHYRKMoFNuGero0R7q3hWGg= github.com/ipfs/go-hamt-ipld v0.0.15-0.20200204200533-99b8553ef242/go.mod h1:kq3Pi+UP3oHhAdKexE+kHHYRKMoFNuGero0R7q3hWGg=
github.com/ipfs/go-hamt-ipld v0.1.1-0.20200501020327-d53d20a7063e/go.mod h1:giiPqWYCnRBYpNTsJ/EX1ojldX5kTXrXYckSJQ7ko9M= github.com/ipfs/go-hamt-ipld v0.1.1 h1:0IQdvwnAAUKmDE+PMJa5y1QiwOPHpI9+eAbQEEEYthk=
github.com/ipfs/go-hamt-ipld v0.1.1-0.20200605182717-0310ad2b0b1f h1:mchhWiYYUSoCuE3wDfRCo8cho5kqSoxkgnOtGcnNMZw= github.com/ipfs/go-hamt-ipld v0.1.1/go.mod h1:1EZCr2v0jlCnhpa+aZ0JZYp8Tt2w16+JJOAVz17YcDk=
github.com/ipfs/go-hamt-ipld v0.1.1-0.20200605182717-0310ad2b0b1f/go.mod h1:phOFBB7W73N9dg1glcb1fQ9HtQFDUpeyJgatW8ns0bw=
github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08= 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.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.4/go.mod h1:Jxm3XMVjh6R17WvxFEiyKBLUGr86HgIYJW/D/MwqeYQ=
@ -1353,14 +1358,14 @@ github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158/go.mod h1:X
github.com/whyrusleeping/cbor-gen v0.0.0-20200206220010-03c9665e2a66/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI= github.com/whyrusleeping/cbor-gen v0.0.0-20200206220010-03c9665e2a66/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI=
github.com/whyrusleeping/cbor-gen v0.0.0-20200402171437-3d27c146c105/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI= github.com/whyrusleeping/cbor-gen v0.0.0-20200402171437-3d27c146c105/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI=
github.com/whyrusleeping/cbor-gen v0.0.0-20200414195334-429a0b5e922e/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI= github.com/whyrusleeping/cbor-gen v0.0.0-20200414195334-429a0b5e922e/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI=
github.com/whyrusleeping/cbor-gen v0.0.0-20200501014322-5f9941ef88e0/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI=
github.com/whyrusleeping/cbor-gen v0.0.0-20200501232601-351665a6e756/go.mod h1:W5MvapuoHRP8rz4vxjwCK1pDqF1aQcWsV5PZ+AHbqdg= github.com/whyrusleeping/cbor-gen v0.0.0-20200501232601-351665a6e756/go.mod h1:W5MvapuoHRP8rz4vxjwCK1pDqF1aQcWsV5PZ+AHbqdg=
github.com/whyrusleeping/cbor-gen v0.0.0-20200504204219-64967432584d h1:Y25auOnuZb/GuJvqMflRSDWBz8/HBRME8fiD+H8zLfs= github.com/whyrusleeping/cbor-gen v0.0.0-20200504204219-64967432584d h1:Y25auOnuZb/GuJvqMflRSDWBz8/HBRME8fiD+H8zLfs=
github.com/whyrusleeping/cbor-gen v0.0.0-20200504204219-64967432584d/go.mod h1:W5MvapuoHRP8rz4vxjwCK1pDqF1aQcWsV5PZ+AHbqdg= github.com/whyrusleeping/cbor-gen v0.0.0-20200504204219-64967432584d/go.mod h1:W5MvapuoHRP8rz4vxjwCK1pDqF1aQcWsV5PZ+AHbqdg=
github.com/whyrusleeping/cbor-gen v0.0.0-20200710004633-5379fc63235d h1:wSxKhvbN7kUoP0sfRS+w2tWr45qlU8409i94hHLOT8w= github.com/whyrusleeping/cbor-gen v0.0.0-20200710004633-5379fc63235d h1:wSxKhvbN7kUoP0sfRS+w2tWr45qlU8409i94hHLOT8w=
github.com/whyrusleeping/cbor-gen v0.0.0-20200710004633-5379fc63235d/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20200710004633-5379fc63235d/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ=
github.com/whyrusleeping/cbor-gen v0.0.0-20200715143311-227fab5a2377 h1:LHFlP/ktDvOnCap7PsT87cs7Gwd0p+qv6Qm5g2ZPR+I=
github.com/whyrusleeping/cbor-gen v0.0.0-20200715143311-227fab5a2377/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20200715143311-227fab5a2377/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ=
github.com/whyrusleeping/cbor-gen v0.0.0-20200723182808-cb5de1c427f5 h1:dJgLhFKggti1Xd7GczL4DetAUyx68RhpCKCfV71ongg=
github.com/whyrusleeping/cbor-gen v0.0.0-20200723182808-cb5de1c427f5/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 h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E=
github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f/go.mod h1:p9UJB6dDgdPgMJZs7UjUOdulKyRr9fqkS+6JKAInPy8= 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= github.com/whyrusleeping/go-ctrlnet v0.0.0-20180313164037-f564fbbdaa95/go.mod h1:SJqKCCPXRfBFCwXjfNT/skfsceF7+MBFLI2OrvuRA7g=

View File

@ -1,34 +0,0 @@
package adtutil
import (
"context"
"github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/filecoin-project/specs-actors/actors/util/adt"
)
func NewStore(ctx context.Context, cst *cbor.BasicIpldStore) adt.Store {
return &store{
cst: cst,
ctx: ctx,
}
}
type store struct {
cst cbor.IpldStore
ctx context.Context
}
func (a *store) Context() context.Context {
return a.ctx
}
func (a *store) Get(ctx context.Context, c cid.Cid, out interface{}) error {
return a.cst.Get(ctx, c, out)
}
func (a *store) Put(ctx context.Context, v interface{}) (cid.Cid, error) {
return a.cst.Put(ctx, v)
}

View File

@ -104,7 +104,12 @@ func (bs *BufferedBS) Get(c cid.Cid) (block.Block, error) {
} }
func (bs *BufferedBS) GetSize(c cid.Cid) (int, error) { func (bs *BufferedBS) GetSize(c cid.Cid) (int, error) {
panic("nyi") s, err := bs.read.GetSize(c)
if err == bstore.ErrNotFound || s == 0 {
return bs.write.GetSize(c)
}
return s, err
} }
func (bs *BufferedBS) Put(blk block.Block) error { func (bs *BufferedBS) Put(blk block.Block) error {

View File

@ -25,10 +25,14 @@ type IpfsBstore struct {
} }
func NewIpfsBstore(ctx context.Context) (*IpfsBstore, error) { func NewIpfsBstore(ctx context.Context) (*IpfsBstore, error) {
api, err := httpapi.NewLocalApi() localApi, err := httpapi.NewLocalApi()
if err != nil { if err != nil {
return nil, xerrors.Errorf("getting local ipfs api: %w", err) return nil, xerrors.Errorf("getting local ipfs api: %w", err)
} }
api, err := localApi.WithOptions(options.Api.Offline(true))
if err != nil {
return nil, xerrors.Errorf("setting offline mode: %s", err)
}
return &IpfsBstore{ return &IpfsBstore{
ctx: ctx, ctx: ctx,
@ -37,9 +41,13 @@ func NewIpfsBstore(ctx context.Context) (*IpfsBstore, error) {
} }
func NewRemoteIpfsBstore(ctx context.Context, maddr multiaddr.Multiaddr) (*IpfsBstore, error) { func NewRemoteIpfsBstore(ctx context.Context, maddr multiaddr.Multiaddr) (*IpfsBstore, error) {
api, err := httpapi.NewApi(maddr) httpApi, err := httpapi.NewApi(maddr)
if err != nil { if err != nil {
return nil, xerrors.Errorf("getting remote ipfs api: %w", err) return nil, xerrors.Errorf("setting remote ipfs api: %w", err)
}
api, err := httpApi.WithOptions(options.Api.Offline(true))
if err != nil {
return nil, xerrors.Errorf("applying offline mode: %s", err)
} }
return &IpfsBstore{ return &IpfsBstore{
@ -55,6 +63,13 @@ func (i *IpfsBstore) DeleteBlock(cid cid.Cid) error {
func (i *IpfsBstore) Has(cid cid.Cid) (bool, error) { func (i *IpfsBstore) Has(cid cid.Cid) (bool, error) {
_, err := i.api.Block().Stat(i.ctx, path.IpldPath(cid)) _, err := i.api.Block().Stat(i.ctx, path.IpldPath(cid))
if err != nil { if err != nil {
// The underlying client is running in Offline mode.
// Stat() will fail with an err if the block isn't in the
// blockstore. If that's the case, return false without
// an error since that's the original intention of this method.
if err.Error() == "blockservice: key not found" {
return false, nil
}
return false, xerrors.Errorf("getting ipfs block: %w", err) return false, xerrors.Errorf("getting ipfs block: %w", err)
} }

View File

@ -25,7 +25,6 @@ import (
"github.com/filecoin-project/go-fil-markets/storagemarket" "github.com/filecoin-project/go-fil-markets/storagemarket"
"github.com/filecoin-project/go-fil-markets/storagemarket/impl/storedask" "github.com/filecoin-project/go-fil-markets/storagemarket/impl/storedask"
"github.com/filecoin-project/specs-actors/actors/runtime"
storage2 "github.com/filecoin-project/specs-storage/storage" storage2 "github.com/filecoin-project/specs-storage/storage"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
@ -57,6 +56,7 @@ import (
"github.com/filecoin-project/lotus/node/modules/testing" "github.com/filecoin-project/lotus/node/modules/testing"
"github.com/filecoin-project/lotus/node/repo" "github.com/filecoin-project/lotus/node/repo"
"github.com/filecoin-project/lotus/paychmgr" "github.com/filecoin-project/lotus/paychmgr"
"github.com/filecoin-project/lotus/paychmgr/settler"
"github.com/filecoin-project/lotus/storage" "github.com/filecoin-project/lotus/storage"
"github.com/filecoin-project/lotus/storage/sectorblocks" "github.com/filecoin-project/lotus/storage/sectorblocks"
sectorstorage "github.com/filecoin-project/sector-storage" sectorstorage "github.com/filecoin-project/sector-storage"
@ -118,6 +118,7 @@ const (
// daemon // daemon
ExtractApiKey ExtractApiKey
HeadMetricsKey HeadMetricsKey
SettlePaymentChannelsKey
RunPeerTaggerKey RunPeerTaggerKey
JournalKey JournalKey
@ -225,7 +226,7 @@ func Online() Option {
Override(HandleIncomingMessagesKey, modules.HandleIncomingMessages), Override(HandleIncomingMessagesKey, modules.HandleIncomingMessages),
Override(new(ffiwrapper.Verifier), ffiwrapper.ProofVerifier), Override(new(ffiwrapper.Verifier), ffiwrapper.ProofVerifier),
Override(new(runtime.Syscalls), vm.Syscalls), Override(new(vm.SyscallBuilder), vm.Syscalls),
Override(new(*store.ChainStore), modules.ChainStore), Override(new(*store.ChainStore), modules.ChainStore),
Override(new(*stmgr.StateManager), stmgr.NewStateManager), Override(new(*stmgr.StateManager), stmgr.NewStateManager),
Override(new(*wallet.Wallet), wallet.NewWallet), Override(new(*wallet.Wallet), wallet.NewWallet),
@ -272,6 +273,7 @@ func Online() Option {
Override(new(*paychmgr.Store), paychmgr.NewStore), Override(new(*paychmgr.Store), paychmgr.NewStore),
Override(new(*paychmgr.Manager), paychmgr.NewManager), Override(new(*paychmgr.Manager), paychmgr.NewManager),
Override(new(*market.FundMgr), market.NewFundMgr), Override(new(*market.FundMgr), market.NewFundMgr),
Override(SettlePaymentChannelsKey, settler.SettlePaymentChannels),
), ),
// miner // miner

View File

@ -5,6 +5,7 @@ import (
"time" "time"
"github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/abi"
xerrors "golang.org/x/xerrors"
"github.com/filecoin-project/specs-actors/actors/abi/big" "github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
@ -125,7 +126,7 @@ func (hs *Service) HandleStream(s inet.Stream) {
func (hs *Service) SayHello(ctx context.Context, pid peer.ID) error { func (hs *Service) SayHello(ctx context.Context, pid peer.ID) error {
s, err := hs.h.NewStream(ctx, pid, ProtocolID) s, err := hs.h.NewStream(ctx, pid, ProtocolID)
if err != nil { if err != nil {
return err return xerrors.Errorf("error opening stream: %w", err)
} }
hts := hs.cs.GetHeaviestTipSet() hts := hs.cs.GetHeaviestTipSet()
@ -149,7 +150,7 @@ func (hs *Service) SayHello(ctx context.Context, pid peer.ID) error {
t0 := build.Clock.Now() t0 := build.Clock.Now()
if err := cborutil.WriteCborRPC(s, hmsg); err != nil { if err := cborutil.WriteCborRPC(s, hmsg); err != nil {
return err return xerrors.Errorf("writing rpc to peer: %w", err)
} }
go func() { go func() {

View File

@ -31,6 +31,7 @@ import (
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-fil-markets/pieceio" "github.com/filecoin-project/go-fil-markets/pieceio"
rm "github.com/filecoin-project/go-fil-markets/retrievalmarket" rm "github.com/filecoin-project/go-fil-markets/retrievalmarket"
"github.com/filecoin-project/go-fil-markets/shared"
"github.com/filecoin-project/go-fil-markets/storagemarket" "github.com/filecoin-project/go-fil-markets/storagemarket"
"github.com/filecoin-project/sector-storage/ffiwrapper" "github.com/filecoin-project/sector-storage/ffiwrapper"
"github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/abi"
@ -261,6 +262,7 @@ func (a *API) makeRetrievalQuery(ctx context.Context, rp rm.RetrievalPeer, paylo
Piece: piece, Piece: piece,
Size: queryResponse.Size, Size: queryResponse.Size,
MinPrice: queryResponse.PieceRetrievalPrice(), MinPrice: queryResponse.PieceRetrievalPrice(),
UnsealPrice: queryResponse.UnsealPrice,
PaymentInterval: queryResponse.MaxPaymentInterval, PaymentInterval: queryResponse.MaxPaymentInterval,
PaymentIntervalIncrease: queryResponse.MaxPaymentIntervalIncrease, PaymentIntervalIncrease: queryResponse.MaxPaymentIntervalIncrease,
Miner: queryResponse.PaymentAddress, // TODO: check Miner: queryResponse.PaymentAddress, // TODO: check
@ -418,10 +420,14 @@ func (a *API) ClientRetrieve(ctx context.Context, order api.RetrievalOrder, ref
ppb := types.BigDiv(order.Total, types.NewInt(order.Size)) ppb := types.BigDiv(order.Total, types.NewInt(order.Size))
_, err := a.Retrieval.Retrieve( params, err := rm.NewParamsV1(ppb, order.PaymentInterval, order.PaymentIntervalIncrease, shared.AllSelector(), order.Piece, order.UnsealPrice)
if err != nil {
return xerrors.Errorf("Error in retrieval params: %s", err)
}
_, err = a.Retrieval.Retrieve(
ctx, ctx,
order.Root, order.Root,
rm.NewParamsV0(ppb, order.PaymentInterval, order.PaymentIntervalIncrease), params,
order.Total, order.Total,
order.MinerPeerID, order.MinerPeerID,
order.Client, order.Client,
@ -434,7 +440,7 @@ func (a *API) ClientRetrieve(ctx context.Context, order api.RetrievalOrder, ref
return xerrors.New("Retrieval Timed Out") return xerrors.New("Retrieval Timed Out")
case err := <-retrievalResult: case err := <-retrievalResult:
if err != nil { if err != nil {
return xerrors.Errorf("RetrieveUnixfs: %w", err) return xerrors.Errorf("Retrieve: %w", err)
} }
} }
@ -494,6 +500,7 @@ func (a *API) ClientCalcCommP(ctx context.Context, inpath string, miner address.
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer rdr.Close()
stat, err := rdr.Stat() stat, err := rdr.Stat()
if err != nil { if err != nil {
@ -554,6 +561,7 @@ func (a *API) clientImport(ctx context.Context, ref api.FileRef, store *importmg
if err != nil { if err != nil {
return cid.Undef, err return cid.Undef, err
} }
defer f.Close()
stat, err := f.Stat() stat, err := f.Stat()
if err != nil { if err != nil {

View File

@ -4,19 +4,16 @@ import (
"bytes" "bytes"
"context" "context"
"encoding/json" "encoding/json"
"fmt"
"io" "io"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
"github.com/filecoin-project/go-amt-ipld/v2"
"github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/crypto" "github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/ipfs/go-blockservice" "github.com/ipfs/go-blockservice"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/ipfs/go-hamt-ipld"
blockstore "github.com/ipfs/go-ipfs-blockstore" blockstore "github.com/ipfs/go-ipfs-blockstore"
offline "github.com/ipfs/go-ipfs-exchange-offline" offline "github.com/ipfs/go-ipfs-exchange-offline"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
@ -26,6 +23,7 @@ import (
"github.com/ipfs/go-path" "github.com/ipfs/go-path"
"github.com/ipfs/go-path/resolver" "github.com/ipfs/go-path/resolver"
mh "github.com/multiformats/go-multihash" mh "github.com/multiformats/go-multihash"
cbg "github.com/whyrusleeping/cbor-gen"
"go.uber.org/fx" "go.uber.org/fx"
"golang.org/x/xerrors" "golang.org/x/xerrors"
@ -265,8 +263,17 @@ func (a *ChainAPI) ChainTipSetWeight(ctx context.Context, tsk types.TipSetKey) (
return a.Chain.Weight(ctx, ts) return a.Chain.Weight(ctx, ts)
} }
// This allows us to lookup string keys in the actor's adt.Map type.
type stringKey string
func (s stringKey) Key() string {
return (string)(s)
}
func resolveOnce(bs blockstore.Blockstore) func(ctx context.Context, ds ipld.NodeGetter, nd ipld.Node, names []string) (*ipld.Link, []string, error) { 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) { return func(ctx context.Context, ds ipld.NodeGetter, nd ipld.Node, names []string) (*ipld.Link, []string, error) {
store := adt.WrapStore(ctx, cbor.NewCborStore(bs))
if strings.HasPrefix(names[0], "@Ha:") { if strings.HasPrefix(names[0], "@Ha:") {
addr, err := address.NewFromString(names[0][4:]) addr, err := address.NewFromString(names[0][4:])
if err != nil { if err != nil {
@ -290,7 +297,7 @@ func resolveOnce(bs blockstore.Blockstore) func(ctx context.Context, ds ipld.Nod
if strings.HasPrefix(names[0], "@Hu:") { if strings.HasPrefix(names[0], "@Hu:") {
i, err := strconv.ParseUint(names[0][4:], 10, 64) i, err := strconv.ParseUint(names[0][4:], 10, 64)
if err != nil { if err != nil {
return nil, nil, xerrors.Errorf("parsing int64: %w", err) return nil, nil, xerrors.Errorf("parsing uint64: %w", err)
} }
ik := adt.UIntKey(i) ik := adt.UIntKey(i)
@ -299,16 +306,20 @@ func resolveOnce(bs blockstore.Blockstore) func(ctx context.Context, ds ipld.Nod
} }
if strings.HasPrefix(names[0], "@H:") { if strings.HasPrefix(names[0], "@H:") {
cst := cbor.NewCborStore(bs) h, err := adt.AsMap(store, nd.Cid())
h, err := hamt.LoadNode(ctx, cst, nd.Cid(), hamt.UseTreeBitWidth(5))
if err != nil { if err != nil {
return nil, nil, xerrors.Errorf("resolving hamt link: %w", err) return nil, nil, xerrors.Errorf("resolving hamt link: %w", err)
} }
var m interface{} var deferred cbg.Deferred
if err := h.Find(ctx, names[0][3:], &m); err != nil { if found, err := h.Get(stringKey(names[0][3:]), &deferred); err != nil {
return nil, nil, xerrors.Errorf("resolve hamt: %w", err) return nil, nil, xerrors.Errorf("resolve hamt: %w", err)
} else if !found {
return nil, nil, xerrors.Errorf("resolve hamt: not found")
}
var m interface{}
if err := cbor.DecodeInto(deferred.Raw, &m); err != nil {
return nil, nil, xerrors.Errorf("failed to decode cbor object: %w", err)
} }
if c, ok := m.(cid.Cid); ok { if c, ok := m.(cid.Cid); ok {
return &ipld.Link{ return &ipld.Link{
@ -337,7 +348,7 @@ func resolveOnce(bs blockstore.Blockstore) func(ctx context.Context, ds ipld.Nod
} }
if strings.HasPrefix(names[0], "@A:") { if strings.HasPrefix(names[0], "@A:") {
a, err := amt.LoadAMT(ctx, cbor.NewCborStore(bs), nd.Cid()) a, err := adt.AsArray(store, nd.Cid())
if err != nil { if err != nil {
return nil, nil, xerrors.Errorf("load amt: %w", err) return nil, nil, xerrors.Errorf("load amt: %w", err)
} }
@ -347,11 +358,17 @@ func resolveOnce(bs blockstore.Blockstore) func(ctx context.Context, ds ipld.Nod
return nil, nil, xerrors.Errorf("parsing amt index: %w", err) return nil, nil, xerrors.Errorf("parsing amt index: %w", err)
} }
var m interface{} var deferred cbg.Deferred
if err := a.Get(ctx, idx, &m); err != nil { if found, err := a.Get(idx, &deferred); err != nil {
return nil, nil, xerrors.Errorf("amt get: %w", err) return nil, nil, xerrors.Errorf("resolve amt: %w", err)
} else if !found {
return nil, nil, xerrors.Errorf("resolve amt: not found")
} }
fmt.Printf("AG %T %v\n", m, m) var m interface{}
if err := cbor.DecodeInto(deferred.Raw, &m); err != nil {
return nil, nil, xerrors.Errorf("failed to decode cbor object: %w", err)
}
if c, ok := m.(cid.Cid); ok { if c, ok := m.(cid.Cid); ok {
return &ipld.Link{ return &ipld.Link{
Name: names[0][3:], Name: names[0][3:],

View File

@ -5,6 +5,7 @@ import (
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/build" "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/stmgr"
"github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
@ -17,6 +18,7 @@ type GasAPI struct {
fx.In fx.In
Stmgr *stmgr.StateManager Stmgr *stmgr.StateManager
Cs *store.ChainStore Cs *store.ChainStore
Mpool *messagepool.MessagePool
} }
const MinGasPrice = 1 const MinGasPrice = 1
@ -35,19 +37,25 @@ func (a *GasAPI) GasEstimateGasPrice(ctx context.Context, nblocksincl uint64,
} }
} }
func (a *GasAPI) GasEstimateGasLimit(ctx context.Context, msgIn *types.Message, func (a *GasAPI) GasEstimateGasLimit(ctx context.Context, msgIn *types.Message, _ types.TipSetKey) (int64, error) {
tsk types.TipSetKey) (int64, error) {
msg := *msgIn msg := *msgIn
msg.GasLimit = build.BlockGasLimit msg.GasLimit = build.BlockGasLimit
msg.GasPrice = types.NewInt(1) msg.GasPrice = types.NewInt(1)
ts, err := a.Cs.GetTipSetFromKey(tsk) currTs := a.Cs.GetHeaviestTipSet()
fromA, err := a.Stmgr.ResolveToKeyAddress(ctx, msgIn.From, currTs)
if err != nil { if err != nil {
return -1, xerrors.Errorf("could not get tipset: %w", err) return -1, xerrors.Errorf("getting key address: %w", err)
} }
res, err := a.Stmgr.CallWithGas(ctx, &msg, ts) pending, ts := a.Mpool.PendingFor(fromA)
priorMsgs := make([]types.ChainMsg, 0, len(pending))
for _, m := range pending {
priorMsgs = append(priorMsgs, m)
}
res, err := a.Stmgr.CallWithGas(ctx, &msg, priorMsgs, ts)
if err != nil { if err != nil {
return -1, xerrors.Errorf("CallWithGas failed: %w", err) return -1, xerrors.Errorf("CallWithGas failed: %w", err)
} }

View File

@ -8,14 +8,12 @@ import (
"strconv" "strconv"
cid "github.com/ipfs/go-cid" cid "github.com/ipfs/go-cid"
"github.com/ipfs/go-hamt-ipld"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
"go.uber.org/fx" "go.uber.org/fx"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-amt-ipld/v2"
"github.com/filecoin-project/go-bitfield" "github.com/filecoin-project/go-bitfield"
"github.com/filecoin-project/sector-storage/ffiwrapper" "github.com/filecoin-project/sector-storage/ffiwrapper"
"github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/abi"
@ -522,30 +520,27 @@ func (a *StateAPI) StateMarketParticipants(ctx context.Context, tsk types.TipSet
if _, err := a.StateManager.LoadActorState(ctx, builtin.StorageMarketActorAddr, &state, ts); err != nil { if _, err := a.StateManager.LoadActorState(ctx, builtin.StorageMarketActorAddr, &state, ts); err != nil {
return nil, err return nil, err
} }
cst := cbor.NewCborStore(a.StateManager.ChainStore().Blockstore()) store := a.StateManager.ChainStore().Store(ctx)
escrow, err := hamt.LoadNode(ctx, cst, state.EscrowTable, hamt.UseTreeBitWidth(5)) // todo: adt map escrow, err := adt.AsMap(store, state.EscrowTable)
if err != nil { if err != nil {
return nil, err return nil, err
} }
locked, err := hamt.LoadNode(ctx, cst, state.LockedTable, hamt.UseTreeBitWidth(5)) locked, err := adt.AsMap(store, state.LockedTable)
if err != nil { if err != nil {
return nil, err return nil, err
} }
err = escrow.ForEach(ctx, func(k string, val interface{}) error { var es, lk abi.TokenAmount
cv := val.(*cbg.Deferred) err = escrow.ForEach(&es, func(k string) error {
a, err := address.NewFromBytes([]byte(k)) a, err := address.NewFromBytes([]byte(k))
if err != nil { if err != nil {
return err return err
} }
var es abi.TokenAmount if found, err := locked.Get(adt.AddrKey(a), &lk); err != nil {
if err := es.UnmarshalCBOR(bytes.NewReader(cv.Raw)); err != nil {
return err
}
var lk abi.TokenAmount
if err := locked.Find(ctx, k, &es); err != nil {
return err return err
} else if !found {
return fmt.Errorf("locked funds not found")
} }
out[a.String()] = api.MarketBalance{ out[a.String()] = api.MarketBalance{
@ -572,29 +567,23 @@ func (a *StateAPI) StateMarketDeals(ctx context.Context, tsk types.TipSetKey) (m
return nil, err return nil, err
} }
blks := cbor.NewCborStore(a.StateManager.ChainStore().Blockstore()) store := a.StateManager.ChainStore().Store(ctx)
da, err := amt.LoadAMT(ctx, blks, state.Proposals) da, err := adt.AsArray(store, state.Proposals)
if err != nil { if err != nil {
return nil, err return nil, err
} }
sa, err := amt.LoadAMT(ctx, blks, state.States) sa, err := adt.AsArray(store, state.States)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if err := da.ForEach(ctx, func(i uint64, v *cbg.Deferred) error {
var d market.DealProposal var d market.DealProposal
if err := d.UnmarshalCBOR(bytes.NewReader(v.Raw)); err != nil { if err := da.ForEach(&d, func(i int64) error {
return err
}
var s market.DealState var s market.DealState
if err := sa.Get(ctx, i, &s); err != nil { if found, err := sa.Get(uint64(i), &s); err != nil {
if _, ok := err.(*amt.ErrNotFound); !ok {
return xerrors.Errorf("failed to get state for deal in proposals array: %w", err) return xerrors.Errorf("failed to get state for deal in proposals array: %w", err)
} } else if !found {
s.SectorStartEpoch = -1 s.SectorStartEpoch = -1
} }
out[strconv.FormatInt(int64(i), 10)] = api.MarketDeal{ out[strconv.FormatInt(int64(i), 10)] = api.MarketDeal{
@ -617,47 +606,51 @@ func (a *StateAPI) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID
} }
func (a *StateAPI) StateChangedActors(ctx context.Context, old cid.Cid, new cid.Cid) (map[string]types.Actor, error) { func (a *StateAPI) StateChangedActors(ctx context.Context, old cid.Cid, new cid.Cid) (map[string]types.Actor, error) {
cst := cbor.NewCborStore(a.Chain.Blockstore()) store := adt.WrapStore(ctx, cbor.NewCborStore(a.Chain.Blockstore()))
nh, err := hamt.LoadNode(ctx, cst, new, hamt.UseTreeBitWidth(5)) nh, err := adt.AsMap(store, new)
if err != nil { if err != nil {
return nil, err return nil, err
} }
oh, err := hamt.LoadNode(ctx, cst, old, hamt.UseTreeBitWidth(5)) oh, err := adt.AsMap(store, old)
if err != nil { if err != nil {
return nil, err return nil, err
} }
out := map[string]types.Actor{} out := map[string]types.Actor{}
err = nh.ForEach(ctx, func(k string, nval interface{}) error { var (
ncval := nval.(*cbg.Deferred) ncval, ocval cbg.Deferred
buf = bytes.NewReader(nil)
)
err = nh.ForEach(&ncval, func(k string) error {
var act types.Actor var act types.Actor
var ocval cbg.Deferred
switch err := oh.Find(ctx, k, &ocval); err {
case nil:
if bytes.Equal(ocval.Raw, ncval.Raw) {
return nil // not changed
}
fallthrough
case hamt.ErrNotFound:
if err := act.UnmarshalCBOR(bytes.NewReader(ncval.Raw)); err != nil {
return err
}
addr, err := address.NewFromBytes([]byte(k)) addr, err := address.NewFromBytes([]byte(k))
if err != nil { if err != nil {
return xerrors.Errorf("address in state tree was not valid: %w", err) return xerrors.Errorf("address in state tree was not valid: %w", err)
} }
out[addr.String()] = act found, err := oh.Get(adt.AddrKey(addr), &ocval)
default: if err != nil {
return err return err
} }
if found && bytes.Equal(ocval.Raw, ncval.Raw) {
return nil // not changed
}
buf.Reset(ncval.Raw)
err = act.UnmarshalCBOR(buf)
buf.Reset(nil)
if err != nil {
return err
}
out[addr.String()] = act
return nil return nil
}) })
if err != nil { if err != nil {
@ -1000,7 +993,7 @@ func (a *StateAPI) StateMinerInitialPledgeCollateral(ctx context.Context, maddr
} }
sectorWeight := miner.QAPowerForWeight(ssize, duration, dealWeights.DealWeight, dealWeights.VerifiedDealWeight) sectorWeight := miner.QAPowerForWeight(ssize, duration, dealWeights.DealWeight, dealWeights.VerifiedDealWeight)
initialPledge := miner.InitialPledgeForPower(sectorWeight, powerState.TotalQualityAdjPower, reward.BaselinePowerAt(ts.Height()), powerState.TotalPledgeCollateral, rewardState.ThisEpochReward, circSupply) initialPledge := miner.InitialPledgeForPower(sectorWeight, powerState.TotalQualityAdjPower, reward.SlowConvenientBaselineForEpoch(ts.Height()), powerState.TotalPledgeCollateral, rewardState.ThisEpochReward, circSupply)
return types.BigDiv(types.BigMul(initialPledge, initialPledgeNum), initialPledgeDen), nil return types.BigDiv(types.BigMul(initialPledge, initialPledgeNum), initialPledgeDen), nil
} }
@ -1039,24 +1032,23 @@ func (a *StateAPI) StateVerifiedClientStatus(ctx context.Context, addr address.A
return nil, err return nil, err
} }
cst := cbor.NewCborStore(a.StateManager.ChainStore().Blockstore()) store := a.StateManager.ChainStore().Store(ctx)
var st verifreg.State var st verifreg.State
if err := cst.Get(ctx, act.Head, &st); err != nil { if err := store.Get(ctx, act.Head, &st); err != nil {
return nil, err return nil, err
} }
vh, err := hamt.LoadNode(ctx, cst, st.VerifiedClients, hamt.UseTreeBitWidth(5)) vh, err := adt.AsMap(store, st.VerifiedClients)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var dcap verifreg.DataCap var dcap verifreg.DataCap
if err := vh.Find(ctx, string(addr.Bytes()), &dcap); err != nil { if found, err := vh.Get(adt.AddrKey(addr), &dcap); err != nil {
if err == hamt.ErrNotFound {
return nil, nil
}
return nil, err return nil, err
} else if !found {
return nil, nil
} }
return &dcap, nil return &dcap, nil

View File

@ -2,6 +2,8 @@ package full
import ( import (
"context" "context"
"github.com/filecoin-project/specs-actors/actors/abi/big"
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
"github.com/filecoin-project/lotus/lib/sigs" "github.com/filecoin-project/lotus/lib/sigs"
@ -37,10 +39,16 @@ func (a *WalletAPI) WalletList(ctx context.Context) ([]address.Address, error) {
func (a *WalletAPI) WalletBalance(ctx context.Context, addr address.Address) (types.BigInt, error) { func (a *WalletAPI) WalletBalance(ctx context.Context, addr address.Address) (types.BigInt, error) {
var bal types.BigInt var bal types.BigInt
return bal, a.StateManager.WithParentStateTsk(types.EmptyTSK, a.StateManager.WithActor(addr, func(act *types.Actor) error { err := a.StateManager.WithParentStateTsk(types.EmptyTSK, a.StateManager.WithActor(addr, func(act *types.Actor) error {
bal = act.Balance bal = act.Balance
return nil return nil
})) }))
if xerrors.Is(err, init_.ErrAddressNotFound) {
return big.Zero(), nil
} else {
return bal, err
}
} }
func (a *WalletAPI) WalletSign(ctx context.Context, k address.Address, msg []byte) (*crypto.Signature, error) { func (a *WalletAPI) WalletSign(ctx context.Context, k address.Address, msg []byte) (*crypto.Signature, error) {

View File

@ -107,36 +107,43 @@ func (a *PaychAPI) PaychStatus(ctx context.Context, pch address.Address) (*api.P
}, nil }, nil
} }
func (a *PaychAPI) PaychClose(ctx context.Context, addr address.Address) (cid.Cid, error) { func (a *PaychAPI) PaychSettle(ctx context.Context, addr address.Address) (cid.Cid, error) {
panic("TODO Settle logic")
ci, err := a.PaychMgr.GetChannelInfo(addr) ci, err := a.PaychMgr.GetChannelInfo(addr)
if err != nil { if err != nil {
return cid.Undef, err return cid.Undef, err
} }
nonce, err := a.MpoolGetNonce(ctx, ci.Control)
if err != nil {
return cid.Undef, err
}
msg := &types.Message{ msg := &types.Message{
To: addr, To: addr,
From: ci.Control, From: ci.Control,
Value: types.NewInt(0), Value: types.NewInt(0),
Method: builtin.MethodsPaych.Settle, Method: builtin.MethodsPaych.Settle,
Nonce: nonce,
GasLimit: 0,
GasPrice: types.NewInt(0),
} }
smgs, err := a.MpoolPushMessage(ctx, msg)
smsg, err := a.WalletSignMessage(ctx, ci.Control, msg) if err != nil {
return cid.Undef, err
}
return smgs.Cid(), nil
}
func (a *PaychAPI) PaychCollect(ctx context.Context, addr address.Address) (cid.Cid, error) {
ci, err := a.PaychMgr.GetChannelInfo(addr)
if err != nil { if err != nil {
return cid.Undef, err return cid.Undef, err
} }
if _, err := a.MpoolPush(ctx, smsg); err != nil { msg := &types.Message{
To: addr,
From: ci.Control,
Value: types.NewInt(0),
Method: builtin.MethodsPaych.Collect,
}
smsg, err := a.MpoolPushMessage(ctx, msg)
if err != nil {
return cid.Undef, err return cid.Undef, err
} }
@ -219,11 +226,6 @@ func (a *PaychAPI) PaychVoucherSubmit(ctx context.Context, ch address.Address, s
return cid.Undef, err return cid.Undef, err
} }
nonce, err := a.MpoolGetNonce(ctx, ci.Control)
if err != nil {
return cid.Undef, err
}
if sv.Extra != nil || len(sv.SecretPreimage) > 0 { if sv.Extra != nil || len(sv.SecretPreimage) > 0 {
return cid.Undef, fmt.Errorf("cant handle more advanced payment channel stuff yet") return cid.Undef, fmt.Errorf("cant handle more advanced payment channel stuff yet")
} }
@ -239,22 +241,14 @@ func (a *PaychAPI) PaychVoucherSubmit(ctx context.Context, ch address.Address, s
From: ci.Control, From: ci.Control,
To: ch, To: ch,
Value: types.NewInt(0), Value: types.NewInt(0),
Nonce: nonce,
Method: builtin.MethodsPaych.UpdateChannelState, Method: builtin.MethodsPaych.UpdateChannelState,
Params: enc, Params: enc,
GasLimit: 0,
GasPrice: types.NewInt(0),
} }
smsg, err := a.WalletSignMessage(ctx, ci.Control, msg) smsg, err := a.MpoolPushMessage(ctx, msg)
if err != nil { if err != nil {
return cid.Undef, err return cid.Undef, err
} }
if _, err := a.MpoolPush(ctx, smsg); err != nil {
return cid.Undef, err
}
// TODO: should we wait for it...?
return smsg.Cid(), nil return smsg.Cid(), nil
} }

View File

@ -74,6 +74,10 @@ func (sm *StorageMinerAPI) WorkerStats(context.Context) (map[uint64]storiface.Wo
return sm.StorageMgr.WorkerStats(), nil return sm.StorageMgr.WorkerStats(), nil
} }
func (sm *StorageMinerAPI) WorkerJobs(ctx context.Context) (map[uint64][]storiface.WorkerJob, error) {
return sm.StorageMgr.WorkerJobs(), nil
}
func (sm *StorageMinerAPI) ActorAddress(context.Context) (address.Address, error) { func (sm *StorageMinerAPI) ActorAddress(context.Context) (address.Address, error) {
return sm.Miner.Address(), nil return sm.Miner.Address(), nil
} }

View File

@ -3,6 +3,7 @@ package modules
import ( import (
"bytes" "bytes"
"context" "context"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/ipfs/go-bitswap" "github.com/ipfs/go-bitswap"
"github.com/ipfs/go-bitswap/network" "github.com/ipfs/go-bitswap/network"
@ -17,7 +18,6 @@ import (
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/sector-storage/ffiwrapper" "github.com/filecoin-project/sector-storage/ffiwrapper"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/lotus/chain" "github.com/filecoin-project/lotus/chain"
"github.com/filecoin-project/lotus/chain/beacon" "github.com/filecoin-project/lotus/chain/beacon"
@ -83,7 +83,7 @@ func ChainBlockservice(bs dtypes.ChainBlockstore, rem dtypes.ChainExchange) dtyp
return blockservice.New(bs, rem) return blockservice.New(bs, rem)
} }
func ChainStore(lc fx.Lifecycle, bs dtypes.ChainBlockstore, ds dtypes.MetadataDS, syscalls runtime.Syscalls) *store.ChainStore { func ChainStore(lc fx.Lifecycle, bs dtypes.ChainBlockstore, ds dtypes.MetadataDS, syscalls vm.SyscallBuilder) *store.ChainStore {
chain := store.NewChainStore(bs, ds, syscalls) chain := store.NewChainStore(bs, ds, syscalls)
if err := chain.Load(); err != nil { if err := chain.Load(); err != nil {

View File

@ -92,8 +92,8 @@ func BuiltinBootstrap() (dtypes.BootstrapPeers, error) {
return build.BuiltinBootstrap() return build.BuiltinBootstrap()
} }
func DrandBootstrap() (dtypes.DrandBootstrap, error) { func DrandBootstrap(d dtypes.DrandConfig) (dtypes.DrandBootstrap, error) {
return build.DrandBootstrap() return addrutil.ParseAddresses(context.TODO(), d.Relays)
} }
func SetupJournal(lr repo.LockedRepo) error { func SetupJournal(lr repo.LockedRepo) error {

View File

@ -2,5 +2,6 @@ package dtypes
type DrandConfig struct { type DrandConfig struct {
Servers []string Servers []string
Relays []string
ChainInfoJSON string ChainInfoJSON string
} }

View File

@ -41,7 +41,9 @@ func RunHello(mctx helpers.MetricsCtx, lc fx.Lifecycle, h host.Host, svc *hello.
pic := evt.(event.EvtPeerIdentificationCompleted) pic := evt.(event.EvtPeerIdentificationCompleted)
go func() { go func() {
if err := svc.SayHello(helpers.LifecycleCtx(mctx, lc), pic.Peer); err != nil { if err := svc.SayHello(helpers.LifecycleCtx(mctx, lc), pic.Peer); err != nil {
log.Warnw("failed to say hello", "error", err, "peer", pic.Peer) protos, _ := h.Peerstore().GetProtocols(pic.Peer)
agent, _ := h.Peerstore().Get(pic.Peer, "AgentVersion")
log.Warnw("failed to say hello", "error", err, "peer", pic.Peer, "supported", protos, "agent", agent)
return return
} }
}() }()
@ -114,7 +116,7 @@ type RandomBeaconParams struct {
} }
func BuiltinDrandConfig() dtypes.DrandConfig { func BuiltinDrandConfig() dtypes.DrandConfig {
return build.DrandConfig return build.DrandConfig()
} }
func RandomBeacon(p RandomBeaconParams, _ dtypes.AfterGenesisSet) (beacon.RandomBeacon, error) { func RandomBeacon(p RandomBeaconParams, _ dtypes.AfterGenesisSet) (beacon.RandomBeacon, error) {

View File

@ -17,12 +17,11 @@ import (
"github.com/mitchellh/go-homedir" "github.com/mitchellh/go-homedir"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/gen" "github.com/filecoin-project/lotus/chain/gen"
genesis2 "github.com/filecoin-project/lotus/chain/gen/genesis" genesis2 "github.com/filecoin-project/lotus/chain/gen/genesis"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/genesis" "github.com/filecoin-project/lotus/genesis"
"github.com/filecoin-project/lotus/node/modules" "github.com/filecoin-project/lotus/node/modules"
"github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/dtypes"
@ -30,8 +29,8 @@ import (
var glog = logging.Logger("genesis") var glog = logging.Logger("genesis")
func MakeGenesisMem(out io.Writer, template genesis.Template) func(bs dtypes.ChainBlockstore, syscalls runtime.Syscalls) modules.Genesis { func MakeGenesisMem(out io.Writer, template genesis.Template) func(bs dtypes.ChainBlockstore, syscalls vm.SyscallBuilder) modules.Genesis {
return func(bs dtypes.ChainBlockstore, syscalls runtime.Syscalls) modules.Genesis { return func(bs dtypes.ChainBlockstore, syscalls vm.SyscallBuilder) modules.Genesis {
return func() (*types.BlockHeader, error) { return func() (*types.BlockHeader, error) {
glog.Warn("Generating new random genesis block, note that this SHOULD NOT happen unless you are setting up new network") glog.Warn("Generating new random genesis block, note that this SHOULD NOT happen unless you are setting up new network")
b, err := genesis2.MakeGenesisBlock(context.TODO(), bs, syscalls, template) b, err := genesis2.MakeGenesisBlock(context.TODO(), bs, syscalls, template)
@ -51,8 +50,8 @@ func MakeGenesisMem(out io.Writer, template genesis.Template) func(bs dtypes.Cha
} }
} }
func MakeGenesis(outFile, genesisTemplate string) func(bs dtypes.ChainBlockstore, syscalls runtime.Syscalls) modules.Genesis { func MakeGenesis(outFile, genesisTemplate string) func(bs dtypes.ChainBlockstore, syscalls vm.SyscallBuilder) modules.Genesis {
return func(bs dtypes.ChainBlockstore, syscalls runtime.Syscalls) modules.Genesis { return func(bs dtypes.ChainBlockstore, syscalls vm.SyscallBuilder) modules.Genesis {
return func() (*types.BlockHeader, error) { return func() (*types.BlockHeader, error) {
glog.Warn("Generating new random genesis block, note that this SHOULD NOT happen unless you are setting up new network") glog.Warn("Generating new random genesis block, note that this SHOULD NOT happen unless you are setting up new network")
genesisTemplate, err := homedir.Expand(genesisTemplate) genesisTemplate, err := homedir.Expand(genesisTemplate)

View File

@ -382,8 +382,12 @@ func mockSbBuilder(t *testing.T, nFull int, storage []test.StorageMiner) ([]test
} }
} }
for i, def := range storage { for i, def := range storage {
// TODO: support non-bootstrap miners // TODO: support non-bootstrap miners
minerID := abi.ActorID(genesis2.MinerStart + uint64(i))
if def.Full != 0 { if def.Full != 0 {
t.Fatal("storage nodes only supported on the first full node") t.Fatal("storage nodes only supported on the first full node")
} }
@ -396,9 +400,17 @@ func mockSbBuilder(t *testing.T, nFull int, storage []test.StorageMiner) ([]test
return nil, nil return nil, nil
} }
sectors := make([]abi.SectorID, len(genms[i].Sectors))
for i, sector := range genms[i].Sectors {
sectors[i] = abi.SectorID{
Miner: minerID,
Number: sector.SectorID,
}
}
storers[i] = testStorageNode(ctx, t, genms[i].Worker, maddrs[i], pidKeys[i], f, mn, node.Options( storers[i] = testStorageNode(ctx, t, genms[i].Worker, maddrs[i], pidKeys[i], f, mn, node.Options(
node.Override(new(sectorstorage.SectorManager), func() (sectorstorage.SectorManager, error) { node.Override(new(sectorstorage.SectorManager), func() (sectorstorage.SectorManager, error) {
return mock.NewMockSectorMgr(build.DefaultSectorSize()), nil return mock.NewMockSectorMgr(build.DefaultSectorSize(), sectors), nil
}), }),
node.Override(new(ffiwrapper.Verifier), mock.MockVerifier), node.Override(new(ffiwrapper.Verifier), mock.MockVerifier),
node.Unset(new(*sectorstorage.Manager)), node.Unset(new(*sectorstorage.Manager)),
@ -536,7 +548,7 @@ func TestWindowedPost(t *testing.T) {
logging.SetLogLevel("sub", "ERROR") logging.SetLogLevel("sub", "ERROR")
logging.SetLogLevel("storageminer", "ERROR") logging.SetLogLevel("storageminer", "ERROR")
test.TestWindowPost(t, mockSbBuilder, 5*time.Millisecond, 10) test.TestWindowPost(t, mockSbBuilder, 2*time.Millisecond, 10)
} }
func TestCCUpgrade(t *testing.T) { func TestCCUpgrade(t *testing.T) {
@ -548,3 +560,14 @@ func TestCCUpgrade(t *testing.T) {
test.TestCCUpgrade(t, mockSbBuilder, 5*time.Millisecond) test.TestCCUpgrade(t, mockSbBuilder, 5*time.Millisecond)
} }
func TestPaymentChannels(t *testing.T) {
logging.SetLogLevel("miner", "ERROR")
logging.SetLogLevel("chainstore", "ERROR")
logging.SetLogLevel("chain", "ERROR")
logging.SetLogLevel("sub", "ERROR")
logging.SetLogLevel("pubsub", "ERROR")
logging.SetLogLevel("storageminer", "ERROR")
test.TestPaymentChannels(t, mockSbBuilder, 5*time.Millisecond)
}

View File

@ -390,6 +390,7 @@ func (fsr *fsLockedRepo) List() ([]string, error) {
if err != nil { if err != nil {
return nil, xerrors.Errorf("opening dir to list keystore: %w", err) return nil, xerrors.Errorf("opening dir to list keystore: %w", err)
} }
defer dir.Close() //nolint:errcheck
files, err := dir.Readdir(-1) files, err := dir.Readdir(-1)
if err != nil { if err != nil {
return nil, xerrors.Errorf("reading keystore dir: %w", err) return nil, xerrors.Errorf("reading keystore dir: %w", err)

View File

@ -185,7 +185,7 @@ func (pm *Manager) checkVoucherValid(ctx context.Context, ch address.Address, sv
// CheckVoucherSpendable checks if the given voucher is currently spendable // CheckVoucherSpendable checks if the given voucher is currently spendable
func (pm *Manager) CheckVoucherSpendable(ctx context.Context, ch address.Address, sv *paych.SignedVoucher, secret []byte, proof []byte) (bool, error) { func (pm *Manager) CheckVoucherSpendable(ctx context.Context, ch address.Address, sv *paych.SignedVoucher, secret []byte, proof []byte) (bool, error) {
owner, err := pm.getPaychOwner(ctx, ch) recipient, err := pm.getPaychRecipient(ctx, ch)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -222,7 +222,7 @@ func (pm *Manager) CheckVoucherSpendable(ctx context.Context, ch address.Address
} }
ret, err := pm.sm.Call(ctx, &types.Message{ ret, err := pm.sm.Call(ctx, &types.Message{
From: owner, From: recipient,
To: ch, To: ch,
Method: builtin.MethodsPaych.UpdateChannelState, Method: builtin.MethodsPaych.UpdateChannelState,
Params: enc, Params: enc,
@ -238,13 +238,13 @@ func (pm *Manager) CheckVoucherSpendable(ctx context.Context, ch address.Address
return true, nil return true, nil
} }
func (pm *Manager) getPaychOwner(ctx context.Context, ch address.Address) (address.Address, error) { func (pm *Manager) getPaychRecipient(ctx context.Context, ch address.Address) (address.Address, error) {
var state paych.State var state paych.State
if _, err := pm.sm.LoadActorState(ctx, ch, &state, nil); err != nil { if _, err := pm.sm.LoadActorState(ctx, ch, &state, nil); err != nil {
return address.Address{}, err return address.Address{}, err
} }
return state.From, nil return state.To, nil
} }
func (pm *Manager) AddVoucher(ctx context.Context, ch address.Address, sv *paych.SignedVoucher, proof []byte, minDelta types.BigInt) (types.BigInt, error) { func (pm *Manager) AddVoucher(ctx context.Context, ch address.Address, sv *paych.SignedVoucher, proof []byte, minDelta types.BigInt) (types.BigInt, error) {

141
paychmgr/settler/settler.go Normal file
View File

@ -0,0 +1,141 @@
package settler
import (
"context"
"sync"
"go.uber.org/fx"
"github.com/ipfs/go-cid"
logging "github.com/ipfs/go-log/v2"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/events"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/impl/full"
payapi "github.com/filecoin-project/lotus/node/impl/paych"
)
var log = logging.Logger("payment-channel-settler")
// API are the dependencies need to run the payment channel settler
type API struct {
fx.In
full.ChainAPI
full.StateAPI
payapi.PaychAPI
}
type settlerAPI interface {
PaychList(context.Context) ([]address.Address, error)
PaychStatus(context.Context, address.Address) (*api.PaychStatus, error)
PaychVoucherCheckSpendable(context.Context, address.Address, *paych.SignedVoucher, []byte, []byte) (bool, error)
PaychVoucherList(context.Context, address.Address) ([]*paych.SignedVoucher, error)
PaychVoucherSubmit(context.Context, address.Address, *paych.SignedVoucher) (cid.Cid, error)
StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64) (*api.MsgLookup, error)
}
type paymentChannelSettler struct {
ctx context.Context
api settlerAPI
}
// SettlePaymentChannels checks the chain for events related to payment channels settling and
// submits any vouchers for inbound channels tracked for this node
func SettlePaymentChannels(lc fx.Lifecycle, api API) error {
lc.Append(fx.Hook{
OnStart: func(ctx context.Context) error {
pcs := newPaymentChannelSettler(ctx, &api)
ev := events.NewEvents(ctx, &api)
return ev.Called(pcs.check, pcs.messageHandler, pcs.revertHandler, int(build.MessageConfidence+1), events.NoTimeout, pcs.matcher)
},
})
return nil
}
func newPaymentChannelSettler(ctx context.Context, api settlerAPI) *paymentChannelSettler {
return &paymentChannelSettler{
ctx: ctx,
api: api,
}
}
func (pcs *paymentChannelSettler) check(ts *types.TipSet) (done bool, more bool, err error) {
return false, true, nil
}
func (pcs *paymentChannelSettler) messageHandler(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH abi.ChainEpoch) (more bool, err error) {
vouchers, err := pcs.api.PaychVoucherList(pcs.ctx, msg.To)
if err != nil {
return true, err
}
bestByLane := make(map[uint64]*paych.SignedVoucher)
for _, voucher := range vouchers {
spendable, err := pcs.api.PaychVoucherCheckSpendable(pcs.ctx, msg.To, voucher, nil, nil)
if err != nil {
return true, err
}
if spendable {
if bestByLane[voucher.Lane] == nil || voucher.Amount.GreaterThan(bestByLane[voucher.Lane].Amount) {
bestByLane[voucher.Lane] = voucher
}
}
}
var wg sync.WaitGroup
wg.Add(len(bestByLane))
for _, voucher := range bestByLane {
submitMessageCID, err := pcs.api.PaychVoucherSubmit(pcs.ctx, msg.To, voucher)
if err != nil {
return true, err
}
go func(voucher *paych.SignedVoucher, submitMessageCID cid.Cid) {
defer wg.Done()
msgLookup, err := pcs.api.StateWaitMsg(pcs.ctx, submitMessageCID, build.MessageConfidence)
if err != nil {
log.Errorf("submitting voucher: %s", err.Error())
}
if msgLookup.Receipt.ExitCode != 0 {
log.Errorf("failed submitting voucher: %+v", voucher)
}
}(voucher, submitMessageCID)
}
wg.Wait()
return true, nil
}
func (pcs *paymentChannelSettler) revertHandler(ctx context.Context, ts *types.TipSet) error {
return nil
}
func (pcs *paymentChannelSettler) matcher(msg *types.Message) (matchOnce bool, matched bool, err error) {
// Check if this is a settle payment channel message
if msg.Method != builtin.MethodsPaych.Settle {
return false, false, nil
}
// Check if this payment channel is of concern to this node (i.e. tracked in payment channel store),
// and its inbound (i.e. we're getting vouchers that we may need to redeem)
trackedAddresses, err := pcs.api.PaychList(pcs.ctx)
if err != nil {
return false, false, err
}
for _, addr := range trackedAddresses {
if msg.To == addr {
status, err := pcs.api.PaychStatus(pcs.ctx, addr)
if err != nil {
return false, false, err
}
if status.Direction == api.PCHInbound {
return false, true, nil
}
}
}
return false, false, nil
}

View File

@ -331,7 +331,7 @@ func (s *WindowPoStScheduler) runPost(ctx context.Context, di miner.DeadlineInfo
params := &miner.SubmitWindowedPoStParams{ params := &miner.SubmitWindowedPoStParams{
Deadline: di.Index, Deadline: di.Index,
Partitions: make([]miner.PoStPartition, len(partitions)), Partitions: make([]miner.PoStPartition, 0, len(partitions)),
Proofs: nil, Proofs: nil,
} }
@ -373,20 +373,19 @@ func (s *WindowPoStScheduler) runPost(ctx context.Context, di miner.DeadlineInfo
return nil, xerrors.Errorf("getting sorted sector info: %w", err) return nil, xerrors.Errorf("getting sorted sector info: %w", err)
} }
if len(ssi) == 0 {
continue
}
sinfos = append(sinfos, ssi...) sinfos = append(sinfos, ssi...)
for _, si := range ssi { for _, si := range ssi {
sidToPart[si.SectorNumber] = uint64(partIdx) sidToPart[si.SectorNumber] = uint64(partIdx)
} }
if len(ssi) == 0 { params.Partitions = append(params.Partitions, miner.PoStPartition{
log.Warn("attempted to run windowPost without any sectors...")
return nil, xerrors.Errorf("no sectors to run windowPost on")
}
params.Partitions[partIdx] = miner.PoStPartition{
Index: uint64(partIdx), Index: uint64(partIdx),
Skipped: skipped, Skipped: skipped,
} })
} }
if len(sinfos) == 0 { if len(sinfos) == 0 {
@ -463,9 +462,7 @@ func (s *WindowPoStScheduler) submitPost(ctx context.Context, proof *miner.Submi
Method: builtin.MethodsMiner.SubmitWindowedPoSt, Method: builtin.MethodsMiner.SubmitWindowedPoSt,
Params: enc, Params: enc,
Value: types.NewInt(1000), // currently hard-coded late fee in actor, returned if not late Value: types.NewInt(1000), // currently hard-coded late fee in actor, returned if not late
// TODO: Gaslimit needs to be calculated accurately. Before that, use the largest Gaslimit GasPrice: types.NewInt(3),
GasLimit: build.BlockGasLimit,
GasPrice: types.NewInt(1),
} }
// TODO: consider maybe caring about the output // TODO: consider maybe caring about the output