updating faucet url and removing secp256k1 addresses to reduce confusion

This commit is contained in:
eshon 2019-10-16 19:39:21 +02:00
commit 2386537dfc
62 changed files with 957 additions and 315 deletions

3
.gitignore vendored
View File

@ -2,8 +2,11 @@
/lotus-storage-miner
/pond
/townhall
/fountain
/lotuspond/front/node_modules
/lotuspond/front/build
/cmd/lotus-townhall/townhall/node_modules
/cmd/lotus-townhall/townhall/build
**/*.h
**/*.a
**/*.pc

View File

@ -76,6 +76,9 @@ build: lotus lotus-storage-miner
.PHONY: build
install:
install -C ./lotus /usr/local/bin/lotus
install -C ./lotus /usr/local/bin/lotus-storage-miner
benchmarks:
go run github.com/whyrusleeping/bencher ./... > bench.json
@ -95,6 +98,12 @@ townhall:
go run github.com/GeertJohan/go.rice/rice append --exec townhall -i ./cmd/lotus-townhall
.PHONY: townhall
fountain:
rm -f fountain
go build -o fountain ./cmd/lotus-fountain
go run github.com/GeertJohan/go.rice/rice append --exec fountain -i ./cmd/lotus-fountain
.PHONY: fountain
clean:
rm -rf $(CLEAN)
-$(MAKE) -C $(BLS_PATH) clean

View File

@ -11,8 +11,10 @@ All work is tracked via issues. An attempt at keeping an up-to-date view on rema
## Building
*Dependencies:*
We currently only provide the option to build lotus from source. Binary installation options are coming soon!
In order to run lotus, please do the following:
1. Make sure you have these dependencies installed:
- go (1.13 or higher)
- gcc (7.4.0 or higher)
- git
@ -20,19 +22,27 @@ All work is tracked via issues. An attempt at keeping an up-to-date view on rema
- jq
- pkg-config
*Building:*
2. Clone this repo & `cd` into it
```
$ git clone https://github.com/filecoin-project/lotus.git
$ cd lotus/
```
3. Build and install the source code
```
$ make
$ sudo make install
```
Now, you should be able to perform the commands listed below.
## Devnet
### Node setup
If you have run lotus before and want to remove all previous data: `rm -rf ~/.lotus ~/.lotusstorage`
[You can copy `lotus` and `lotus-storage-miner` to your `$GOPATH/bin` or `$PATH`, or reference all lotus commands below from your local build directory with `./lotus`]
The following sections describe how to use the lotus CLI. Alternately you can run lotus nodes and miners using the [Pond GUI](#pond).
### Genesis & Bootstrap
@ -58,6 +68,9 @@ You can follow sync status with:
$ watch lotus sync status
```
You can view the latest block height along with other network metrics at the [lotus Devnet dashboard](https://lotus-metrics.kittyhawk.wtf/d/z6FtI92Zz/chain?orgId=1&refresh=5s&kiosk).
[It may take a few minutes for the chain to finish syncing. You will see `Height: 0` until the full chain is synced and validated.]
### Basics
@ -67,19 +80,15 @@ $ lotus wallet new bls
t3...
```
Grab some funds from faucet - go to http://147.75.80.29:777/, paste the address
Grab some funds from faucet - go to https://lotus-faucet.kittyhawk.wtf, paste the address
you just created, and press Send.
(You can also generate a public key address using secp256k1 with
`lotus wallet new secp256k1`. BLS signatures use less space so will have lower fees.)
Check the wallet balance:
Check the wallet balance (balance is listed in attoFIL, where 1 attoFIL = 10^-18 FIL):
```sh
$ lotus wallet balance [optional address (t3...)]
```
(NOTE: If you see an error like `actor not found` after executing this command,
it means that either there are no transactions to this address on chain - using
faucet should 'fix' this, or your node isn't fully synced).
(NOTE: If you see an error like `actor not found` after executing this command, it means that either your node isn't fully synced or there are no transactions to this address yet on chain. If the latter, using the faucet should 'fix' this).
### Mining
@ -88,7 +97,7 @@ cover pledge collateral:
```sh
$ lotus state pledge-collateral
1234
$ lotus wallet balance t3...
$ lotus wallet balance [t3...]
8999
```
(Balance must be higher than the returned pledge collateral for the next step to work)
@ -129,12 +138,6 @@ $ lotus-storage-miner state power <miner>
$ lotus-storage-miner state sectors <miner>
```
You can view a list of miners with:
```sh
$ lotus state list-miners
```
### Stage Data
Import some data:
@ -158,14 +161,17 @@ $ lotus client local
(It is possible for a Client to make a deal with a Miner on the same lotus Node.)
```sh
# List all miners in the system. Choose one to make a deal with.
$ lotus state list-miners
# List asks proposed by a miner
$ lotus client query-ask <miner>
# Propose a deal with a miner
# Propose a deal with a miner. Price is in attoFIL/byte/block. Duration is # of blocks.
$ lotus client deal <Data CID> <miner> <price> <duration>
```
For example `$ lotus client deal bafkre...qvtjsi t0111 36000 12` proposes a deal to store CID `bafkre...qvtjsi` with miner `t0111` at price `36000` for a duration of `12` blocks.
For example `$ lotus client deal bafkre...qvtjsi t0111 36000 12` proposes a deal to store CID `bafkre...qvtjsi` with miner `t0111` at price `36000` for a duration of `12` blocks. If successful, the `client deal` command will return a deal CID.
### Search & Retrieval

View File

@ -50,8 +50,7 @@ type FullNode interface {
// ChainNotify returns channel with chain head updates
// First message is guaranteed to be of len == 1, and type == 'current'
ChainNotify(context.Context) (<-chan []*store.HeadChange, error)
ChainHead(context.Context) (*types.TipSet, error) // TODO: check serialization
ChainSubmitBlock(ctx context.Context, blk *types.BlockMsg) error // TODO: check serialization
ChainHead(context.Context) (*types.TipSet, error)
ChainGetRandomness(context.Context, *types.TipSet, []*types.Ticket, int) ([]byte, error)
ChainGetBlock(context.Context, cid.Cid) (*types.BlockHeader, error)
ChainGetTipSet(context.Context, []cid.Cid) (*types.TipSet, error)
@ -62,12 +61,13 @@ type FullNode interface {
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
ChainSetHead(context.Context, *types.TipSet) error
ChainGetGenesis(context.Context) (*types.TipSet, error)
ChainTipSetWeight(context.Context, *types.TipSet) (types.BigInt, error)
// syncer
SyncState(context.Context) (*SyncState, error)
SyncSubmitBlock(ctx context.Context, blk *types.BlockMsg) error
// messages
MpoolPending(context.Context, *types.TipSet) ([]*types.SignedMessage, error)
MpoolPush(context.Context, *types.SignedMessage) error // TODO: remove
MpoolPushMessage(context.Context, *types.Message) (*types.SignedMessage, error) // get nonce, sign, push
@ -150,7 +150,7 @@ type FullNode interface {
type StorageMiner interface {
Common
ActorAddresses(context.Context) ([]address.Address, error)
ActorAddress(context.Context) (address.Address, error)
// Temp api for testing
StoreGarbageData(context.Context) (uint64, error)
@ -159,7 +159,7 @@ type StorageMiner interface {
SectorsStatus(context.Context, uint64) (sectorbuilder.SectorSealingStatus, error)
// List all staged sectors
SectorsStagedList(context.Context) ([]sectorbuilder.StagedSectorMetadata, error)
SectorsList(context.Context) ([]uint64, error)
// Seal all staged sectors
SectorsStagedSeal(context.Context) error

View File

@ -38,7 +38,6 @@ type FullNodeStruct struct {
Internal struct {
ChainNotify func(context.Context) (<-chan []*store.HeadChange, error) `perm:"read"`
ChainSubmitBlock func(ctx context.Context, blk *types.BlockMsg) error `perm:"write"`
ChainHead func(context.Context) (*types.TipSet, error) `perm:"read"`
ChainGetRandomness func(context.Context, *types.TipSet, []*types.Ticket, int) ([]byte, error) `perm:"read"`
ChainGetBlock func(context.Context, cid.Cid) (*types.BlockHeader, error) `perm:"read"`
@ -50,8 +49,10 @@ type FullNodeStruct struct {
ChainReadObj func(context.Context, cid.Cid) ([]byte, error) `perm:"read"`
ChainSetHead func(context.Context, *types.TipSet) error `perm:"admin"`
ChainGetGenesis func(context.Context) (*types.TipSet, error) `perm:"read"`
ChainTipSetWeight func(context.Context, *types.TipSet) (types.BigInt, error) `perm:"read"`
SyncState func(context.Context) (*SyncState, error) `perm:"read"`
SyncSubmitBlock func(ctx context.Context, blk *types.BlockMsg) error `perm:"write"`
MpoolPending func(context.Context, *types.TipSet) ([]*types.SignedMessage, error) `perm:"read"`
MpoolPush func(context.Context, *types.SignedMessage) error `perm:"write"`
@ -118,12 +119,12 @@ type StorageMinerStruct struct {
CommonStruct
Internal struct {
ActorAddresses func(context.Context) ([]address.Address, error) `perm:"read"`
ActorAddress func(context.Context) (address.Address, error) `perm:"read"`
StoreGarbageData func(context.Context) (uint64, error) `perm:"write"`
SectorsStatus func(context.Context, uint64) (sectorbuilder.SectorSealingStatus, error) `perm:"read"`
SectorsStagedList func(context.Context) ([]sectorbuilder.StagedSectorMetadata, error) `perm:"read"`
SectorsList func(context.Context) ([]uint64, error) `perm:"read"`
SectorsStagedSeal func(context.Context) error `perm:"write"`
SectorsRefs func(context.Context) (map[string][]SealedRef, error) `perm:"read"`
@ -228,10 +229,6 @@ func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, addr address.Addr
return c.Internal.MinerCreateBlock(ctx, addr, base, tickets, eproof, msgs, ts)
}
func (c *FullNodeStruct) ChainSubmitBlock(ctx context.Context, blk *types.BlockMsg) error {
return c.Internal.ChainSubmitBlock(ctx, blk)
}
func (c *FullNodeStruct) ChainHead(ctx context.Context) (*types.TipSet, error) {
return c.Internal.ChainHead(ctx)
}
@ -320,10 +317,18 @@ func (c *FullNodeStruct) ChainGetGenesis(ctx context.Context) (*types.TipSet, er
return c.Internal.ChainGetGenesis(ctx)
}
func (c *FullNodeStruct) ChainTipSetWeight(ctx context.Context, ts *types.TipSet) (types.BigInt, error) {
return c.Internal.ChainTipSetWeight(ctx, ts)
}
func (c *FullNodeStruct) SyncState(ctx context.Context) (*SyncState, error) {
return c.Internal.SyncState(ctx)
}
func (c *FullNodeStruct) SyncSubmitBlock(ctx context.Context, blk *types.BlockMsg) error {
return c.Internal.SyncSubmitBlock(ctx, blk)
}
func (c *FullNodeStruct) StateMinerSectors(ctx context.Context, addr address.Address) ([]*SectorInfo, error) {
return c.Internal.StateMinerSectors(ctx, addr)
}
@ -426,8 +431,8 @@ func (c *FullNodeStruct) PaychVoucherSubmit(ctx context.Context, ch address.Addr
return c.Internal.PaychVoucherSubmit(ctx, ch, sv)
}
func (c *StorageMinerStruct) ActorAddresses(ctx context.Context) ([]address.Address, error) {
return c.Internal.ActorAddresses(ctx)
func (c *StorageMinerStruct) ActorAddress(ctx context.Context) (address.Address, error) {
return c.Internal.ActorAddress(ctx)
}
func (c *StorageMinerStruct) StoreGarbageData(ctx context.Context) (uint64, error) {
@ -440,8 +445,8 @@ func (c *StorageMinerStruct) SectorsStatus(ctx context.Context, sid uint64) (sec
}
// List all staged sectors
func (c *StorageMinerStruct) SectorsStagedList(ctx context.Context) ([]sectorbuilder.StagedSectorMetadata, error) {
return c.Internal.SectorsStagedList(ctx)
func (c *StorageMinerStruct) SectorsList(ctx context.Context) ([]uint64, error) {
return c.Internal.SectorsList(ctx)
}
// Seal all staged sectors

View File

@ -1 +1 @@
/ip4/147.75.80.17/tcp/1347/p2p/12D3KooWJdB9SxJfUb327CsBMCyEqzkDCHaqcrwaHGZ88wUuoc5F
/ip4/147.75.80.17/tcp/1347/p2p/12D3KooWB54edC5VTSaQpvcYbqG8XKAziP77Natf75CieA5xKDJx

View File

@ -1 +1 @@
/ip4/147.75.80.29/tcp/1347/p2p/12D3KooWAShT7qd3oM7QPC8AsQffs6ThH69fZGui4xCW68E35rDP
/ip4/147.75.80.29/tcp/1347/p2p/12D3KooWGdsbvHwscFKT1kqBeeooPe6EneJvjXzTrWSzwKhc1ssn

Binary file not shown.

View File

@ -38,6 +38,9 @@ const AllowableClockDrift = BlockDelay * 2
// Blocks
const ForkLengthThreshold = 100
// Blocks (e)
const BlocksPerEpoch = 1
// /////
// Proofs / Mining

View File

@ -185,7 +185,7 @@ func (sma StorageMinerActor) StorageMinerConstructor(act *types.Actor, vmctx typ
sectors := amt.NewAMT(types.WrapStorage(vmctx.Storage()))
scid, serr := sectors.Flush()
if serr != nil {
return nil, aerrors.Escalate(serr, "initializing AMT")
return nil, aerrors.HandleExternalError(serr, "initializing AMT")
}
self.Sectors = scid
@ -270,7 +270,7 @@ func (sma StorageMinerActor) CommitSector(act *types.Actor, vmctx types.VMContex
// time to prove than large sectors do. Sector size is selected when pledging.
pss, lerr := amt.LoadAMT(types.WrapStorage(vmctx.Storage()), self.ProvingSet)
if lerr != nil {
return nil, aerrors.Escalate(lerr, "could not load proving set node")
return nil, aerrors.HandleExternalError(lerr, "could not load proving set node")
}
if pss.Count == 0 {
@ -366,7 +366,7 @@ func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext,
pss, lerr := amt.LoadAMT(types.WrapStorage(vmctx.Storage()), self.ProvingSet)
if lerr != nil {
return nil, aerrors.Escalate(lerr, "could not load proving set node")
return nil, aerrors.HandleExternalError(lerr, "could not load proving set node")
}
var sectorInfos []sectorbuilder.SectorInfo
@ -409,19 +409,19 @@ func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext,
ss, lerr := amt.LoadAMT(types.WrapStorage(vmctx.Storage()), self.ProvingSet)
if lerr != nil {
return nil, aerrors.Escalate(lerr, "could not load proving set node")
return nil, aerrors.HandleExternalError(lerr, "could not load proving set node")
}
if err := ss.BatchDelete(params.DoneSet.All()); err != nil {
// TODO: this could fail for system reasons (block not found) or for
// bad user input reasons (e.g. bad doneset). The latter should be a
// non-fatal error
return nil, aerrors.Escalate(err, "failed to delete sectors in done set")
return nil, aerrors.HandleExternalError(err, "failed to delete sectors in done set")
}
self.ProvingSet, lerr = ss.Flush()
if lerr != nil {
return nil, aerrors.Escalate(lerr, "could not flush AMT")
return nil, aerrors.HandleExternalError(lerr, "could not flush AMT")
}
oldPower := self.Power
@ -433,7 +433,7 @@ func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext,
return nil, err
}
_, err = vmctx.Send(StorageMarketAddress, SMAMethods.UpdateStorage, types.NewInt(0), enc)
_, err = vmctx.Send(StorageMarketAddress, SPAMethods.UpdateStorage, types.NewInt(0), enc)
if err != nil {
return nil, err
}
@ -474,16 +474,16 @@ func SectorIsUnique(ctx context.Context, s types.Storage, sroot cid.Cid, sid uin
func AddToSectorSet(ctx context.Context, s types.Storage, ss cid.Cid, sectorID uint64, commR, commD []byte) (cid.Cid, ActorError) {
ssr, err := amt.LoadAMT(types.WrapStorage(s), ss)
if err != nil {
return cid.Undef, aerrors.Escalate(err, "could not load sector set node")
return cid.Undef, aerrors.HandleExternalError(err, "could not load sector set node")
}
if err := ssr.Set(sectorID, [][]byte{commR, commD}); err != nil {
return cid.Undef, aerrors.Escalate(err, "failed to set commitment in sector set")
return cid.Undef, aerrors.HandleExternalError(err, "failed to set commitment in sector set")
}
ncid, err := ssr.Flush()
if err != nil {
return cid.Undef, aerrors.Escalate(err, "failed to flush sector set")
return cid.Undef, aerrors.HandleExternalError(err, "failed to flush sector set")
}
return ncid, nil
@ -492,7 +492,7 @@ func AddToSectorSet(ctx context.Context, s types.Storage, ss cid.Cid, sectorID u
func GetFromSectorSet(ctx context.Context, s types.Storage, ss cid.Cid, sectorID uint64) (bool, []byte, []byte, ActorError) {
ssr, err := amt.LoadAMT(types.WrapStorage(s), ss)
if err != nil {
return false, nil, nil, aerrors.Escalate(err, "could not load sector set node")
return false, nil, nil, aerrors.HandleExternalError(err, "could not load sector set node")
}
var comms [][]byte
@ -501,11 +501,11 @@ func GetFromSectorSet(ctx context.Context, s types.Storage, ss cid.Cid, sectorID
if _, ok := err.(*amt.ErrNotFound); ok {
return false, nil, nil, nil
}
return false, nil, nil, aerrors.Escalate(err, "failed to find sector in sector set")
return false, nil, nil, aerrors.HandleExternalError(err, "failed to find sector in sector set")
}
if len(comms) != 2 {
return false, nil, nil, aerrors.Escalate(xerrors.New("sector set entry should only have 2 elements"), "")
return false, nil, nil, aerrors.Newf(20, "sector set entry should only have 2 elements")
}
return true, comms[0], comms[1], nil
@ -514,7 +514,7 @@ func GetFromSectorSet(ctx context.Context, s types.Storage, ss cid.Cid, sectorID
func ValidatePoRep(maddr address.Address, ssize types.BigInt, params *CommitSectorParams) (bool, ActorError) {
ok, err := sectorbuilder.VerifySeal(ssize.Uint64(), params.CommR, params.CommD, params.CommRStar, maddr, params.SectorID, params.Proof)
if err != nil {
return false, aerrors.Escalate(err, "verify seal failed")
return false, aerrors.Absorb(err, 25, "verify seal failed")
}
return ok, nil
@ -659,11 +659,11 @@ func (sma StorageMinerActor) PaymentVerifyInclusion(act *types.Actor, vmctx type
var voucherData PieceInclVoucherData
if err := cbor.DecodeInto(params.Extra, &voucherData); err != nil {
return nil, aerrors.Escalate(err, "failed to decode storage voucher data for verification")
return nil, aerrors.Absorb(err, 2, "failed to decode storage voucher data for verification")
}
var proof InclusionProof
if err := cbor.DecodeInto(params.Proof, &proof); err != nil {
return nil, aerrors.Escalate(err, "failed to decode storage payment proof")
return nil, aerrors.Absorb(err, 3, "failed to decode storage payment proof")
}
ok, _, commD, aerr := GetFromSectorSet(context.TODO(), vmctx.Storage(), self.Sectors, proof.Sector)
@ -671,15 +671,15 @@ func (sma StorageMinerActor) PaymentVerifyInclusion(act *types.Actor, vmctx type
return nil, aerr
}
if !ok {
return nil, aerrors.New(1, "miner does not have required sector")
return nil, aerrors.New(4, "miner does not have required sector")
}
ok, err := sectorbuilder.VerifyPieceInclusionProof(mi.SectorSize.Uint64(), voucherData.PieceSize.Uint64(), voucherData.CommP, commD, proof.Proof)
if err != nil {
return nil, aerrors.Escalate(err, "verify piece inclusion proof failed")
return nil, aerrors.Absorb(err, 5, "verify piece inclusion proof failed")
}
if !ok {
return nil, aerrors.New(2, "piece inclusion proof was invalid")
return nil, aerrors.New(6, "piece inclusion proof was invalid")
}
return nil, nil

View File

@ -2,7 +2,6 @@ package actors
import (
"context"
"fmt"
"github.com/filecoin-project/go-lotus/build"
"github.com/filecoin-project/go-lotus/chain/actors/aerrors"
@ -16,9 +15,9 @@ import (
xerrors "golang.org/x/xerrors"
)
type StorageMarketActor struct{}
type StoragePowerActor struct{}
type smaMethods struct {
type spaMethods struct {
Constructor uint64
CreateStorageMiner uint64
ArbitrateConsensusFault uint64
@ -29,22 +28,22 @@ type smaMethods struct {
PledgeCollateralForSize uint64
}
var SMAMethods = smaMethods{1, 2, 3, 4, 5, 6, 7, 8}
var SPAMethods = spaMethods{1, 2, 3, 4, 5, 6, 7, 8}
func (sma StorageMarketActor) Exports() []interface{} {
func (spa StoragePowerActor) Exports() []interface{} {
return []interface{}{
//1: sma.StorageMarketConstructor,
2: sma.CreateStorageMiner,
3: sma.ArbitrateConsensusFault,
4: sma.UpdateStorage,
5: sma.GetTotalStorage,
6: sma.PowerLookup,
7: sma.IsMiner,
8: sma.PledgeCollateralForSize,
//1: spa.StoragePowerConstructor,
2: spa.CreateStorageMiner,
3: spa.ArbitrateConsensusFault,
4: spa.UpdateStorage,
5: spa.GetTotalStorage,
6: spa.PowerLookup,
7: spa.IsMiner,
8: spa.PledgeCollateralForSize,
}
}
type StorageMarketState struct {
type StoragePowerState struct {
Miners cid.Cid
MinerCount uint64
@ -58,12 +57,12 @@ type CreateStorageMinerParams struct {
PeerID peer.ID
}
func (sma StorageMarketActor) CreateStorageMiner(act *types.Actor, vmctx types.VMContext, params *CreateStorageMinerParams) ([]byte, ActorError) {
func (spa StoragePowerActor) CreateStorageMiner(act *types.Actor, vmctx types.VMContext, params *CreateStorageMinerParams) ([]byte, ActorError) {
if !SupportedSectorSize(params.SectorSize) {
return nil, aerrors.New(1, "Unsupported sector size")
}
var self StorageMarketState
var self StoragePowerState
old := vmctx.Storage().GetHead()
if err := vmctx.Storage().Get(old, &self); err != nil {
return nil, err
@ -129,7 +128,7 @@ type ArbitrateConsensusFaultParams struct {
Block2 *types.BlockHeader
}
func (sma StorageMarketActor) ArbitrateConsensusFault(act *types.Actor, vmctx types.VMContext, params *ArbitrateConsensusFaultParams) ([]byte, ActorError) {
func (spa StoragePowerActor) ArbitrateConsensusFault(act *types.Actor, vmctx types.VMContext, params *ArbitrateConsensusFaultParams) ([]byte, ActorError) {
if params.Block1.Miner != params.Block2.Miner {
return nil, aerrors.New(2, "blocks must be from the same miner")
}
@ -145,11 +144,11 @@ func (sma StorageMarketActor) ArbitrateConsensusFault(act *types.Actor, vmctx ty
return nil, aerrors.Absorb(oerr, 3, "response from 'GetWorkerAddr' was not a valid address")
}
if err := params.Block1.CheckBlockSignature(worker); err != nil {
if err := params.Block1.CheckBlockSignature(vmctx.Context(), worker); err != nil {
return nil, aerrors.Absorb(err, 4, "block1 did not have valid signature")
}
if err := params.Block2.CheckBlockSignature(worker); err != nil {
if err := params.Block2.CheckBlockSignature(vmctx.Context(), worker); err != nil {
return nil, aerrors.Absorb(err, 5, "block2 did not have valid signature")
}
@ -159,18 +158,18 @@ func (sma StorageMarketActor) ArbitrateConsensusFault(act *types.Actor, vmctx ty
return nil, aerrors.New(6, "blocks do not prove a slashable offense")
}
var self StorageMarketState
var self StoragePowerState
old := vmctx.Storage().GetHead()
if err := vmctx.Storage().Get(old, &self); err != nil {
return nil, err
}
if types.BigCmp(self.TotalStorage, types.NewInt(0)) == 0 {
return nil, aerrors.Fatal("invalid state, storage market actor has zero total storage")
return nil, aerrors.Fatal("invalid state, storage power actor has zero total storage")
}
miner := params.Block1.Miner
if has, err := MinerSetHas(context.TODO(), vmctx, self.Miners, miner); err != nil {
if has, err := MinerSetHas(vmctx, self.Miners, miner); err != nil {
return nil, aerrors.Wrapf(err, "failed to check miner in set")
} else if !has {
return nil, aerrors.New(7, "either already slashed or not a miner")
@ -270,14 +269,14 @@ type UpdateStorageParams struct {
Delta types.BigInt
}
func (sma StorageMarketActor) UpdateStorage(act *types.Actor, vmctx types.VMContext, params *UpdateStorageParams) ([]byte, ActorError) {
var self StorageMarketState
func (spa StoragePowerActor) UpdateStorage(act *types.Actor, vmctx types.VMContext, params *UpdateStorageParams) ([]byte, ActorError) {
var self StoragePowerState
old := vmctx.Storage().GetHead()
if err := vmctx.Storage().Get(old, &self); err != nil {
return nil, err
}
has, err := MinerSetHas(context.TODO(), vmctx, self.Miners, vmctx.Message().From)
has, err := MinerSetHas(vmctx, self.Miners, vmctx.Message().From)
if err != nil {
return nil, err
}
@ -300,8 +299,8 @@ func (sma StorageMarketActor) UpdateStorage(act *types.Actor, vmctx types.VMCont
return nil, nil
}
func (sma StorageMarketActor) GetTotalStorage(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) {
var self StorageMarketState
func (spa StoragePowerActor) GetTotalStorage(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) {
var self StoragePowerState
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
return nil, err
}
@ -313,8 +312,8 @@ type PowerLookupParams struct {
Miner address.Address
}
func (sma StorageMarketActor) PowerLookup(act *types.Actor, vmctx types.VMContext, params *PowerLookupParams) ([]byte, ActorError) {
var self StorageMarketState
func (spa StoragePowerActor) PowerLookup(act *types.Actor, vmctx types.VMContext, params *PowerLookupParams) ([]byte, ActorError) {
var self StoragePowerState
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
return nil, aerrors.Wrap(err, "getting head")
}
@ -327,14 +326,14 @@ func (sma StorageMarketActor) PowerLookup(act *types.Actor, vmctx types.VMContex
return pow.Bytes(), nil
}
func powerLookup(ctx context.Context, vmctx types.VMContext, self *StorageMarketState, miner address.Address) (types.BigInt, ActorError) {
has, err := MinerSetHas(context.TODO(), vmctx, self.Miners, miner)
func powerLookup(ctx context.Context, vmctx types.VMContext, self *StoragePowerState, miner address.Address) (types.BigInt, ActorError) {
has, err := MinerSetHas(vmctx, self.Miners, miner)
if err != nil {
return types.EmptyInt, err
}
if !has {
return types.EmptyInt, aerrors.New(1, "miner not registered with storage market")
return types.EmptyInt, aerrors.New(1, "miner not registered with storage power actor")
}
ret, err := vmctx.Send(miner, MAMethods.GetPower, types.NewInt(0), nil)
@ -349,13 +348,13 @@ type IsMinerParam struct {
Addr address.Address
}
func (sma StorageMarketActor) IsMiner(act *types.Actor, vmctx types.VMContext, param *IsMinerParam) ([]byte, ActorError) {
var self StorageMarketState
func (spa StoragePowerActor) IsMiner(act *types.Actor, vmctx types.VMContext, param *IsMinerParam) ([]byte, ActorError) {
var self StoragePowerState
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
return nil, err
}
has, err := MinerSetHas(context.TODO(), vmctx, self.Miners, param.Addr)
has, err := MinerSetHas(vmctx, self.Miners, param.Addr)
if err != nil {
return nil, err
}
@ -367,8 +366,8 @@ type PledgeCollateralParams struct {
Size types.BigInt
}
func (sma StorageMarketActor) PledgeCollateralForSize(act *types.Actor, vmctx types.VMContext, param *PledgeCollateralParams) ([]byte, ActorError) {
var self StorageMarketState
func (spa StoragePowerActor) PledgeCollateralForSize(act *types.Actor, vmctx types.VMContext, param *PledgeCollateralParams) ([]byte, ActorError) {
var self StoragePowerState
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
return nil, err
}
@ -433,20 +432,20 @@ func pledgeCollateralForSize(vmctx types.VMContext, size, totalStorage types.Big
return types.BigAdd(powerCollateral, perCapCollateral), nil
}
func MinerSetHas(ctx context.Context, vmctx types.VMContext, rcid cid.Cid, maddr address.Address) (bool, aerrors.ActorError) {
nd, err := hamt.LoadNode(ctx, vmctx.Ipld(), rcid)
func MinerSetHas(vmctx types.VMContext, rcid cid.Cid, maddr address.Address) (bool, aerrors.ActorError) {
nd, err := hamt.LoadNode(vmctx.Context(), vmctx.Ipld(), rcid)
if err != nil {
return false, aerrors.Escalate(err, "failed to load miner set")
return false, aerrors.HandleExternalError(err, "failed to load miner set")
}
err = nd.Find(ctx, string(maddr.Bytes()), nil)
err = nd.Find(vmctx.Context(), string(maddr.Bytes()), nil)
switch err {
case hamt.ErrNotFound:
return false, nil
case nil:
return true, nil
default:
return false, aerrors.Escalate(err, "failed to do set lookup")
return false, aerrors.HandleExternalError(err, "failed to do set lookup")
}
}
@ -475,30 +474,30 @@ func MinerSetList(ctx context.Context, cst *hamt.CborIpldStore, rcid cid.Cid) ([
func MinerSetAdd(ctx context.Context, vmctx types.VMContext, rcid cid.Cid, maddr address.Address) (cid.Cid, aerrors.ActorError) {
nd, err := hamt.LoadNode(ctx, vmctx.Ipld(), rcid)
if err != nil {
return cid.Undef, aerrors.Escalate(err, "failed to load miner set")
return cid.Undef, aerrors.HandleExternalError(err, "failed to load miner set")
}
mkey := string(maddr.Bytes())
err = nd.Find(ctx, mkey, nil)
if err == nil {
return cid.Undef, aerrors.Escalate(fmt.Errorf("miner already found"), "miner set add failed")
return cid.Undef, aerrors.New(20, "miner already in set")
}
if !xerrors.Is(err, hamt.ErrNotFound) {
return cid.Undef, aerrors.Escalate(err, "failed to do miner set check")
return cid.Undef, aerrors.HandleExternalError(err, "failed to do miner set check")
}
if err := nd.Set(ctx, mkey, uint64(1)); err != nil {
return cid.Undef, aerrors.Escalate(err, "adding miner address to set failed")
return cid.Undef, aerrors.HandleExternalError(err, "adding miner address to set failed")
}
if err := nd.Flush(ctx); err != nil {
return cid.Undef, aerrors.Escalate(err, "failed to flush miner set")
return cid.Undef, aerrors.HandleExternalError(err, "failed to flush miner set")
}
c, err := vmctx.Ipld().Put(ctx, nd)
if err != nil {
return cid.Undef, aerrors.Escalate(err, "failed to persist miner set to storage")
return cid.Undef, aerrors.HandleExternalError(err, "failed to persist miner set to storage")
}
return c, nil
@ -507,7 +506,7 @@ func MinerSetAdd(ctx context.Context, vmctx types.VMContext, rcid cid.Cid, maddr
func MinerSetRemove(ctx context.Context, vmctx types.VMContext, rcid cid.Cid, maddr address.Address) (cid.Cid, aerrors.ActorError) {
nd, err := hamt.LoadNode(ctx, vmctx.Ipld(), rcid)
if err != nil {
return cid.Undef, aerrors.Escalate(err, "failed to load miner set")
return cid.Undef, aerrors.HandleExternalError(err, "failed to load miner set")
}
mkey := string(maddr.Bytes())
@ -515,17 +514,17 @@ func MinerSetRemove(ctx context.Context, vmctx types.VMContext, rcid cid.Cid, ma
case hamt.ErrNotFound:
return cid.Undef, aerrors.New(1, "miner not found in set on delete")
default:
return cid.Undef, aerrors.Escalate(err, "failed to delete miner from set")
return cid.Undef, aerrors.HandleExternalError(err, "failed to delete miner from set")
case nil:
}
if err := nd.Flush(ctx); err != nil {
return cid.Undef, aerrors.Escalate(err, "failed to flush miner set")
return cid.Undef, aerrors.HandleExternalError(err, "failed to flush miner set")
}
c, err := vmctx.Ipld().Put(ctx, nd)
if err != nil {
return cid.Undef, aerrors.Escalate(err, "failed to persist miner set to storage")
return cid.Undef, aerrors.HandleExternalError(err, "failed to persist miner set to storage")
}
return c, nil

View File

@ -37,7 +37,7 @@ func TestStorageMarketCreateAndSlashMiner(t *testing.T) {
// cheating the bootstrapping problem
cheatStorageMarketTotal(t, h.vm, h.cs.Blockstore())
ret, _ := h.InvokeWithValue(t, ownerAddr, StorageMarketAddress, SMAMethods.CreateStorageMiner,
ret, _ := h.InvokeWithValue(t, ownerAddr, StorageMarketAddress, SPAMethods.CreateStorageMiner,
types.NewInt(500000),
&CreateStorageMinerParams{
Owner: ownerAddr,
@ -52,7 +52,7 @@ func TestStorageMarketCreateAndSlashMiner(t *testing.T) {
}
{
ret, _ := h.Invoke(t, ownerAddr, StorageMarketAddress, SMAMethods.IsMiner,
ret, _ := h.Invoke(t, ownerAddr, StorageMarketAddress, SPAMethods.IsMiner,
&IsMinerParam{Addr: minerAddr})
ApplyOK(t, ret)
@ -68,7 +68,7 @@ func TestStorageMarketCreateAndSlashMiner(t *testing.T) {
}
{
ret, _ := h.Invoke(t, ownerAddr, StorageMarketAddress, SMAMethods.PowerLookup,
ret, _ := h.Invoke(t, ownerAddr, StorageMarketAddress, SPAMethods.PowerLookup,
&PowerLookupParams{Miner: minerAddr})
ApplyOK(t, ret)
power := types.BigFromBytes(ret.Return)
@ -93,7 +93,7 @@ func TestStorageMarketCreateAndSlashMiner(t *testing.T) {
signBlock(t, h.w, workerAddr, b1)
signBlock(t, h.w, workerAddr, b2)
ret, _ := h.Invoke(t, ownerAddr, StorageMarketAddress, SMAMethods.ArbitrateConsensusFault,
ret, _ := h.Invoke(t, ownerAddr, StorageMarketAddress, SPAMethods.ArbitrateConsensusFault,
&ArbitrateConsensusFaultParams{
Block1: b1,
Block2: b2,
@ -102,13 +102,13 @@ func TestStorageMarketCreateAndSlashMiner(t *testing.T) {
}
{
ret, _ := h.Invoke(t, ownerAddr, StorageMarketAddress, SMAMethods.PowerLookup,
ret, _ := h.Invoke(t, ownerAddr, StorageMarketAddress, SPAMethods.PowerLookup,
&PowerLookupParams{Miner: minerAddr})
assert.Equal(t, ret.ExitCode, byte(1))
}
{
ret, _ := h.Invoke(t, ownerAddr, StorageMarketAddress, SMAMethods.IsMiner, &IsMinerParam{minerAddr})
ret, _ := h.Invoke(t, ownerAddr, StorageMarketAddress, SPAMethods.IsMiner, &IsMinerParam{minerAddr})
ApplyOK(t, ret)
assert.Equal(t, ret.Return, cbg.CborBoolFalse)
}
@ -124,7 +124,7 @@ func cheatStorageMarketTotal(t *testing.T, vm *vm.VM, bs bstore.Blockstore) {
cst := hamt.CSTFromBstore(bs)
var smastate StorageMarketState
var smastate StoragePowerState
if err := cst.Get(context.TODO(), sma.Head, &smastate); err != nil {
t.Fatal(err)
}

View File

@ -53,7 +53,7 @@ func setupVMTestEnv(t *testing.T) (*vm.VM, []address.Address, bstore.Blockstore)
cs := store.NewChainStore(bs, nil)
// TODO: should probabaly mock out the randomness bit, nil works for now
vm, err := vm.NewVM(stateroot, 1, nil, maddr, cs)
vm, err := vm.NewVM(stateroot, 1, nil, maddr, cs.Blockstore())
if err != nil {
t.Fatal(err)
}
@ -65,7 +65,7 @@ func TestVMInvokeMethod(t *testing.T) {
from := addrs[0]
var err error
cenc, err := SerializeParams(&StorageMinerConstructorParams{})
cenc, err := SerializeParams(&StorageMinerConstructorParams{Owner: from, Worker: from})
if err != nil {
t.Fatal(err)
}
@ -116,6 +116,7 @@ func TestStorageMarketActorCreateMiner(t *testing.T) {
cheatStorageMarketTotal(t, vm, bs)
params := &StorageMinerConstructorParams{
Owner: maddr,
Worker: maddr,
SectorSize: types.NewInt(build.SectorSize),
PeerID: "fakepeerid",
@ -129,7 +130,7 @@ func TestStorageMarketActorCreateMiner(t *testing.T) {
msg := &types.Message{
To: StorageMarketAddress,
From: from,
Method: SMAMethods.CreateStorageMiner,
Method: SPAMethods.CreateStorageMiner,
Params: enc,
GasPrice: types.NewInt(1),
GasLimit: types.NewInt(10000),

View File

@ -103,7 +103,7 @@ func Absorb(err error, retCode uint8, msg string) ActorError {
fatal: true,
retCode: 0,
msg: "tried absorbing an error that is alreay an fatal error",
msg: "tried absorbing an error that is already a fatal error",
frame: xerrors.Caller(1),
err: err,
}
@ -142,3 +142,28 @@ func Escalate(err error, msg string) ActorError {
err: err,
}
}
func HandleExternalError(err error, msg string) ActorError {
if err == nil {
return nil
}
if aerr, ok := err.(ActorError); ok {
return &actorError{
fatal: IsFatal(aerr),
retCode: RetCode(aerr),
msg: msg,
frame: xerrors.Caller(1),
err: aerr,
}
}
return &actorError{
fatal: true,
msg: msg,
frame: xerrors.Caller(1),
err: err,
}
}

View File

@ -2379,7 +2379,7 @@ func (t *PaymentInfo) UnmarshalCBOR(r io.Reader) error {
return nil
}
func (t *StorageMarketState) MarshalCBOR(w io.Writer) error {
func (t *StoragePowerState) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)
return err
@ -2406,7 +2406,7 @@ func (t *StorageMarketState) MarshalCBOR(w io.Writer) error {
return nil
}
func (t *StorageMarketState) UnmarshalCBOR(r io.Reader) error {
func (t *StoragePowerState) UnmarshalCBOR(r io.Reader) error {
br := cbg.GetPeeker(r)
maj, extra, err := cbg.CborReadHeader(br)

View File

@ -158,7 +158,7 @@ func NewHarness(t *testing.T, options ...HarnessOpt) *Harness {
t.Fatal(err)
}
h.cs = store.NewChainStore(h.bs, nil)
h.vm, err = vm.NewVM(stateroot, 1, nil, h.HI.Miner, h.cs)
h.vm, err = vm.NewVM(stateroot, 1, nil, h.HI.Miner, h.cs.Blockstore())
if err != nil {
t.Fatal(err)
}

View File

@ -325,6 +325,10 @@ func hash(ingest []byte, cfg *blake2b.Config) []byte {
}
func (a Address) MarshalCBOR(w io.Writer) error {
if a == Undef {
return fmt.Errorf("cannot marshal undefined address")
}
abytes := a.Bytes()
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(abytes)))); err != nil {
return err
@ -360,6 +364,9 @@ func (a *Address) UnmarshalCBOR(br io.Reader) error {
if err != nil {
return err
}
if addr == Undef {
return fmt.Errorf("cbor input should not contain empty addresses")
}
*a = addr

View File

@ -121,13 +121,13 @@ func (e *heightEvents) headChangeAt(rev, app []*types.TipSet) error {
//
// ts passed to handlers is the tipset at the specified, or above, if lower tipsets were null
func (e *heightEvents) ChainAt(hnd HeightHandler, rev RevertHandler, confidence int, h uint64) error {
e.lk.Lock()
defer e.lk.Unlock()
e.lk.Lock() // Tricky locking, check your locks if you modify this function!
bestH := e.tsc.best().Height()
if bestH >= h+uint64(confidence) {
ts, err := e.tsc.get(h)
ts, err := e.tsc.getNonNull(h)
if err != nil {
log.Warnf("events.ChainAt: calling HandleFunc with nil tipset, not found in cache: %s", err)
}
@ -140,6 +140,8 @@ func (e *heightEvents) ChainAt(hnd HeightHandler, rev RevertHandler, confidence
bestH = e.tsc.best().Height()
}
defer e.lk.Unlock()
if bestH >= h+uint64(confidence)+e.gcConfidence {
return nil
}

View File

@ -45,9 +45,11 @@ func (fcs *fakeCS) ChainGetTipSetByHeight(context.Context, uint64, *types.TipSet
}
func makeTs(t *testing.T, h uint64, msgcid cid.Cid) *types.TipSet {
a, _ := address.NewFromString("t00")
ts, err := types.NewTipSet([]*types.BlockHeader{
{
Height: h,
Miner: a,
ParentStateRoot: dummyCid,
Messages: msgcid,
@ -432,6 +434,35 @@ func TestAtChainedConfidence(t *testing.T) {
require.Equal(t, false, reverted)
}
func TestAtChainedConfidenceNull(t *testing.T) {
fcs := &fakeCS{
t: t,
h: 1,
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
}
require.NoError(t, fcs.tsc.add(makeTs(t, 1, dummyCid)))
events := NewEvents(context.Background(), fcs)
fcs.advance(0, 15, nil, 5)
var applied bool
var reverted bool
err := events.ChainAt(func(ts *types.TipSet, curH uint64) error {
applied = true
require.Equal(t, 6, int(ts.Height()))
return nil
}, func(ts *types.TipSet) error {
reverted = true
return nil
}, 3, 5)
require.NoError(t, err)
require.Equal(t, true, applied)
require.Equal(t, false, reverted)
}
func TestCalled(t *testing.T) {
fcs := &fakeCS{
t: t,
@ -479,7 +510,7 @@ func TestCalled(t *testing.T) {
fcs.advance(0, 3, map[int]cid.Cid{ // msg at H=6; H=8 (confidence=2)
0: fcs.fakeMsgs(fakeMsg{
bmsgs: []*types.Message{
{To: t0123, Method: 5, Nonce: 1},
{To: t0123, From: t0123, Method: 5, Nonce: 1},
},
}),
})
@ -520,7 +551,7 @@ func TestCalled(t *testing.T) {
n2msg := fcs.fakeMsgs(fakeMsg{
bmsgs: []*types.Message{
{To: t0123, Method: 5, Nonce: 2},
{To: t0123, From: t0123, Method: 5, Nonce: 2},
},
})
@ -574,7 +605,7 @@ func TestCalled(t *testing.T) {
fcs.advance(0, 1, map[int]cid.Cid{ // msg at H=16; H=16
0: fcs.fakeMsgs(fakeMsg{
bmsgs: []*types.Message{
{To: t0123, Method: 5, Nonce: 3},
{To: t0123, From: t0123, Method: 5, Nonce: 3},
},
}),
})
@ -597,7 +628,7 @@ func TestCalled(t *testing.T) {
fcs.advance(0, 4, map[int]cid.Cid{ // msg at H=26; H=29
0: fcs.fakeMsgs(fakeMsg{
bmsgs: []*types.Message{
{To: t0123, Method: 5, Nonce: 4}, // this signals we don't want more
{To: t0123, From: t0123, Method: 5, Nonce: 4}, // this signals we don't want more
},
}),
})
@ -609,7 +640,7 @@ func TestCalled(t *testing.T) {
fcs.advance(0, 4, map[int]cid.Cid{ // msg at H=26; H=29
0: fcs.fakeMsgs(fakeMsg{
bmsgs: []*types.Message{
{To: t0123, Method: 5, Nonce: 5},
{To: t0123, From: t0123, Method: 5, Nonce: 5},
},
}),
})
@ -754,12 +785,12 @@ func TestCalledOrder(t *testing.T) {
fcs.advance(0, 10, map[int]cid.Cid{
1: fcs.fakeMsgs(fakeMsg{
bmsgs: []*types.Message{
{To: t0123, Method: 5, Nonce: 1},
{To: t0123, From: t0123, Method: 5, Nonce: 1},
},
}),
2: fcs.fakeMsgs(fakeMsg{
bmsgs: []*types.Message{
{To: t0123, Method: 5, Nonce: 2},
{To: t0123, From: t0123, Method: 5, Nonce: 2},
},
}),
})

View File

@ -2,9 +2,11 @@ package events
import (
"context"
"github.com/stretchr/testify/require"
"testing"
"github.com/stretchr/testify/require"
"github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/types"
)
@ -16,8 +18,11 @@ func TestTsCache(t *testing.T) {
h := uint64(75)
a, _ := address.NewFromString("t00")
add := func() {
ts, err := types.NewTipSet([]*types.BlockHeader{{
Miner: a,
Height: h,
ParentStateRoot: dummyCid,
Messages: dummyCid,
@ -54,8 +59,10 @@ func TestTsCacheNulls(t *testing.T) {
h := uint64(75)
a, _ := address.NewFromString("t00")
add := func() {
ts, err := types.NewTipSet([]*types.BlockHeader{{
Miner: a,
Height: h,
ParentStateRoot: dummyCid,
Messages: dummyCid,

View File

@ -413,7 +413,7 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, ticks []*types.Ticket,
return false, nil, xerrors.Errorf("failed to check power: %w", err)
}
return types.PowerCmp(vrfout, pow.MinerPower, pow.TotalPower), vrfout, nil
return types.PowerCmp(vrfout, types.BigMul(pow.MinerPower, types.NewInt(build.BlocksPerEpoch)), pow.TotalPower), vrfout, nil
}
type SignFunc func(context.Context, address.Address, []byte) (*types.Signature, error)

View File

@ -96,8 +96,11 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wal
}
next.BLSAggregate = aggSig
pweight := sm.ChainStore().Weight(parents)
next.ParentWeight = types.NewInt(pweight)
pweight, err := sm.ChainStore().Weight(ctx, parents)
if err != nil {
return nil, err
}
next.ParentWeight = pweight
cst := hamt.CSTFromBstore(sm.ChainStore().Blockstore())
tree, err := state.LoadStateTree(cst, st)

View File

@ -143,7 +143,7 @@ func SetupStorageMarketActor(bs bstore.Blockstore) (*types.Actor, error) {
return nil, err
}
sms := &actors.StorageMarketState{
sms := &actors.StoragePowerState{
Miners: emptyhamt,
TotalStorage: types.NewInt(0),
}
@ -183,7 +183,7 @@ func mustEnc(i cbg.CBORMarshaler) []byte {
}
func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid, gmcfg *GenMinerCfg) (cid.Cid, error) {
vm, err := vm.NewVM(sroot, 0, nil, actors.NetworkAddress, cs)
vm, err := vm.NewVM(sroot, 0, nil, actors.NetworkAddress, cs.Blockstore())
if err != nil {
return cid.Undef, xerrors.Errorf("failed to create NewVM: %w", err)
}
@ -202,7 +202,7 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
// TODO: hardcoding 7000000 here is a little fragile, it changes any
// time anyone changes the initial account allocations
rval, err := doExecValue(ctx, vm, actors.StorageMarketAddress, owner, types.FromFil(6500), actors.SMAMethods.CreateStorageMiner, params)
rval, err := doExecValue(ctx, vm, actors.StorageMarketAddress, owner, types.FromFil(6500), actors.SPAMethods.CreateStorageMiner, params)
if err != nil {
return cid.Undef, xerrors.Errorf("failed to create genesis miner: %w", err)
}
@ -216,7 +216,7 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
params = mustEnc(&actors.UpdateStorageParams{Delta: types.NewInt(5000)})
_, err = doExec(ctx, vm, actors.StorageMarketAddress, maddr, actors.SMAMethods.UpdateStorage, params)
_, err = doExec(ctx, vm, actors.StorageMarketAddress, maddr, actors.SPAMethods.UpdateStorage, params)
if err != nil {
return cid.Undef, xerrors.Errorf("failed to update total storage: %w", err)
}

View File

@ -61,7 +61,6 @@ func (ms *msgSet) add(m *types.SignedMessage) error {
log.Error("Add with duplicate nonce")
return xerrors.Errorf("message to %s with nonce %d already in mpool")
}
log.Warn("Add called with the same message multiple times")
}
ms.msgs[m.Message.Nonce] = m

View File

@ -89,11 +89,16 @@ func sendHeadNotifs(ctx context.Context, ps *pubsub.PubSub, topic string, chain
case notif := <-notifs:
n := notif[len(notif)-1]
w, err := chain.ChainTipSetWeight(ctx, n.Val)
if err != nil {
return err
}
m := message{
Cids: n.Val.Cids(),
Blocks: n.Val.Blocks(),
Height: n.Val.Height(),
Weight: n.Val.Weight(),
Weight: w,
NodeName: nickname,
}

View File

@ -4,16 +4,17 @@ import (
"context"
"fmt"
"github.com/filecoin-project/go-lotus/chain/actors"
"github.com/filecoin-project/go-lotus/chain/types"
"github.com/filecoin-project/go-lotus/chain/vm"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-lotus/chain/actors"
"github.com/filecoin-project/go-lotus/chain/store"
"github.com/filecoin-project/go-lotus/chain/types"
"github.com/filecoin-project/go-lotus/chain/vm"
)
func (sm *StateManager) CallRaw(ctx context.Context, msg *types.Message, bstate cid.Cid, r vm.Rand, bheight uint64) (*types.MessageReceipt, error) {
vmi, err := vm.NewVM(bstate, bheight, r, actors.NetworkAddress, sm.cs)
vmi, err := vm.NewVM(bstate, bheight, r, actors.NetworkAddress, sm.cs.Blockstore())
if err != nil {
return nil, xerrors.Errorf("failed to set up vm: %w", err)
}
@ -55,7 +56,7 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types.
state := ts.ParentState()
r := vm.NewChainRand(sm.cs, ts.Cids(), ts.Height(), nil)
r := store.NewChainRand(sm.cs, ts.Cids(), ts.Height(), nil)
return sm.CallRaw(ctx, msg, state, r, ts.Height())
}

View File

@ -89,9 +89,9 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
cids[i] = v.Cid()
}
r := vm.NewChainRand(sm.cs, cids, blks[0].Height, nil)
r := store.NewChainRand(sm.cs, cids, blks[0].Height, nil)
vmi, err := vm.NewVM(pstate, blks[0].Height, r, address.Undef, sm.cs)
vmi, err := vm.NewVM(pstate, blks[0].Height, r, address.Undef, sm.cs.Blockstore())
if err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("instantiating VM failed: %w", err)
}

View File

@ -2,7 +2,6 @@ package stmgr
import (
"context"
"github.com/filecoin-project/go-lotus/api"
"github.com/filecoin-project/go-lotus/chain/actors"
"github.com/filecoin-project/go-lotus/chain/address"
@ -71,18 +70,18 @@ func GetMinerOwner(ctx context.Context, sm *StateManager, st cid.Cid, maddr addr
func GetPower(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (types.BigInt, types.BigInt, error) {
var err error
enc, err := actors.SerializeParams(&actors.PowerLookupParams{maddr})
if err != nil {
return types.EmptyInt, types.EmptyInt, err
}
var mpow types.BigInt
if maddr != address.Undef {
enc, aerr := actors.SerializeParams(&actors.PowerLookupParams{maddr})
if aerr != nil {
return types.EmptyInt, types.EmptyInt, aerr
}
ret, err := sm.Call(ctx, &types.Message{
From: maddr,
To: actors.StorageMarketAddress,
Method: actors.SMAMethods.PowerLookup,
Method: actors.SPAMethods.PowerLookup,
Params: enc,
}, ts)
if err != nil {
@ -98,7 +97,7 @@ func GetPower(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr add
ret, err := sm.Call(ctx, &types.Message{
From: actors.StorageMarketAddress,
To: actors.StorageMarketAddress,
Method: actors.SMAMethods.GetTotalStorage,
Method: actors.SPAMethods.GetTotalStorage,
}, ts)
if err != nil {
return types.EmptyInt, types.EmptyInt, xerrors.Errorf("failed to get total power from chain: %w", err)

View File

@ -7,9 +7,12 @@ import (
"fmt"
"sync"
"github.com/filecoin-project/go-lotus/chain/vm"
"github.com/filecoin-project/go-lotus/build"
"github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/state"
"go.opencensus.io/trace"
"go.uber.org/zap"
amt "github.com/filecoin-project/go-amt-ipld"
@ -182,14 +185,14 @@ func (cs *ChainStore) SetGenesis(b *types.BlockHeader) error {
return err
}
if err := cs.PutTipSet(ts); err != nil {
if err := cs.PutTipSet(context.TODO(), ts); err != nil {
return err
}
return cs.ds.Put(dstore.NewKey("0"), b.Cid().Bytes())
}
func (cs *ChainStore) PutTipSet(ts *types.TipSet) error {
func (cs *ChainStore) PutTipSet(ctx context.Context, ts *types.TipSet) error {
for _, b := range ts.Blocks() {
if err := cs.PersistBlockHeader(b); err != nil {
return err
@ -202,16 +205,25 @@ func (cs *ChainStore) PutTipSet(ts *types.TipSet) error {
}
log.Debugf("expanded %s into %s\n", ts.Cids(), expanded.Cids())
if err := cs.MaybeTakeHeavierTipSet(expanded); err != nil {
if err := cs.MaybeTakeHeavierTipSet(ctx, expanded); err != nil {
return errors.Wrap(err, "MaybeTakeHeavierTipSet failed in PutTipSet")
}
return nil
}
func (cs *ChainStore) MaybeTakeHeavierTipSet(ts *types.TipSet) error {
func (cs *ChainStore) MaybeTakeHeavierTipSet(ctx context.Context, ts *types.TipSet) error {
cs.heaviestLk.Lock()
defer cs.heaviestLk.Unlock()
if cs.heaviest == nil || cs.Weight(ts) > cs.Weight(cs.heaviest) {
w, err := cs.Weight(ctx, ts)
if err != nil {
return err
}
heaviestW, err := cs.Weight(ctx, cs.heaviest)
if err != nil {
return err
}
if w.GreaterThan(heaviestW) {
// TODO: don't do this for initial sync. Now that we don't have a
// difference between 'bootstrap sync' and 'caught up' sync, we need
// some other heuristic.
@ -261,7 +273,7 @@ func (cs *ChainStore) takeHeaviestTipSet(ts *types.TipSet) error {
new: ts,
}
} else {
log.Warn("no heaviest tipset found, using %s", ts.Cids())
log.Warnf("no heaviest tipset found, using %s", ts.Cids())
}
log.Debugf("New heaviest tipset! %s", ts.Cids())
@ -377,10 +389,6 @@ func (cs *ChainStore) ReorgOps(a, b *types.TipSet) ([]*types.TipSet, []*types.Ti
return leftChain, rightChain, nil
}
func (cs *ChainStore) Weight(ts *types.TipSet) uint64 {
return ts.Blocks()[0].ParentWeight.Uint64() + uint64(len(ts.Cids()))
}
func (cs *ChainStore) GetHeaviestTipSet() *types.TipSet {
cs.heaviestLk.Lock()
defer cs.heaviestLk.Unlock()
@ -469,7 +477,7 @@ func (cs *ChainStore) expandTipset(b *types.BlockHeader) (*types.TipSet, error)
return types.NewTipSet(all)
}
func (cs *ChainStore) AddBlock(b *types.BlockHeader) error {
func (cs *ChainStore) AddBlock(ctx context.Context, b *types.BlockHeader) error {
if err := cs.PersistBlockHeader(b); err != nil {
return err
}
@ -479,7 +487,7 @@ func (cs *ChainStore) AddBlock(b *types.BlockHeader) error {
return err
}
if err := cs.MaybeTakeHeavierTipSet(ts); err != nil {
if err := cs.MaybeTakeHeavierTipSet(ctx, ts); err != nil {
return errors.Wrap(err, "MaybeTakeHeavierTipSet failed")
}
@ -720,6 +728,9 @@ func (cs *ChainStore) TryFillTipSet(ts *types.TipSet) (*FullTipSet, error) {
}
func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, tickets []*types.Ticket, lb int64) ([]byte, error) {
ctx, span := trace.StartSpan(ctx, "store.GetRandomness")
defer span.End()
if lb < 0 {
return nil, fmt.Errorf("negative lookback parameters are not valid (got %d)", lb)
}
@ -793,3 +804,24 @@ func (cs *ChainStore) GetTipsetByHeight(ctx context.Context, h uint64, ts *types
ts = pts
}
}
type chainRand struct {
cs *ChainStore
blks []cid.Cid
bh uint64
tickets []*types.Ticket
}
func NewChainRand(cs *ChainStore, blks []cid.Cid, bheight uint64, tickets []*types.Ticket) vm.Rand {
return &chainRand{
cs: cs,
blks: blks,
bh: bheight,
tickets: tickets,
}
}
func (cr *chainRand) GetRandomness(ctx context.Context, h int64) ([]byte, error) {
lb := (int64(cr.bh) + int64(len(cr.tickets))) - h
return cr.cs.GetRandomness(ctx, cr.blks, cr.tickets, lb)
}

94
chain/store/weight.go Normal file
View File

@ -0,0 +1,94 @@
package store
import (
"context"
"github.com/filecoin-project/go-lotus/build"
"github.com/filecoin-project/go-lotus/chain/actors"
"github.com/filecoin-project/go-lotus/chain/types"
"github.com/filecoin-project/go-lotus/chain/vm"
"golang.org/x/xerrors"
"math/big"
)
var zero = types.NewInt(0)
func (cs *ChainStore) Weight(ctx context.Context, ts *types.TipSet) (types.BigInt, error) {
if ts == nil {
return types.NewInt(0), nil
}
// >>> w[r] <<< + wFunction(totalPowerAtTipset(ts)) * 2^8 + (wFunction(totalPowerAtTipset(ts)) * len(ts.blocks) * wRatio_num * 2^8) / (e * wRatio_den)
var out = new(big.Int).Set(ts.Blocks()[0].ParentWeight.Int)
// >>> wFunction(totalPowerAtTipset(ts)) * 2^8 <<< + (wFunction(totalPowerAtTipset(ts)) * len(ts.blocks) * wRatio_num * 2^8) / (e * wRatio_den)
ret, err := cs.call(ctx, &types.Message{
From: actors.StorageMarketAddress,
To: actors.StorageMarketAddress,
Method: actors.SPAMethods.GetTotalStorage,
}, ts)
if err != nil {
return types.EmptyInt, xerrors.Errorf("failed to get total power from chain: %w", err)
}
if ret.ExitCode != 0 {
return types.EmptyInt, xerrors.Errorf("failed to get total power from chain (exit code %d)", ret.ExitCode)
}
log2P := int64(0)
tpow := types.BigFromBytes(ret.Return)
if tpow.GreaterThan(zero) {
log2P = int64(tpow.BitLen() - 1)
}
out.Add(out, big.NewInt(log2P*256))
// (wFunction(totalPowerAtTipset(ts)) * len(ts.blocks) * wRatio_num * 2^8) / (e * wRatio_den)
wRatioNum := int64(1)
wRatioDen := 2
eWeight := big.NewInt((log2P * int64(len(ts.Blocks())) * wRatioNum) << 8)
eWeight.Div(eWeight, big.NewInt(int64(build.BlocksPerEpoch*wRatioDen)))
out.Add(out, eWeight)
return types.BigInt{Int: out}, nil
}
// todo: dedupe with state manager
func (cs *ChainStore) call(ctx context.Context, msg *types.Message, ts *types.TipSet) (*types.MessageReceipt, error) {
bstate := ts.ParentState()
r := NewChainRand(cs, ts.Cids(), ts.Height(), nil)
vmi, err := vm.NewVM(bstate, ts.Height(), r, actors.NetworkAddress, cs.bs)
if err != nil {
return nil, xerrors.Errorf("failed to set up vm: %w", err)
}
if msg.GasLimit == types.EmptyInt {
msg.GasLimit = types.NewInt(10000000000)
}
if msg.GasPrice == types.EmptyInt {
msg.GasPrice = types.NewInt(0)
}
if msg.Value == types.EmptyInt {
msg.Value = types.NewInt(0)
}
fromActor, err := vmi.StateTree().GetActor(msg.From)
if err != nil {
return nil, xerrors.Errorf("call raw get actor: %s", err)
}
msg.Nonce = fromActor.Nonce
// TODO: maybe just use the invoker directly?
ret, err := vmi.ApplyMessage(ctx, msg)
if err != nil {
return nil, xerrors.Errorf("apply message failed: %w", err)
}
if ret.ActorErr != nil {
log.Warnf("chain call failed: %s", ret.ActorErr)
}
return &ret.MessageReceipt, nil
}

View File

@ -94,7 +94,7 @@ func (syncer *Syncer) InformNewHead(from peer.ID, fts *store.FullTipSet) {
}
for _, b := range fts.Blocks {
if err := syncer.validateMsgMeta(b); err != nil {
if err := syncer.ValidateMsgMeta(b); err != nil {
log.Warnf("invalid block received: %s", err)
return
}
@ -122,7 +122,7 @@ func (syncer *Syncer) InformNewHead(from peer.ID, fts *store.FullTipSet) {
}()
}
func (syncer *Syncer) validateMsgMeta(fblk *types.FullBlock) error {
func (syncer *Syncer) ValidateMsgMeta(fblk *types.FullBlock) error {
var bcids, scids []cbg.CBORMarshaler
for _, m := range fblk.BlsMessages {
c := cbg.CborCid(m.Cid())
@ -147,6 +147,14 @@ func (syncer *Syncer) validateMsgMeta(fblk *types.FullBlock) error {
return nil
}
func (syncer *Syncer) LocalPeer() peer.ID {
return syncer.self
}
func (syncer *Syncer) ChainStore() *store.ChainStore {
return syncer.store
}
func (syncer *Syncer) InformNewBlock(from peer.ID, blk *types.FullBlock) {
// TODO: search for other blocks that could form a tipset with this block
// and then send that tipset to InformNewHead
@ -253,7 +261,7 @@ func computeMsgMeta(bs amt.Blocks, bmsgCids, smsgCids []cbg.CBORMarshaler) (cid.
return mrcid, nil
}
func (syncer *Syncer) selectHead(heads map[peer.ID]*types.TipSet) (*types.TipSet, error) {
func (syncer *Syncer) selectHead(ctx context.Context, heads map[peer.ID]*types.TipSet) (*types.TipSet, error) {
var headsArr []*types.TipSet
for _, ts := range heads {
headsArr = append(headsArr, ts)
@ -290,7 +298,16 @@ func (syncer *Syncer) selectHead(heads map[peer.ID]*types.TipSet) (*types.TipSet
return nil, fmt.Errorf("Conflict exists in heads set")
}
if syncer.store.Weight(cur) > syncer.store.Weight(sel) {
curw, err := syncer.store.Weight(ctx, cur)
if err != nil {
return nil, err
}
selw, err := syncer.store.Weight(ctx, sel)
if err != nil {
return nil, err
}
if curw.GreaterThan(selw) {
sel = cur
}
}
@ -344,7 +361,7 @@ func (syncer *Syncer) Sync(ctx context.Context, maybeHead *types.TipSet) error {
return xerrors.Errorf("collectChain failed: %w", err)
}
if err := syncer.store.PutTipSet(maybeHead); err != nil {
if err := syncer.store.PutTipSet(ctx, maybeHead); err != nil {
return xerrors.Errorf("failed to put synced tipset to chainstore: %w", err)
}
@ -383,7 +400,7 @@ func (syncer *Syncer) minerIsValid(ctx context.Context, maddr address.Address, b
ret, err := syncer.sm.Call(ctx, &types.Message{
To: actors.StorageMarketAddress,
From: maddr,
Method: actors.SMAMethods.IsMiner,
Method: actors.SPAMethods.IsMiner,
Params: enc,
}, baseTs)
if err != nil {
@ -467,7 +484,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
return xerrors.Errorf("GetMinerWorker failed: %w", err)
}
if err := h.CheckBlockSignature(waddr); err != nil {
if err := h.CheckBlockSignature(ctx, waddr); err != nil {
return xerrors.Errorf("check block signature failed: %w", err)
}
@ -564,7 +581,7 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock
pubks = append(pubks, pubk)
}
if err := syncer.verifyBlsAggregate(b.Header.BLSAggregate, sigCids, pubks); err != nil {
if err := syncer.verifyBlsAggregate(ctx, b.Header.BLSAggregate, sigCids, pubks); err != nil {
return xerrors.Errorf("bls aggregate signature was invalid: %w", err)
}
@ -612,7 +629,13 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock
return nil
}
func (syncer *Syncer) verifyBlsAggregate(sig types.Signature, msgs []cid.Cid, pubks []bls.PublicKey) error {
func (syncer *Syncer) verifyBlsAggregate(ctx context.Context, sig types.Signature, msgs []cid.Cid, pubks []bls.PublicKey) error {
ctx, span := trace.StartSpan(ctx, "syncer.verifyBlsAggregate")
defer span.End()
span.AddAttributes(
trace.Int64Attribute("msgCount", int64(len(msgs))),
)
var digests []bls.Digest
for _, c := range msgs {
digests = append(digests, bls.Hash(bls.Message(c.Bytes())))

View File

@ -32,9 +32,6 @@ func (tu *syncTestUtil) repoWithChain(t testing.TB, h int) (repo.Repo, []byte, [
require.NoError(t, err)
blks[i] = mts.TipSet
ts := mts.TipSet.TipSet()
fmt.Printf("tipset at H:%d: %s\n", ts.Height(), ts.Cids())
}
r, err := tu.g.YieldRepo()
@ -94,8 +91,38 @@ func (tu *syncTestUtil) Shutdown() {
tu.cancel()
}
func (tu *syncTestUtil) printHeads() {
for i, n := range tu.nds {
head, err := n.ChainHead(tu.ctx)
if err != nil {
tu.t.Fatal(err)
}
fmt.Printf("Node %d: %s\n", i, head.Cids())
}
}
func (tu *syncTestUtil) pushFtsAndWait(to int, fts *store.FullTipSet, wait bool) {
// TODO: would be great if we could pass a whole tipset here...
tu.pushTsExpectErr(to, fts, false)
if wait {
start := time.Now()
h, err := tu.nds[to].ChainHead(tu.ctx)
require.NoError(tu.t, err)
for !h.Equals(fts.TipSet()) {
time.Sleep(time.Millisecond * 50)
h, err = tu.nds[to].ChainHead(tu.ctx)
require.NoError(tu.t, err)
if time.Since(start) > time.Second*10 {
tu.t.Fatal("took too long waiting for block to be accepted")
}
}
}
}
func (tu *syncTestUtil) pushTsExpectErr(to int, fts *store.FullTipSet, experr bool) {
for _, fb := range fts.Blocks {
var b types.BlockMsg
@ -115,27 +142,17 @@ func (tu *syncTestUtil) pushFtsAndWait(to int, fts *store.FullTipSet, wait bool)
b.BlsMessages = append(b.BlsMessages, c)
}
require.NoError(tu.t, tu.nds[to].ChainSubmitBlock(tu.ctx, &b))
}
if wait {
start := time.Now()
h, err := tu.nds[to].ChainHead(tu.ctx)
err := tu.nds[to].SyncSubmitBlock(tu.ctx, &b)
if experr {
require.Error(tu.t, err, "expected submit block to fail")
} else {
require.NoError(tu.t, err)
for !h.Equals(fts.TipSet()) {
time.Sleep(time.Millisecond * 50)
h, err = tu.nds[to].ChainHead(tu.ctx)
require.NoError(tu.t, err)
if time.Since(start) > time.Second*10 {
tu.t.Fatal("took too long waiting for block to be accepted")
}
}
}
}
func (tu *syncTestUtil) mineOnBlock(blk *store.FullTipSet, src int, miners []int, wait bool) *store.FullTipSet {
}
func (tu *syncTestUtil) mineOnBlock(blk *store.FullTipSet, src int, miners []int, wait, fail bool) *store.FullTipSet {
if miners == nil {
for i := range tu.g.Miners {
miners = append(miners, i)
@ -152,13 +169,17 @@ func (tu *syncTestUtil) mineOnBlock(blk *store.FullTipSet, src int, miners []int
mts, err := tu.g.NextTipSetFromMiners(blk.TipSet(), maddrs)
require.NoError(tu.t, err)
if fail {
tu.pushTsExpectErr(src, mts.TipSet, true)
} else {
tu.pushFtsAndWait(src, mts.TipSet, wait)
}
return mts.TipSet
}
func (tu *syncTestUtil) mineNewBlock(src int, miners []int) {
mts := tu.mineOnBlock(tu.g.CurTipset, src, miners, true)
mts := tu.mineOnBlock(tu.g.CurTipset, src, miners, true, false)
tu.g.CurTipset = mts
}
@ -197,7 +218,9 @@ func (tu *syncTestUtil) addSourceNode(gen int) {
lastTs := blocks[len(blocks)-1].Blocks
for _, lastB := range lastTs {
err = out.(*impl.FullNodeAPI).ChainAPI.Chain.AddBlock(lastB.Header)
cs := out.(*impl.FullNodeAPI).ChainAPI.Chain
require.NoError(tu.t, cs.AddToTipSetTracker(lastB.Header))
err = cs.AddBlock(tu.ctx, lastB.Header)
require.NoError(tu.t, err)
}
@ -368,12 +391,17 @@ func TestSyncBadTimestamp(t *testing.T) {
return pts.MinTimestamp() + 2
}
a1 := tu.mineOnBlock(base, 0, nil, false)
fmt.Println("BASE: ", base.Cids())
tu.printHeads()
a1 := tu.mineOnBlock(base, 0, nil, false, true)
tu.g.Timestamper = nil
tu.g.ResyncBankerNonce(a1.TipSet())
a2 := tu.mineOnBlock(base, 0, nil, true)
fmt.Println("After mine bad block!")
tu.printHeads()
a2 := tu.mineOnBlock(base, 0, nil, true, false)
tu.waitUntilSync(0, client)
@ -427,16 +455,16 @@ func TestSyncFork(t *testing.T) {
fmt.Println("Mining base: ", base.TipSet().Cids(), base.TipSet().Height())
// The two nodes fork at this point into 'a' and 'b'
a1 := tu.mineOnBlock(base, p1, []int{0}, true)
a := tu.mineOnBlock(a1, p1, []int{0}, true)
a = tu.mineOnBlock(a, p1, []int{0}, true)
a1 := tu.mineOnBlock(base, p1, []int{0}, true, false)
a := tu.mineOnBlock(a1, p1, []int{0}, true, false)
a = tu.mineOnBlock(a, p1, []int{0}, true, false)
tu.g.ResyncBankerNonce(a1.TipSet())
// chain B will now be heaviest
b := tu.mineOnBlock(base, p2, []int{1}, true)
b = tu.mineOnBlock(b, p2, []int{1}, true)
b = tu.mineOnBlock(b, p2, []int{1}, true)
b = tu.mineOnBlock(b, p2, []int{1}, true)
b := tu.mineOnBlock(base, p2, []int{1}, true, false)
b = tu.mineOnBlock(b, p2, []int{1}, true, false)
b = tu.mineOnBlock(b, p2, []int{1}, true, false)
b = tu.mineOnBlock(b, p2, []int{1}, true, false)
fmt.Println("A: ", a.Cids(), a.TipSet().Height())
fmt.Println("B: ", b.Cids(), b.TipSet().Height())

View File

@ -133,6 +133,10 @@ func (bi *BigInt) cborBytes() []byte {
}
func fromCborBytes(buf []byte) (BigInt, error) {
if len(buf) == 0 {
return NewInt(0), nil
}
var negative bool
switch buf[0] {
case 0:

View File

@ -7,7 +7,7 @@ import (
func TestBigIntSerializationRoundTrip(t *testing.T) {
testValues := []string{
"0", "1", "10", "9999", "12345678901234567891234567890123456789012345678901234567890",
"0", "1", "10", "-10", "9999", "12345678901234567891234567890123456789012345678901234567890",
}
for _, v := range testValues {
@ -29,5 +29,6 @@ func TestBigIntSerializationRoundTrip(t *testing.T) {
if BigCmp(out, bi) != 0 {
t.Fatal("failed to round trip BigInt through cbor")
}
}
}

View File

@ -2,12 +2,14 @@ package types
import (
"bytes"
"context"
"crypto/sha256"
"math/big"
block "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
"github.com/multiformats/go-multihash"
"go.opencensus.io/trace"
xerrors "golang.org/x/xerrors"
"github.com/filecoin-project/go-lotus/chain/address"
@ -98,7 +100,10 @@ func (blk *BlockHeader) SigningBytes() ([]byte, error) {
return blkcopy.Serialize()
}
func (blk *BlockHeader) CheckBlockSignature(worker address.Address) error {
func (blk *BlockHeader) CheckBlockSignature(ctx context.Context, worker address.Address) error {
ctx, span := trace.StartSpan(ctx, "checkBlockSignature")
defer span.End()
sigb, err := blk.SigningBytes()
if err != nil {
return xerrors.Errorf("failed to get block signing bytes: %w", err)

View File

@ -75,6 +75,8 @@ func NewTipSet(blks []*BlockHeader) (*TipSet, error) {
return nil, fmt.Errorf("cannot create tipset with mismatching heights")
}
ts.cids = append(ts.cids, b.Cid())
// TODO: ensure the same parents
}
ts.height = blks[0].Height
@ -89,12 +91,6 @@ func (ts *TipSet) Height() uint64 {
return ts.height
}
func (ts *TipSet) Weight() BigInt {
// TODO: implement correctly
log.Warn("Called TipSet.Weight: TODO: correct implementation")
return BigAdd(ts.blks[0].ParentWeight, NewInt(1))
}
func (ts *TipSet) Parents() []cid.Cid {
return ts.blks[0].Parents
}

View File

@ -1,6 +1,8 @@
package types
import (
"context"
amt "github.com/filecoin-project/go-amt-ipld"
"github.com/filecoin-project/go-lotus/chain/actors/aerrors"
"github.com/filecoin-project/go-lotus/chain/address"
@ -38,6 +40,8 @@ type VMContext interface {
ChargeGas(uint64) aerrors.ActorError
GetRandomness(height uint64) ([]byte, aerrors.ActorError)
GetBalance(address.Address) (BigInt, aerrors.ActorError)
Context() context.Context
}
type storageWrapper struct {

View File

@ -30,7 +30,7 @@ func newInvoker() *invoker {
// add builtInCode using: register(cid, singleton)
inv.register(actors.InitActorCodeCid, actors.InitActor{}, actors.InitActorState{})
inv.register(actors.StorageMarketActorCodeCid, actors.StorageMarketActor{}, actors.StorageMarketState{})
inv.register(actors.StorageMarketActorCodeCid, actors.StoragePowerActor{}, actors.StoragePowerState{})
inv.register(actors.StorageMinerCodeCid, actors.StorageMinerActor{}, actors.StorageMinerActorState{})
inv.register(actors.MultisigActorCodeCid, actors.MultiSigActor{}, actors.MultiSigActorState{})
inv.register(actors.PaymentChannelActorCodeCid, actors.PaymentChannelActor{}, actors.PaymentChannelActorState{})

View File

@ -3,15 +3,16 @@ package vm
import (
"context"
"github.com/ipfs/go-cid"
dstore "github.com/ipfs/go-datastore"
hamt "github.com/ipfs/go-hamt-ipld"
bstore "github.com/ipfs/go-ipfs-blockstore"
"github.com/filecoin-project/go-lotus/chain/actors"
"github.com/filecoin-project/go-lotus/chain/actors/aerrors"
"github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/state"
"github.com/filecoin-project/go-lotus/chain/types"
"github.com/ipfs/go-cid"
dstore "github.com/ipfs/go-datastore"
hamt "github.com/ipfs/go-hamt-ipld"
bstore "github.com/ipfs/go-ipfs-blockstore"
)
func init() {

View File

@ -3,6 +3,7 @@ package vm
import (
"context"
"fmt"
blockstore "github.com/ipfs/go-ipfs-blockstore"
"math/big"
"github.com/filecoin-project/go-lotus/build"
@ -10,7 +11,6 @@ import (
"github.com/filecoin-project/go-lotus/chain/actors/aerrors"
"github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/state"
"github.com/filecoin-project/go-lotus/chain/store"
"github.com/filecoin-project/go-lotus/chain/types"
"github.com/filecoin-project/go-lotus/lib/bufbstore"
cbg "github.com/whyrusleeping/cbor-gen"
@ -239,6 +239,10 @@ func (vmctx *VMContext) GetBalance(a address.Address) (types.BigInt, aerrors.Act
}
}
func (vmctx *VMContext) Context() context.Context {
return vmctx.ctx
}
type hBlocks interface {
GetBlock(context.Context, cid.Cid) (block.Block, error)
AddBlock(block.Block) error
@ -296,7 +300,6 @@ func (vm *VM) makeVMContext(ctx context.Context, sroot cid.Cid, msg *types.Messa
type VM struct {
cstate *state.StateTree
base cid.Cid
cs *store.ChainStore
cst *hamt.CborIpldStore
buf *bufbstore.BufferedBS
blockHeight uint64
@ -305,8 +308,8 @@ type VM struct {
rand Rand
}
func NewVM(base cid.Cid, height uint64, r Rand, maddr address.Address, cs *store.ChainStore) (*VM, error) {
buf := bufbstore.NewBufferedBstore(cs.Blockstore())
func NewVM(base cid.Cid, height uint64, r Rand, maddr address.Address, cbs blockstore.Blockstore) (*VM, error) {
buf := bufbstore.NewBufferedBstore(cbs)
cst := hamt.CSTFromBstore(buf)
state, err := state.LoadStateTree(cst, base)
if err != nil {
@ -316,7 +319,6 @@ func NewVM(base cid.Cid, height uint64, r Rand, maddr address.Address, cs *store
return &VM{
cstate: state,
base: base,
cs: cs,
cst: cst,
buf: buf,
blockHeight: height,
@ -330,27 +332,6 @@ type Rand interface {
GetRandomness(ctx context.Context, h int64) ([]byte, error)
}
type chainRand struct {
cs *store.ChainStore
blks []cid.Cid
bh uint64
tickets []*types.Ticket
}
func NewChainRand(cs *store.ChainStore, blks []cid.Cid, bheight uint64, tickets []*types.Ticket) Rand {
return &chainRand{
cs: cs,
blks: blks,
bh: bheight,
tickets: tickets,
}
}
func (cr *chainRand) GetRandomness(ctx context.Context, h int64) ([]byte, error) {
lb := (int64(cr.bh) + int64(len(cr.tickets))) - h
return cr.cs.GetRandomness(ctx, cr.blks, cr.tickets, lb)
}
type ApplyRet struct {
types.MessageReceipt
ActorErr aerrors.ActorError

View File

@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"fmt"
"strings"
"time"
cid "github.com/ipfs/go-cid"
@ -279,7 +280,12 @@ var chainListCmd = &cli.Command{
Usage: "View a segment of the chain",
Flags: []cli.Flag{
&cli.Uint64Flag{Name: "height"},
&cli.UintFlag{Name: "count", Value: 30},
&cli.IntFlag{Name: "count", Value: 30},
&cli.StringFlag{
Name: "format",
Usage: "specify the format to print out tipsets",
Value: "<height>: (<time>) <blocks>",
},
},
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
@ -300,15 +306,15 @@ var chainListCmd = &cli.Command{
return err
}
count := cctx.Uint("count")
count := cctx.Int("count")
if count < 1 {
return nil
}
tss := make([]*types.TipSet, count)
tss[0] = head
tss := make([]*types.TipSet, 0, count)
tss = append(tss, head)
for i := 1; i < len(tss); i++ {
for i := 1; i < count; i++ {
if head.Height() == 0 {
break
}
@ -318,18 +324,26 @@ var chainListCmd = &cli.Command{
return err
}
tss[i] = head
tss = append(tss, head)
}
for i := len(tss) - 1; i >= 0; i-- {
mints := tss[i].MinTimestamp()
t := time.Unix(int64(mints), 0)
fmt.Printf("%d: (%s) [ ", tss[i].Height(), t.Format(time.Stamp))
for _, b := range tss[i].Blocks() {
fmt.Printf("%s: %s,", b.Cid(), b.Miner)
}
fmt.Println("]")
printTipSet(cctx.String("format"), tss[i])
}
return nil
},
}
func printTipSet(format string, ts *types.TipSet) {
format = strings.ReplaceAll(format, "<height>", fmt.Sprint(ts.Height()))
format = strings.ReplaceAll(format, "<time>", time.Unix(int64(ts.MinTimestamp()), 0).Format(time.Stamp))
blks := "[ "
for _, b := range ts.Blocks() {
blks += fmt.Sprintf("%s: %s,", b.Cid(), b.Miner)
}
blks += " ]"
format = strings.ReplaceAll(format, "<blocks>", blks)
format = strings.ReplaceAll(format, "<weight>", fmt.Sprint(ts.Blocks()[0].ParentWeight))
fmt.Println(format)
}

View File

@ -71,7 +71,7 @@ var createMinerCmd = &cli.Command{
msg := &types.Message{
To: actors.StorageMarketAddress,
From: addr,
Method: actors.SMAMethods.CreateStorageMiner,
Method: actors.SPAMethods.CreateStorageMiner,
Params: params,
Value: types.NewInt(0),
GasPrice: types.NewInt(0),

View File

@ -1,6 +1,7 @@
package cli
import (
"encoding/json"
"fmt"
"gopkg.in/urfave/cli.v2"
@ -32,7 +33,11 @@ var mpoolPending = &cli.Command{
}
for _, msg := range msgs {
fmt.Println(msg)
out, err := json.MarshalIndent(msg, "", " ")
if err != nil {
return err
}
fmt.Println(string(out))
}
return nil

View File

@ -2,11 +2,13 @@ package cli
import (
"fmt"
"time"
cid "github.com/ipfs/go-cid"
"gopkg.in/urfave/cli.v2"
"github.com/filecoin-project/go-lotus/api"
"github.com/filecoin-project/go-lotus/chain"
cid "github.com/ipfs/go-cid"
)
var syncCmd = &cli.Command{
@ -14,6 +16,7 @@ var syncCmd = &cli.Command{
Usage: "Inspect or interact with the chain syncer",
Subcommands: []*cli.Command{
syncStatusCmd,
syncWaitCmd,
},
}
@ -49,3 +52,36 @@ var syncStatusCmd = &cli.Command{
return nil
},
}
var syncWaitCmd = &cli.Command{
Name: "wait",
Usage: "Wait for sync to be complete",
Action: func(cctx *cli.Context) error {
napi, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
for {
ss, err := napi.SyncState(ctx)
if err != nil {
return err
}
var target []cid.Cid
if ss.Target != nil {
target = ss.Target.Cids()
}
fmt.Printf("\r\x1b[2KTarget: %s\tState: %s\tHeight: %d", target, chain.SyncStageString(ss.Stage), ss.Height)
if ss.Stage == api.StageSyncComplete {
fmt.Println("\nDone")
return nil
}
time.Sleep(1 * time.Second)
}
},
}

93
cmd/chain-noise/main.go Normal file
View File

@ -0,0 +1,93 @@
package main
import (
"context"
"fmt"
"math/rand"
"os"
"time"
"github.com/filecoin-project/go-lotus/api"
"github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/types"
lcli "github.com/filecoin-project/go-lotus/cli"
"gopkg.in/urfave/cli.v2"
)
func main() {
app := &cli.App{
Name: "chain-noise",
Usage: "Generate some spam transactions in the network",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "repo",
EnvVars: []string{"LOTUS_PATH"},
Hidden: true,
Value: "~/.lotus", // TODO: Consider XDG_DATA_HOME
},
},
Commands: []*cli.Command{runCmd},
}
if err := app.Run(os.Args); err != nil {
fmt.Println("Error: ", err)
os.Exit(1)
}
}
var runCmd = &cli.Command{
Name: "run",
Action: func(cctx *cli.Context) error {
addr, err := address.NewFromString(cctx.Args().First())
if err != nil {
return err
}
api, closer, err := lcli.GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := lcli.ReqContext(cctx)
sendSmallFundsTxs(ctx, api, addr, 5)
return nil
},
}
func sendSmallFundsTxs(ctx context.Context, api api.FullNode, from address.Address, rate int) error {
var sendSet []address.Address
for i := 0; i < 20; i++ {
naddr, err := api.WalletNew(ctx, "bls")
if err != nil {
return err
}
sendSet = append(sendSet, naddr)
}
tick := time.NewTicker(time.Second / time.Duration(rate))
for {
select {
case <-tick.C:
msg := &types.Message{
From: from,
To: sendSet[rand.Intn(20)],
Value: types.NewInt(1),
GasLimit: types.NewInt(100000),
GasPrice: types.NewInt(0),
}
smsg, err := api.MpoolPushMessage(ctx, msg)
if err != nil {
return err
}
fmt.Println("Message sent: ", smsg.Cid())
case <-ctx.Done():
return nil
}
}
return nil
}

View File

@ -6,6 +6,7 @@ import (
"net/http"
"os"
rice "github.com/GeertJohan/go.rice"
logging "github.com/ipfs/go-log"
"golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2"
@ -89,8 +90,9 @@ var runCmd = &cli.Command{
from: from,
}
http.HandleFunc("/", h.index)
http.Handle("/", http.FileServer(rice.MustFindBox("site").HTTPBox()))
http.HandleFunc("/send", h.send)
http.HandleFunc("/sendcoll", h.sendColl)
fmt.Printf("Open http://%s\n", cctx.String("front"))
@ -110,13 +112,6 @@ type handler struct {
from address.Address
}
func (h *handler) index(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "<!DOCTYPE html>\n<html><head><title>Lotus Fountain</title><style>body {font-family: 'monospace';}</style></head><body>")
fmt.Fprintf(w, "<form action='/send' method='get'>Enter destination address: ")
fmt.Fprintf(w, "<input type='text' name='address'><br><button type='submit'>Send</button>")
fmt.Fprintf(w, "</form></body></html>")
}
func (h *handler) send(w http.ResponseWriter, r *http.Request) {
to, err := address.NewFromString(r.FormValue("address"))
if err != nil {
@ -141,3 +136,33 @@ func (h *handler) send(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(smsg.Cid().String()))
}
func (h *handler) sendColl(w http.ResponseWriter, r *http.Request) {
to, err := address.NewFromString(r.FormValue("address"))
if err != nil {
w.WriteHeader(400)
w.Write([]byte(err.Error()))
return
}
coll, err := h.api.StatePledgeCollateral(h.ctx, nil)
if err != nil {
return
}
smsg, err := h.api.MpoolPushMessage(h.ctx, &types.Message{
Value: coll,
From: h.from,
To: to,
GasPrice: types.NewInt(0),
GasLimit: types.NewInt(1000),
})
if err != nil {
w.WriteHeader(400)
w.Write([]byte(err.Error()))
return
}
w.Write([]byte(smsg.Cid().String()))
}

View File

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head>
<title>Lotus Fountain</title>
<style>
body {
font-family: 'monospace';
background: #1f1f1f;
color: #f0f0f0;
}
</style>
</head>
<body>
<form action='/send' method='get'>
<span>Enter destination address:</span>
<input type='text' name='address' style="width: 300px">
<button type='submit'>Send</button>
</form>
</body>
</html>

View File

@ -1,11 +1,15 @@
package main
import (
"context"
"fmt"
"gopkg.in/urfave/cli.v2"
"github.com/filecoin-project/go-lotus/api"
"github.com/filecoin-project/go-lotus/chain/types"
lcli "github.com/filecoin-project/go-lotus/cli"
sectorstate "github.com/filecoin-project/go-sectorbuilder/sealing_state"
)
var infoCmd = &cli.Command{
@ -17,14 +21,40 @@ var infoCmd = &cli.Command{
return err
}
defer closer()
api, acloser, err := lcli.GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer acloser()
ctx := lcli.ReqContext(cctx)
aaddr, err := nodeApi.ActorAddresses(ctx)
maddr, err := nodeApi.ActorAddress(ctx)
if err != nil {
return err
}
fmt.Printf("actor address: %s\n", aaddr)
fmt.Printf("Miner: %s\n", maddr)
pow, err := api.StateMinerPower(ctx, maddr, nil)
if err != nil {
return err
}
percI := types.BigDiv(types.BigMul(pow.MinerPower, types.NewInt(1000)), pow.TotalPower)
fmt.Printf("Power: %s / %s (%0.2f%%)\n", pow.MinerPower, pow.TotalPower, float64(percI.Int64())/1000*100)
sinfo, err := sectorsInfo(ctx, nodeApi)
if err != nil {
return err
}
fmt.Println("Sealed Sectors:\t", sinfo.SealedCount)
fmt.Println("Sealing Sectors:\t", sinfo.SealingCount)
fmt.Println("Pending Sectors:\t", sinfo.PendingCount)
fmt.Println("Failed Sectors:\t", sinfo.FailedCount)
// TODO: grab actr state / info
// * Sector size
// * Sealed sectors (count / bytes)
@ -32,3 +62,42 @@ var infoCmd = &cli.Command{
return nil
},
}
type SectorsInfo struct {
TotalCount int
SealingCount int
FailedCount int
SealedCount int
PendingCount int
}
func sectorsInfo(ctx context.Context, napi api.StorageMiner) (*SectorsInfo, error) {
sectors, err := napi.SectorsList(ctx)
if err != nil {
return nil, err
}
out := SectorsInfo{
TotalCount: len(sectors),
}
for _, s := range sectors {
st, err := napi.SectorsStatus(ctx, s)
if err != nil {
return nil, err
}
switch st.State {
case sectorstate.Sealed:
out.SealedCount++
case sectorstate.Pending:
out.PendingCount++
case sectorstate.Sealing:
out.SealingCount++
case sectorstate.Failed:
out.FailedCount++
case sectorstate.Unknown:
}
}
return &out, nil
}

View File

@ -289,7 +289,7 @@ func createStorageMiner(ctx context.Context, api api.FullNode, peerid peer.ID, c
From: owner,
Value: collateral,
Method: actors.SMAMethods.CreateStorageMiner,
Method: actors.SPAMethods.CreateStorageMiner,
Params: params,
GasLimit: types.NewInt(10000),
@ -309,6 +309,10 @@ func createStorageMiner(ctx context.Context, api api.FullNode, peerid peer.ID, c
return address.Undef, err
}
if mw.Receipt.ExitCode != 0 {
return address.Undef, xerrors.Errorf("create storage miner failed: exit code %d", mw.Receipt.ExitCode)
}
addr, err = address.NewFromBytes(mw.Receipt.Return)
if err != nil {
return address.Undef, err

View File

@ -89,7 +89,7 @@ var sectorsStagedListCmd = &cli.Command{
defer closer()
ctx := lcli.ReqContext(cctx)
staged, err := nodeApi.SectorsStagedList(ctx)
staged, err := nodeApi.SectorsList(ctx)
if err != nil {
return err
}

View File

@ -18,7 +18,7 @@ import (
"github.com/filecoin-project/go-lotus/node/modules/lp2p"
)
const topic = "/fil/headnotifs/bafy2bzacedjqrkfbuafakygo6vlkrqozvsju2d5k6g24ry3mjjfxwrvet2636"
const topic = "/fil/headnotifs/bafy2bzacecyfz2wfi5a6d4epch6nmedrlan3mdfswgv3y74an5aeqxaq5gqlu"
var upgrader = websocket.Upgrader{
WriteBufferSize: 1024,
@ -49,7 +49,7 @@ func main() {
}
pi, err := addrutil.ParseAddresses(ctx, []string{
"/ip4/147.75.80.29/tcp/1347/p2p/12D3KooWAShT7qd3oM7QPC8AsQffs6ThH69fZGui4xCW68E35rDP",
"/ip4/147.75.80.29/tcp/1347/p2p/12D3KooWGdsbvHwscFKT1kqBeeooPe6EneJvjXzTrWSzwKhc1ssn",
})
if err != nil {
panic(err)

View File

@ -67,7 +67,7 @@ func main() {
actors.LaneState{},
actors.PCAUpdateChannelStateParams{},
actors.PaymentInfo{},
actors.StorageMarketState{},
actors.StoragePowerState{},
actors.CreateStorageMinerParams{},
actors.IsMinerParam{},
actors.PowerLookupParams{},

View File

@ -4,6 +4,7 @@ import (
"encoding/binary"
"io"
"os"
"sort"
"sync"
"unsafe"
@ -94,8 +95,22 @@ func (sb *SectorBuilder) SealStatus(sector uint64) (SectorSealingStatus, error)
return sectorbuilder.GetSectorSealingStatusByID(sb.handle, sector)
}
func (sb *SectorBuilder) GetAllStagedSectors() ([]StagedSectorMetadata, error) {
return sectorbuilder.GetAllStagedSectors(sb.handle)
func (sb *SectorBuilder) GetAllStagedSectors() ([]uint64, error) {
sectors, err := sectorbuilder.GetAllStagedSectors(sb.handle)
if err != nil {
return nil, err
}
out := make([]uint64, len(sectors))
for i, v := range sectors {
out[i] = v.SectorID
}
sort.Slice(out, func(i, j int) bool {
return out[i] < out[j]
})
return out, nil
}
func (sb *SectorBuilder) GeneratePoSt(sectorInfo SortedSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]byte, error) {

View File

@ -70,7 +70,7 @@ class StorageNode extends React.Component {
async loadInfo() {
const version = await this.state.client.call("Filecoin.Version", [])
const peers = await this.state.client.call("Filecoin.NetPeers", [])
const [actor] = await this.state.client.call("Filecoin.ActorAddresses", [])
const actor = await this.state.client.call("Filecoin.ActorAddress", [])
const stActor = await this.props.fullConn.call('Filecoin.StateGetActor', [actor, null])
const actorState = await this.props.fullConn.call('Filecoin.StateReadState', [stActor, null])
@ -80,9 +80,9 @@ class StorageNode extends React.Component {
}
async stagedList() {
let stagedList = await this.state.client.call("Filecoin.SectorsStagedList", [])
let stagedList = await this.state.client.call("Filecoin.SectorsList", [])
let staged = await stagedList
.map(sector => this.state.client.call("Filecoin.SectorsStatus", [sector.SectorID]))
.map(sector => this.state.client.call("Filecoin.SectorsStatus", [sector]))
.reduce(async (p, n) => [...await p, await n], Promise.resolve([]))
let statusCounts = staged.reduce((p, n) => p.map((e, i) => e + (i === n.State ? 1 : 0) ), [0, 0, 0, 0, 0])

View File

@ -27,6 +27,7 @@ type api struct {
fx.In
full.ChainAPI
full.SyncAPI
full.MpoolAPI
full.WalletAPI
full.StateAPI
@ -154,13 +155,13 @@ func (m *Miner) mine(ctx context.Context) {
return
}
base, err := m.GetBestMiningCandidate()
base, err := m.GetBestMiningCandidate(ctx)
if err != nil {
log.Errorf("failed to get best mining candidate: %s", err)
continue
}
if base.ts.Equals(lastBase.ts) && len(lastBase.tickets) == len(base.tickets) {
log.Error("BestMiningCandidate from the previous round: %s (tkts:%d)", lastBase.ts.Cids(), len(lastBase.tickets))
log.Errorf("BestMiningCandidate from the previous round: %s (tkts:%d)", lastBase.ts.Cids(), len(lastBase.tickets))
time.Sleep(build.BlockDelay * time.Second)
continue
}
@ -183,7 +184,7 @@ func (m *Miner) mine(ctx context.Context) {
"time", time.Now(), "duration", time.Now().Sub(btime))
}
if err := m.api.ChainSubmitBlock(ctx, b); err != nil {
if err := m.api.SyncSubmitBlock(ctx, b); err != nil {
log.Errorf("failed to submit newly mined block: %s", err)
}
} else {
@ -198,8 +199,8 @@ type MiningBase struct {
tickets []*types.Ticket
}
func (m *Miner) GetBestMiningCandidate() (*MiningBase, error) {
bts, err := m.api.ChainHead(context.TODO())
func (m *Miner) GetBestMiningCandidate(ctx context.Context) (*MiningBase, error) {
bts, err := m.api.ChainHead(ctx)
if err != nil {
return nil, err
}
@ -209,7 +210,16 @@ func (m *Miner) GetBestMiningCandidate() (*MiningBase, error) {
return m.lastWork, nil
}
if types.BigCmp(bts.Weight(), m.lastWork.ts.Weight()) <= 0 {
btsw, err := m.api.ChainTipSetWeight(ctx, bts)
if err != nil {
return nil, err
}
ltsw, err := m.api.ChainTipSetWeight(ctx, m.lastWork.ts)
if err != nil {
return nil, err
}
if types.BigCmp(btsw, ltsw) <= 0 {
return m.lastWork, nil
}
}

View File

@ -3,6 +3,7 @@ package hello
import (
"context"
"fmt"
"github.com/filecoin-project/go-lotus/chain/types"
"github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
@ -26,7 +27,7 @@ func init() {
type Message struct {
HeaviestTipSet []cid.Cid
HeaviestTipSetWeight uint64
HeaviestTipSetWeight types.BigInt
GenesisHash cid.Cid
}
@ -83,7 +84,10 @@ func (hs *Service) SayHello(ctx context.Context, pid peer.ID) error {
defer s.Close()
hts := hs.cs.GetHeaviestTipSet()
weight := hs.cs.Weight(hts)
weight, err := hs.cs.Weight(ctx, hts)
if err != nil {
return err
}
gen, err := hs.cs.GetGenesis()
if err != nil {
return err

View File

@ -9,7 +9,6 @@ import (
"golang.org/x/xerrors"
"github.com/ipfs/go-cid"
pubsub "github.com/libp2p/go-libp2p-pubsub"
"go.uber.org/fx"
)
@ -19,25 +18,12 @@ type ChainAPI struct {
WalletAPI
Chain *store.ChainStore
PubSub *pubsub.PubSub
}
func (a *ChainAPI) ChainNotify(ctx context.Context) (<-chan []*store.HeadChange, error) {
return a.Chain.SubHeadChanges(ctx), nil
}
func (a *ChainAPI) ChainSubmitBlock(ctx context.Context, blk *types.BlockMsg) error {
// TODO: should we have some sort of fast path to adding a local block?
b, err := blk.Serialize()
if err != nil {
return xerrors.Errorf("serializing block for pubsub publishing failed: %w", err)
}
// TODO: anything else to do here?
return a.PubSub.Publish("/fil/blocks", b)
}
func (a *ChainAPI) ChainHead(context.Context) (*types.TipSet, error) {
return a.Chain.GetHeaviestTipSet(), nil
}
@ -174,3 +160,7 @@ func (a *ChainAPI) ChainGetGenesis(ctx context.Context) (*types.TipSet, error) {
return types.NewTipSet([]*types.BlockHeader{genb})
}
func (a *ChainAPI) ChainTipSetWeight(ctx context.Context, ts *types.TipSet) (types.BigInt, error) {
return a.Chain.Weight(ctx, ts)
}

View File

@ -92,7 +92,7 @@ func (a *StateAPI) StatePledgeCollateral(ctx context.Context, ts *types.TipSet)
ret, aerr := a.StateManager.Call(ctx, &types.Message{
From: actors.StorageMarketAddress,
To: actors.StorageMarketAddress,
Method: actors.SMAMethods.PledgeCollateralForSize,
Method: actors.SPAMethods.PledgeCollateralForSize,
Params: param,
}, ts)
@ -209,7 +209,7 @@ func (a *StateAPI) StateWaitMsg(ctx context.Context, msg cid.Cid) (*api.MsgWait,
}
func (a *StateAPI) StateListMiners(ctx context.Context, ts *types.TipSet) ([]address.Address, error) {
var state actors.StorageMarketState
var state actors.StoragePowerState
if _, err := a.StateManager.LoadActorState(ctx, actors.StorageMarketAddress, &state, ts); err != nil {
return nil, err
}

View File

@ -5,13 +5,18 @@ import (
"github.com/filecoin-project/go-lotus/api"
"github.com/filecoin-project/go-lotus/chain"
"github.com/filecoin-project/go-lotus/chain/types"
pubsub "github.com/libp2p/go-libp2p-pubsub"
"go.uber.org/fx"
"golang.org/x/xerrors"
)
type SyncAPI struct {
fx.In
Syncer *chain.Syncer
PubSub *pubsub.PubSub
}
func (a *SyncAPI) SyncState(ctx context.Context) (*api.SyncState, error) {
@ -23,3 +28,42 @@ func (a *SyncAPI) SyncState(ctx context.Context) (*api.SyncState, error) {
Height: ss.Height,
}, nil
}
func (a *SyncAPI) SyncSubmitBlock(ctx context.Context, blk *types.BlockMsg) error {
// TODO: should we have some sort of fast path to adding a local block?
bmsgs, err := a.Syncer.ChainStore().LoadMessagesFromCids(blk.BlsMessages)
if err != nil {
return xerrors.Errorf("failed to load bls messages: %w", err)
}
smsgs, err := a.Syncer.ChainStore().LoadSignedMessagesFromCids(blk.SecpkMessages)
if err != nil {
return xerrors.Errorf("failed to load secpk message: %w", err)
}
fb := &types.FullBlock{
Header: blk.Header,
BlsMessages: bmsgs,
SecpkMessages: smsgs,
}
if err := a.Syncer.ValidateMsgMeta(fb); err != nil {
xerrors.Errorf("provided messages did not match block: %w", err)
}
ts, err := types.NewTipSet([]*types.BlockHeader{blk.Header})
if err != nil {
return xerrors.Errorf("somehow failed to make a tipset out of a single block: %w", err)
}
if err := a.Syncer.Sync(ctx, ts); err != nil {
return xerrors.Errorf("sync to submitted block failed: %w", err)
}
b, err := blk.Serialize()
if err != nil {
return xerrors.Errorf("serializing block for pubsub publishing failed: %w", err)
}
// TODO: anything else to do here?
return a.PubSub.Publish("/fil/blocks", b)
}

View File

@ -26,8 +26,8 @@ type StorageMinerAPI struct {
Miner *storage.Miner
}
func (sm *StorageMinerAPI) ActorAddresses(context.Context) ([]address.Address, error) {
return []address.Address{sm.SectorBuilderConfig.Miner}, nil
func (sm *StorageMinerAPI) ActorAddress(context.Context) (address.Address, error) {
return sm.SectorBuilderConfig.Miner, nil
}
func (sm *StorageMinerAPI) StoreGarbageData(ctx context.Context) (uint64, error) {
@ -47,7 +47,7 @@ func (sm *StorageMinerAPI) SectorsStatus(ctx context.Context, sid uint64) (secto
}
// List all staged sectors
func (sm *StorageMinerAPI) SectorsStagedList(context.Context) ([]sectorbuilder.StagedSectorMetadata, error) {
func (sm *StorageMinerAPI) SectorsList(context.Context) ([]uint64, error) {
return sm.SectorBuilder.GetAllStagedSectors()
}

16
scripts/deploy-miner.sh Executable file
View File

@ -0,0 +1,16 @@
#!/usr/bin/env bash
HOST=$1
ssh "$HOST" 'lotus wallet new bls > addr'
ssh "$HOST" 'curl http://147.75.80.29:777/sendcoll?address=$(cat addr)' &
ssh "$HOST" 'curl http://147.75.80.29:777/sendcoll?address=$(cat addr)' &
ssh "$HOST" 'curl http://147.75.80.29:777/send?address=$(cat addr)' &
wait
echo "SYNC WAIT"
sleep 30
ssh "$HOST" 'lotus sync wait'
ssh "$HOST" 'lotus-storage-miner init --owner=$(cat addr)'
ssh "$HOST" 'systemctl start lotus-storage-miner' &

23
scripts/deploy-node.sh Executable file
View File

@ -0,0 +1,23 @@
#!/usr/bin/env bash
HOST=$1
# upload binaries
# TODO: destroy
ssh "$HOST" 'systemctl stop lotus-storage-miner'
ssh "$HOST" 'systemctl stop lotus-daemon'
ssh "$HOST" 'mkdir -p .lotus .lotusstorage' &
scp "./lotus" "$HOST:/usr/local/bin" &
scp "./lotus-storage-miner" "$HOST:/usr/local/bin" &
scp -C scripts/daemon.service "${HOST}:/etc/systemd/system/lotus-daemon.service" &
scp -C scripts/sminer.service "${HOST}:/etc/systemd/system/lotus-storage-miner.service" &
wait
ssh "$HOST" 'systemctl daemon-reload'
ssh "$HOST" 'systemctl start lotus-daemon' &
wait
# setup miner actor