updating faucet url and removing secp256k1 addresses to reduce confusion
This commit is contained in:
commit
2386537dfc
3
.gitignore
vendored
3
.gitignore
vendored
@ -2,8 +2,11 @@
|
||||
/lotus-storage-miner
|
||||
/pond
|
||||
/townhall
|
||||
/fountain
|
||||
/lotuspond/front/node_modules
|
||||
/lotuspond/front/build
|
||||
/cmd/lotus-townhall/townhall/node_modules
|
||||
/cmd/lotus-townhall/townhall/build
|
||||
**/*.h
|
||||
**/*.a
|
||||
**/*.pc
|
||||
|
9
Makefile
9
Makefile
@ -76,6 +76,9 @@ build: lotus lotus-storage-miner
|
||||
|
||||
.PHONY: build
|
||||
|
||||
install:
|
||||
install -C ./lotus /usr/local/bin/lotus
|
||||
install -C ./lotus /usr/local/bin/lotus-storage-miner
|
||||
|
||||
benchmarks:
|
||||
go run github.com/whyrusleeping/bencher ./... > bench.json
|
||||
@ -95,6 +98,12 @@ townhall:
|
||||
go run github.com/GeertJohan/go.rice/rice append --exec townhall -i ./cmd/lotus-townhall
|
||||
.PHONY: townhall
|
||||
|
||||
fountain:
|
||||
rm -f fountain
|
||||
go build -o fountain ./cmd/lotus-fountain
|
||||
go run github.com/GeertJohan/go.rice/rice append --exec fountain -i ./cmd/lotus-fountain
|
||||
.PHONY: fountain
|
||||
|
||||
clean:
|
||||
rm -rf $(CLEAN)
|
||||
-$(MAKE) -C $(BLS_PATH) clean
|
||||
|
48
README.md
48
README.md
@ -11,8 +11,10 @@ All work is tracked via issues. An attempt at keeping an up-to-date view on rema
|
||||
|
||||
## Building
|
||||
|
||||
*Dependencies:*
|
||||
We currently only provide the option to build lotus from source. Binary installation options are coming soon!
|
||||
|
||||
In order to run lotus, please do the following:
|
||||
1. Make sure you have these dependencies installed:
|
||||
- go (1.13 or higher)
|
||||
- gcc (7.4.0 or higher)
|
||||
- git
|
||||
@ -20,19 +22,27 @@ All work is tracked via issues. An attempt at keeping an up-to-date view on rema
|
||||
- jq
|
||||
- pkg-config
|
||||
|
||||
*Building:*
|
||||
|
||||
2. Clone this repo & `cd` into it
|
||||
```
|
||||
$ git clone https://github.com/filecoin-project/lotus.git
|
||||
$ cd lotus/
|
||||
```
|
||||
|
||||
3. Build and install the source code
|
||||
```
|
||||
$ make
|
||||
$ sudo make install
|
||||
```
|
||||
|
||||
Now, you should be able to perform the commands listed below.
|
||||
|
||||
## Devnet
|
||||
|
||||
### Node setup
|
||||
|
||||
If you have run lotus before and want to remove all previous data: `rm -rf ~/.lotus ~/.lotusstorage`
|
||||
|
||||
[You can copy `lotus` and `lotus-storage-miner` to your `$GOPATH/bin` or `$PATH`, or reference all lotus commands below from your local build directory with `./lotus`]
|
||||
|
||||
The following sections describe how to use the lotus CLI. Alternately you can run lotus nodes and miners using the [Pond GUI](#pond).
|
||||
|
||||
### Genesis & Bootstrap
|
||||
@ -58,6 +68,9 @@ You can follow sync status with:
|
||||
$ watch lotus sync status
|
||||
```
|
||||
|
||||
You can view the latest block height along with other network metrics at the [lotus Devnet dashboard](https://lotus-metrics.kittyhawk.wtf/d/z6FtI92Zz/chain?orgId=1&refresh=5s&kiosk).
|
||||
|
||||
[It may take a few minutes for the chain to finish syncing. You will see `Height: 0` until the full chain is synced and validated.]
|
||||
|
||||
### Basics
|
||||
|
||||
@ -67,19 +80,15 @@ $ lotus wallet new bls
|
||||
t3...
|
||||
```
|
||||
|
||||
Grab some funds from faucet - go to http://147.75.80.29:777/, paste the address
|
||||
Grab some funds from faucet - go to https://lotus-faucet.kittyhawk.wtf, paste the address
|
||||
you just created, and press Send.
|
||||
|
||||
(You can also generate a public key address using secp256k1 with
|
||||
`lotus wallet new secp256k1`. BLS signatures use less space so will have lower fees.)
|
||||
|
||||
Check the wallet balance:
|
||||
Check the wallet balance (balance is listed in attoFIL, where 1 attoFIL = 10^-18 FIL):
|
||||
```sh
|
||||
$ lotus wallet balance [optional address (t3...)]
|
||||
```
|
||||
(NOTE: If you see an error like `actor not found` after executing this command,
|
||||
it means that either there are no transactions to this address on chain - using
|
||||
faucet should 'fix' this, or your node isn't fully synced).
|
||||
|
||||
(NOTE: If you see an error like `actor not found` after executing this command, it means that either your node isn't fully synced or there are no transactions to this address yet on chain. If the latter, using the faucet should 'fix' this).
|
||||
|
||||
### Mining
|
||||
|
||||
@ -88,7 +97,7 @@ cover pledge collateral:
|
||||
```sh
|
||||
$ lotus state pledge-collateral
|
||||
1234
|
||||
$ lotus wallet balance t3...
|
||||
$ lotus wallet balance [t3...]
|
||||
8999
|
||||
```
|
||||
(Balance must be higher than the returned pledge collateral for the next step to work)
|
||||
@ -129,12 +138,6 @@ $ lotus-storage-miner state power <miner>
|
||||
$ lotus-storage-miner state sectors <miner>
|
||||
```
|
||||
|
||||
You can view a list of miners with:
|
||||
|
||||
```sh
|
||||
$ lotus state list-miners
|
||||
```
|
||||
|
||||
### Stage Data
|
||||
|
||||
Import some data:
|
||||
@ -158,14 +161,17 @@ $ lotus client local
|
||||
(It is possible for a Client to make a deal with a Miner on the same lotus Node.)
|
||||
|
||||
```sh
|
||||
# List all miners in the system. Choose one to make a deal with.
|
||||
$ lotus state list-miners
|
||||
|
||||
# List asks proposed by a miner
|
||||
$ lotus client query-ask <miner>
|
||||
|
||||
# Propose a deal with a miner
|
||||
# Propose a deal with a miner. Price is in attoFIL/byte/block. Duration is # of blocks.
|
||||
$ lotus client deal <Data CID> <miner> <price> <duration>
|
||||
```
|
||||
|
||||
For example `$ lotus client deal bafkre...qvtjsi t0111 36000 12` proposes a deal to store CID `bafkre...qvtjsi` with miner `t0111` at price `36000` for a duration of `12` blocks.
|
||||
For example `$ lotus client deal bafkre...qvtjsi t0111 36000 12` proposes a deal to store CID `bafkre...qvtjsi` with miner `t0111` at price `36000` for a duration of `12` blocks. If successful, the `client deal` command will return a deal CID.
|
||||
|
||||
### Search & Retrieval
|
||||
|
||||
|
10
api/api.go
10
api/api.go
@ -50,8 +50,7 @@ type FullNode interface {
|
||||
// ChainNotify returns channel with chain head updates
|
||||
// First message is guaranteed to be of len == 1, and type == 'current'
|
||||
ChainNotify(context.Context) (<-chan []*store.HeadChange, error)
|
||||
ChainHead(context.Context) (*types.TipSet, error) // TODO: check serialization
|
||||
ChainSubmitBlock(ctx context.Context, blk *types.BlockMsg) error // TODO: check serialization
|
||||
ChainHead(context.Context) (*types.TipSet, error)
|
||||
ChainGetRandomness(context.Context, *types.TipSet, []*types.Ticket, int) ([]byte, error)
|
||||
ChainGetBlock(context.Context, cid.Cid) (*types.BlockHeader, error)
|
||||
ChainGetTipSet(context.Context, []cid.Cid) (*types.TipSet, error)
|
||||
@ -62,12 +61,13 @@ type FullNode interface {
|
||||
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
|
||||
ChainSetHead(context.Context, *types.TipSet) error
|
||||
ChainGetGenesis(context.Context) (*types.TipSet, error)
|
||||
ChainTipSetWeight(context.Context, *types.TipSet) (types.BigInt, error)
|
||||
|
||||
// syncer
|
||||
SyncState(context.Context) (*SyncState, error)
|
||||
SyncSubmitBlock(ctx context.Context, blk *types.BlockMsg) error
|
||||
|
||||
// messages
|
||||
|
||||
MpoolPending(context.Context, *types.TipSet) ([]*types.SignedMessage, error)
|
||||
MpoolPush(context.Context, *types.SignedMessage) error // TODO: remove
|
||||
MpoolPushMessage(context.Context, *types.Message) (*types.SignedMessage, error) // get nonce, sign, push
|
||||
@ -150,7 +150,7 @@ type FullNode interface {
|
||||
type StorageMiner interface {
|
||||
Common
|
||||
|
||||
ActorAddresses(context.Context) ([]address.Address, error)
|
||||
ActorAddress(context.Context) (address.Address, error)
|
||||
|
||||
// Temp api for testing
|
||||
StoreGarbageData(context.Context) (uint64, error)
|
||||
@ -159,7 +159,7 @@ type StorageMiner interface {
|
||||
SectorsStatus(context.Context, uint64) (sectorbuilder.SectorSealingStatus, error)
|
||||
|
||||
// List all staged sectors
|
||||
SectorsStagedList(context.Context) ([]sectorbuilder.StagedSectorMetadata, error)
|
||||
SectorsList(context.Context) ([]uint64, error)
|
||||
|
||||
// Seal all staged sectors
|
||||
SectorsStagedSeal(context.Context) error
|
||||
|
@ -38,7 +38,6 @@ type FullNodeStruct struct {
|
||||
|
||||
Internal struct {
|
||||
ChainNotify func(context.Context) (<-chan []*store.HeadChange, error) `perm:"read"`
|
||||
ChainSubmitBlock func(ctx context.Context, blk *types.BlockMsg) error `perm:"write"`
|
||||
ChainHead func(context.Context) (*types.TipSet, error) `perm:"read"`
|
||||
ChainGetRandomness func(context.Context, *types.TipSet, []*types.Ticket, int) ([]byte, error) `perm:"read"`
|
||||
ChainGetBlock func(context.Context, cid.Cid) (*types.BlockHeader, error) `perm:"read"`
|
||||
@ -50,8 +49,10 @@ type FullNodeStruct struct {
|
||||
ChainReadObj func(context.Context, cid.Cid) ([]byte, error) `perm:"read"`
|
||||
ChainSetHead func(context.Context, *types.TipSet) error `perm:"admin"`
|
||||
ChainGetGenesis func(context.Context) (*types.TipSet, error) `perm:"read"`
|
||||
ChainTipSetWeight func(context.Context, *types.TipSet) (types.BigInt, error) `perm:"read"`
|
||||
|
||||
SyncState func(context.Context) (*SyncState, error) `perm:"read"`
|
||||
SyncSubmitBlock func(ctx context.Context, blk *types.BlockMsg) error `perm:"write"`
|
||||
|
||||
MpoolPending func(context.Context, *types.TipSet) ([]*types.SignedMessage, error) `perm:"read"`
|
||||
MpoolPush func(context.Context, *types.SignedMessage) error `perm:"write"`
|
||||
@ -118,12 +119,12 @@ type StorageMinerStruct struct {
|
||||
CommonStruct
|
||||
|
||||
Internal struct {
|
||||
ActorAddresses func(context.Context) ([]address.Address, error) `perm:"read"`
|
||||
ActorAddress func(context.Context) (address.Address, error) `perm:"read"`
|
||||
|
||||
StoreGarbageData func(context.Context) (uint64, error) `perm:"write"`
|
||||
|
||||
SectorsStatus func(context.Context, uint64) (sectorbuilder.SectorSealingStatus, error) `perm:"read"`
|
||||
SectorsStagedList func(context.Context) ([]sectorbuilder.StagedSectorMetadata, error) `perm:"read"`
|
||||
SectorsList func(context.Context) ([]uint64, error) `perm:"read"`
|
||||
SectorsStagedSeal func(context.Context) error `perm:"write"`
|
||||
|
||||
SectorsRefs func(context.Context) (map[string][]SealedRef, error) `perm:"read"`
|
||||
@ -228,10 +229,6 @@ func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, addr address.Addr
|
||||
return c.Internal.MinerCreateBlock(ctx, addr, base, tickets, eproof, msgs, ts)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) ChainSubmitBlock(ctx context.Context, blk *types.BlockMsg) error {
|
||||
return c.Internal.ChainSubmitBlock(ctx, blk)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) ChainHead(ctx context.Context) (*types.TipSet, error) {
|
||||
return c.Internal.ChainHead(ctx)
|
||||
}
|
||||
@ -320,10 +317,18 @@ func (c *FullNodeStruct) ChainGetGenesis(ctx context.Context) (*types.TipSet, er
|
||||
return c.Internal.ChainGetGenesis(ctx)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) ChainTipSetWeight(ctx context.Context, ts *types.TipSet) (types.BigInt, error) {
|
||||
return c.Internal.ChainTipSetWeight(ctx, ts)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) SyncState(ctx context.Context) (*SyncState, error) {
|
||||
return c.Internal.SyncState(ctx)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) SyncSubmitBlock(ctx context.Context, blk *types.BlockMsg) error {
|
||||
return c.Internal.SyncSubmitBlock(ctx, blk)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) StateMinerSectors(ctx context.Context, addr address.Address) ([]*SectorInfo, error) {
|
||||
return c.Internal.StateMinerSectors(ctx, addr)
|
||||
}
|
||||
@ -426,8 +431,8 @@ func (c *FullNodeStruct) PaychVoucherSubmit(ctx context.Context, ch address.Addr
|
||||
return c.Internal.PaychVoucherSubmit(ctx, ch, sv)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) ActorAddresses(ctx context.Context) ([]address.Address, error) {
|
||||
return c.Internal.ActorAddresses(ctx)
|
||||
func (c *StorageMinerStruct) ActorAddress(ctx context.Context) (address.Address, error) {
|
||||
return c.Internal.ActorAddress(ctx)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) StoreGarbageData(ctx context.Context) (uint64, error) {
|
||||
@ -440,8 +445,8 @@ func (c *StorageMinerStruct) SectorsStatus(ctx context.Context, sid uint64) (sec
|
||||
}
|
||||
|
||||
// List all staged sectors
|
||||
func (c *StorageMinerStruct) SectorsStagedList(ctx context.Context) ([]sectorbuilder.StagedSectorMetadata, error) {
|
||||
return c.Internal.SectorsStagedList(ctx)
|
||||
func (c *StorageMinerStruct) SectorsList(ctx context.Context) ([]uint64, error) {
|
||||
return c.Internal.SectorsList(ctx)
|
||||
}
|
||||
|
||||
// Seal all staged sectors
|
||||
|
@ -1 +1 @@
|
||||
/ip4/147.75.80.17/tcp/1347/p2p/12D3KooWJdB9SxJfUb327CsBMCyEqzkDCHaqcrwaHGZ88wUuoc5F
|
||||
/ip4/147.75.80.17/tcp/1347/p2p/12D3KooWB54edC5VTSaQpvcYbqG8XKAziP77Natf75CieA5xKDJx
|
||||
|
@ -1 +1 @@
|
||||
/ip4/147.75.80.29/tcp/1347/p2p/12D3KooWAShT7qd3oM7QPC8AsQffs6ThH69fZGui4xCW68E35rDP
|
||||
/ip4/147.75.80.29/tcp/1347/p2p/12D3KooWGdsbvHwscFKT1kqBeeooPe6EneJvjXzTrWSzwKhc1ssn
|
||||
|
Binary file not shown.
@ -38,6 +38,9 @@ const AllowableClockDrift = BlockDelay * 2
|
||||
// Blocks
|
||||
const ForkLengthThreshold = 100
|
||||
|
||||
// Blocks (e)
|
||||
const BlocksPerEpoch = 1
|
||||
|
||||
// /////
|
||||
// Proofs / Mining
|
||||
|
||||
|
@ -185,7 +185,7 @@ func (sma StorageMinerActor) StorageMinerConstructor(act *types.Actor, vmctx typ
|
||||
sectors := amt.NewAMT(types.WrapStorage(vmctx.Storage()))
|
||||
scid, serr := sectors.Flush()
|
||||
if serr != nil {
|
||||
return nil, aerrors.Escalate(serr, "initializing AMT")
|
||||
return nil, aerrors.HandleExternalError(serr, "initializing AMT")
|
||||
}
|
||||
|
||||
self.Sectors = scid
|
||||
@ -270,7 +270,7 @@ func (sma StorageMinerActor) CommitSector(act *types.Actor, vmctx types.VMContex
|
||||
// time to prove than large sectors do. Sector size is selected when pledging.
|
||||
pss, lerr := amt.LoadAMT(types.WrapStorage(vmctx.Storage()), self.ProvingSet)
|
||||
if lerr != nil {
|
||||
return nil, aerrors.Escalate(lerr, "could not load proving set node")
|
||||
return nil, aerrors.HandleExternalError(lerr, "could not load proving set node")
|
||||
}
|
||||
|
||||
if pss.Count == 0 {
|
||||
@ -366,7 +366,7 @@ func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext,
|
||||
|
||||
pss, lerr := amt.LoadAMT(types.WrapStorage(vmctx.Storage()), self.ProvingSet)
|
||||
if lerr != nil {
|
||||
return nil, aerrors.Escalate(lerr, "could not load proving set node")
|
||||
return nil, aerrors.HandleExternalError(lerr, "could not load proving set node")
|
||||
}
|
||||
|
||||
var sectorInfos []sectorbuilder.SectorInfo
|
||||
@ -409,19 +409,19 @@ func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext,
|
||||
|
||||
ss, lerr := amt.LoadAMT(types.WrapStorage(vmctx.Storage()), self.ProvingSet)
|
||||
if lerr != nil {
|
||||
return nil, aerrors.Escalate(lerr, "could not load proving set node")
|
||||
return nil, aerrors.HandleExternalError(lerr, "could not load proving set node")
|
||||
}
|
||||
|
||||
if err := ss.BatchDelete(params.DoneSet.All()); err != nil {
|
||||
// TODO: this could fail for system reasons (block not found) or for
|
||||
// bad user input reasons (e.g. bad doneset). The latter should be a
|
||||
// non-fatal error
|
||||
return nil, aerrors.Escalate(err, "failed to delete sectors in done set")
|
||||
return nil, aerrors.HandleExternalError(err, "failed to delete sectors in done set")
|
||||
}
|
||||
|
||||
self.ProvingSet, lerr = ss.Flush()
|
||||
if lerr != nil {
|
||||
return nil, aerrors.Escalate(lerr, "could not flush AMT")
|
||||
return nil, aerrors.HandleExternalError(lerr, "could not flush AMT")
|
||||
}
|
||||
|
||||
oldPower := self.Power
|
||||
@ -433,7 +433,7 @@ func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = vmctx.Send(StorageMarketAddress, SMAMethods.UpdateStorage, types.NewInt(0), enc)
|
||||
_, err = vmctx.Send(StorageMarketAddress, SPAMethods.UpdateStorage, types.NewInt(0), enc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -474,16 +474,16 @@ func SectorIsUnique(ctx context.Context, s types.Storage, sroot cid.Cid, sid uin
|
||||
func AddToSectorSet(ctx context.Context, s types.Storage, ss cid.Cid, sectorID uint64, commR, commD []byte) (cid.Cid, ActorError) {
|
||||
ssr, err := amt.LoadAMT(types.WrapStorage(s), ss)
|
||||
if err != nil {
|
||||
return cid.Undef, aerrors.Escalate(err, "could not load sector set node")
|
||||
return cid.Undef, aerrors.HandleExternalError(err, "could not load sector set node")
|
||||
}
|
||||
|
||||
if err := ssr.Set(sectorID, [][]byte{commR, commD}); err != nil {
|
||||
return cid.Undef, aerrors.Escalate(err, "failed to set commitment in sector set")
|
||||
return cid.Undef, aerrors.HandleExternalError(err, "failed to set commitment in sector set")
|
||||
}
|
||||
|
||||
ncid, err := ssr.Flush()
|
||||
if err != nil {
|
||||
return cid.Undef, aerrors.Escalate(err, "failed to flush sector set")
|
||||
return cid.Undef, aerrors.HandleExternalError(err, "failed to flush sector set")
|
||||
}
|
||||
|
||||
return ncid, nil
|
||||
@ -492,7 +492,7 @@ func AddToSectorSet(ctx context.Context, s types.Storage, ss cid.Cid, sectorID u
|
||||
func GetFromSectorSet(ctx context.Context, s types.Storage, ss cid.Cid, sectorID uint64) (bool, []byte, []byte, ActorError) {
|
||||
ssr, err := amt.LoadAMT(types.WrapStorage(s), ss)
|
||||
if err != nil {
|
||||
return false, nil, nil, aerrors.Escalate(err, "could not load sector set node")
|
||||
return false, nil, nil, aerrors.HandleExternalError(err, "could not load sector set node")
|
||||
}
|
||||
|
||||
var comms [][]byte
|
||||
@ -501,11 +501,11 @@ func GetFromSectorSet(ctx context.Context, s types.Storage, ss cid.Cid, sectorID
|
||||
if _, ok := err.(*amt.ErrNotFound); ok {
|
||||
return false, nil, nil, nil
|
||||
}
|
||||
return false, nil, nil, aerrors.Escalate(err, "failed to find sector in sector set")
|
||||
return false, nil, nil, aerrors.HandleExternalError(err, "failed to find sector in sector set")
|
||||
}
|
||||
|
||||
if len(comms) != 2 {
|
||||
return false, nil, nil, aerrors.Escalate(xerrors.New("sector set entry should only have 2 elements"), "")
|
||||
return false, nil, nil, aerrors.Newf(20, "sector set entry should only have 2 elements")
|
||||
}
|
||||
|
||||
return true, comms[0], comms[1], nil
|
||||
@ -514,7 +514,7 @@ func GetFromSectorSet(ctx context.Context, s types.Storage, ss cid.Cid, sectorID
|
||||
func ValidatePoRep(maddr address.Address, ssize types.BigInt, params *CommitSectorParams) (bool, ActorError) {
|
||||
ok, err := sectorbuilder.VerifySeal(ssize.Uint64(), params.CommR, params.CommD, params.CommRStar, maddr, params.SectorID, params.Proof)
|
||||
if err != nil {
|
||||
return false, aerrors.Escalate(err, "verify seal failed")
|
||||
return false, aerrors.Absorb(err, 25, "verify seal failed")
|
||||
}
|
||||
|
||||
return ok, nil
|
||||
@ -659,11 +659,11 @@ func (sma StorageMinerActor) PaymentVerifyInclusion(act *types.Actor, vmctx type
|
||||
|
||||
var voucherData PieceInclVoucherData
|
||||
if err := cbor.DecodeInto(params.Extra, &voucherData); err != nil {
|
||||
return nil, aerrors.Escalate(err, "failed to decode storage voucher data for verification")
|
||||
return nil, aerrors.Absorb(err, 2, "failed to decode storage voucher data for verification")
|
||||
}
|
||||
var proof InclusionProof
|
||||
if err := cbor.DecodeInto(params.Proof, &proof); err != nil {
|
||||
return nil, aerrors.Escalate(err, "failed to decode storage payment proof")
|
||||
return nil, aerrors.Absorb(err, 3, "failed to decode storage payment proof")
|
||||
}
|
||||
|
||||
ok, _, commD, aerr := GetFromSectorSet(context.TODO(), vmctx.Storage(), self.Sectors, proof.Sector)
|
||||
@ -671,15 +671,15 @@ func (sma StorageMinerActor) PaymentVerifyInclusion(act *types.Actor, vmctx type
|
||||
return nil, aerr
|
||||
}
|
||||
if !ok {
|
||||
return nil, aerrors.New(1, "miner does not have required sector")
|
||||
return nil, aerrors.New(4, "miner does not have required sector")
|
||||
}
|
||||
|
||||
ok, err := sectorbuilder.VerifyPieceInclusionProof(mi.SectorSize.Uint64(), voucherData.PieceSize.Uint64(), voucherData.CommP, commD, proof.Proof)
|
||||
if err != nil {
|
||||
return nil, aerrors.Escalate(err, "verify piece inclusion proof failed")
|
||||
return nil, aerrors.Absorb(err, 5, "verify piece inclusion proof failed")
|
||||
}
|
||||
if !ok {
|
||||
return nil, aerrors.New(2, "piece inclusion proof was invalid")
|
||||
return nil, aerrors.New(6, "piece inclusion proof was invalid")
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
|
@ -2,7 +2,6 @@ package actors
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/filecoin-project/go-lotus/build"
|
||||
"github.com/filecoin-project/go-lotus/chain/actors/aerrors"
|
||||
@ -16,9 +15,9 @@ import (
|
||||
xerrors "golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
type StorageMarketActor struct{}
|
||||
type StoragePowerActor struct{}
|
||||
|
||||
type smaMethods struct {
|
||||
type spaMethods struct {
|
||||
Constructor uint64
|
||||
CreateStorageMiner uint64
|
||||
ArbitrateConsensusFault uint64
|
||||
@ -29,22 +28,22 @@ type smaMethods struct {
|
||||
PledgeCollateralForSize uint64
|
||||
}
|
||||
|
||||
var SMAMethods = smaMethods{1, 2, 3, 4, 5, 6, 7, 8}
|
||||
var SPAMethods = spaMethods{1, 2, 3, 4, 5, 6, 7, 8}
|
||||
|
||||
func (sma StorageMarketActor) Exports() []interface{} {
|
||||
func (spa StoragePowerActor) Exports() []interface{} {
|
||||
return []interface{}{
|
||||
//1: sma.StorageMarketConstructor,
|
||||
2: sma.CreateStorageMiner,
|
||||
3: sma.ArbitrateConsensusFault,
|
||||
4: sma.UpdateStorage,
|
||||
5: sma.GetTotalStorage,
|
||||
6: sma.PowerLookup,
|
||||
7: sma.IsMiner,
|
||||
8: sma.PledgeCollateralForSize,
|
||||
//1: spa.StoragePowerConstructor,
|
||||
2: spa.CreateStorageMiner,
|
||||
3: spa.ArbitrateConsensusFault,
|
||||
4: spa.UpdateStorage,
|
||||
5: spa.GetTotalStorage,
|
||||
6: spa.PowerLookup,
|
||||
7: spa.IsMiner,
|
||||
8: spa.PledgeCollateralForSize,
|
||||
}
|
||||
}
|
||||
|
||||
type StorageMarketState struct {
|
||||
type StoragePowerState struct {
|
||||
Miners cid.Cid
|
||||
MinerCount uint64
|
||||
|
||||
@ -58,12 +57,12 @@ type CreateStorageMinerParams struct {
|
||||
PeerID peer.ID
|
||||
}
|
||||
|
||||
func (sma StorageMarketActor) CreateStorageMiner(act *types.Actor, vmctx types.VMContext, params *CreateStorageMinerParams) ([]byte, ActorError) {
|
||||
func (spa StoragePowerActor) CreateStorageMiner(act *types.Actor, vmctx types.VMContext, params *CreateStorageMinerParams) ([]byte, ActorError) {
|
||||
if !SupportedSectorSize(params.SectorSize) {
|
||||
return nil, aerrors.New(1, "Unsupported sector size")
|
||||
}
|
||||
|
||||
var self StorageMarketState
|
||||
var self StoragePowerState
|
||||
old := vmctx.Storage().GetHead()
|
||||
if err := vmctx.Storage().Get(old, &self); err != nil {
|
||||
return nil, err
|
||||
@ -129,7 +128,7 @@ type ArbitrateConsensusFaultParams struct {
|
||||
Block2 *types.BlockHeader
|
||||
}
|
||||
|
||||
func (sma StorageMarketActor) ArbitrateConsensusFault(act *types.Actor, vmctx types.VMContext, params *ArbitrateConsensusFaultParams) ([]byte, ActorError) {
|
||||
func (spa StoragePowerActor) ArbitrateConsensusFault(act *types.Actor, vmctx types.VMContext, params *ArbitrateConsensusFaultParams) ([]byte, ActorError) {
|
||||
if params.Block1.Miner != params.Block2.Miner {
|
||||
return nil, aerrors.New(2, "blocks must be from the same miner")
|
||||
}
|
||||
@ -145,11 +144,11 @@ func (sma StorageMarketActor) ArbitrateConsensusFault(act *types.Actor, vmctx ty
|
||||
return nil, aerrors.Absorb(oerr, 3, "response from 'GetWorkerAddr' was not a valid address")
|
||||
}
|
||||
|
||||
if err := params.Block1.CheckBlockSignature(worker); err != nil {
|
||||
if err := params.Block1.CheckBlockSignature(vmctx.Context(), worker); err != nil {
|
||||
return nil, aerrors.Absorb(err, 4, "block1 did not have valid signature")
|
||||
}
|
||||
|
||||
if err := params.Block2.CheckBlockSignature(worker); err != nil {
|
||||
if err := params.Block2.CheckBlockSignature(vmctx.Context(), worker); err != nil {
|
||||
return nil, aerrors.Absorb(err, 5, "block2 did not have valid signature")
|
||||
}
|
||||
|
||||
@ -159,18 +158,18 @@ func (sma StorageMarketActor) ArbitrateConsensusFault(act *types.Actor, vmctx ty
|
||||
return nil, aerrors.New(6, "blocks do not prove a slashable offense")
|
||||
}
|
||||
|
||||
var self StorageMarketState
|
||||
var self StoragePowerState
|
||||
old := vmctx.Storage().GetHead()
|
||||
if err := vmctx.Storage().Get(old, &self); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if types.BigCmp(self.TotalStorage, types.NewInt(0)) == 0 {
|
||||
return nil, aerrors.Fatal("invalid state, storage market actor has zero total storage")
|
||||
return nil, aerrors.Fatal("invalid state, storage power actor has zero total storage")
|
||||
}
|
||||
|
||||
miner := params.Block1.Miner
|
||||
if has, err := MinerSetHas(context.TODO(), vmctx, self.Miners, miner); err != nil {
|
||||
if has, err := MinerSetHas(vmctx, self.Miners, miner); err != nil {
|
||||
return nil, aerrors.Wrapf(err, "failed to check miner in set")
|
||||
} else if !has {
|
||||
return nil, aerrors.New(7, "either already slashed or not a miner")
|
||||
@ -270,14 +269,14 @@ type UpdateStorageParams struct {
|
||||
Delta types.BigInt
|
||||
}
|
||||
|
||||
func (sma StorageMarketActor) UpdateStorage(act *types.Actor, vmctx types.VMContext, params *UpdateStorageParams) ([]byte, ActorError) {
|
||||
var self StorageMarketState
|
||||
func (spa StoragePowerActor) UpdateStorage(act *types.Actor, vmctx types.VMContext, params *UpdateStorageParams) ([]byte, ActorError) {
|
||||
var self StoragePowerState
|
||||
old := vmctx.Storage().GetHead()
|
||||
if err := vmctx.Storage().Get(old, &self); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
has, err := MinerSetHas(context.TODO(), vmctx, self.Miners, vmctx.Message().From)
|
||||
has, err := MinerSetHas(vmctx, self.Miners, vmctx.Message().From)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -300,8 +299,8 @@ func (sma StorageMarketActor) UpdateStorage(act *types.Actor, vmctx types.VMCont
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (sma StorageMarketActor) GetTotalStorage(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) {
|
||||
var self StorageMarketState
|
||||
func (spa StoragePowerActor) GetTotalStorage(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) {
|
||||
var self StoragePowerState
|
||||
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -313,8 +312,8 @@ type PowerLookupParams struct {
|
||||
Miner address.Address
|
||||
}
|
||||
|
||||
func (sma StorageMarketActor) PowerLookup(act *types.Actor, vmctx types.VMContext, params *PowerLookupParams) ([]byte, ActorError) {
|
||||
var self StorageMarketState
|
||||
func (spa StoragePowerActor) PowerLookup(act *types.Actor, vmctx types.VMContext, params *PowerLookupParams) ([]byte, ActorError) {
|
||||
var self StoragePowerState
|
||||
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
|
||||
return nil, aerrors.Wrap(err, "getting head")
|
||||
}
|
||||
@ -327,14 +326,14 @@ func (sma StorageMarketActor) PowerLookup(act *types.Actor, vmctx types.VMContex
|
||||
return pow.Bytes(), nil
|
||||
}
|
||||
|
||||
func powerLookup(ctx context.Context, vmctx types.VMContext, self *StorageMarketState, miner address.Address) (types.BigInt, ActorError) {
|
||||
has, err := MinerSetHas(context.TODO(), vmctx, self.Miners, miner)
|
||||
func powerLookup(ctx context.Context, vmctx types.VMContext, self *StoragePowerState, miner address.Address) (types.BigInt, ActorError) {
|
||||
has, err := MinerSetHas(vmctx, self.Miners, miner)
|
||||
if err != nil {
|
||||
return types.EmptyInt, err
|
||||
}
|
||||
|
||||
if !has {
|
||||
return types.EmptyInt, aerrors.New(1, "miner not registered with storage market")
|
||||
return types.EmptyInt, aerrors.New(1, "miner not registered with storage power actor")
|
||||
}
|
||||
|
||||
ret, err := vmctx.Send(miner, MAMethods.GetPower, types.NewInt(0), nil)
|
||||
@ -349,13 +348,13 @@ type IsMinerParam struct {
|
||||
Addr address.Address
|
||||
}
|
||||
|
||||
func (sma StorageMarketActor) IsMiner(act *types.Actor, vmctx types.VMContext, param *IsMinerParam) ([]byte, ActorError) {
|
||||
var self StorageMarketState
|
||||
func (spa StoragePowerActor) IsMiner(act *types.Actor, vmctx types.VMContext, param *IsMinerParam) ([]byte, ActorError) {
|
||||
var self StoragePowerState
|
||||
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
has, err := MinerSetHas(context.TODO(), vmctx, self.Miners, param.Addr)
|
||||
has, err := MinerSetHas(vmctx, self.Miners, param.Addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -367,8 +366,8 @@ type PledgeCollateralParams struct {
|
||||
Size types.BigInt
|
||||
}
|
||||
|
||||
func (sma StorageMarketActor) PledgeCollateralForSize(act *types.Actor, vmctx types.VMContext, param *PledgeCollateralParams) ([]byte, ActorError) {
|
||||
var self StorageMarketState
|
||||
func (spa StoragePowerActor) PledgeCollateralForSize(act *types.Actor, vmctx types.VMContext, param *PledgeCollateralParams) ([]byte, ActorError) {
|
||||
var self StoragePowerState
|
||||
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -433,20 +432,20 @@ func pledgeCollateralForSize(vmctx types.VMContext, size, totalStorage types.Big
|
||||
return types.BigAdd(powerCollateral, perCapCollateral), nil
|
||||
}
|
||||
|
||||
func MinerSetHas(ctx context.Context, vmctx types.VMContext, rcid cid.Cid, maddr address.Address) (bool, aerrors.ActorError) {
|
||||
nd, err := hamt.LoadNode(ctx, vmctx.Ipld(), rcid)
|
||||
func MinerSetHas(vmctx types.VMContext, rcid cid.Cid, maddr address.Address) (bool, aerrors.ActorError) {
|
||||
nd, err := hamt.LoadNode(vmctx.Context(), vmctx.Ipld(), rcid)
|
||||
if err != nil {
|
||||
return false, aerrors.Escalate(err, "failed to load miner set")
|
||||
return false, aerrors.HandleExternalError(err, "failed to load miner set")
|
||||
}
|
||||
|
||||
err = nd.Find(ctx, string(maddr.Bytes()), nil)
|
||||
err = nd.Find(vmctx.Context(), string(maddr.Bytes()), nil)
|
||||
switch err {
|
||||
case hamt.ErrNotFound:
|
||||
return false, nil
|
||||
case nil:
|
||||
return true, nil
|
||||
default:
|
||||
return false, aerrors.Escalate(err, "failed to do set lookup")
|
||||
return false, aerrors.HandleExternalError(err, "failed to do set lookup")
|
||||
}
|
||||
}
|
||||
|
||||
@ -475,30 +474,30 @@ func MinerSetList(ctx context.Context, cst *hamt.CborIpldStore, rcid cid.Cid) ([
|
||||
func MinerSetAdd(ctx context.Context, vmctx types.VMContext, rcid cid.Cid, maddr address.Address) (cid.Cid, aerrors.ActorError) {
|
||||
nd, err := hamt.LoadNode(ctx, vmctx.Ipld(), rcid)
|
||||
if err != nil {
|
||||
return cid.Undef, aerrors.Escalate(err, "failed to load miner set")
|
||||
return cid.Undef, aerrors.HandleExternalError(err, "failed to load miner set")
|
||||
}
|
||||
|
||||
mkey := string(maddr.Bytes())
|
||||
err = nd.Find(ctx, mkey, nil)
|
||||
if err == nil {
|
||||
return cid.Undef, aerrors.Escalate(fmt.Errorf("miner already found"), "miner set add failed")
|
||||
return cid.Undef, aerrors.New(20, "miner already in set")
|
||||
}
|
||||
|
||||
if !xerrors.Is(err, hamt.ErrNotFound) {
|
||||
return cid.Undef, aerrors.Escalate(err, "failed to do miner set check")
|
||||
return cid.Undef, aerrors.HandleExternalError(err, "failed to do miner set check")
|
||||
}
|
||||
|
||||
if err := nd.Set(ctx, mkey, uint64(1)); err != nil {
|
||||
return cid.Undef, aerrors.Escalate(err, "adding miner address to set failed")
|
||||
return cid.Undef, aerrors.HandleExternalError(err, "adding miner address to set failed")
|
||||
}
|
||||
|
||||
if err := nd.Flush(ctx); err != nil {
|
||||
return cid.Undef, aerrors.Escalate(err, "failed to flush miner set")
|
||||
return cid.Undef, aerrors.HandleExternalError(err, "failed to flush miner set")
|
||||
}
|
||||
|
||||
c, err := vmctx.Ipld().Put(ctx, nd)
|
||||
if err != nil {
|
||||
return cid.Undef, aerrors.Escalate(err, "failed to persist miner set to storage")
|
||||
return cid.Undef, aerrors.HandleExternalError(err, "failed to persist miner set to storage")
|
||||
}
|
||||
|
||||
return c, nil
|
||||
@ -507,7 +506,7 @@ func MinerSetAdd(ctx context.Context, vmctx types.VMContext, rcid cid.Cid, maddr
|
||||
func MinerSetRemove(ctx context.Context, vmctx types.VMContext, rcid cid.Cid, maddr address.Address) (cid.Cid, aerrors.ActorError) {
|
||||
nd, err := hamt.LoadNode(ctx, vmctx.Ipld(), rcid)
|
||||
if err != nil {
|
||||
return cid.Undef, aerrors.Escalate(err, "failed to load miner set")
|
||||
return cid.Undef, aerrors.HandleExternalError(err, "failed to load miner set")
|
||||
}
|
||||
|
||||
mkey := string(maddr.Bytes())
|
||||
@ -515,17 +514,17 @@ func MinerSetRemove(ctx context.Context, vmctx types.VMContext, rcid cid.Cid, ma
|
||||
case hamt.ErrNotFound:
|
||||
return cid.Undef, aerrors.New(1, "miner not found in set on delete")
|
||||
default:
|
||||
return cid.Undef, aerrors.Escalate(err, "failed to delete miner from set")
|
||||
return cid.Undef, aerrors.HandleExternalError(err, "failed to delete miner from set")
|
||||
case nil:
|
||||
}
|
||||
|
||||
if err := nd.Flush(ctx); err != nil {
|
||||
return cid.Undef, aerrors.Escalate(err, "failed to flush miner set")
|
||||
return cid.Undef, aerrors.HandleExternalError(err, "failed to flush miner set")
|
||||
}
|
||||
|
||||
c, err := vmctx.Ipld().Put(ctx, nd)
|
||||
if err != nil {
|
||||
return cid.Undef, aerrors.Escalate(err, "failed to persist miner set to storage")
|
||||
return cid.Undef, aerrors.HandleExternalError(err, "failed to persist miner set to storage")
|
||||
}
|
||||
|
||||
return c, nil
|
@ -37,7 +37,7 @@ func TestStorageMarketCreateAndSlashMiner(t *testing.T) {
|
||||
// cheating the bootstrapping problem
|
||||
cheatStorageMarketTotal(t, h.vm, h.cs.Blockstore())
|
||||
|
||||
ret, _ := h.InvokeWithValue(t, ownerAddr, StorageMarketAddress, SMAMethods.CreateStorageMiner,
|
||||
ret, _ := h.InvokeWithValue(t, ownerAddr, StorageMarketAddress, SPAMethods.CreateStorageMiner,
|
||||
types.NewInt(500000),
|
||||
&CreateStorageMinerParams{
|
||||
Owner: ownerAddr,
|
||||
@ -52,7 +52,7 @@ func TestStorageMarketCreateAndSlashMiner(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
ret, _ := h.Invoke(t, ownerAddr, StorageMarketAddress, SMAMethods.IsMiner,
|
||||
ret, _ := h.Invoke(t, ownerAddr, StorageMarketAddress, SPAMethods.IsMiner,
|
||||
&IsMinerParam{Addr: minerAddr})
|
||||
ApplyOK(t, ret)
|
||||
|
||||
@ -68,7 +68,7 @@ func TestStorageMarketCreateAndSlashMiner(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
ret, _ := h.Invoke(t, ownerAddr, StorageMarketAddress, SMAMethods.PowerLookup,
|
||||
ret, _ := h.Invoke(t, ownerAddr, StorageMarketAddress, SPAMethods.PowerLookup,
|
||||
&PowerLookupParams{Miner: minerAddr})
|
||||
ApplyOK(t, ret)
|
||||
power := types.BigFromBytes(ret.Return)
|
||||
@ -93,7 +93,7 @@ func TestStorageMarketCreateAndSlashMiner(t *testing.T) {
|
||||
signBlock(t, h.w, workerAddr, b1)
|
||||
signBlock(t, h.w, workerAddr, b2)
|
||||
|
||||
ret, _ := h.Invoke(t, ownerAddr, StorageMarketAddress, SMAMethods.ArbitrateConsensusFault,
|
||||
ret, _ := h.Invoke(t, ownerAddr, StorageMarketAddress, SPAMethods.ArbitrateConsensusFault,
|
||||
&ArbitrateConsensusFaultParams{
|
||||
Block1: b1,
|
||||
Block2: b2,
|
||||
@ -102,13 +102,13 @@ func TestStorageMarketCreateAndSlashMiner(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
ret, _ := h.Invoke(t, ownerAddr, StorageMarketAddress, SMAMethods.PowerLookup,
|
||||
ret, _ := h.Invoke(t, ownerAddr, StorageMarketAddress, SPAMethods.PowerLookup,
|
||||
&PowerLookupParams{Miner: minerAddr})
|
||||
assert.Equal(t, ret.ExitCode, byte(1))
|
||||
}
|
||||
|
||||
{
|
||||
ret, _ := h.Invoke(t, ownerAddr, StorageMarketAddress, SMAMethods.IsMiner, &IsMinerParam{minerAddr})
|
||||
ret, _ := h.Invoke(t, ownerAddr, StorageMarketAddress, SPAMethods.IsMiner, &IsMinerParam{minerAddr})
|
||||
ApplyOK(t, ret)
|
||||
assert.Equal(t, ret.Return, cbg.CborBoolFalse)
|
||||
}
|
||||
@ -124,7 +124,7 @@ func cheatStorageMarketTotal(t *testing.T, vm *vm.VM, bs bstore.Blockstore) {
|
||||
|
||||
cst := hamt.CSTFromBstore(bs)
|
||||
|
||||
var smastate StorageMarketState
|
||||
var smastate StoragePowerState
|
||||
if err := cst.Get(context.TODO(), sma.Head, &smastate); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
@ -53,7 +53,7 @@ func setupVMTestEnv(t *testing.T) (*vm.VM, []address.Address, bstore.Blockstore)
|
||||
cs := store.NewChainStore(bs, nil)
|
||||
|
||||
// TODO: should probabaly mock out the randomness bit, nil works for now
|
||||
vm, err := vm.NewVM(stateroot, 1, nil, maddr, cs)
|
||||
vm, err := vm.NewVM(stateroot, 1, nil, maddr, cs.Blockstore())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -65,7 +65,7 @@ func TestVMInvokeMethod(t *testing.T) {
|
||||
from := addrs[0]
|
||||
|
||||
var err error
|
||||
cenc, err := SerializeParams(&StorageMinerConstructorParams{})
|
||||
cenc, err := SerializeParams(&StorageMinerConstructorParams{Owner: from, Worker: from})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -116,6 +116,7 @@ func TestStorageMarketActorCreateMiner(t *testing.T) {
|
||||
cheatStorageMarketTotal(t, vm, bs)
|
||||
|
||||
params := &StorageMinerConstructorParams{
|
||||
Owner: maddr,
|
||||
Worker: maddr,
|
||||
SectorSize: types.NewInt(build.SectorSize),
|
||||
PeerID: "fakepeerid",
|
||||
@ -129,7 +130,7 @@ func TestStorageMarketActorCreateMiner(t *testing.T) {
|
||||
msg := &types.Message{
|
||||
To: StorageMarketAddress,
|
||||
From: from,
|
||||
Method: SMAMethods.CreateStorageMiner,
|
||||
Method: SPAMethods.CreateStorageMiner,
|
||||
Params: enc,
|
||||
GasPrice: types.NewInt(1),
|
||||
GasLimit: types.NewInt(10000),
|
||||
|
@ -103,7 +103,7 @@ func Absorb(err error, retCode uint8, msg string) ActorError {
|
||||
fatal: true,
|
||||
retCode: 0,
|
||||
|
||||
msg: "tried absorbing an error that is alreay an fatal error",
|
||||
msg: "tried absorbing an error that is already a fatal error",
|
||||
frame: xerrors.Caller(1),
|
||||
err: err,
|
||||
}
|
||||
@ -142,3 +142,28 @@ func Escalate(err error, msg string) ActorError {
|
||||
err: err,
|
||||
}
|
||||
}
|
||||
|
||||
func HandleExternalError(err error, msg string) ActorError {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if aerr, ok := err.(ActorError); ok {
|
||||
return &actorError{
|
||||
fatal: IsFatal(aerr),
|
||||
retCode: RetCode(aerr),
|
||||
|
||||
msg: msg,
|
||||
frame: xerrors.Caller(1),
|
||||
err: aerr,
|
||||
}
|
||||
}
|
||||
|
||||
return &actorError{
|
||||
fatal: true,
|
||||
|
||||
msg: msg,
|
||||
frame: xerrors.Caller(1),
|
||||
err: err,
|
||||
}
|
||||
}
|
||||
|
@ -2379,7 +2379,7 @@ func (t *PaymentInfo) UnmarshalCBOR(r io.Reader) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *StorageMarketState) MarshalCBOR(w io.Writer) error {
|
||||
func (t *StoragePowerState) MarshalCBOR(w io.Writer) error {
|
||||
if t == nil {
|
||||
_, err := w.Write(cbg.CborNull)
|
||||
return err
|
||||
@ -2406,7 +2406,7 @@ func (t *StorageMarketState) MarshalCBOR(w io.Writer) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *StorageMarketState) UnmarshalCBOR(r io.Reader) error {
|
||||
func (t *StoragePowerState) UnmarshalCBOR(r io.Reader) error {
|
||||
br := cbg.GetPeeker(r)
|
||||
|
||||
maj, extra, err := cbg.CborReadHeader(br)
|
||||
|
@ -158,7 +158,7 @@ func NewHarness(t *testing.T, options ...HarnessOpt) *Harness {
|
||||
t.Fatal(err)
|
||||
}
|
||||
h.cs = store.NewChainStore(h.bs, nil)
|
||||
h.vm, err = vm.NewVM(stateroot, 1, nil, h.HI.Miner, h.cs)
|
||||
h.vm, err = vm.NewVM(stateroot, 1, nil, h.HI.Miner, h.cs.Blockstore())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -325,6 +325,10 @@ func hash(ingest []byte, cfg *blake2b.Config) []byte {
|
||||
}
|
||||
|
||||
func (a Address) MarshalCBOR(w io.Writer) error {
|
||||
if a == Undef {
|
||||
return fmt.Errorf("cannot marshal undefined address")
|
||||
}
|
||||
|
||||
abytes := a.Bytes()
|
||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(abytes)))); err != nil {
|
||||
return err
|
||||
@ -360,6 +364,9 @@ func (a *Address) UnmarshalCBOR(br io.Reader) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if addr == Undef {
|
||||
return fmt.Errorf("cbor input should not contain empty addresses")
|
||||
}
|
||||
|
||||
*a = addr
|
||||
|
||||
|
@ -121,13 +121,13 @@ func (e *heightEvents) headChangeAt(rev, app []*types.TipSet) error {
|
||||
//
|
||||
// ts passed to handlers is the tipset at the specified, or above, if lower tipsets were null
|
||||
func (e *heightEvents) ChainAt(hnd HeightHandler, rev RevertHandler, confidence int, h uint64) error {
|
||||
e.lk.Lock()
|
||||
defer e.lk.Unlock()
|
||||
|
||||
e.lk.Lock() // Tricky locking, check your locks if you modify this function!
|
||||
|
||||
bestH := e.tsc.best().Height()
|
||||
|
||||
if bestH >= h+uint64(confidence) {
|
||||
ts, err := e.tsc.get(h)
|
||||
ts, err := e.tsc.getNonNull(h)
|
||||
if err != nil {
|
||||
log.Warnf("events.ChainAt: calling HandleFunc with nil tipset, not found in cache: %s", err)
|
||||
}
|
||||
@ -140,6 +140,8 @@ func (e *heightEvents) ChainAt(hnd HeightHandler, rev RevertHandler, confidence
|
||||
bestH = e.tsc.best().Height()
|
||||
}
|
||||
|
||||
defer e.lk.Unlock()
|
||||
|
||||
if bestH >= h+uint64(confidence)+e.gcConfidence {
|
||||
return nil
|
||||
}
|
||||
|
@ -45,9 +45,11 @@ func (fcs *fakeCS) ChainGetTipSetByHeight(context.Context, uint64, *types.TipSet
|
||||
}
|
||||
|
||||
func makeTs(t *testing.T, h uint64, msgcid cid.Cid) *types.TipSet {
|
||||
a, _ := address.NewFromString("t00")
|
||||
ts, err := types.NewTipSet([]*types.BlockHeader{
|
||||
{
|
||||
Height: h,
|
||||
Miner: a,
|
||||
|
||||
ParentStateRoot: dummyCid,
|
||||
Messages: msgcid,
|
||||
@ -432,6 +434,35 @@ func TestAtChainedConfidence(t *testing.T) {
|
||||
require.Equal(t, false, reverted)
|
||||
}
|
||||
|
||||
func TestAtChainedConfidenceNull(t *testing.T) {
|
||||
fcs := &fakeCS{
|
||||
t: t,
|
||||
h: 1,
|
||||
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
|
||||
}
|
||||
require.NoError(t, fcs.tsc.add(makeTs(t, 1, dummyCid)))
|
||||
|
||||
events := NewEvents(context.Background(), fcs)
|
||||
|
||||
fcs.advance(0, 15, nil, 5)
|
||||
|
||||
var applied bool
|
||||
var reverted bool
|
||||
|
||||
err := events.ChainAt(func(ts *types.TipSet, curH uint64) error {
|
||||
applied = true
|
||||
require.Equal(t, 6, int(ts.Height()))
|
||||
return nil
|
||||
}, func(ts *types.TipSet) error {
|
||||
reverted = true
|
||||
return nil
|
||||
}, 3, 5)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, true, applied)
|
||||
require.Equal(t, false, reverted)
|
||||
}
|
||||
|
||||
func TestCalled(t *testing.T) {
|
||||
fcs := &fakeCS{
|
||||
t: t,
|
||||
@ -479,7 +510,7 @@ func TestCalled(t *testing.T) {
|
||||
fcs.advance(0, 3, map[int]cid.Cid{ // msg at H=6; H=8 (confidence=2)
|
||||
0: fcs.fakeMsgs(fakeMsg{
|
||||
bmsgs: []*types.Message{
|
||||
{To: t0123, Method: 5, Nonce: 1},
|
||||
{To: t0123, From: t0123, Method: 5, Nonce: 1},
|
||||
},
|
||||
}),
|
||||
})
|
||||
@ -520,7 +551,7 @@ func TestCalled(t *testing.T) {
|
||||
|
||||
n2msg := fcs.fakeMsgs(fakeMsg{
|
||||
bmsgs: []*types.Message{
|
||||
{To: t0123, Method: 5, Nonce: 2},
|
||||
{To: t0123, From: t0123, Method: 5, Nonce: 2},
|
||||
},
|
||||
})
|
||||
|
||||
@ -574,7 +605,7 @@ func TestCalled(t *testing.T) {
|
||||
fcs.advance(0, 1, map[int]cid.Cid{ // msg at H=16; H=16
|
||||
0: fcs.fakeMsgs(fakeMsg{
|
||||
bmsgs: []*types.Message{
|
||||
{To: t0123, Method: 5, Nonce: 3},
|
||||
{To: t0123, From: t0123, Method: 5, Nonce: 3},
|
||||
},
|
||||
}),
|
||||
})
|
||||
@ -597,7 +628,7 @@ func TestCalled(t *testing.T) {
|
||||
fcs.advance(0, 4, map[int]cid.Cid{ // msg at H=26; H=29
|
||||
0: fcs.fakeMsgs(fakeMsg{
|
||||
bmsgs: []*types.Message{
|
||||
{To: t0123, Method: 5, Nonce: 4}, // this signals we don't want more
|
||||
{To: t0123, From: t0123, Method: 5, Nonce: 4}, // this signals we don't want more
|
||||
},
|
||||
}),
|
||||
})
|
||||
@ -609,7 +640,7 @@ func TestCalled(t *testing.T) {
|
||||
fcs.advance(0, 4, map[int]cid.Cid{ // msg at H=26; H=29
|
||||
0: fcs.fakeMsgs(fakeMsg{
|
||||
bmsgs: []*types.Message{
|
||||
{To: t0123, Method: 5, Nonce: 5},
|
||||
{To: t0123, From: t0123, Method: 5, Nonce: 5},
|
||||
},
|
||||
}),
|
||||
})
|
||||
@ -754,12 +785,12 @@ func TestCalledOrder(t *testing.T) {
|
||||
fcs.advance(0, 10, map[int]cid.Cid{
|
||||
1: fcs.fakeMsgs(fakeMsg{
|
||||
bmsgs: []*types.Message{
|
||||
{To: t0123, Method: 5, Nonce: 1},
|
||||
{To: t0123, From: t0123, Method: 5, Nonce: 1},
|
||||
},
|
||||
}),
|
||||
2: fcs.fakeMsgs(fakeMsg{
|
||||
bmsgs: []*types.Message{
|
||||
{To: t0123, Method: 5, Nonce: 2},
|
||||
{To: t0123, From: t0123, Method: 5, Nonce: 2},
|
||||
},
|
||||
}),
|
||||
})
|
||||
|
@ -2,9 +2,11 @@ package events
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/filecoin-project/go-lotus/chain/address"
|
||||
"github.com/filecoin-project/go-lotus/chain/types"
|
||||
)
|
||||
|
||||
@ -16,8 +18,11 @@ func TestTsCache(t *testing.T) {
|
||||
|
||||
h := uint64(75)
|
||||
|
||||
a, _ := address.NewFromString("t00")
|
||||
|
||||
add := func() {
|
||||
ts, err := types.NewTipSet([]*types.BlockHeader{{
|
||||
Miner: a,
|
||||
Height: h,
|
||||
ParentStateRoot: dummyCid,
|
||||
Messages: dummyCid,
|
||||
@ -54,8 +59,10 @@ func TestTsCacheNulls(t *testing.T) {
|
||||
|
||||
h := uint64(75)
|
||||
|
||||
a, _ := address.NewFromString("t00")
|
||||
add := func() {
|
||||
ts, err := types.NewTipSet([]*types.BlockHeader{{
|
||||
Miner: a,
|
||||
Height: h,
|
||||
ParentStateRoot: dummyCid,
|
||||
Messages: dummyCid,
|
||||
|
@ -413,7 +413,7 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, ticks []*types.Ticket,
|
||||
return false, nil, xerrors.Errorf("failed to check power: %w", err)
|
||||
}
|
||||
|
||||
return types.PowerCmp(vrfout, pow.MinerPower, pow.TotalPower), vrfout, nil
|
||||
return types.PowerCmp(vrfout, types.BigMul(pow.MinerPower, types.NewInt(build.BlocksPerEpoch)), pow.TotalPower), vrfout, nil
|
||||
}
|
||||
|
||||
type SignFunc func(context.Context, address.Address, []byte) (*types.Signature, error)
|
||||
|
@ -96,8 +96,11 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wal
|
||||
}
|
||||
|
||||
next.BLSAggregate = aggSig
|
||||
pweight := sm.ChainStore().Weight(parents)
|
||||
next.ParentWeight = types.NewInt(pweight)
|
||||
pweight, err := sm.ChainStore().Weight(ctx, parents)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
next.ParentWeight = pweight
|
||||
|
||||
cst := hamt.CSTFromBstore(sm.ChainStore().Blockstore())
|
||||
tree, err := state.LoadStateTree(cst, st)
|
||||
|
@ -143,7 +143,7 @@ func SetupStorageMarketActor(bs bstore.Blockstore) (*types.Actor, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sms := &actors.StorageMarketState{
|
||||
sms := &actors.StoragePowerState{
|
||||
Miners: emptyhamt,
|
||||
TotalStorage: types.NewInt(0),
|
||||
}
|
||||
@ -183,7 +183,7 @@ func mustEnc(i cbg.CBORMarshaler) []byte {
|
||||
}
|
||||
|
||||
func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid, gmcfg *GenMinerCfg) (cid.Cid, error) {
|
||||
vm, err := vm.NewVM(sroot, 0, nil, actors.NetworkAddress, cs)
|
||||
vm, err := vm.NewVM(sroot, 0, nil, actors.NetworkAddress, cs.Blockstore())
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("failed to create NewVM: %w", err)
|
||||
}
|
||||
@ -202,7 +202,7 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
|
||||
|
||||
// TODO: hardcoding 7000000 here is a little fragile, it changes any
|
||||
// time anyone changes the initial account allocations
|
||||
rval, err := doExecValue(ctx, vm, actors.StorageMarketAddress, owner, types.FromFil(6500), actors.SMAMethods.CreateStorageMiner, params)
|
||||
rval, err := doExecValue(ctx, vm, actors.StorageMarketAddress, owner, types.FromFil(6500), actors.SPAMethods.CreateStorageMiner, params)
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("failed to create genesis miner: %w", err)
|
||||
}
|
||||
@ -216,7 +216,7 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
|
||||
|
||||
params = mustEnc(&actors.UpdateStorageParams{Delta: types.NewInt(5000)})
|
||||
|
||||
_, err = doExec(ctx, vm, actors.StorageMarketAddress, maddr, actors.SMAMethods.UpdateStorage, params)
|
||||
_, err = doExec(ctx, vm, actors.StorageMarketAddress, maddr, actors.SPAMethods.UpdateStorage, params)
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("failed to update total storage: %w", err)
|
||||
}
|
||||
|
@ -61,7 +61,6 @@ func (ms *msgSet) add(m *types.SignedMessage) error {
|
||||
log.Error("Add with duplicate nonce")
|
||||
return xerrors.Errorf("message to %s with nonce %d already in mpool")
|
||||
}
|
||||
log.Warn("Add called with the same message multiple times")
|
||||
}
|
||||
ms.msgs[m.Message.Nonce] = m
|
||||
|
||||
|
@ -89,11 +89,16 @@ func sendHeadNotifs(ctx context.Context, ps *pubsub.PubSub, topic string, chain
|
||||
case notif := <-notifs:
|
||||
n := notif[len(notif)-1]
|
||||
|
||||
w, err := chain.ChainTipSetWeight(ctx, n.Val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m := message{
|
||||
Cids: n.Val.Cids(),
|
||||
Blocks: n.Val.Blocks(),
|
||||
Height: n.Val.Height(),
|
||||
Weight: n.Val.Weight(),
|
||||
Weight: w,
|
||||
NodeName: nickname,
|
||||
}
|
||||
|
||||
|
@ -4,16 +4,17 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/filecoin-project/go-lotus/chain/actors"
|
||||
"github.com/filecoin-project/go-lotus/chain/types"
|
||||
"github.com/filecoin-project/go-lotus/chain/vm"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-lotus/chain/actors"
|
||||
"github.com/filecoin-project/go-lotus/chain/store"
|
||||
"github.com/filecoin-project/go-lotus/chain/types"
|
||||
"github.com/filecoin-project/go-lotus/chain/vm"
|
||||
)
|
||||
|
||||
func (sm *StateManager) CallRaw(ctx context.Context, msg *types.Message, bstate cid.Cid, r vm.Rand, bheight uint64) (*types.MessageReceipt, error) {
|
||||
vmi, err := vm.NewVM(bstate, bheight, r, actors.NetworkAddress, sm.cs)
|
||||
vmi, err := vm.NewVM(bstate, bheight, r, actors.NetworkAddress, sm.cs.Blockstore())
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to set up vm: %w", err)
|
||||
}
|
||||
@ -55,7 +56,7 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types.
|
||||
|
||||
state := ts.ParentState()
|
||||
|
||||
r := vm.NewChainRand(sm.cs, ts.Cids(), ts.Height(), nil)
|
||||
r := store.NewChainRand(sm.cs, ts.Cids(), ts.Height(), nil)
|
||||
|
||||
return sm.CallRaw(ctx, msg, state, r, ts.Height())
|
||||
}
|
||||
|
@ -89,9 +89,9 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
|
||||
cids[i] = v.Cid()
|
||||
}
|
||||
|
||||
r := vm.NewChainRand(sm.cs, cids, blks[0].Height, nil)
|
||||
r := store.NewChainRand(sm.cs, cids, blks[0].Height, nil)
|
||||
|
||||
vmi, err := vm.NewVM(pstate, blks[0].Height, r, address.Undef, sm.cs)
|
||||
vmi, err := vm.NewVM(pstate, blks[0].Height, r, address.Undef, sm.cs.Blockstore())
|
||||
if err != nil {
|
||||
return cid.Undef, cid.Undef, xerrors.Errorf("instantiating VM failed: %w", err)
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package stmgr
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/filecoin-project/go-lotus/api"
|
||||
"github.com/filecoin-project/go-lotus/chain/actors"
|
||||
"github.com/filecoin-project/go-lotus/chain/address"
|
||||
@ -71,18 +70,18 @@ func GetMinerOwner(ctx context.Context, sm *StateManager, st cid.Cid, maddr addr
|
||||
|
||||
func GetPower(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (types.BigInt, types.BigInt, error) {
|
||||
var err error
|
||||
enc, err := actors.SerializeParams(&actors.PowerLookupParams{maddr})
|
||||
if err != nil {
|
||||
return types.EmptyInt, types.EmptyInt, err
|
||||
}
|
||||
|
||||
var mpow types.BigInt
|
||||
|
||||
if maddr != address.Undef {
|
||||
enc, aerr := actors.SerializeParams(&actors.PowerLookupParams{maddr})
|
||||
if aerr != nil {
|
||||
return types.EmptyInt, types.EmptyInt, aerr
|
||||
}
|
||||
ret, err := sm.Call(ctx, &types.Message{
|
||||
From: maddr,
|
||||
To: actors.StorageMarketAddress,
|
||||
Method: actors.SMAMethods.PowerLookup,
|
||||
Method: actors.SPAMethods.PowerLookup,
|
||||
Params: enc,
|
||||
}, ts)
|
||||
if err != nil {
|
||||
@ -98,7 +97,7 @@ func GetPower(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr add
|
||||
ret, err := sm.Call(ctx, &types.Message{
|
||||
From: actors.StorageMarketAddress,
|
||||
To: actors.StorageMarketAddress,
|
||||
Method: actors.SMAMethods.GetTotalStorage,
|
||||
Method: actors.SPAMethods.GetTotalStorage,
|
||||
}, ts)
|
||||
if err != nil {
|
||||
return types.EmptyInt, types.EmptyInt, xerrors.Errorf("failed to get total power from chain: %w", err)
|
||||
|
@ -7,9 +7,12 @@ import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/filecoin-project/go-lotus/chain/vm"
|
||||
|
||||
"github.com/filecoin-project/go-lotus/build"
|
||||
"github.com/filecoin-project/go-lotus/chain/address"
|
||||
"github.com/filecoin-project/go-lotus/chain/state"
|
||||
"go.opencensus.io/trace"
|
||||
"go.uber.org/zap"
|
||||
|
||||
amt "github.com/filecoin-project/go-amt-ipld"
|
||||
@ -182,14 +185,14 @@ func (cs *ChainStore) SetGenesis(b *types.BlockHeader) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := cs.PutTipSet(ts); err != nil {
|
||||
if err := cs.PutTipSet(context.TODO(), ts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return cs.ds.Put(dstore.NewKey("0"), b.Cid().Bytes())
|
||||
}
|
||||
|
||||
func (cs *ChainStore) PutTipSet(ts *types.TipSet) error {
|
||||
func (cs *ChainStore) PutTipSet(ctx context.Context, ts *types.TipSet) error {
|
||||
for _, b := range ts.Blocks() {
|
||||
if err := cs.PersistBlockHeader(b); err != nil {
|
||||
return err
|
||||
@ -202,16 +205,25 @@ func (cs *ChainStore) PutTipSet(ts *types.TipSet) error {
|
||||
}
|
||||
log.Debugf("expanded %s into %s\n", ts.Cids(), expanded.Cids())
|
||||
|
||||
if err := cs.MaybeTakeHeavierTipSet(expanded); err != nil {
|
||||
if err := cs.MaybeTakeHeavierTipSet(ctx, expanded); err != nil {
|
||||
return errors.Wrap(err, "MaybeTakeHeavierTipSet failed in PutTipSet")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cs *ChainStore) MaybeTakeHeavierTipSet(ts *types.TipSet) error {
|
||||
func (cs *ChainStore) MaybeTakeHeavierTipSet(ctx context.Context, ts *types.TipSet) error {
|
||||
cs.heaviestLk.Lock()
|
||||
defer cs.heaviestLk.Unlock()
|
||||
if cs.heaviest == nil || cs.Weight(ts) > cs.Weight(cs.heaviest) {
|
||||
w, err := cs.Weight(ctx, ts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
heaviestW, err := cs.Weight(ctx, cs.heaviest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if w.GreaterThan(heaviestW) {
|
||||
// TODO: don't do this for initial sync. Now that we don't have a
|
||||
// difference between 'bootstrap sync' and 'caught up' sync, we need
|
||||
// some other heuristic.
|
||||
@ -261,7 +273,7 @@ func (cs *ChainStore) takeHeaviestTipSet(ts *types.TipSet) error {
|
||||
new: ts,
|
||||
}
|
||||
} else {
|
||||
log.Warn("no heaviest tipset found, using %s", ts.Cids())
|
||||
log.Warnf("no heaviest tipset found, using %s", ts.Cids())
|
||||
}
|
||||
|
||||
log.Debugf("New heaviest tipset! %s", ts.Cids())
|
||||
@ -377,10 +389,6 @@ func (cs *ChainStore) ReorgOps(a, b *types.TipSet) ([]*types.TipSet, []*types.Ti
|
||||
return leftChain, rightChain, nil
|
||||
}
|
||||
|
||||
func (cs *ChainStore) Weight(ts *types.TipSet) uint64 {
|
||||
return ts.Blocks()[0].ParentWeight.Uint64() + uint64(len(ts.Cids()))
|
||||
}
|
||||
|
||||
func (cs *ChainStore) GetHeaviestTipSet() *types.TipSet {
|
||||
cs.heaviestLk.Lock()
|
||||
defer cs.heaviestLk.Unlock()
|
||||
@ -469,7 +477,7 @@ func (cs *ChainStore) expandTipset(b *types.BlockHeader) (*types.TipSet, error)
|
||||
return types.NewTipSet(all)
|
||||
}
|
||||
|
||||
func (cs *ChainStore) AddBlock(b *types.BlockHeader) error {
|
||||
func (cs *ChainStore) AddBlock(ctx context.Context, b *types.BlockHeader) error {
|
||||
if err := cs.PersistBlockHeader(b); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -479,7 +487,7 @@ func (cs *ChainStore) AddBlock(b *types.BlockHeader) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := cs.MaybeTakeHeavierTipSet(ts); err != nil {
|
||||
if err := cs.MaybeTakeHeavierTipSet(ctx, ts); err != nil {
|
||||
return errors.Wrap(err, "MaybeTakeHeavierTipSet failed")
|
||||
}
|
||||
|
||||
@ -720,6 +728,9 @@ func (cs *ChainStore) TryFillTipSet(ts *types.TipSet) (*FullTipSet, error) {
|
||||
}
|
||||
|
||||
func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, tickets []*types.Ticket, lb int64) ([]byte, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "store.GetRandomness")
|
||||
defer span.End()
|
||||
|
||||
if lb < 0 {
|
||||
return nil, fmt.Errorf("negative lookback parameters are not valid (got %d)", lb)
|
||||
}
|
||||
@ -793,3 +804,24 @@ func (cs *ChainStore) GetTipsetByHeight(ctx context.Context, h uint64, ts *types
|
||||
ts = pts
|
||||
}
|
||||
}
|
||||
|
||||
type chainRand struct {
|
||||
cs *ChainStore
|
||||
blks []cid.Cid
|
||||
bh uint64
|
||||
tickets []*types.Ticket
|
||||
}
|
||||
|
||||
func NewChainRand(cs *ChainStore, blks []cid.Cid, bheight uint64, tickets []*types.Ticket) vm.Rand {
|
||||
return &chainRand{
|
||||
cs: cs,
|
||||
blks: blks,
|
||||
bh: bheight,
|
||||
tickets: tickets,
|
||||
}
|
||||
}
|
||||
|
||||
func (cr *chainRand) GetRandomness(ctx context.Context, h int64) ([]byte, error) {
|
||||
lb := (int64(cr.bh) + int64(len(cr.tickets))) - h
|
||||
return cr.cs.GetRandomness(ctx, cr.blks, cr.tickets, lb)
|
||||
}
|
||||
|
94
chain/store/weight.go
Normal file
94
chain/store/weight.go
Normal 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
|
||||
}
|
@ -94,7 +94,7 @@ func (syncer *Syncer) InformNewHead(from peer.ID, fts *store.FullTipSet) {
|
||||
}
|
||||
|
||||
for _, b := range fts.Blocks {
|
||||
if err := syncer.validateMsgMeta(b); err != nil {
|
||||
if err := syncer.ValidateMsgMeta(b); err != nil {
|
||||
log.Warnf("invalid block received: %s", err)
|
||||
return
|
||||
}
|
||||
@ -122,7 +122,7 @@ func (syncer *Syncer) InformNewHead(from peer.ID, fts *store.FullTipSet) {
|
||||
}()
|
||||
}
|
||||
|
||||
func (syncer *Syncer) validateMsgMeta(fblk *types.FullBlock) error {
|
||||
func (syncer *Syncer) ValidateMsgMeta(fblk *types.FullBlock) error {
|
||||
var bcids, scids []cbg.CBORMarshaler
|
||||
for _, m := range fblk.BlsMessages {
|
||||
c := cbg.CborCid(m.Cid())
|
||||
@ -147,6 +147,14 @@ func (syncer *Syncer) validateMsgMeta(fblk *types.FullBlock) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (syncer *Syncer) LocalPeer() peer.ID {
|
||||
return syncer.self
|
||||
}
|
||||
|
||||
func (syncer *Syncer) ChainStore() *store.ChainStore {
|
||||
return syncer.store
|
||||
}
|
||||
|
||||
func (syncer *Syncer) InformNewBlock(from peer.ID, blk *types.FullBlock) {
|
||||
// TODO: search for other blocks that could form a tipset with this block
|
||||
// and then send that tipset to InformNewHead
|
||||
@ -253,7 +261,7 @@ func computeMsgMeta(bs amt.Blocks, bmsgCids, smsgCids []cbg.CBORMarshaler) (cid.
|
||||
return mrcid, nil
|
||||
}
|
||||
|
||||
func (syncer *Syncer) selectHead(heads map[peer.ID]*types.TipSet) (*types.TipSet, error) {
|
||||
func (syncer *Syncer) selectHead(ctx context.Context, heads map[peer.ID]*types.TipSet) (*types.TipSet, error) {
|
||||
var headsArr []*types.TipSet
|
||||
for _, ts := range heads {
|
||||
headsArr = append(headsArr, ts)
|
||||
@ -290,7 +298,16 @@ func (syncer *Syncer) selectHead(heads map[peer.ID]*types.TipSet) (*types.TipSet
|
||||
return nil, fmt.Errorf("Conflict exists in heads set")
|
||||
}
|
||||
|
||||
if syncer.store.Weight(cur) > syncer.store.Weight(sel) {
|
||||
curw, err := syncer.store.Weight(ctx, cur)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
selw, err := syncer.store.Weight(ctx, sel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if curw.GreaterThan(selw) {
|
||||
sel = cur
|
||||
}
|
||||
}
|
||||
@ -344,7 +361,7 @@ func (syncer *Syncer) Sync(ctx context.Context, maybeHead *types.TipSet) error {
|
||||
return xerrors.Errorf("collectChain failed: %w", err)
|
||||
}
|
||||
|
||||
if err := syncer.store.PutTipSet(maybeHead); err != nil {
|
||||
if err := syncer.store.PutTipSet(ctx, maybeHead); err != nil {
|
||||
return xerrors.Errorf("failed to put synced tipset to chainstore: %w", err)
|
||||
}
|
||||
|
||||
@ -383,7 +400,7 @@ func (syncer *Syncer) minerIsValid(ctx context.Context, maddr address.Address, b
|
||||
ret, err := syncer.sm.Call(ctx, &types.Message{
|
||||
To: actors.StorageMarketAddress,
|
||||
From: maddr,
|
||||
Method: actors.SMAMethods.IsMiner,
|
||||
Method: actors.SPAMethods.IsMiner,
|
||||
Params: enc,
|
||||
}, baseTs)
|
||||
if err != nil {
|
||||
@ -467,7 +484,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
|
||||
return xerrors.Errorf("GetMinerWorker failed: %w", err)
|
||||
}
|
||||
|
||||
if err := h.CheckBlockSignature(waddr); err != nil {
|
||||
if err := h.CheckBlockSignature(ctx, waddr); err != nil {
|
||||
return xerrors.Errorf("check block signature failed: %w", err)
|
||||
}
|
||||
|
||||
@ -564,7 +581,7 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock
|
||||
pubks = append(pubks, pubk)
|
||||
}
|
||||
|
||||
if err := syncer.verifyBlsAggregate(b.Header.BLSAggregate, sigCids, pubks); err != nil {
|
||||
if err := syncer.verifyBlsAggregate(ctx, b.Header.BLSAggregate, sigCids, pubks); err != nil {
|
||||
return xerrors.Errorf("bls aggregate signature was invalid: %w", err)
|
||||
}
|
||||
|
||||
@ -612,7 +629,13 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock
|
||||
return nil
|
||||
}
|
||||
|
||||
func (syncer *Syncer) verifyBlsAggregate(sig types.Signature, msgs []cid.Cid, pubks []bls.PublicKey) error {
|
||||
func (syncer *Syncer) verifyBlsAggregate(ctx context.Context, sig types.Signature, msgs []cid.Cid, pubks []bls.PublicKey) error {
|
||||
ctx, span := trace.StartSpan(ctx, "syncer.verifyBlsAggregate")
|
||||
defer span.End()
|
||||
span.AddAttributes(
|
||||
trace.Int64Attribute("msgCount", int64(len(msgs))),
|
||||
)
|
||||
|
||||
var digests []bls.Digest
|
||||
for _, c := range msgs {
|
||||
digests = append(digests, bls.Hash(bls.Message(c.Bytes())))
|
||||
|
@ -32,9 +32,6 @@ func (tu *syncTestUtil) repoWithChain(t testing.TB, h int) (repo.Repo, []byte, [
|
||||
require.NoError(t, err)
|
||||
|
||||
blks[i] = mts.TipSet
|
||||
|
||||
ts := mts.TipSet.TipSet()
|
||||
fmt.Printf("tipset at H:%d: %s\n", ts.Height(), ts.Cids())
|
||||
}
|
||||
|
||||
r, err := tu.g.YieldRepo()
|
||||
@ -94,8 +91,38 @@ func (tu *syncTestUtil) Shutdown() {
|
||||
tu.cancel()
|
||||
}
|
||||
|
||||
func (tu *syncTestUtil) printHeads() {
|
||||
for i, n := range tu.nds {
|
||||
head, err := n.ChainHead(tu.ctx)
|
||||
if err != nil {
|
||||
tu.t.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Printf("Node %d: %s\n", i, head.Cids())
|
||||
}
|
||||
}
|
||||
|
||||
func (tu *syncTestUtil) pushFtsAndWait(to int, fts *store.FullTipSet, wait bool) {
|
||||
// TODO: would be great if we could pass a whole tipset here...
|
||||
tu.pushTsExpectErr(to, fts, false)
|
||||
|
||||
if wait {
|
||||
start := time.Now()
|
||||
h, err := tu.nds[to].ChainHead(tu.ctx)
|
||||
require.NoError(tu.t, err)
|
||||
for !h.Equals(fts.TipSet()) {
|
||||
time.Sleep(time.Millisecond * 50)
|
||||
h, err = tu.nds[to].ChainHead(tu.ctx)
|
||||
require.NoError(tu.t, err)
|
||||
|
||||
if time.Since(start) > time.Second*10 {
|
||||
tu.t.Fatal("took too long waiting for block to be accepted")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (tu *syncTestUtil) pushTsExpectErr(to int, fts *store.FullTipSet, experr bool) {
|
||||
for _, fb := range fts.Blocks {
|
||||
var b types.BlockMsg
|
||||
|
||||
@ -115,27 +142,17 @@ func (tu *syncTestUtil) pushFtsAndWait(to int, fts *store.FullTipSet, wait bool)
|
||||
b.BlsMessages = append(b.BlsMessages, c)
|
||||
}
|
||||
|
||||
require.NoError(tu.t, tu.nds[to].ChainSubmitBlock(tu.ctx, &b))
|
||||
|
||||
}
|
||||
|
||||
if wait {
|
||||
start := time.Now()
|
||||
h, err := tu.nds[to].ChainHead(tu.ctx)
|
||||
require.NoError(tu.t, err)
|
||||
for !h.Equals(fts.TipSet()) {
|
||||
time.Sleep(time.Millisecond * 50)
|
||||
h, err = tu.nds[to].ChainHead(tu.ctx)
|
||||
err := tu.nds[to].SyncSubmitBlock(tu.ctx, &b)
|
||||
if experr {
|
||||
require.Error(tu.t, err, "expected submit block to fail")
|
||||
} else {
|
||||
require.NoError(tu.t, err)
|
||||
}
|
||||
}
|
||||
|
||||
if time.Since(start) > time.Second*10 {
|
||||
tu.t.Fatal("took too long waiting for block to be accepted")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (tu *syncTestUtil) mineOnBlock(blk *store.FullTipSet, src int, miners []int, wait bool) *store.FullTipSet {
|
||||
func (tu *syncTestUtil) mineOnBlock(blk *store.FullTipSet, src int, miners []int, wait, fail bool) *store.FullTipSet {
|
||||
if miners == nil {
|
||||
for i := range tu.g.Miners {
|
||||
miners = append(miners, i)
|
||||
@ -152,13 +169,17 @@ func (tu *syncTestUtil) mineOnBlock(blk *store.FullTipSet, src int, miners []int
|
||||
mts, err := tu.g.NextTipSetFromMiners(blk.TipSet(), maddrs)
|
||||
require.NoError(tu.t, err)
|
||||
|
||||
if fail {
|
||||
tu.pushTsExpectErr(src, mts.TipSet, true)
|
||||
} else {
|
||||
tu.pushFtsAndWait(src, mts.TipSet, wait)
|
||||
}
|
||||
|
||||
return mts.TipSet
|
||||
}
|
||||
|
||||
func (tu *syncTestUtil) mineNewBlock(src int, miners []int) {
|
||||
mts := tu.mineOnBlock(tu.g.CurTipset, src, miners, true)
|
||||
mts := tu.mineOnBlock(tu.g.CurTipset, src, miners, true, false)
|
||||
tu.g.CurTipset = mts
|
||||
}
|
||||
|
||||
@ -197,7 +218,9 @@ func (tu *syncTestUtil) addSourceNode(gen int) {
|
||||
|
||||
lastTs := blocks[len(blocks)-1].Blocks
|
||||
for _, lastB := range lastTs {
|
||||
err = out.(*impl.FullNodeAPI).ChainAPI.Chain.AddBlock(lastB.Header)
|
||||
cs := out.(*impl.FullNodeAPI).ChainAPI.Chain
|
||||
require.NoError(tu.t, cs.AddToTipSetTracker(lastB.Header))
|
||||
err = cs.AddBlock(tu.ctx, lastB.Header)
|
||||
require.NoError(tu.t, err)
|
||||
}
|
||||
|
||||
@ -368,12 +391,17 @@ func TestSyncBadTimestamp(t *testing.T) {
|
||||
return pts.MinTimestamp() + 2
|
||||
}
|
||||
|
||||
a1 := tu.mineOnBlock(base, 0, nil, false)
|
||||
fmt.Println("BASE: ", base.Cids())
|
||||
tu.printHeads()
|
||||
|
||||
a1 := tu.mineOnBlock(base, 0, nil, false, true)
|
||||
|
||||
tu.g.Timestamper = nil
|
||||
tu.g.ResyncBankerNonce(a1.TipSet())
|
||||
|
||||
a2 := tu.mineOnBlock(base, 0, nil, true)
|
||||
fmt.Println("After mine bad block!")
|
||||
tu.printHeads()
|
||||
a2 := tu.mineOnBlock(base, 0, nil, true, false)
|
||||
|
||||
tu.waitUntilSync(0, client)
|
||||
|
||||
@ -427,16 +455,16 @@ func TestSyncFork(t *testing.T) {
|
||||
fmt.Println("Mining base: ", base.TipSet().Cids(), base.TipSet().Height())
|
||||
|
||||
// The two nodes fork at this point into 'a' and 'b'
|
||||
a1 := tu.mineOnBlock(base, p1, []int{0}, true)
|
||||
a := tu.mineOnBlock(a1, p1, []int{0}, true)
|
||||
a = tu.mineOnBlock(a, p1, []int{0}, true)
|
||||
a1 := tu.mineOnBlock(base, p1, []int{0}, true, false)
|
||||
a := tu.mineOnBlock(a1, p1, []int{0}, true, false)
|
||||
a = tu.mineOnBlock(a, p1, []int{0}, true, false)
|
||||
|
||||
tu.g.ResyncBankerNonce(a1.TipSet())
|
||||
// chain B will now be heaviest
|
||||
b := tu.mineOnBlock(base, p2, []int{1}, true)
|
||||
b = tu.mineOnBlock(b, p2, []int{1}, true)
|
||||
b = tu.mineOnBlock(b, p2, []int{1}, true)
|
||||
b = tu.mineOnBlock(b, p2, []int{1}, true)
|
||||
b := tu.mineOnBlock(base, p2, []int{1}, true, false)
|
||||
b = tu.mineOnBlock(b, p2, []int{1}, true, false)
|
||||
b = tu.mineOnBlock(b, p2, []int{1}, true, false)
|
||||
b = tu.mineOnBlock(b, p2, []int{1}, true, false)
|
||||
|
||||
fmt.Println("A: ", a.Cids(), a.TipSet().Height())
|
||||
fmt.Println("B: ", b.Cids(), b.TipSet().Height())
|
||||
|
@ -133,6 +133,10 @@ func (bi *BigInt) cborBytes() []byte {
|
||||
}
|
||||
|
||||
func fromCborBytes(buf []byte) (BigInt, error) {
|
||||
if len(buf) == 0 {
|
||||
return NewInt(0), nil
|
||||
}
|
||||
|
||||
var negative bool
|
||||
switch buf[0] {
|
||||
case 0:
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
|
||||
func TestBigIntSerializationRoundTrip(t *testing.T) {
|
||||
testValues := []string{
|
||||
"0", "1", "10", "9999", "12345678901234567891234567890123456789012345678901234567890",
|
||||
"0", "1", "10", "-10", "9999", "12345678901234567891234567890123456789012345678901234567890",
|
||||
}
|
||||
|
||||
for _, v := range testValues {
|
||||
@ -29,5 +29,6 @@ func TestBigIntSerializationRoundTrip(t *testing.T) {
|
||||
if BigCmp(out, bi) != 0 {
|
||||
t.Fatal("failed to round trip BigInt through cbor")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -2,12 +2,14 @@ package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"math/big"
|
||||
|
||||
block "github.com/ipfs/go-block-format"
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/multiformats/go-multihash"
|
||||
"go.opencensus.io/trace"
|
||||
xerrors "golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-lotus/chain/address"
|
||||
@ -98,7 +100,10 @@ func (blk *BlockHeader) SigningBytes() ([]byte, error) {
|
||||
return blkcopy.Serialize()
|
||||
}
|
||||
|
||||
func (blk *BlockHeader) CheckBlockSignature(worker address.Address) error {
|
||||
func (blk *BlockHeader) CheckBlockSignature(ctx context.Context, worker address.Address) error {
|
||||
ctx, span := trace.StartSpan(ctx, "checkBlockSignature")
|
||||
defer span.End()
|
||||
|
||||
sigb, err := blk.SigningBytes()
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to get block signing bytes: %w", err)
|
||||
|
@ -75,6 +75,8 @@ func NewTipSet(blks []*BlockHeader) (*TipSet, error) {
|
||||
return nil, fmt.Errorf("cannot create tipset with mismatching heights")
|
||||
}
|
||||
ts.cids = append(ts.cids, b.Cid())
|
||||
|
||||
// TODO: ensure the same parents
|
||||
}
|
||||
ts.height = blks[0].Height
|
||||
|
||||
@ -89,12 +91,6 @@ func (ts *TipSet) Height() uint64 {
|
||||
return ts.height
|
||||
}
|
||||
|
||||
func (ts *TipSet) Weight() BigInt {
|
||||
// TODO: implement correctly
|
||||
log.Warn("Called TipSet.Weight: TODO: correct implementation")
|
||||
return BigAdd(ts.blks[0].ParentWeight, NewInt(1))
|
||||
}
|
||||
|
||||
func (ts *TipSet) Parents() []cid.Cid {
|
||||
return ts.blks[0].Parents
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
amt "github.com/filecoin-project/go-amt-ipld"
|
||||
"github.com/filecoin-project/go-lotus/chain/actors/aerrors"
|
||||
"github.com/filecoin-project/go-lotus/chain/address"
|
||||
@ -38,6 +40,8 @@ type VMContext interface {
|
||||
ChargeGas(uint64) aerrors.ActorError
|
||||
GetRandomness(height uint64) ([]byte, aerrors.ActorError)
|
||||
GetBalance(address.Address) (BigInt, aerrors.ActorError)
|
||||
|
||||
Context() context.Context
|
||||
}
|
||||
|
||||
type storageWrapper struct {
|
||||
|
@ -30,7 +30,7 @@ func newInvoker() *invoker {
|
||||
|
||||
// add builtInCode using: register(cid, singleton)
|
||||
inv.register(actors.InitActorCodeCid, actors.InitActor{}, actors.InitActorState{})
|
||||
inv.register(actors.StorageMarketActorCodeCid, actors.StorageMarketActor{}, actors.StorageMarketState{})
|
||||
inv.register(actors.StorageMarketActorCodeCid, actors.StoragePowerActor{}, actors.StoragePowerState{})
|
||||
inv.register(actors.StorageMinerCodeCid, actors.StorageMinerActor{}, actors.StorageMinerActorState{})
|
||||
inv.register(actors.MultisigActorCodeCid, actors.MultiSigActor{}, actors.MultiSigActorState{})
|
||||
inv.register(actors.PaymentChannelActorCodeCid, actors.PaymentChannelActor{}, actors.PaymentChannelActorState{})
|
||||
|
@ -3,15 +3,16 @@ package vm
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
dstore "github.com/ipfs/go-datastore"
|
||||
hamt "github.com/ipfs/go-hamt-ipld"
|
||||
bstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
|
||||
"github.com/filecoin-project/go-lotus/chain/actors"
|
||||
"github.com/filecoin-project/go-lotus/chain/actors/aerrors"
|
||||
"github.com/filecoin-project/go-lotus/chain/address"
|
||||
"github.com/filecoin-project/go-lotus/chain/state"
|
||||
"github.com/filecoin-project/go-lotus/chain/types"
|
||||
"github.com/ipfs/go-cid"
|
||||
dstore "github.com/ipfs/go-datastore"
|
||||
hamt "github.com/ipfs/go-hamt-ipld"
|
||||
bstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -3,6 +3,7 @@ package vm
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
"math/big"
|
||||
|
||||
"github.com/filecoin-project/go-lotus/build"
|
||||
@ -10,7 +11,6 @@ import (
|
||||
"github.com/filecoin-project/go-lotus/chain/actors/aerrors"
|
||||
"github.com/filecoin-project/go-lotus/chain/address"
|
||||
"github.com/filecoin-project/go-lotus/chain/state"
|
||||
"github.com/filecoin-project/go-lotus/chain/store"
|
||||
"github.com/filecoin-project/go-lotus/chain/types"
|
||||
"github.com/filecoin-project/go-lotus/lib/bufbstore"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
@ -239,6 +239,10 @@ func (vmctx *VMContext) GetBalance(a address.Address) (types.BigInt, aerrors.Act
|
||||
}
|
||||
}
|
||||
|
||||
func (vmctx *VMContext) Context() context.Context {
|
||||
return vmctx.ctx
|
||||
}
|
||||
|
||||
type hBlocks interface {
|
||||
GetBlock(context.Context, cid.Cid) (block.Block, error)
|
||||
AddBlock(block.Block) error
|
||||
@ -296,7 +300,6 @@ func (vm *VM) makeVMContext(ctx context.Context, sroot cid.Cid, msg *types.Messa
|
||||
type VM struct {
|
||||
cstate *state.StateTree
|
||||
base cid.Cid
|
||||
cs *store.ChainStore
|
||||
cst *hamt.CborIpldStore
|
||||
buf *bufbstore.BufferedBS
|
||||
blockHeight uint64
|
||||
@ -305,8 +308,8 @@ type VM struct {
|
||||
rand Rand
|
||||
}
|
||||
|
||||
func NewVM(base cid.Cid, height uint64, r Rand, maddr address.Address, cs *store.ChainStore) (*VM, error) {
|
||||
buf := bufbstore.NewBufferedBstore(cs.Blockstore())
|
||||
func NewVM(base cid.Cid, height uint64, r Rand, maddr address.Address, cbs blockstore.Blockstore) (*VM, error) {
|
||||
buf := bufbstore.NewBufferedBstore(cbs)
|
||||
cst := hamt.CSTFromBstore(buf)
|
||||
state, err := state.LoadStateTree(cst, base)
|
||||
if err != nil {
|
||||
@ -316,7 +319,6 @@ func NewVM(base cid.Cid, height uint64, r Rand, maddr address.Address, cs *store
|
||||
return &VM{
|
||||
cstate: state,
|
||||
base: base,
|
||||
cs: cs,
|
||||
cst: cst,
|
||||
buf: buf,
|
||||
blockHeight: height,
|
||||
@ -330,27 +332,6 @@ type Rand interface {
|
||||
GetRandomness(ctx context.Context, h int64) ([]byte, error)
|
||||
}
|
||||
|
||||
type chainRand struct {
|
||||
cs *store.ChainStore
|
||||
blks []cid.Cid
|
||||
bh uint64
|
||||
tickets []*types.Ticket
|
||||
}
|
||||
|
||||
func NewChainRand(cs *store.ChainStore, blks []cid.Cid, bheight uint64, tickets []*types.Ticket) Rand {
|
||||
return &chainRand{
|
||||
cs: cs,
|
||||
blks: blks,
|
||||
bh: bheight,
|
||||
tickets: tickets,
|
||||
}
|
||||
}
|
||||
|
||||
func (cr *chainRand) GetRandomness(ctx context.Context, h int64) ([]byte, error) {
|
||||
lb := (int64(cr.bh) + int64(len(cr.tickets))) - h
|
||||
return cr.cs.GetRandomness(ctx, cr.blks, cr.tickets, lb)
|
||||
}
|
||||
|
||||
type ApplyRet struct {
|
||||
types.MessageReceipt
|
||||
ActorErr aerrors.ActorError
|
||||
|
40
cli/chain.go
40
cli/chain.go
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
cid "github.com/ipfs/go-cid"
|
||||
@ -279,7 +280,12 @@ var chainListCmd = &cli.Command{
|
||||
Usage: "View a segment of the chain",
|
||||
Flags: []cli.Flag{
|
||||
&cli.Uint64Flag{Name: "height"},
|
||||
&cli.UintFlag{Name: "count", Value: 30},
|
||||
&cli.IntFlag{Name: "count", Value: 30},
|
||||
&cli.StringFlag{
|
||||
Name: "format",
|
||||
Usage: "specify the format to print out tipsets",
|
||||
Value: "<height>: (<time>) <blocks>",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
api, closer, err := GetFullNodeAPI(cctx)
|
||||
@ -300,15 +306,15 @@ var chainListCmd = &cli.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
count := cctx.Uint("count")
|
||||
count := cctx.Int("count")
|
||||
if count < 1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
tss := make([]*types.TipSet, count)
|
||||
tss[0] = head
|
||||
tss := make([]*types.TipSet, 0, count)
|
||||
tss = append(tss, head)
|
||||
|
||||
for i := 1; i < len(tss); i++ {
|
||||
for i := 1; i < count; i++ {
|
||||
if head.Height() == 0 {
|
||||
break
|
||||
}
|
||||
@ -318,18 +324,26 @@ var chainListCmd = &cli.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
tss[i] = head
|
||||
tss = append(tss, head)
|
||||
}
|
||||
|
||||
for i := len(tss) - 1; i >= 0; i-- {
|
||||
mints := tss[i].MinTimestamp()
|
||||
t := time.Unix(int64(mints), 0)
|
||||
fmt.Printf("%d: (%s) [ ", tss[i].Height(), t.Format(time.Stamp))
|
||||
for _, b := range tss[i].Blocks() {
|
||||
fmt.Printf("%s: %s,", b.Cid(), b.Miner)
|
||||
}
|
||||
fmt.Println("]")
|
||||
printTipSet(cctx.String("format"), tss[i])
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func printTipSet(format string, ts *types.TipSet) {
|
||||
format = strings.ReplaceAll(format, "<height>", fmt.Sprint(ts.Height()))
|
||||
format = strings.ReplaceAll(format, "<time>", time.Unix(int64(ts.MinTimestamp()), 0).Format(time.Stamp))
|
||||
blks := "[ "
|
||||
for _, b := range ts.Blocks() {
|
||||
blks += fmt.Sprintf("%s: %s,", b.Cid(), b.Miner)
|
||||
}
|
||||
blks += " ]"
|
||||
format = strings.ReplaceAll(format, "<blocks>", blks)
|
||||
format = strings.ReplaceAll(format, "<weight>", fmt.Sprint(ts.Blocks()[0].ParentWeight))
|
||||
|
||||
fmt.Println(format)
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ var createMinerCmd = &cli.Command{
|
||||
msg := &types.Message{
|
||||
To: actors.StorageMarketAddress,
|
||||
From: addr,
|
||||
Method: actors.SMAMethods.CreateStorageMiner,
|
||||
Method: actors.SPAMethods.CreateStorageMiner,
|
||||
Params: params,
|
||||
Value: types.NewInt(0),
|
||||
GasPrice: types.NewInt(0),
|
||||
|
@ -1,6 +1,7 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"gopkg.in/urfave/cli.v2"
|
||||
@ -32,7 +33,11 @@ var mpoolPending = &cli.Command{
|
||||
}
|
||||
|
||||
for _, msg := range msgs {
|
||||
fmt.Println(msg)
|
||||
out, err := json.MarshalIndent(msg, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(string(out))
|
||||
}
|
||||
|
||||
return nil
|
||||
|
38
cli/sync.go
38
cli/sync.go
@ -2,11 +2,13 @@ package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
cid "github.com/ipfs/go-cid"
|
||||
"gopkg.in/urfave/cli.v2"
|
||||
|
||||
"github.com/filecoin-project/go-lotus/api"
|
||||
"github.com/filecoin-project/go-lotus/chain"
|
||||
cid "github.com/ipfs/go-cid"
|
||||
)
|
||||
|
||||
var syncCmd = &cli.Command{
|
||||
@ -14,6 +16,7 @@ var syncCmd = &cli.Command{
|
||||
Usage: "Inspect or interact with the chain syncer",
|
||||
Subcommands: []*cli.Command{
|
||||
syncStatusCmd,
|
||||
syncWaitCmd,
|
||||
},
|
||||
}
|
||||
|
||||
@ -49,3 +52,36 @@ var syncStatusCmd = &cli.Command{
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var syncWaitCmd = &cli.Command{
|
||||
Name: "wait",
|
||||
Usage: "Wait for sync to be complete",
|
||||
Action: func(cctx *cli.Context) error {
|
||||
napi, closer, err := GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
ctx := ReqContext(cctx)
|
||||
|
||||
for {
|
||||
ss, err := napi.SyncState(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var target []cid.Cid
|
||||
if ss.Target != nil {
|
||||
target = ss.Target.Cids()
|
||||
}
|
||||
|
||||
fmt.Printf("\r\x1b[2KTarget: %s\tState: %s\tHeight: %d", target, chain.SyncStageString(ss.Stage), ss.Height)
|
||||
if ss.Stage == api.StageSyncComplete {
|
||||
fmt.Println("\nDone")
|
||||
return nil
|
||||
}
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
93
cmd/chain-noise/main.go
Normal file
93
cmd/chain-noise/main.go
Normal 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
|
||||
}
|
@ -6,6 +6,7 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
rice "github.com/GeertJohan/go.rice"
|
||||
logging "github.com/ipfs/go-log"
|
||||
"golang.org/x/xerrors"
|
||||
"gopkg.in/urfave/cli.v2"
|
||||
@ -89,8 +90,9 @@ var runCmd = &cli.Command{
|
||||
from: from,
|
||||
}
|
||||
|
||||
http.HandleFunc("/", h.index)
|
||||
http.Handle("/", http.FileServer(rice.MustFindBox("site").HTTPBox()))
|
||||
http.HandleFunc("/send", h.send)
|
||||
http.HandleFunc("/sendcoll", h.sendColl)
|
||||
|
||||
fmt.Printf("Open http://%s\n", cctx.String("front"))
|
||||
|
||||
@ -110,13 +112,6 @@ type handler struct {
|
||||
from address.Address
|
||||
}
|
||||
|
||||
func (h *handler) index(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, "<!DOCTYPE html>\n<html><head><title>Lotus Fountain</title><style>body {font-family: 'monospace';}</style></head><body>")
|
||||
fmt.Fprintf(w, "<form action='/send' method='get'>Enter destination address: ")
|
||||
fmt.Fprintf(w, "<input type='text' name='address'><br><button type='submit'>Send</button>")
|
||||
fmt.Fprintf(w, "</form></body></html>")
|
||||
}
|
||||
|
||||
func (h *handler) send(w http.ResponseWriter, r *http.Request) {
|
||||
to, err := address.NewFromString(r.FormValue("address"))
|
||||
if err != nil {
|
||||
@ -141,3 +136,33 @@ func (h *handler) send(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
w.Write([]byte(smsg.Cid().String()))
|
||||
}
|
||||
|
||||
func (h *handler) sendColl(w http.ResponseWriter, r *http.Request) {
|
||||
to, err := address.NewFromString(r.FormValue("address"))
|
||||
if err != nil {
|
||||
w.WriteHeader(400)
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
coll, err := h.api.StatePledgeCollateral(h.ctx, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
smsg, err := h.api.MpoolPushMessage(h.ctx, &types.Message{
|
||||
Value: coll,
|
||||
From: h.from,
|
||||
To: to,
|
||||
|
||||
GasPrice: types.NewInt(0),
|
||||
GasLimit: types.NewInt(1000),
|
||||
})
|
||||
if err != nil {
|
||||
w.WriteHeader(400)
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
w.Write([]byte(smsg.Cid().String()))
|
||||
}
|
||||
|
20
cmd/lotus-fountain/site/index.html
Normal file
20
cmd/lotus-fountain/site/index.html
Normal 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>
|
@ -1,11 +1,15 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"gopkg.in/urfave/cli.v2"
|
||||
|
||||
"github.com/filecoin-project/go-lotus/api"
|
||||
"github.com/filecoin-project/go-lotus/chain/types"
|
||||
lcli "github.com/filecoin-project/go-lotus/cli"
|
||||
sectorstate "github.com/filecoin-project/go-sectorbuilder/sealing_state"
|
||||
)
|
||||
|
||||
var infoCmd = &cli.Command{
|
||||
@ -17,14 +21,40 @@ var infoCmd = &cli.Command{
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
|
||||
api, acloser, err := lcli.GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer acloser()
|
||||
|
||||
ctx := lcli.ReqContext(cctx)
|
||||
|
||||
aaddr, err := nodeApi.ActorAddresses(ctx)
|
||||
maddr, err := nodeApi.ActorAddress(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("actor address: %s\n", aaddr)
|
||||
fmt.Printf("Miner: %s\n", maddr)
|
||||
|
||||
pow, err := api.StateMinerPower(ctx, maddr, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
percI := types.BigDiv(types.BigMul(pow.MinerPower, types.NewInt(1000)), pow.TotalPower)
|
||||
fmt.Printf("Power: %s / %s (%0.2f%%)\n", pow.MinerPower, pow.TotalPower, float64(percI.Int64())/1000*100)
|
||||
|
||||
sinfo, err := sectorsInfo(ctx, nodeApi)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("Sealed Sectors:\t", sinfo.SealedCount)
|
||||
fmt.Println("Sealing Sectors:\t", sinfo.SealingCount)
|
||||
fmt.Println("Pending Sectors:\t", sinfo.PendingCount)
|
||||
fmt.Println("Failed Sectors:\t", sinfo.FailedCount)
|
||||
|
||||
// TODO: grab actr state / info
|
||||
// * Sector size
|
||||
// * Sealed sectors (count / bytes)
|
||||
@ -32,3 +62,42 @@ var infoCmd = &cli.Command{
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
type SectorsInfo struct {
|
||||
TotalCount int
|
||||
SealingCount int
|
||||
FailedCount int
|
||||
SealedCount int
|
||||
PendingCount int
|
||||
}
|
||||
|
||||
func sectorsInfo(ctx context.Context, napi api.StorageMiner) (*SectorsInfo, error) {
|
||||
sectors, err := napi.SectorsList(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out := SectorsInfo{
|
||||
TotalCount: len(sectors),
|
||||
}
|
||||
for _, s := range sectors {
|
||||
st, err := napi.SectorsStatus(ctx, s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch st.State {
|
||||
case sectorstate.Sealed:
|
||||
out.SealedCount++
|
||||
case sectorstate.Pending:
|
||||
out.PendingCount++
|
||||
case sectorstate.Sealing:
|
||||
out.SealingCount++
|
||||
case sectorstate.Failed:
|
||||
out.FailedCount++
|
||||
case sectorstate.Unknown:
|
||||
}
|
||||
}
|
||||
|
||||
return &out, nil
|
||||
}
|
||||
|
@ -289,7 +289,7 @@ func createStorageMiner(ctx context.Context, api api.FullNode, peerid peer.ID, c
|
||||
From: owner,
|
||||
Value: collateral,
|
||||
|
||||
Method: actors.SMAMethods.CreateStorageMiner,
|
||||
Method: actors.SPAMethods.CreateStorageMiner,
|
||||
Params: params,
|
||||
|
||||
GasLimit: types.NewInt(10000),
|
||||
@ -309,6 +309,10 @@ func createStorageMiner(ctx context.Context, api api.FullNode, peerid peer.ID, c
|
||||
return address.Undef, err
|
||||
}
|
||||
|
||||
if mw.Receipt.ExitCode != 0 {
|
||||
return address.Undef, xerrors.Errorf("create storage miner failed: exit code %d", mw.Receipt.ExitCode)
|
||||
}
|
||||
|
||||
addr, err = address.NewFromBytes(mw.Receipt.Return)
|
||||
if err != nil {
|
||||
return address.Undef, err
|
||||
|
@ -89,7 +89,7 @@ var sectorsStagedListCmd = &cli.Command{
|
||||
defer closer()
|
||||
ctx := lcli.ReqContext(cctx)
|
||||
|
||||
staged, err := nodeApi.SectorsStagedList(ctx)
|
||||
staged, err := nodeApi.SectorsList(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ import (
|
||||
"github.com/filecoin-project/go-lotus/node/modules/lp2p"
|
||||
)
|
||||
|
||||
const topic = "/fil/headnotifs/bafy2bzacedjqrkfbuafakygo6vlkrqozvsju2d5k6g24ry3mjjfxwrvet2636"
|
||||
const topic = "/fil/headnotifs/bafy2bzacecyfz2wfi5a6d4epch6nmedrlan3mdfswgv3y74an5aeqxaq5gqlu"
|
||||
|
||||
var upgrader = websocket.Upgrader{
|
||||
WriteBufferSize: 1024,
|
||||
@ -49,7 +49,7 @@ func main() {
|
||||
}
|
||||
|
||||
pi, err := addrutil.ParseAddresses(ctx, []string{
|
||||
"/ip4/147.75.80.29/tcp/1347/p2p/12D3KooWAShT7qd3oM7QPC8AsQffs6ThH69fZGui4xCW68E35rDP",
|
||||
"/ip4/147.75.80.29/tcp/1347/p2p/12D3KooWGdsbvHwscFKT1kqBeeooPe6EneJvjXzTrWSzwKhc1ssn",
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -67,7 +67,7 @@ func main() {
|
||||
actors.LaneState{},
|
||||
actors.PCAUpdateChannelStateParams{},
|
||||
actors.PaymentInfo{},
|
||||
actors.StorageMarketState{},
|
||||
actors.StoragePowerState{},
|
||||
actors.CreateStorageMinerParams{},
|
||||
actors.IsMinerParam{},
|
||||
actors.PowerLookupParams{},
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"os"
|
||||
"sort"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
@ -94,8 +95,22 @@ func (sb *SectorBuilder) SealStatus(sector uint64) (SectorSealingStatus, error)
|
||||
return sectorbuilder.GetSectorSealingStatusByID(sb.handle, sector)
|
||||
}
|
||||
|
||||
func (sb *SectorBuilder) GetAllStagedSectors() ([]StagedSectorMetadata, error) {
|
||||
return sectorbuilder.GetAllStagedSectors(sb.handle)
|
||||
func (sb *SectorBuilder) GetAllStagedSectors() ([]uint64, error) {
|
||||
sectors, err := sectorbuilder.GetAllStagedSectors(sb.handle)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out := make([]uint64, len(sectors))
|
||||
for i, v := range sectors {
|
||||
out[i] = v.SectorID
|
||||
}
|
||||
|
||||
sort.Slice(out, func(i, j int) bool {
|
||||
return out[i] < out[j]
|
||||
})
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (sb *SectorBuilder) GeneratePoSt(sectorInfo SortedSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]byte, error) {
|
||||
|
@ -70,7 +70,7 @@ class StorageNode extends React.Component {
|
||||
async loadInfo() {
|
||||
const version = await this.state.client.call("Filecoin.Version", [])
|
||||
const peers = await this.state.client.call("Filecoin.NetPeers", [])
|
||||
const [actor] = await this.state.client.call("Filecoin.ActorAddresses", [])
|
||||
const actor = await this.state.client.call("Filecoin.ActorAddress", [])
|
||||
|
||||
const stActor = await this.props.fullConn.call('Filecoin.StateGetActor', [actor, null])
|
||||
const actorState = await this.props.fullConn.call('Filecoin.StateReadState', [stActor, null])
|
||||
@ -80,9 +80,9 @@ class StorageNode extends React.Component {
|
||||
}
|
||||
|
||||
async stagedList() {
|
||||
let stagedList = await this.state.client.call("Filecoin.SectorsStagedList", [])
|
||||
let stagedList = await this.state.client.call("Filecoin.SectorsList", [])
|
||||
let staged = await stagedList
|
||||
.map(sector => this.state.client.call("Filecoin.SectorsStatus", [sector.SectorID]))
|
||||
.map(sector => this.state.client.call("Filecoin.SectorsStatus", [sector]))
|
||||
.reduce(async (p, n) => [...await p, await n], Promise.resolve([]))
|
||||
|
||||
let statusCounts = staged.reduce((p, n) => p.map((e, i) => e + (i === n.State ? 1 : 0) ), [0, 0, 0, 0, 0])
|
||||
|
@ -27,6 +27,7 @@ type api struct {
|
||||
fx.In
|
||||
|
||||
full.ChainAPI
|
||||
full.SyncAPI
|
||||
full.MpoolAPI
|
||||
full.WalletAPI
|
||||
full.StateAPI
|
||||
@ -154,13 +155,13 @@ func (m *Miner) mine(ctx context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
base, err := m.GetBestMiningCandidate()
|
||||
base, err := m.GetBestMiningCandidate(ctx)
|
||||
if err != nil {
|
||||
log.Errorf("failed to get best mining candidate: %s", err)
|
||||
continue
|
||||
}
|
||||
if base.ts.Equals(lastBase.ts) && len(lastBase.tickets) == len(base.tickets) {
|
||||
log.Error("BestMiningCandidate from the previous round: %s (tkts:%d)", lastBase.ts.Cids(), len(lastBase.tickets))
|
||||
log.Errorf("BestMiningCandidate from the previous round: %s (tkts:%d)", lastBase.ts.Cids(), len(lastBase.tickets))
|
||||
time.Sleep(build.BlockDelay * time.Second)
|
||||
continue
|
||||
}
|
||||
@ -183,7 +184,7 @@ func (m *Miner) mine(ctx context.Context) {
|
||||
"time", time.Now(), "duration", time.Now().Sub(btime))
|
||||
}
|
||||
|
||||
if err := m.api.ChainSubmitBlock(ctx, b); err != nil {
|
||||
if err := m.api.SyncSubmitBlock(ctx, b); err != nil {
|
||||
log.Errorf("failed to submit newly mined block: %s", err)
|
||||
}
|
||||
} else {
|
||||
@ -198,8 +199,8 @@ type MiningBase struct {
|
||||
tickets []*types.Ticket
|
||||
}
|
||||
|
||||
func (m *Miner) GetBestMiningCandidate() (*MiningBase, error) {
|
||||
bts, err := m.api.ChainHead(context.TODO())
|
||||
func (m *Miner) GetBestMiningCandidate(ctx context.Context) (*MiningBase, error) {
|
||||
bts, err := m.api.ChainHead(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -209,7 +210,16 @@ func (m *Miner) GetBestMiningCandidate() (*MiningBase, error) {
|
||||
return m.lastWork, nil
|
||||
}
|
||||
|
||||
if types.BigCmp(bts.Weight(), m.lastWork.ts.Weight()) <= 0 {
|
||||
btsw, err := m.api.ChainTipSetWeight(ctx, bts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ltsw, err := m.api.ChainTipSetWeight(ctx, m.lastWork.ts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if types.BigCmp(btsw, ltsw) <= 0 {
|
||||
return m.lastWork, nil
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package hello
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/filecoin-project/go-lotus/chain/types"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
@ -26,7 +27,7 @@ func init() {
|
||||
|
||||
type Message struct {
|
||||
HeaviestTipSet []cid.Cid
|
||||
HeaviestTipSetWeight uint64
|
||||
HeaviestTipSetWeight types.BigInt
|
||||
GenesisHash cid.Cid
|
||||
}
|
||||
|
||||
@ -83,7 +84,10 @@ func (hs *Service) SayHello(ctx context.Context, pid peer.ID) error {
|
||||
defer s.Close()
|
||||
|
||||
hts := hs.cs.GetHeaviestTipSet()
|
||||
weight := hs.cs.Weight(hts)
|
||||
weight, err := hs.cs.Weight(ctx, hts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
gen, err := hs.cs.GetGenesis()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -9,7 +9,6 @@ import (
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
||||
"go.uber.org/fx"
|
||||
)
|
||||
|
||||
@ -19,25 +18,12 @@ type ChainAPI struct {
|
||||
WalletAPI
|
||||
|
||||
Chain *store.ChainStore
|
||||
PubSub *pubsub.PubSub
|
||||
}
|
||||
|
||||
func (a *ChainAPI) ChainNotify(ctx context.Context) (<-chan []*store.HeadChange, error) {
|
||||
return a.Chain.SubHeadChanges(ctx), nil
|
||||
}
|
||||
|
||||
func (a *ChainAPI) ChainSubmitBlock(ctx context.Context, blk *types.BlockMsg) error {
|
||||
// TODO: should we have some sort of fast path to adding a local block?
|
||||
|
||||
b, err := blk.Serialize()
|
||||
if err != nil {
|
||||
return xerrors.Errorf("serializing block for pubsub publishing failed: %w", err)
|
||||
}
|
||||
|
||||
// TODO: anything else to do here?
|
||||
return a.PubSub.Publish("/fil/blocks", b)
|
||||
}
|
||||
|
||||
func (a *ChainAPI) ChainHead(context.Context) (*types.TipSet, error) {
|
||||
return a.Chain.GetHeaviestTipSet(), nil
|
||||
}
|
||||
@ -174,3 +160,7 @@ func (a *ChainAPI) ChainGetGenesis(ctx context.Context) (*types.TipSet, error) {
|
||||
|
||||
return types.NewTipSet([]*types.BlockHeader{genb})
|
||||
}
|
||||
|
||||
func (a *ChainAPI) ChainTipSetWeight(ctx context.Context, ts *types.TipSet) (types.BigInt, error) {
|
||||
return a.Chain.Weight(ctx, ts)
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ func (a *StateAPI) StatePledgeCollateral(ctx context.Context, ts *types.TipSet)
|
||||
ret, aerr := a.StateManager.Call(ctx, &types.Message{
|
||||
From: actors.StorageMarketAddress,
|
||||
To: actors.StorageMarketAddress,
|
||||
Method: actors.SMAMethods.PledgeCollateralForSize,
|
||||
Method: actors.SPAMethods.PledgeCollateralForSize,
|
||||
|
||||
Params: param,
|
||||
}, ts)
|
||||
@ -209,7 +209,7 @@ func (a *StateAPI) StateWaitMsg(ctx context.Context, msg cid.Cid) (*api.MsgWait,
|
||||
}
|
||||
|
||||
func (a *StateAPI) StateListMiners(ctx context.Context, ts *types.TipSet) ([]address.Address, error) {
|
||||
var state actors.StorageMarketState
|
||||
var state actors.StoragePowerState
|
||||
if _, err := a.StateManager.LoadActorState(ctx, actors.StorageMarketAddress, &state, ts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -5,13 +5,18 @@ import (
|
||||
|
||||
"github.com/filecoin-project/go-lotus/api"
|
||||
"github.com/filecoin-project/go-lotus/chain"
|
||||
"github.com/filecoin-project/go-lotus/chain/types"
|
||||
|
||||
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
||||
"go.uber.org/fx"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
type SyncAPI struct {
|
||||
fx.In
|
||||
|
||||
Syncer *chain.Syncer
|
||||
PubSub *pubsub.PubSub
|
||||
}
|
||||
|
||||
func (a *SyncAPI) SyncState(ctx context.Context) (*api.SyncState, error) {
|
||||
@ -23,3 +28,42 @@ func (a *SyncAPI) SyncState(ctx context.Context) (*api.SyncState, error) {
|
||||
Height: ss.Height,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *SyncAPI) SyncSubmitBlock(ctx context.Context, blk *types.BlockMsg) error {
|
||||
// TODO: should we have some sort of fast path to adding a local block?
|
||||
bmsgs, err := a.Syncer.ChainStore().LoadMessagesFromCids(blk.BlsMessages)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to load bls messages: %w", err)
|
||||
}
|
||||
|
||||
smsgs, err := a.Syncer.ChainStore().LoadSignedMessagesFromCids(blk.SecpkMessages)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to load secpk message: %w", err)
|
||||
}
|
||||
|
||||
fb := &types.FullBlock{
|
||||
Header: blk.Header,
|
||||
BlsMessages: bmsgs,
|
||||
SecpkMessages: smsgs,
|
||||
}
|
||||
|
||||
if err := a.Syncer.ValidateMsgMeta(fb); err != nil {
|
||||
xerrors.Errorf("provided messages did not match block: %w", err)
|
||||
}
|
||||
|
||||
ts, err := types.NewTipSet([]*types.BlockHeader{blk.Header})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("somehow failed to make a tipset out of a single block: %w", err)
|
||||
}
|
||||
if err := a.Syncer.Sync(ctx, ts); err != nil {
|
||||
return xerrors.Errorf("sync to submitted block failed: %w", err)
|
||||
}
|
||||
|
||||
b, err := blk.Serialize()
|
||||
if err != nil {
|
||||
return xerrors.Errorf("serializing block for pubsub publishing failed: %w", err)
|
||||
}
|
||||
|
||||
// TODO: anything else to do here?
|
||||
return a.PubSub.Publish("/fil/blocks", b)
|
||||
}
|
||||
|
@ -26,8 +26,8 @@ type StorageMinerAPI struct {
|
||||
Miner *storage.Miner
|
||||
}
|
||||
|
||||
func (sm *StorageMinerAPI) ActorAddresses(context.Context) ([]address.Address, error) {
|
||||
return []address.Address{sm.SectorBuilderConfig.Miner}, nil
|
||||
func (sm *StorageMinerAPI) ActorAddress(context.Context) (address.Address, error) {
|
||||
return sm.SectorBuilderConfig.Miner, nil
|
||||
}
|
||||
|
||||
func (sm *StorageMinerAPI) StoreGarbageData(ctx context.Context) (uint64, error) {
|
||||
@ -47,7 +47,7 @@ func (sm *StorageMinerAPI) SectorsStatus(ctx context.Context, sid uint64) (secto
|
||||
}
|
||||
|
||||
// List all staged sectors
|
||||
func (sm *StorageMinerAPI) SectorsStagedList(context.Context) ([]sectorbuilder.StagedSectorMetadata, error) {
|
||||
func (sm *StorageMinerAPI) SectorsList(context.Context) ([]uint64, error) {
|
||||
return sm.SectorBuilder.GetAllStagedSectors()
|
||||
}
|
||||
|
||||
|
16
scripts/deploy-miner.sh
Executable file
16
scripts/deploy-miner.sh
Executable 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
23
scripts/deploy-node.sh
Executable 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
|
Loading…
Reference in New Issue
Block a user