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 /lotus-storage-miner
/pond /pond
/townhall /townhall
/fountain
/lotuspond/front/node_modules /lotuspond/front/node_modules
/lotuspond/front/build /lotuspond/front/build
/cmd/lotus-townhall/townhall/node_modules
/cmd/lotus-townhall/townhall/build
**/*.h **/*.h
**/*.a **/*.a
**/*.pc **/*.pc

View File

@ -76,6 +76,9 @@ build: lotus lotus-storage-miner
.PHONY: build .PHONY: build
install:
install -C ./lotus /usr/local/bin/lotus
install -C ./lotus /usr/local/bin/lotus-storage-miner
benchmarks: benchmarks:
go run github.com/whyrusleeping/bencher ./... > bench.json 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 go run github.com/GeertJohan/go.rice/rice append --exec townhall -i ./cmd/lotus-townhall
.PHONY: 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: clean:
rm -rf $(CLEAN) rm -rf $(CLEAN)
-$(MAKE) -C $(BLS_PATH) 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 ## 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) - go (1.13 or higher)
- gcc (7.4.0 or higher) - gcc (7.4.0 or higher)
- git - git
@ -20,19 +22,27 @@ All work is tracked via issues. An attempt at keeping an up-to-date view on rema
- jq - jq
- pkg-config - 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 $ make
$ sudo make install
``` ```
Now, you should be able to perform the commands listed below.
## Devnet ## Devnet
### Node setup ### Node setup
If you have run lotus before and want to remove all previous data: `rm -rf ~/.lotus ~/.lotusstorage` 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). 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 ### Genesis & Bootstrap
@ -58,6 +68,9 @@ You can follow sync status with:
$ watch lotus sync status $ 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 ### Basics
@ -67,19 +80,15 @@ $ lotus wallet new bls
t3... 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 just created, and press Send.
(You can also generate a public key address using secp256k1 with Check the wallet balance (balance is listed in attoFIL, where 1 attoFIL = 10^-18 FIL):
`lotus wallet new secp256k1`. BLS signatures use less space so will have lower fees.)
Check the wallet balance:
```sh ```sh
$ lotus wallet balance [optional address (t3...)] $ 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 (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).
faucet should 'fix' this, or your node isn't fully synced).
### Mining ### Mining
@ -88,7 +97,7 @@ cover pledge collateral:
```sh ```sh
$ lotus state pledge-collateral $ lotus state pledge-collateral
1234 1234
$ lotus wallet balance t3... $ lotus wallet balance [t3...]
8999 8999
``` ```
(Balance must be higher than the returned pledge collateral for the next step to work) (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> $ lotus-storage-miner state sectors <miner>
``` ```
You can view a list of miners with:
```sh
$ lotus state list-miners
```
### Stage Data ### Stage Data
Import some 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.) (It is possible for a Client to make a deal with a Miner on the same lotus Node.)
```sh ```sh
# List all miners in the system. Choose one to make a deal with.
$ lotus state list-miners
# List asks proposed by a miner # List asks proposed by a miner
$ lotus client query-ask <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> $ 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 ### Search & Retrieval

View File

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

View File

@ -38,7 +38,6 @@ type FullNodeStruct struct {
Internal struct { Internal struct {
ChainNotify func(context.Context) (<-chan []*store.HeadChange, error) `perm:"read"` 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"` ChainHead func(context.Context) (*types.TipSet, error) `perm:"read"`
ChainGetRandomness func(context.Context, *types.TipSet, []*types.Ticket, int) ([]byte, 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"` 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"` ChainReadObj func(context.Context, cid.Cid) ([]byte, error) `perm:"read"`
ChainSetHead func(context.Context, *types.TipSet) error `perm:"admin"` ChainSetHead func(context.Context, *types.TipSet) error `perm:"admin"`
ChainGetGenesis func(context.Context) (*types.TipSet, error) `perm:"read"` 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"` 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"` MpoolPending func(context.Context, *types.TipSet) ([]*types.SignedMessage, error) `perm:"read"`
MpoolPush func(context.Context, *types.SignedMessage) error `perm:"write"` MpoolPush func(context.Context, *types.SignedMessage) error `perm:"write"`
@ -118,12 +119,12 @@ type StorageMinerStruct struct {
CommonStruct CommonStruct
Internal struct { 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"` StoreGarbageData func(context.Context) (uint64, error) `perm:"write"`
SectorsStatus func(context.Context, uint64) (sectorbuilder.SectorSealingStatus, error) `perm:"read"` 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"` SectorsStagedSeal func(context.Context) error `perm:"write"`
SectorsRefs func(context.Context) (map[string][]SealedRef, error) `perm:"read"` 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) 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) { func (c *FullNodeStruct) ChainHead(ctx context.Context) (*types.TipSet, error) {
return c.Internal.ChainHead(ctx) return c.Internal.ChainHead(ctx)
} }
@ -320,10 +317,18 @@ func (c *FullNodeStruct) ChainGetGenesis(ctx context.Context) (*types.TipSet, er
return c.Internal.ChainGetGenesis(ctx) 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) { func (c *FullNodeStruct) SyncState(ctx context.Context) (*SyncState, error) {
return c.Internal.SyncState(ctx) 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) { func (c *FullNodeStruct) StateMinerSectors(ctx context.Context, addr address.Address) ([]*SectorInfo, error) {
return c.Internal.StateMinerSectors(ctx, addr) 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) return c.Internal.PaychVoucherSubmit(ctx, ch, sv)
} }
func (c *StorageMinerStruct) ActorAddresses(ctx context.Context) ([]address.Address, error) { func (c *StorageMinerStruct) ActorAddress(ctx context.Context) (address.Address, error) {
return c.Internal.ActorAddresses(ctx) return c.Internal.ActorAddress(ctx)
} }
func (c *StorageMinerStruct) StoreGarbageData(ctx context.Context) (uint64, error) { 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 // List all staged sectors
func (c *StorageMinerStruct) SectorsStagedList(ctx context.Context) ([]sectorbuilder.StagedSectorMetadata, error) { func (c *StorageMinerStruct) SectorsList(ctx context.Context) ([]uint64, error) {
return c.Internal.SectorsStagedList(ctx) return c.Internal.SectorsList(ctx)
} }
// Seal all staged sectors // 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 // Blocks
const ForkLengthThreshold = 100 const ForkLengthThreshold = 100
// Blocks (e)
const BlocksPerEpoch = 1
// ///// // /////
// Proofs / Mining // Proofs / Mining

View File

@ -185,7 +185,7 @@ func (sma StorageMinerActor) StorageMinerConstructor(act *types.Actor, vmctx typ
sectors := amt.NewAMT(types.WrapStorage(vmctx.Storage())) sectors := amt.NewAMT(types.WrapStorage(vmctx.Storage()))
scid, serr := sectors.Flush() scid, serr := sectors.Flush()
if serr != nil { if serr != nil {
return nil, aerrors.Escalate(serr, "initializing AMT") return nil, aerrors.HandleExternalError(serr, "initializing AMT")
} }
self.Sectors = scid 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. // time to prove than large sectors do. Sector size is selected when pledging.
pss, lerr := amt.LoadAMT(types.WrapStorage(vmctx.Storage()), self.ProvingSet) pss, lerr := amt.LoadAMT(types.WrapStorage(vmctx.Storage()), self.ProvingSet)
if lerr != nil { 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 { 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) pss, lerr := amt.LoadAMT(types.WrapStorage(vmctx.Storage()), self.ProvingSet)
if lerr != nil { 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 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) ss, lerr := amt.LoadAMT(types.WrapStorage(vmctx.Storage()), self.ProvingSet)
if lerr != nil { 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 { if err := ss.BatchDelete(params.DoneSet.All()); err != nil {
// TODO: this could fail for system reasons (block not found) or for // 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 // bad user input reasons (e.g. bad doneset). The latter should be a
// non-fatal error // 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() self.ProvingSet, lerr = ss.Flush()
if lerr != nil { if lerr != nil {
return nil, aerrors.Escalate(lerr, "could not flush AMT") return nil, aerrors.HandleExternalError(lerr, "could not flush AMT")
} }
oldPower := self.Power oldPower := self.Power
@ -433,7 +433,7 @@ func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext,
return nil, err 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 { if err != nil {
return nil, err 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) { 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) ssr, err := amt.LoadAMT(types.WrapStorage(s), ss)
if err != nil { 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 { 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() ncid, err := ssr.Flush()
if err != nil { 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 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) { 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) ssr, err := amt.LoadAMT(types.WrapStorage(s), ss)
if err != nil { 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 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 { if _, ok := err.(*amt.ErrNotFound); ok {
return false, nil, nil, nil 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 { 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 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) { 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) ok, err := sectorbuilder.VerifySeal(ssize.Uint64(), params.CommR, params.CommD, params.CommRStar, maddr, params.SectorID, params.Proof)
if err != nil { if err != nil {
return false, aerrors.Escalate(err, "verify seal failed") return false, aerrors.Absorb(err, 25, "verify seal failed")
} }
return ok, nil return ok, nil
@ -659,11 +659,11 @@ func (sma StorageMinerActor) PaymentVerifyInclusion(act *types.Actor, vmctx type
var voucherData PieceInclVoucherData var voucherData PieceInclVoucherData
if err := cbor.DecodeInto(params.Extra, &voucherData); err != nil { 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 var proof InclusionProof
if err := cbor.DecodeInto(params.Proof, &proof); err != nil { 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) 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 return nil, aerr
} }
if !ok { 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) ok, err := sectorbuilder.VerifyPieceInclusionProof(mi.SectorSize.Uint64(), voucherData.PieceSize.Uint64(), voucherData.CommP, commD, proof.Proof)
if err != nil { 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 { 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 return nil, nil

View File

@ -2,7 +2,6 @@ package actors
import ( import (
"context" "context"
"fmt"
"github.com/filecoin-project/go-lotus/build" "github.com/filecoin-project/go-lotus/build"
"github.com/filecoin-project/go-lotus/chain/actors/aerrors" "github.com/filecoin-project/go-lotus/chain/actors/aerrors"
@ -16,9 +15,9 @@ import (
xerrors "golang.org/x/xerrors" xerrors "golang.org/x/xerrors"
) )
type StorageMarketActor struct{} type StoragePowerActor struct{}
type smaMethods struct { type spaMethods struct {
Constructor uint64 Constructor uint64
CreateStorageMiner uint64 CreateStorageMiner uint64
ArbitrateConsensusFault uint64 ArbitrateConsensusFault uint64
@ -29,22 +28,22 @@ type smaMethods struct {
PledgeCollateralForSize uint64 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{}{ return []interface{}{
//1: sma.StorageMarketConstructor, //1: spa.StoragePowerConstructor,
2: sma.CreateStorageMiner, 2: spa.CreateStorageMiner,
3: sma.ArbitrateConsensusFault, 3: spa.ArbitrateConsensusFault,
4: sma.UpdateStorage, 4: spa.UpdateStorage,
5: sma.GetTotalStorage, 5: spa.GetTotalStorage,
6: sma.PowerLookup, 6: spa.PowerLookup,
7: sma.IsMiner, 7: spa.IsMiner,
8: sma.PledgeCollateralForSize, 8: spa.PledgeCollateralForSize,
} }
} }
type StorageMarketState struct { type StoragePowerState struct {
Miners cid.Cid Miners cid.Cid
MinerCount uint64 MinerCount uint64
@ -58,12 +57,12 @@ type CreateStorageMinerParams struct {
PeerID peer.ID 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) { if !SupportedSectorSize(params.SectorSize) {
return nil, aerrors.New(1, "Unsupported sector size") return nil, aerrors.New(1, "Unsupported sector size")
} }
var self StorageMarketState var self StoragePowerState
old := vmctx.Storage().GetHead() old := vmctx.Storage().GetHead()
if err := vmctx.Storage().Get(old, &self); err != nil { if err := vmctx.Storage().Get(old, &self); err != nil {
return nil, err return nil, err
@ -129,7 +128,7 @@ type ArbitrateConsensusFaultParams struct {
Block2 *types.BlockHeader 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 { if params.Block1.Miner != params.Block2.Miner {
return nil, aerrors.New(2, "blocks must be from the same 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") 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") 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") 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") return nil, aerrors.New(6, "blocks do not prove a slashable offense")
} }
var self StorageMarketState var self StoragePowerState
old := vmctx.Storage().GetHead() old := vmctx.Storage().GetHead()
if err := vmctx.Storage().Get(old, &self); err != nil { if err := vmctx.Storage().Get(old, &self); err != nil {
return nil, err return nil, err
} }
if types.BigCmp(self.TotalStorage, types.NewInt(0)) == 0 { 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 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") return nil, aerrors.Wrapf(err, "failed to check miner in set")
} else if !has { } else if !has {
return nil, aerrors.New(7, "either already slashed or not a miner") return nil, aerrors.New(7, "either already slashed or not a miner")
@ -270,14 +269,14 @@ type UpdateStorageParams struct {
Delta types.BigInt Delta types.BigInt
} }
func (sma StorageMarketActor) UpdateStorage(act *types.Actor, vmctx types.VMContext, params *UpdateStorageParams) ([]byte, ActorError) { func (spa StoragePowerActor) UpdateStorage(act *types.Actor, vmctx types.VMContext, params *UpdateStorageParams) ([]byte, ActorError) {
var self StorageMarketState var self StoragePowerState
old := vmctx.Storage().GetHead() old := vmctx.Storage().GetHead()
if err := vmctx.Storage().Get(old, &self); err != nil { if err := vmctx.Storage().Get(old, &self); err != nil {
return nil, err 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 { if err != nil {
return nil, err return nil, err
} }
@ -300,8 +299,8 @@ func (sma StorageMarketActor) UpdateStorage(act *types.Actor, vmctx types.VMCont
return nil, nil return nil, nil
} }
func (sma StorageMarketActor) GetTotalStorage(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) { func (spa StoragePowerActor) GetTotalStorage(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) {
var self StorageMarketState var self StoragePowerState
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil { if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
return nil, err return nil, err
} }
@ -313,8 +312,8 @@ type PowerLookupParams struct {
Miner address.Address Miner address.Address
} }
func (sma StorageMarketActor) PowerLookup(act *types.Actor, vmctx types.VMContext, params *PowerLookupParams) ([]byte, ActorError) { func (spa StoragePowerActor) PowerLookup(act *types.Actor, vmctx types.VMContext, params *PowerLookupParams) ([]byte, ActorError) {
var self StorageMarketState var self StoragePowerState
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil { if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
return nil, aerrors.Wrap(err, "getting head") 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 return pow.Bytes(), nil
} }
func powerLookup(ctx context.Context, vmctx types.VMContext, self *StorageMarketState, miner address.Address) (types.BigInt, ActorError) { func powerLookup(ctx context.Context, vmctx types.VMContext, self *StoragePowerState, miner address.Address) (types.BigInt, ActorError) {
has, err := MinerSetHas(context.TODO(), vmctx, self.Miners, miner) has, err := MinerSetHas(vmctx, self.Miners, miner)
if err != nil { if err != nil {
return types.EmptyInt, err return types.EmptyInt, err
} }
if !has { 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) ret, err := vmctx.Send(miner, MAMethods.GetPower, types.NewInt(0), nil)
@ -349,13 +348,13 @@ type IsMinerParam struct {
Addr address.Address Addr address.Address
} }
func (sma StorageMarketActor) IsMiner(act *types.Actor, vmctx types.VMContext, param *IsMinerParam) ([]byte, ActorError) { func (spa StoragePowerActor) IsMiner(act *types.Actor, vmctx types.VMContext, param *IsMinerParam) ([]byte, ActorError) {
var self StorageMarketState var self StoragePowerState
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil { if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
return nil, err return nil, err
} }
has, err := MinerSetHas(context.TODO(), vmctx, self.Miners, param.Addr) has, err := MinerSetHas(vmctx, self.Miners, param.Addr)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -367,8 +366,8 @@ type PledgeCollateralParams struct {
Size types.BigInt Size types.BigInt
} }
func (sma StorageMarketActor) PledgeCollateralForSize(act *types.Actor, vmctx types.VMContext, param *PledgeCollateralParams) ([]byte, ActorError) { func (spa StoragePowerActor) PledgeCollateralForSize(act *types.Actor, vmctx types.VMContext, param *PledgeCollateralParams) ([]byte, ActorError) {
var self StorageMarketState var self StoragePowerState
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil { if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
return nil, err return nil, err
} }
@ -433,20 +432,20 @@ func pledgeCollateralForSize(vmctx types.VMContext, size, totalStorage types.Big
return types.BigAdd(powerCollateral, perCapCollateral), nil return types.BigAdd(powerCollateral, perCapCollateral), nil
} }
func MinerSetHas(ctx context.Context, vmctx types.VMContext, rcid cid.Cid, maddr address.Address) (bool, aerrors.ActorError) { func MinerSetHas(vmctx types.VMContext, rcid cid.Cid, maddr address.Address) (bool, aerrors.ActorError) {
nd, err := hamt.LoadNode(ctx, vmctx.Ipld(), rcid) nd, err := hamt.LoadNode(vmctx.Context(), vmctx.Ipld(), rcid)
if err != nil { 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 { switch err {
case hamt.ErrNotFound: case hamt.ErrNotFound:
return false, nil return false, nil
case nil: case nil:
return true, nil return true, nil
default: 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) { 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) nd, err := hamt.LoadNode(ctx, vmctx.Ipld(), rcid)
if err != nil { 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()) mkey := string(maddr.Bytes())
err = nd.Find(ctx, mkey, nil) err = nd.Find(ctx, mkey, nil)
if err == 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) { 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 { 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 { 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) c, err := vmctx.Ipld().Put(ctx, nd)
if err != nil { 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 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) { 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) nd, err := hamt.LoadNode(ctx, vmctx.Ipld(), rcid)
if err != nil { 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()) mkey := string(maddr.Bytes())
@ -515,17 +514,17 @@ func MinerSetRemove(ctx context.Context, vmctx types.VMContext, rcid cid.Cid, ma
case hamt.ErrNotFound: case hamt.ErrNotFound:
return cid.Undef, aerrors.New(1, "miner not found in set on delete") return cid.Undef, aerrors.New(1, "miner not found in set on delete")
default: 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: case nil:
} }
if err := nd.Flush(ctx); err != 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) c, err := vmctx.Ipld().Put(ctx, nd)
if err != nil { 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 return c, nil

View File

@ -37,7 +37,7 @@ func TestStorageMarketCreateAndSlashMiner(t *testing.T) {
// cheating the bootstrapping problem // cheating the bootstrapping problem
cheatStorageMarketTotal(t, h.vm, h.cs.Blockstore()) 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), types.NewInt(500000),
&CreateStorageMinerParams{ &CreateStorageMinerParams{
Owner: ownerAddr, 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}) &IsMinerParam{Addr: minerAddr})
ApplyOK(t, ret) 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}) &PowerLookupParams{Miner: minerAddr})
ApplyOK(t, ret) ApplyOK(t, ret)
power := types.BigFromBytes(ret.Return) 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, b1)
signBlock(t, h.w, workerAddr, b2) signBlock(t, h.w, workerAddr, b2)
ret, _ := h.Invoke(t, ownerAddr, StorageMarketAddress, SMAMethods.ArbitrateConsensusFault, ret, _ := h.Invoke(t, ownerAddr, StorageMarketAddress, SPAMethods.ArbitrateConsensusFault,
&ArbitrateConsensusFaultParams{ &ArbitrateConsensusFaultParams{
Block1: b1, Block1: b1,
Block2: b2, 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}) &PowerLookupParams{Miner: minerAddr})
assert.Equal(t, ret.ExitCode, byte(1)) 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) ApplyOK(t, ret)
assert.Equal(t, ret.Return, cbg.CborBoolFalse) 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) cst := hamt.CSTFromBstore(bs)
var smastate StorageMarketState var smastate StoragePowerState
if err := cst.Get(context.TODO(), sma.Head, &smastate); err != nil { if err := cst.Get(context.TODO(), sma.Head, &smastate); err != nil {
t.Fatal(err) 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) cs := store.NewChainStore(bs, nil)
// TODO: should probabaly mock out the randomness bit, nil works for now // 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 { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -65,7 +65,7 @@ func TestVMInvokeMethod(t *testing.T) {
from := addrs[0] from := addrs[0]
var err error var err error
cenc, err := SerializeParams(&StorageMinerConstructorParams{}) cenc, err := SerializeParams(&StorageMinerConstructorParams{Owner: from, Worker: from})
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -116,6 +116,7 @@ func TestStorageMarketActorCreateMiner(t *testing.T) {
cheatStorageMarketTotal(t, vm, bs) cheatStorageMarketTotal(t, vm, bs)
params := &StorageMinerConstructorParams{ params := &StorageMinerConstructorParams{
Owner: maddr,
Worker: maddr, Worker: maddr,
SectorSize: types.NewInt(build.SectorSize), SectorSize: types.NewInt(build.SectorSize),
PeerID: "fakepeerid", PeerID: "fakepeerid",
@ -129,7 +130,7 @@ func TestStorageMarketActorCreateMiner(t *testing.T) {
msg := &types.Message{ msg := &types.Message{
To: StorageMarketAddress, To: StorageMarketAddress,
From: from, From: from,
Method: SMAMethods.CreateStorageMiner, Method: SPAMethods.CreateStorageMiner,
Params: enc, Params: enc,
GasPrice: types.NewInt(1), GasPrice: types.NewInt(1),
GasLimit: types.NewInt(10000), GasLimit: types.NewInt(10000),

View File

@ -103,7 +103,7 @@ func Absorb(err error, retCode uint8, msg string) ActorError {
fatal: true, fatal: true,
retCode: 0, 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), frame: xerrors.Caller(1),
err: err, err: err,
} }
@ -142,3 +142,28 @@ func Escalate(err error, msg string) ActorError {
err: err, 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 return nil
} }
func (t *StorageMarketState) MarshalCBOR(w io.Writer) error { func (t *StoragePowerState) MarshalCBOR(w io.Writer) error {
if t == nil { if t == nil {
_, err := w.Write(cbg.CborNull) _, err := w.Write(cbg.CborNull)
return err return err
@ -2406,7 +2406,7 @@ func (t *StorageMarketState) MarshalCBOR(w io.Writer) error {
return nil return nil
} }
func (t *StorageMarketState) UnmarshalCBOR(r io.Reader) error { func (t *StoragePowerState) UnmarshalCBOR(r io.Reader) error {
br := cbg.GetPeeker(r) br := cbg.GetPeeker(r)
maj, extra, err := cbg.CborReadHeader(br) maj, extra, err := cbg.CborReadHeader(br)

View File

@ -158,7 +158,7 @@ func NewHarness(t *testing.T, options ...HarnessOpt) *Harness {
t.Fatal(err) t.Fatal(err)
} }
h.cs = store.NewChainStore(h.bs, nil) 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 { if err != nil {
t.Fatal(err) 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 { func (a Address) MarshalCBOR(w io.Writer) error {
if a == Undef {
return fmt.Errorf("cannot marshal undefined address")
}
abytes := a.Bytes() abytes := a.Bytes()
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(abytes)))); err != nil { if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(abytes)))); err != nil {
return err return err
@ -360,6 +364,9 @@ func (a *Address) UnmarshalCBOR(br io.Reader) error {
if err != nil { if err != nil {
return err return err
} }
if addr == Undef {
return fmt.Errorf("cbor input should not contain empty addresses")
}
*a = addr *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 // 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 { 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() bestH := e.tsc.best().Height()
if bestH >= h+uint64(confidence) { if bestH >= h+uint64(confidence) {
ts, err := e.tsc.get(h) ts, err := e.tsc.getNonNull(h)
if err != nil { if err != nil {
log.Warnf("events.ChainAt: calling HandleFunc with nil tipset, not found in cache: %s", err) 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() bestH = e.tsc.best().Height()
} }
defer e.lk.Unlock()
if bestH >= h+uint64(confidence)+e.gcConfidence { if bestH >= h+uint64(confidence)+e.gcConfidence {
return nil 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 { func makeTs(t *testing.T, h uint64, msgcid cid.Cid) *types.TipSet {
a, _ := address.NewFromString("t00")
ts, err := types.NewTipSet([]*types.BlockHeader{ ts, err := types.NewTipSet([]*types.BlockHeader{
{ {
Height: h, Height: h,
Miner: a,
ParentStateRoot: dummyCid, ParentStateRoot: dummyCid,
Messages: msgcid, Messages: msgcid,
@ -432,6 +434,35 @@ func TestAtChainedConfidence(t *testing.T) {
require.Equal(t, false, reverted) 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) { func TestCalled(t *testing.T) {
fcs := &fakeCS{ fcs := &fakeCS{
t: t, 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) fcs.advance(0, 3, map[int]cid.Cid{ // msg at H=6; H=8 (confidence=2)
0: fcs.fakeMsgs(fakeMsg{ 0: fcs.fakeMsgs(fakeMsg{
bmsgs: []*types.Message{ 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{ n2msg := fcs.fakeMsgs(fakeMsg{
bmsgs: []*types.Message{ 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 fcs.advance(0, 1, map[int]cid.Cid{ // msg at H=16; H=16
0: fcs.fakeMsgs(fakeMsg{ 0: fcs.fakeMsgs(fakeMsg{
bmsgs: []*types.Message{ 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 fcs.advance(0, 4, map[int]cid.Cid{ // msg at H=26; H=29
0: fcs.fakeMsgs(fakeMsg{ 0: fcs.fakeMsgs(fakeMsg{
bmsgs: []*types.Message{ 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 fcs.advance(0, 4, map[int]cid.Cid{ // msg at H=26; H=29
0: fcs.fakeMsgs(fakeMsg{ 0: fcs.fakeMsgs(fakeMsg{
bmsgs: []*types.Message{ 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{ fcs.advance(0, 10, map[int]cid.Cid{
1: fcs.fakeMsgs(fakeMsg{ 1: fcs.fakeMsgs(fakeMsg{
bmsgs: []*types.Message{ bmsgs: []*types.Message{
{To: t0123, Method: 5, Nonce: 1}, {To: t0123, From: t0123, Method: 5, Nonce: 1},
}, },
}), }),
2: fcs.fakeMsgs(fakeMsg{ 2: fcs.fakeMsgs(fakeMsg{
bmsgs: []*types.Message{ 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 ( import (
"context" "context"
"github.com/stretchr/testify/require"
"testing" "testing"
"github.com/stretchr/testify/require"
"github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/types" "github.com/filecoin-project/go-lotus/chain/types"
) )
@ -16,8 +18,11 @@ func TestTsCache(t *testing.T) {
h := uint64(75) h := uint64(75)
a, _ := address.NewFromString("t00")
add := func() { add := func() {
ts, err := types.NewTipSet([]*types.BlockHeader{{ ts, err := types.NewTipSet([]*types.BlockHeader{{
Miner: a,
Height: h, Height: h,
ParentStateRoot: dummyCid, ParentStateRoot: dummyCid,
Messages: dummyCid, Messages: dummyCid,
@ -54,8 +59,10 @@ func TestTsCacheNulls(t *testing.T) {
h := uint64(75) h := uint64(75)
a, _ := address.NewFromString("t00")
add := func() { add := func() {
ts, err := types.NewTipSet([]*types.BlockHeader{{ ts, err := types.NewTipSet([]*types.BlockHeader{{
Miner: a,
Height: h, Height: h,
ParentStateRoot: dummyCid, ParentStateRoot: dummyCid,
Messages: 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 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) 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 next.BLSAggregate = aggSig
pweight := sm.ChainStore().Weight(parents) pweight, err := sm.ChainStore().Weight(ctx, parents)
next.ParentWeight = types.NewInt(pweight) if err != nil {
return nil, err
}
next.ParentWeight = pweight
cst := hamt.CSTFromBstore(sm.ChainStore().Blockstore()) cst := hamt.CSTFromBstore(sm.ChainStore().Blockstore())
tree, err := state.LoadStateTree(cst, st) tree, err := state.LoadStateTree(cst, st)

View File

@ -143,7 +143,7 @@ func SetupStorageMarketActor(bs bstore.Blockstore) (*types.Actor, error) {
return nil, err return nil, err
} }
sms := &actors.StorageMarketState{ sms := &actors.StoragePowerState{
Miners: emptyhamt, Miners: emptyhamt,
TotalStorage: types.NewInt(0), 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) { 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 { 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)
} }
@ -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 // TODO: hardcoding 7000000 here is a little fragile, it changes any
// time anyone changes the initial account allocations // 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 { if err != nil {
return cid.Undef, xerrors.Errorf("failed to create genesis miner: %w", err) 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)}) 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 { if err != nil {
return cid.Undef, xerrors.Errorf("failed to update total storage: %w", err) 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") log.Error("Add with duplicate nonce")
return xerrors.Errorf("message to %s with nonce %d already in mpool") 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 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: case notif := <-notifs:
n := notif[len(notif)-1] n := notif[len(notif)-1]
w, err := chain.ChainTipSetWeight(ctx, n.Val)
if err != nil {
return err
}
m := message{ m := message{
Cids: n.Val.Cids(), Cids: n.Val.Cids(),
Blocks: n.Val.Blocks(), Blocks: n.Val.Blocks(),
Height: n.Val.Height(), Height: n.Val.Height(),
Weight: n.Val.Weight(), Weight: w,
NodeName: nickname, NodeName: nickname,
} }

View File

@ -4,16 +4,17 @@ import (
"context" "context"
"fmt" "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" "github.com/ipfs/go-cid"
"golang.org/x/xerrors" "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) { 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 { 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)
} }
@ -55,7 +56,7 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types.
state := ts.ParentState() 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()) 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() 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 { if err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("instantiating VM failed: %w", err) return cid.Undef, cid.Undef, xerrors.Errorf("instantiating VM failed: %w", err)
} }

View File

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

View File

@ -7,9 +7,12 @@ import (
"fmt" "fmt"
"sync" "sync"
"github.com/filecoin-project/go-lotus/chain/vm"
"github.com/filecoin-project/go-lotus/build" "github.com/filecoin-project/go-lotus/build"
"github.com/filecoin-project/go-lotus/chain/address" "github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/state" "github.com/filecoin-project/go-lotus/chain/state"
"go.opencensus.io/trace"
"go.uber.org/zap" "go.uber.org/zap"
amt "github.com/filecoin-project/go-amt-ipld" amt "github.com/filecoin-project/go-amt-ipld"
@ -182,14 +185,14 @@ func (cs *ChainStore) SetGenesis(b *types.BlockHeader) error {
return err return err
} }
if err := cs.PutTipSet(ts); err != nil { if err := cs.PutTipSet(context.TODO(), ts); err != nil {
return err return err
} }
return cs.ds.Put(dstore.NewKey("0"), b.Cid().Bytes()) 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() { for _, b := range ts.Blocks() {
if err := cs.PersistBlockHeader(b); err != nil { if err := cs.PersistBlockHeader(b); err != nil {
return err 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()) 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 errors.Wrap(err, "MaybeTakeHeavierTipSet failed in PutTipSet")
} }
return nil return nil
} }
func (cs *ChainStore) MaybeTakeHeavierTipSet(ts *types.TipSet) error { func (cs *ChainStore) MaybeTakeHeavierTipSet(ctx context.Context, ts *types.TipSet) error {
cs.heaviestLk.Lock() cs.heaviestLk.Lock()
defer cs.heaviestLk.Unlock() 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 // 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 // difference between 'bootstrap sync' and 'caught up' sync, we need
// some other heuristic. // some other heuristic.
@ -261,7 +273,7 @@ func (cs *ChainStore) takeHeaviestTipSet(ts *types.TipSet) error {
new: ts, new: ts,
} }
} else { } 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()) 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 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 { func (cs *ChainStore) GetHeaviestTipSet() *types.TipSet {
cs.heaviestLk.Lock() cs.heaviestLk.Lock()
defer cs.heaviestLk.Unlock() defer cs.heaviestLk.Unlock()
@ -469,7 +477,7 @@ func (cs *ChainStore) expandTipset(b *types.BlockHeader) (*types.TipSet, error)
return types.NewTipSet(all) 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 { if err := cs.PersistBlockHeader(b); err != nil {
return err return err
} }
@ -479,7 +487,7 @@ func (cs *ChainStore) AddBlock(b *types.BlockHeader) error {
return err return err
} }
if err := cs.MaybeTakeHeavierTipSet(ts); err != nil { if err := cs.MaybeTakeHeavierTipSet(ctx, ts); err != nil {
return errors.Wrap(err, "MaybeTakeHeavierTipSet failed") 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) { 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 { if lb < 0 {
return nil, fmt.Errorf("negative lookback parameters are not valid (got %d)", lb) 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 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 { 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) log.Warnf("invalid block received: %s", err)
return 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 var bcids, scids []cbg.CBORMarshaler
for _, m := range fblk.BlsMessages { for _, m := range fblk.BlsMessages {
c := cbg.CborCid(m.Cid()) c := cbg.CborCid(m.Cid())
@ -147,6 +147,14 @@ func (syncer *Syncer) validateMsgMeta(fblk *types.FullBlock) error {
return nil 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) { func (syncer *Syncer) InformNewBlock(from peer.ID, blk *types.FullBlock) {
// TODO: search for other blocks that could form a tipset with this block // TODO: search for other blocks that could form a tipset with this block
// and then send that tipset to InformNewHead // and then send that tipset to InformNewHead
@ -253,7 +261,7 @@ func computeMsgMeta(bs amt.Blocks, bmsgCids, smsgCids []cbg.CBORMarshaler) (cid.
return mrcid, nil 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 var headsArr []*types.TipSet
for _, ts := range heads { for _, ts := range heads {
headsArr = append(headsArr, ts) 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") 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 sel = cur
} }
} }
@ -344,7 +361,7 @@ func (syncer *Syncer) Sync(ctx context.Context, maybeHead *types.TipSet) error {
return xerrors.Errorf("collectChain failed: %w", err) 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) 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{ ret, err := syncer.sm.Call(ctx, &types.Message{
To: actors.StorageMarketAddress, To: actors.StorageMarketAddress,
From: maddr, From: maddr,
Method: actors.SMAMethods.IsMiner, Method: actors.SPAMethods.IsMiner,
Params: enc, Params: enc,
}, baseTs) }, baseTs)
if err != nil { 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) 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) 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) 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) 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 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 var digests []bls.Digest
for _, c := range msgs { for _, c := range msgs {
digests = append(digests, bls.Hash(bls.Message(c.Bytes()))) 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) require.NoError(t, err)
blks[i] = mts.TipSet 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() r, err := tu.g.YieldRepo()
@ -94,8 +91,38 @@ func (tu *syncTestUtil) Shutdown() {
tu.cancel() 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) { func (tu *syncTestUtil) pushFtsAndWait(to int, fts *store.FullTipSet, wait bool) {
// TODO: would be great if we could pass a whole tipset here... // 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 { for _, fb := range fts.Blocks {
var b types.BlockMsg 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) b.BlsMessages = append(b.BlsMessages, c)
} }
require.NoError(tu.t, tu.nds[to].ChainSubmitBlock(tu.ctx, &b)) err := tu.nds[to].SyncSubmitBlock(tu.ctx, &b)
if experr {
} require.Error(tu.t, err, "expected submit block to fail")
} else {
if wait {
start := time.Now()
h, err := tu.nds[to].ChainHead(tu.ctx)
require.NoError(tu.t, err) 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 { if miners == nil {
for i := range tu.g.Miners { for i := range tu.g.Miners {
miners = append(miners, i) 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) mts, err := tu.g.NextTipSetFromMiners(blk.TipSet(), maddrs)
require.NoError(tu.t, err) require.NoError(tu.t, err)
if fail {
tu.pushTsExpectErr(src, mts.TipSet, true)
} else {
tu.pushFtsAndWait(src, mts.TipSet, wait) tu.pushFtsAndWait(src, mts.TipSet, wait)
}
return mts.TipSet return mts.TipSet
} }
func (tu *syncTestUtil) mineNewBlock(src int, miners []int) { 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 tu.g.CurTipset = mts
} }
@ -197,7 +218,9 @@ func (tu *syncTestUtil) addSourceNode(gen int) {
lastTs := blocks[len(blocks)-1].Blocks lastTs := blocks[len(blocks)-1].Blocks
for _, lastB := range lastTs { 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) require.NoError(tu.t, err)
} }
@ -368,12 +391,17 @@ func TestSyncBadTimestamp(t *testing.T) {
return pts.MinTimestamp() + 2 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.Timestamper = nil
tu.g.ResyncBankerNonce(a1.TipSet()) 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) tu.waitUntilSync(0, client)
@ -427,16 +455,16 @@ func TestSyncFork(t *testing.T) {
fmt.Println("Mining base: ", base.TipSet().Cids(), base.TipSet().Height()) fmt.Println("Mining base: ", base.TipSet().Cids(), base.TipSet().Height())
// The two nodes fork at this point into 'a' and 'b' // The two nodes fork at this point into 'a' and 'b'
a1 := tu.mineOnBlock(base, p1, []int{0}, true) a1 := tu.mineOnBlock(base, p1, []int{0}, true, false)
a := tu.mineOnBlock(a1, p1, []int{0}, true) a := tu.mineOnBlock(a1, p1, []int{0}, true, false)
a = tu.mineOnBlock(a, p1, []int{0}, true) a = tu.mineOnBlock(a, p1, []int{0}, true, false)
tu.g.ResyncBankerNonce(a1.TipSet()) tu.g.ResyncBankerNonce(a1.TipSet())
// chain B will now be heaviest // chain B will now be heaviest
b := tu.mineOnBlock(base, p2, []int{1}, true) b := tu.mineOnBlock(base, p2, []int{1}, true, false)
b = tu.mineOnBlock(b, p2, []int{1}, true) b = tu.mineOnBlock(b, p2, []int{1}, true, false)
b = tu.mineOnBlock(b, p2, []int{1}, true) b = tu.mineOnBlock(b, p2, []int{1}, true, false)
b = tu.mineOnBlock(b, p2, []int{1}, true) b = tu.mineOnBlock(b, p2, []int{1}, true, false)
fmt.Println("A: ", a.Cids(), a.TipSet().Height()) fmt.Println("A: ", a.Cids(), a.TipSet().Height())
fmt.Println("B: ", b.Cids(), b.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) { func fromCborBytes(buf []byte) (BigInt, error) {
if len(buf) == 0 {
return NewInt(0), nil
}
var negative bool var negative bool
switch buf[0] { switch buf[0] {
case 0: case 0:

View File

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

View File

@ -2,12 +2,14 @@ package types
import ( import (
"bytes" "bytes"
"context"
"crypto/sha256" "crypto/sha256"
"math/big" "math/big"
block "github.com/ipfs/go-block-format" block "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/multiformats/go-multihash" "github.com/multiformats/go-multihash"
"go.opencensus.io/trace"
xerrors "golang.org/x/xerrors" xerrors "golang.org/x/xerrors"
"github.com/filecoin-project/go-lotus/chain/address" "github.com/filecoin-project/go-lotus/chain/address"
@ -98,7 +100,10 @@ func (blk *BlockHeader) SigningBytes() ([]byte, error) {
return blkcopy.Serialize() 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() sigb, err := blk.SigningBytes()
if err != nil { if err != nil {
return xerrors.Errorf("failed to get block signing bytes: %w", err) 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") return nil, fmt.Errorf("cannot create tipset with mismatching heights")
} }
ts.cids = append(ts.cids, b.Cid()) ts.cids = append(ts.cids, b.Cid())
// TODO: ensure the same parents
} }
ts.height = blks[0].Height ts.height = blks[0].Height
@ -89,12 +91,6 @@ func (ts *TipSet) Height() uint64 {
return ts.height 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 { func (ts *TipSet) Parents() []cid.Cid {
return ts.blks[0].Parents return ts.blks[0].Parents
} }

View File

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

View File

@ -30,7 +30,7 @@ func newInvoker() *invoker {
// add builtInCode using: register(cid, singleton) // add builtInCode using: register(cid, singleton)
inv.register(actors.InitActorCodeCid, actors.InitActor{}, actors.InitActorState{}) 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.StorageMinerCodeCid, actors.StorageMinerActor{}, actors.StorageMinerActorState{})
inv.register(actors.MultisigActorCodeCid, actors.MultiSigActor{}, actors.MultiSigActorState{}) inv.register(actors.MultisigActorCodeCid, actors.MultiSigActor{}, actors.MultiSigActorState{})
inv.register(actors.PaymentChannelActorCodeCid, actors.PaymentChannelActor{}, actors.PaymentChannelActorState{}) inv.register(actors.PaymentChannelActorCodeCid, actors.PaymentChannelActor{}, actors.PaymentChannelActorState{})

View File

@ -3,15 +3,16 @@ package vm
import ( import (
"context" "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"
"github.com/filecoin-project/go-lotus/chain/actors/aerrors" "github.com/filecoin-project/go-lotus/chain/actors/aerrors"
"github.com/filecoin-project/go-lotus/chain/address" "github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/state" "github.com/filecoin-project/go-lotus/chain/state"
"github.com/filecoin-project/go-lotus/chain/types" "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() { func init() {

View File

@ -3,6 +3,7 @@ package vm
import ( import (
"context" "context"
"fmt" "fmt"
blockstore "github.com/ipfs/go-ipfs-blockstore"
"math/big" "math/big"
"github.com/filecoin-project/go-lotus/build" "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/actors/aerrors"
"github.com/filecoin-project/go-lotus/chain/address" "github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/state" "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/chain/types"
"github.com/filecoin-project/go-lotus/lib/bufbstore" "github.com/filecoin-project/go-lotus/lib/bufbstore"
cbg "github.com/whyrusleeping/cbor-gen" 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 { type hBlocks interface {
GetBlock(context.Context, cid.Cid) (block.Block, error) GetBlock(context.Context, cid.Cid) (block.Block, error)
AddBlock(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 { type VM struct {
cstate *state.StateTree cstate *state.StateTree
base cid.Cid base cid.Cid
cs *store.ChainStore
cst *hamt.CborIpldStore cst *hamt.CborIpldStore
buf *bufbstore.BufferedBS buf *bufbstore.BufferedBS
blockHeight uint64 blockHeight uint64
@ -305,8 +308,8 @@ type VM struct {
rand Rand rand Rand
} }
func NewVM(base cid.Cid, height uint64, r Rand, maddr address.Address, cs *store.ChainStore) (*VM, error) { func NewVM(base cid.Cid, height uint64, r Rand, maddr address.Address, cbs blockstore.Blockstore) (*VM, error) {
buf := bufbstore.NewBufferedBstore(cs.Blockstore()) buf := bufbstore.NewBufferedBstore(cbs)
cst := hamt.CSTFromBstore(buf) cst := hamt.CSTFromBstore(buf)
state, err := state.LoadStateTree(cst, base) state, err := state.LoadStateTree(cst, base)
if err != nil { if err != nil {
@ -316,7 +319,6 @@ func NewVM(base cid.Cid, height uint64, r Rand, maddr address.Address, cs *store
return &VM{ return &VM{
cstate: state, cstate: state,
base: base, base: base,
cs: cs,
cst: cst, cst: cst,
buf: buf, buf: buf,
blockHeight: height, blockHeight: height,
@ -330,27 +332,6 @@ type Rand interface {
GetRandomness(ctx context.Context, h int64) ([]byte, error) 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 { type ApplyRet struct {
types.MessageReceipt types.MessageReceipt
ActorErr aerrors.ActorError ActorErr aerrors.ActorError

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"strings"
"time" "time"
cid "github.com/ipfs/go-cid" cid "github.com/ipfs/go-cid"
@ -279,7 +280,12 @@ var chainListCmd = &cli.Command{
Usage: "View a segment of the chain", Usage: "View a segment of the chain",
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.Uint64Flag{Name: "height"}, &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 { Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx) api, closer, err := GetFullNodeAPI(cctx)
@ -300,15 +306,15 @@ var chainListCmd = &cli.Command{
return err return err
} }
count := cctx.Uint("count") count := cctx.Int("count")
if count < 1 { if count < 1 {
return nil return nil
} }
tss := make([]*types.TipSet, count) tss := make([]*types.TipSet, 0, count)
tss[0] = head tss = append(tss, head)
for i := 1; i < len(tss); i++ { for i := 1; i < count; i++ {
if head.Height() == 0 { if head.Height() == 0 {
break break
} }
@ -318,18 +324,26 @@ var chainListCmd = &cli.Command{
return err return err
} }
tss[i] = head tss = append(tss, head)
} }
for i := len(tss) - 1; i >= 0; i-- { for i := len(tss) - 1; i >= 0; i-- {
mints := tss[i].MinTimestamp() printTipSet(cctx.String("format"), tss[i])
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("]")
} }
return nil 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{ msg := &types.Message{
To: actors.StorageMarketAddress, To: actors.StorageMarketAddress,
From: addr, From: addr,
Method: actors.SMAMethods.CreateStorageMiner, Method: actors.SPAMethods.CreateStorageMiner,
Params: params, Params: params,
Value: types.NewInt(0), Value: types.NewInt(0),
GasPrice: types.NewInt(0), GasPrice: types.NewInt(0),

View File

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

View File

@ -2,11 +2,13 @@ package cli
import ( import (
"fmt" "fmt"
"time"
cid "github.com/ipfs/go-cid"
"gopkg.in/urfave/cli.v2" "gopkg.in/urfave/cli.v2"
"github.com/filecoin-project/go-lotus/api"
"github.com/filecoin-project/go-lotus/chain" "github.com/filecoin-project/go-lotus/chain"
cid "github.com/ipfs/go-cid"
) )
var syncCmd = &cli.Command{ var syncCmd = &cli.Command{
@ -14,6 +16,7 @@ var syncCmd = &cli.Command{
Usage: "Inspect or interact with the chain syncer", Usage: "Inspect or interact with the chain syncer",
Subcommands: []*cli.Command{ Subcommands: []*cli.Command{
syncStatusCmd, syncStatusCmd,
syncWaitCmd,
}, },
} }
@ -49,3 +52,36 @@ var syncStatusCmd = &cli.Command{
return nil 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" "net/http"
"os" "os"
rice "github.com/GeertJohan/go.rice"
logging "github.com/ipfs/go-log" logging "github.com/ipfs/go-log"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2" "gopkg.in/urfave/cli.v2"
@ -89,8 +90,9 @@ var runCmd = &cli.Command{
from: from, from: from,
} }
http.HandleFunc("/", h.index) http.Handle("/", http.FileServer(rice.MustFindBox("site").HTTPBox()))
http.HandleFunc("/send", h.send) http.HandleFunc("/send", h.send)
http.HandleFunc("/sendcoll", h.sendColl)
fmt.Printf("Open http://%s\n", cctx.String("front")) fmt.Printf("Open http://%s\n", cctx.String("front"))
@ -110,13 +112,6 @@ type handler struct {
from address.Address 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) { func (h *handler) send(w http.ResponseWriter, r *http.Request) {
to, err := address.NewFromString(r.FormValue("address")) to, err := address.NewFromString(r.FormValue("address"))
if err != nil { if err != nil {
@ -141,3 +136,33 @@ func (h *handler) send(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(smsg.Cid().String())) 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 package main
import ( import (
"context"
"fmt" "fmt"
"gopkg.in/urfave/cli.v2" "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" lcli "github.com/filecoin-project/go-lotus/cli"
sectorstate "github.com/filecoin-project/go-sectorbuilder/sealing_state"
) )
var infoCmd = &cli.Command{ var infoCmd = &cli.Command{
@ -17,14 +21,40 @@ var infoCmd = &cli.Command{
return err return err
} }
defer closer() defer closer()
api, acloser, err := lcli.GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer acloser()
ctx := lcli.ReqContext(cctx) ctx := lcli.ReqContext(cctx)
aaddr, err := nodeApi.ActorAddresses(ctx) maddr, err := nodeApi.ActorAddress(ctx)
if err != nil { if err != nil {
return err 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 // TODO: grab actr state / info
// * Sector size // * Sector size
// * Sealed sectors (count / bytes) // * Sealed sectors (count / bytes)
@ -32,3 +62,42 @@ var infoCmd = &cli.Command{
return nil 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, From: owner,
Value: collateral, Value: collateral,
Method: actors.SMAMethods.CreateStorageMiner, Method: actors.SPAMethods.CreateStorageMiner,
Params: params, Params: params,
GasLimit: types.NewInt(10000), GasLimit: types.NewInt(10000),
@ -309,6 +309,10 @@ func createStorageMiner(ctx context.Context, api api.FullNode, peerid peer.ID, c
return address.Undef, err 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) addr, err = address.NewFromBytes(mw.Receipt.Return)
if err != nil { if err != nil {
return address.Undef, err return address.Undef, err

View File

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

View File

@ -18,7 +18,7 @@ import (
"github.com/filecoin-project/go-lotus/node/modules/lp2p" "github.com/filecoin-project/go-lotus/node/modules/lp2p"
) )
const topic = "/fil/headnotifs/bafy2bzacedjqrkfbuafakygo6vlkrqozvsju2d5k6g24ry3mjjfxwrvet2636" const topic = "/fil/headnotifs/bafy2bzacecyfz2wfi5a6d4epch6nmedrlan3mdfswgv3y74an5aeqxaq5gqlu"
var upgrader = websocket.Upgrader{ var upgrader = websocket.Upgrader{
WriteBufferSize: 1024, WriteBufferSize: 1024,
@ -49,7 +49,7 @@ func main() {
} }
pi, err := addrutil.ParseAddresses(ctx, []string{ 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 { if err != nil {
panic(err) panic(err)

View File

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

View File

@ -4,6 +4,7 @@ import (
"encoding/binary" "encoding/binary"
"io" "io"
"os" "os"
"sort"
"sync" "sync"
"unsafe" "unsafe"
@ -94,8 +95,22 @@ func (sb *SectorBuilder) SealStatus(sector uint64) (SectorSealingStatus, error)
return sectorbuilder.GetSectorSealingStatusByID(sb.handle, sector) return sectorbuilder.GetSectorSealingStatusByID(sb.handle, sector)
} }
func (sb *SectorBuilder) GetAllStagedSectors() ([]StagedSectorMetadata, error) { func (sb *SectorBuilder) GetAllStagedSectors() ([]uint64, error) {
return sectorbuilder.GetAllStagedSectors(sb.handle) 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) { 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() { async loadInfo() {
const version = await this.state.client.call("Filecoin.Version", []) const version = await this.state.client.call("Filecoin.Version", [])
const peers = await this.state.client.call("Filecoin.NetPeers", []) 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 stActor = await this.props.fullConn.call('Filecoin.StateGetActor', [actor, null])
const actorState = await this.props.fullConn.call('Filecoin.StateReadState', [stActor, null]) const actorState = await this.props.fullConn.call('Filecoin.StateReadState', [stActor, null])
@ -80,9 +80,9 @@ class StorageNode extends React.Component {
} }
async stagedList() { async stagedList() {
let stagedList = await this.state.client.call("Filecoin.SectorsStagedList", []) let stagedList = await this.state.client.call("Filecoin.SectorsList", [])
let staged = await stagedList 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([])) .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]) 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 fx.In
full.ChainAPI full.ChainAPI
full.SyncAPI
full.MpoolAPI full.MpoolAPI
full.WalletAPI full.WalletAPI
full.StateAPI full.StateAPI
@ -154,13 +155,13 @@ func (m *Miner) mine(ctx context.Context) {
return return
} }
base, err := m.GetBestMiningCandidate() base, err := m.GetBestMiningCandidate(ctx)
if err != nil { if err != nil {
log.Errorf("failed to get best mining candidate: %s", err) log.Errorf("failed to get best mining candidate: %s", err)
continue continue
} }
if base.ts.Equals(lastBase.ts) && len(lastBase.tickets) == len(base.tickets) { 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) time.Sleep(build.BlockDelay * time.Second)
continue continue
} }
@ -183,7 +184,7 @@ func (m *Miner) mine(ctx context.Context) {
"time", time.Now(), "duration", time.Now().Sub(btime)) "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) log.Errorf("failed to submit newly mined block: %s", err)
} }
} else { } else {
@ -198,8 +199,8 @@ type MiningBase struct {
tickets []*types.Ticket tickets []*types.Ticket
} }
func (m *Miner) GetBestMiningCandidate() (*MiningBase, error) { func (m *Miner) GetBestMiningCandidate(ctx context.Context) (*MiningBase, error) {
bts, err := m.api.ChainHead(context.TODO()) bts, err := m.api.ChainHead(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -209,7 +210,16 @@ func (m *Miner) GetBestMiningCandidate() (*MiningBase, error) {
return m.lastWork, nil 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 return m.lastWork, nil
} }
} }

View File

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

View File

@ -9,7 +9,6 @@ import (
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
pubsub "github.com/libp2p/go-libp2p-pubsub"
"go.uber.org/fx" "go.uber.org/fx"
) )
@ -19,25 +18,12 @@ type ChainAPI struct {
WalletAPI WalletAPI
Chain *store.ChainStore Chain *store.ChainStore
PubSub *pubsub.PubSub
} }
func (a *ChainAPI) ChainNotify(ctx context.Context) (<-chan []*store.HeadChange, error) { func (a *ChainAPI) ChainNotify(ctx context.Context) (<-chan []*store.HeadChange, error) {
return a.Chain.SubHeadChanges(ctx), nil 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) { func (a *ChainAPI) ChainHead(context.Context) (*types.TipSet, error) {
return a.Chain.GetHeaviestTipSet(), nil 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}) 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{ ret, aerr := a.StateManager.Call(ctx, &types.Message{
From: actors.StorageMarketAddress, From: actors.StorageMarketAddress,
To: actors.StorageMarketAddress, To: actors.StorageMarketAddress,
Method: actors.SMAMethods.PledgeCollateralForSize, Method: actors.SPAMethods.PledgeCollateralForSize,
Params: param, Params: param,
}, ts) }, 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) { 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 { if _, err := a.StateManager.LoadActorState(ctx, actors.StorageMarketAddress, &state, ts); err != nil {
return nil, err return nil, err
} }

View File

@ -5,13 +5,18 @@ import (
"github.com/filecoin-project/go-lotus/api" "github.com/filecoin-project/go-lotus/api"
"github.com/filecoin-project/go-lotus/chain" "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" "go.uber.org/fx"
"golang.org/x/xerrors"
) )
type SyncAPI struct { type SyncAPI struct {
fx.In fx.In
Syncer *chain.Syncer Syncer *chain.Syncer
PubSub *pubsub.PubSub
} }
func (a *SyncAPI) SyncState(ctx context.Context) (*api.SyncState, error) { 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, Height: ss.Height,
}, nil }, 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 Miner *storage.Miner
} }
func (sm *StorageMinerAPI) ActorAddresses(context.Context) ([]address.Address, error) { func (sm *StorageMinerAPI) ActorAddress(context.Context) (address.Address, error) {
return []address.Address{sm.SectorBuilderConfig.Miner}, nil return sm.SectorBuilderConfig.Miner, nil
} }
func (sm *StorageMinerAPI) StoreGarbageData(ctx context.Context) (uint64, error) { 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 // 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() 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