Merge branch 'feat/election-post' into feat/remote-workers

This commit is contained in:
Łukasz Magiera 2019-11-30 09:41:52 +01:00
commit 8767d8c16b
113 changed files with 3588 additions and 1512 deletions

View File

@ -46,6 +46,15 @@ jobs:
- go/mod-download
- go/mod-tidy-check
build-all:
executor: golang
steps:
- install-deps
- prepare
- go/mod-download
- run:
command: make buildall
test:
description: |
Run tests with gotestsum.
@ -166,3 +175,4 @@ workflows:
- test:
codecov-upload: true
- mod-tidy-check
- build-all

4
.gitignore vendored
View File

@ -1,9 +1,13 @@
/lotus
/lotus-storage-miner
/lotus-seal-worker
/lotus-seed
/pond
/townhall
/fountain
/stats
/bench
/bench.json
/lotuspond/front/node_modules
/lotuspond/front/build
/cmd/lotus-townhall/townhall/node_modules

10
.gitmodules vendored
View File

@ -1,6 +1,4 @@
[submodule "extern/go-bls-sigs"]
path = extern/go-bls-sigs
url = https://github.com/filecoin-project/go-bls-sigs.git
[submodule "extern/go-sectorbuilder"]
path = extern/go-sectorbuilder
url = https://github.com/filecoin-project/go-sectorbuilder
[submodule "extern/filecoin-ffi"]
path = extern/filecoin-ffi
url = https://github.com/filecoin-project/filecoin-ffi.git
branch = master

View File

@ -12,37 +12,21 @@ MODULES:=
CLEAN:=
## BLS
## FFI
BLS_PATH:=extern/go-bls-sigs/
BLS_DEPS:=libbls_signatures.a libbls_signatures.pc libbls_signatures.h
BLS_DEPS:=$(addprefix $(BLS_PATH),$(BLS_DEPS))
FFI_PATH:=extern/filecoin-ffi/
FFI_DEPS:=libfilecoin.a filecoin.pc filecoin.h
FFI_DEPS:=$(addprefix $(FFI_PATH),$(FFI_DEPS))
$(BLS_DEPS): build/.bls-install ;
$(FFI_DEPS): build/.filecoin-install ;
build/.bls-install: $(BLS_PATH)
$(MAKE) -C $(BLS_PATH) $(BLS_DEPS:$(BLS_PATH)%=%)
build/.filecoin-install: $(FFI_PATH)
$(MAKE) -C $(FFI_PATH) $(FFI_DEPS:$(FFI_PATH)%=%)
@touch $@
MODULES+=$(BLS_PATH)
BUILD_DEPS+=build/.bls-install
CLEAN+=build/.bls-install
## SECTOR BUILDER
SECTOR_BUILDER_PATH:=extern/go-sectorbuilder/
SECTOR_BUILDER_DEPS:=libsector_builder_ffi.a sector_builder_ffi.pc sector_builder_ffi.h
SECTOR_BUILDER_DEPS:=$(addprefix $(SECTOR_BUILDER_PATH),$(SECTOR_BUILDER_DEPS))
$(SECTOR_BUILDER_DEPS): build/.sector-builder-install ;
build/.sector-builder-install: $(SECTOR_BUILDER_PATH)
$(MAKE) -C $(SECTOR_BUILDER_PATH) $(SECTOR_BUILDER_DEPS:$(SECTOR_BUILDER_PATH)%=%)
@touch $@
MODULES+=$(SECTOR_BUILDER_PATH)
BUILD_DEPS+=build/.sector-builder-install
CLEAN+=build/.sector-builder-install
MODULES+=$(FFI_PATH)
BUILD_DEPS+=build/.filecoin-install
CLEAN+=build/.filecoin-install
$(MODULES): build/.update-modules ;
@ -53,43 +37,55 @@ build/.update-modules:
# end git modules
## PROOFS
## MAIN BINARIES
CLEAN+=build/.update-modules
deps: $(BUILD_DEPS)
.PHONY: deps
debug: GOFLAGS=-tags=debug
debug: lotus lotus-storage-miner
lotus: $(BUILD_DEPS)
rm -f lotus
go build -o lotus ./cmd/lotus
go build $(GOFLAGS) -o lotus ./cmd/lotus
go run github.com/GeertJohan/go.rice/rice append --exec lotus -i ./build
.PHONY: lotus
CLEAN+=lotus
BINS+=lotus
lotus-storage-miner: $(BUILD_DEPS)
rm -f lotus-storage-miner
go build -o lotus-storage-miner ./cmd/lotus-storage-miner
go build $(GOFLAGS) -o lotus-storage-miner ./cmd/lotus-storage-miner
go run github.com/GeertJohan/go.rice/rice append --exec lotus-storage-miner -i ./build
.PHONY: lotus-storage-miner
BINS+=lotus-storage-miner
lotus-seal-worker: $(BUILD_DEPS)
rm -f lotus-seal-worker
go build -o lotus-seal-worker ./cmd/lotus-seal-worker
go run github.com/GeertJohan/go.rice/rice append --exec lotus-seal-worker -i ./build
.PHONY: lotus-seal-worker
CLEAN+=lotus-storage-miner
BINS+=lotus-seal-worker
build: lotus lotus-storage-miner
.PHONY: build
install:
install -C ./lotus /usr/local/bin/lotus
install -C ./lotus-storage-miner /usr/local/bin/lotus-storage-miner
# TOOLS
lotus-seed: $(BUILD_DEPS)
rm -f lotus-seed
go build -o lotus-seed ./cmd/lotus-seed
go run github.com/GeertJohan/go.rice/rice append --exec lotus-seed -i ./build
.PHONY: lotus-seed
BINS+=lotus-seed
benchmarks:
go run github.com/whyrusleeping/bencher ./... > bench.json
@echo Submitting results
@ -100,6 +96,7 @@ pond: build
go build -o pond ./lotuspond
(cd lotuspond/front && npm i && npm run build)
.PHONY: pond
BINS+=pond
townhall:
rm -f townhall
@ -107,28 +104,42 @@ townhall:
(cd ./cmd/lotus-townhall/townhall && npm i && npm run build)
go run github.com/GeertJohan/go.rice/rice append --exec townhall -i ./cmd/lotus-townhall -i ./build
.PHONY: townhall
BINS+=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
BINS+=fountain
chainwatch:
rm -f chainwatch
go build -o chainwatch ./cmd/lotus-chainwatch
go run github.com/GeertJohan/go.rice/rice append --exec chainwatch -i ./cmd/lotus-chainwatch
.PHONY: chainwatch
BINS+=chainwatch
bench:
rm -f bench
go build -o bench ./cmd/lotus-bench
go run github.com/GeertJohan/go.rice/rice append --exec bench -i ./build
.PHONY: bench
BINS+=bench
stats:
rm -f stats
go build -o stats ./tools/stats
.PHONY: stats
BINS+=stats
# MISC
buildall: $(BINS)
clean:
rm -rf $(CLEAN)
-$(MAKE) -C $(BLS_PATH) clean
-$(MAKE) -C $(SECTOR_BUILDER_PATH) clean
rm -rf $(CLEAN) $(BINS)
-$(MAKE) -C $(FFI_PATH) clean
.PHONY: clean
dist-clean:

View File

@ -23,7 +23,7 @@ type FullNode interface {
// 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)
ChainGetRandomness(context.Context, types.TipSetKey, []*types.Ticket, int) ([]byte, error)
ChainGetRandomness(context.Context, types.TipSetKey, int64) ([]byte, error)
ChainGetBlock(context.Context, cid.Cid) (*types.BlockHeader, error)
ChainGetTipSet(context.Context, types.TipSetKey) (*types.TipSet, error)
ChainGetBlockMessages(context.Context, cid.Cid) (*BlockMessages, error)
@ -51,10 +51,7 @@ type FullNode interface {
// miner
MinerRegister(context.Context, address.Address) error
MinerUnregister(context.Context, address.Address) error
MinerAddresses(context.Context) ([]address.Address, error)
MinerCreateBlock(context.Context, address.Address, *types.TipSet, []*types.Ticket, types.ElectionProof, []*types.SignedMessage, uint64) (*types.BlockMsg, error)
MinerCreateBlock(context.Context, address.Address, *types.TipSet, *types.Ticket, *types.EPostProof, []*types.SignedMessage, uint64, uint64) (*types.BlockMsg, error)
// // UX ?
@ -102,7 +99,7 @@ type FullNode interface {
StateMinerPower(context.Context, address.Address, *types.TipSet) (MinerPower, error)
StateMinerWorker(context.Context, address.Address, *types.TipSet) (address.Address, error)
StateMinerPeerID(ctx context.Context, m address.Address, ts *types.TipSet) (peer.ID, error)
StateMinerProvingPeriodEnd(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error)
StateMinerElectionPeriodStart(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error)
StateMinerSectorSize(context.Context, address.Address, *types.TipSet) (uint64, error)
StatePledgeCollateral(context.Context, *types.TipSet) (types.BigInt, error)
StateWaitMsg(context.Context, cid.Cid) (*MsgWait, error)

View File

@ -38,19 +38,19 @@ type FullNodeStruct struct {
CommonStruct
Internal struct {
ChainNotify func(context.Context) (<-chan []*store.HeadChange, error) `perm:"read"`
ChainHead func(context.Context) (*types.TipSet, error) `perm:"read"`
ChainGetRandomness func(context.Context, types.TipSetKey, []*types.Ticket, int) ([]byte, error) `perm:"read"`
ChainGetBlock func(context.Context, cid.Cid) (*types.BlockHeader, error) `perm:"read"`
ChainGetTipSet func(context.Context, types.TipSetKey) (*types.TipSet, error) `perm:"read"`
ChainGetBlockMessages func(context.Context, cid.Cid) (*BlockMessages, error) `perm:"read"`
ChainGetParentReceipts func(context.Context, cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"`
ChainGetParentMessages func(context.Context, cid.Cid) ([]Message, error) `perm:"read"`
ChainGetTipSetByHeight func(context.Context, uint64, *types.TipSet) (*types.TipSet, error) `perm:"read"`
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"`
ChainNotify func(context.Context) (<-chan []*store.HeadChange, error) `perm:"read"`
ChainHead func(context.Context) (*types.TipSet, error) `perm:"read"`
ChainGetRandomness func(context.Context, types.TipSetKey, int64) ([]byte, error) `perm:"read"`
ChainGetBlock func(context.Context, cid.Cid) (*types.BlockHeader, error) `perm:"read"`
ChainGetTipSet func(context.Context, types.TipSetKey) (*types.TipSet, error) `perm:"read"`
ChainGetBlockMessages func(context.Context, cid.Cid) (*BlockMessages, error) `perm:"read"`
ChainGetParentReceipts func(context.Context, cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"`
ChainGetParentMessages func(context.Context, cid.Cid) ([]Message, error) `perm:"read"`
ChainGetTipSetByHeight func(context.Context, uint64, *types.TipSet) (*types.TipSet, error) `perm:"read"`
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"`
@ -62,10 +62,7 @@ type FullNodeStruct struct {
MpoolGetNonce func(context.Context, address.Address) (uint64, error) `perm:"read"`
MpoolSub func(context.Context) (<-chan MpoolUpdate, error) `perm:"read"`
MinerRegister func(context.Context, address.Address) error `perm:"admin"`
MinerUnregister func(context.Context, address.Address) error `perm:"admin"`
MinerAddresses func(context.Context) ([]address.Address, error) `perm:"write"`
MinerCreateBlock func(context.Context, address.Address, *types.TipSet, []*types.Ticket, types.ElectionProof, []*types.SignedMessage, uint64) (*types.BlockMsg, error) `perm:"write"`
MinerCreateBlock func(context.Context, address.Address, *types.TipSet, *types.Ticket, *types.EPostProof, []*types.SignedMessage, uint64, uint64) (*types.BlockMsg, error) `perm:"write"`
WalletNew func(context.Context, string) (address.Address, error) `perm:"write"`
WalletHas func(context.Context, address.Address) (bool, error) `perm:"write"`
@ -88,28 +85,28 @@ type FullNodeStruct struct {
ClientRetrieve func(ctx context.Context, order RetrievalOrder, path string) error `perm:"admin"`
ClientQueryAsk func(ctx context.Context, p peer.ID, miner address.Address) (*types.SignedStorageAsk, error) `perm:"read"`
StateMinerSectors func(context.Context, address.Address, *types.TipSet) ([]*ChainSectorInfo, error) `perm:"read"`
StateMinerProvingSet func(context.Context, address.Address, *types.TipSet) ([]*ChainSectorInfo, error) `perm:"read"`
StateMinerPower func(context.Context, address.Address, *types.TipSet) (MinerPower, error) `perm:"read"`
StateMinerWorker func(context.Context, address.Address, *types.TipSet) (address.Address, error) `perm:"read"`
StateMinerPeerID func(ctx context.Context, m address.Address, ts *types.TipSet) (peer.ID, error) `perm:"read"`
StateMinerProvingPeriodEnd func(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error) `perm:"read"`
StateMinerSectorSize func(context.Context, address.Address, *types.TipSet) (uint64, error) `perm:"read"`
StateCall func(context.Context, *types.Message, *types.TipSet) (*types.MessageReceipt, error) `perm:"read"`
StateReplay func(context.Context, *types.TipSet, cid.Cid) (*ReplayResults, error) `perm:"read"`
StateGetActor func(context.Context, address.Address, *types.TipSet) (*types.Actor, error) `perm:"read"`
StateReadState func(context.Context, *types.Actor, *types.TipSet) (*ActorState, error) `perm:"read"`
StatePledgeCollateral func(context.Context, *types.TipSet) (types.BigInt, error) `perm:"read"`
StateWaitMsg func(context.Context, cid.Cid) (*MsgWait, error) `perm:"read"`
StateListMiners func(context.Context, *types.TipSet) ([]address.Address, error) `perm:"read"`
StateListActors func(context.Context, *types.TipSet) ([]address.Address, error) `perm:"read"`
StateMarketBalance func(context.Context, address.Address, *types.TipSet) (actors.StorageParticipantBalance, error) `perm:"read"`
StateMarketParticipants func(context.Context, *types.TipSet) (map[string]actors.StorageParticipantBalance, error) `perm:"read"`
StateMarketDeals func(context.Context, *types.TipSet) (map[string]actors.OnChainDeal, error) `perm:"read"`
StateMarketStorageDeal func(context.Context, uint64, *types.TipSet) (*actors.OnChainDeal, error) `perm:"read"`
StateLookupID func(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) `perm:"read"`
StateChangedActors func(context.Context, cid.Cid, cid.Cid) (map[string]types.Actor, error) `perm:"read"`
StateGetReceipt func(context.Context, cid.Cid, *types.TipSet) (*types.MessageReceipt, error) `perm:"read"`
StateMinerSectors func(context.Context, address.Address, *types.TipSet) ([]*ChainSectorInfo, error) `perm:"read"`
StateMinerProvingSet func(context.Context, address.Address, *types.TipSet) ([]*ChainSectorInfo, error) `perm:"read"`
StateMinerPower func(context.Context, address.Address, *types.TipSet) (MinerPower, error) `perm:"read"`
StateMinerWorker func(context.Context, address.Address, *types.TipSet) (address.Address, error) `perm:"read"`
StateMinerPeerID func(ctx context.Context, m address.Address, ts *types.TipSet) (peer.ID, error) `perm:"read"`
StateMinerElectionPeriodStart func(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error) `perm:"read"`
StateMinerSectorSize func(context.Context, address.Address, *types.TipSet) (uint64, error) `perm:"read"`
StateCall func(context.Context, *types.Message, *types.TipSet) (*types.MessageReceipt, error) `perm:"read"`
StateReplay func(context.Context, *types.TipSet, cid.Cid) (*ReplayResults, error) `perm:"read"`
StateGetActor func(context.Context, address.Address, *types.TipSet) (*types.Actor, error) `perm:"read"`
StateReadState func(context.Context, *types.Actor, *types.TipSet) (*ActorState, error) `perm:"read"`
StatePledgeCollateral func(context.Context, *types.TipSet) (types.BigInt, error) `perm:"read"`
StateWaitMsg func(context.Context, cid.Cid) (*MsgWait, error) `perm:"read"`
StateListMiners func(context.Context, *types.TipSet) ([]address.Address, error) `perm:"read"`
StateListActors func(context.Context, *types.TipSet) ([]address.Address, error) `perm:"read"`
StateMarketBalance func(context.Context, address.Address, *types.TipSet) (actors.StorageParticipantBalance, error) `perm:"read"`
StateMarketParticipants func(context.Context, *types.TipSet) (map[string]actors.StorageParticipantBalance, error) `perm:"read"`
StateMarketDeals func(context.Context, *types.TipSet) (map[string]actors.OnChainDeal, error) `perm:"read"`
StateMarketStorageDeal func(context.Context, uint64, *types.TipSet) (*actors.OnChainDeal, error) `perm:"read"`
StateLookupID func(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) `perm:"read"`
StateChangedActors func(context.Context, cid.Cid, cid.Cid) (map[string]types.Actor, error) `perm:"read"`
StateGetReceipt func(context.Context, cid.Cid, *types.TipSet) (*types.MessageReceipt, error) `perm:"read"`
MarketEnsureAvailable func(context.Context, address.Address, types.BigInt) error `perm:"sign"`
@ -238,28 +235,16 @@ func (c *FullNodeStruct) MpoolSub(ctx context.Context) (<-chan MpoolUpdate, erro
return c.Internal.MpoolSub(ctx)
}
func (c *FullNodeStruct) MinerRegister(ctx context.Context, addr address.Address) error {
return c.Internal.MinerRegister(ctx, addr)
}
func (c *FullNodeStruct) MinerUnregister(ctx context.Context, addr address.Address) error {
return c.Internal.MinerUnregister(ctx, addr)
}
func (c *FullNodeStruct) MinerAddresses(ctx context.Context) ([]address.Address, error) {
return c.Internal.MinerAddresses(ctx)
}
func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, addr address.Address, base *types.TipSet, tickets []*types.Ticket, eproof types.ElectionProof, msgs []*types.SignedMessage, ts uint64) (*types.BlockMsg, error) {
return c.Internal.MinerCreateBlock(ctx, addr, base, tickets, eproof, msgs, ts)
func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, addr address.Address, base *types.TipSet, ticket *types.Ticket, eproof *types.EPostProof, msgs []*types.SignedMessage, height, ts uint64) (*types.BlockMsg, error) {
return c.Internal.MinerCreateBlock(ctx, addr, base, ticket, eproof, msgs, height, ts)
}
func (c *FullNodeStruct) ChainHead(ctx context.Context) (*types.TipSet, error) {
return c.Internal.ChainHead(ctx)
}
func (c *FullNodeStruct) ChainGetRandomness(ctx context.Context, pts types.TipSetKey, ticks []*types.Ticket, lb int) ([]byte, error) {
return c.Internal.ChainGetRandomness(ctx, pts, ticks, lb)
func (c *FullNodeStruct) ChainGetRandomness(ctx context.Context, pts types.TipSetKey, round int64) ([]byte, error) {
return c.Internal.ChainGetRandomness(ctx, pts, round)
}
func (c *FullNodeStruct) ChainGetTipSetByHeight(ctx context.Context, h uint64, ts *types.TipSet) (*types.TipSet, error) {
@ -382,8 +367,8 @@ func (c *FullNodeStruct) StateMinerPeerID(ctx context.Context, m address.Address
return c.Internal.StateMinerPeerID(ctx, m, ts)
}
func (c *FullNodeStruct) StateMinerProvingPeriodEnd(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error) {
return c.Internal.StateMinerProvingPeriodEnd(ctx, actor, ts)
func (c *FullNodeStruct) StateMinerElectionPeriodStart(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error) {
return c.Internal.StateMinerElectionPeriodStart(ctx, actor, ts)
}
func (c *FullNodeStruct) StateMinerSectorSize(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error) {

View File

@ -42,7 +42,7 @@ func TestDealFlow(t *testing.T, b APIBuilder) {
t.Fatal(err)
}
maddr, err := address.NewFromString("t0101")
maddr, err := address.NewFromString("t0102")
if err != nil {
t.Fatal(err)
}

View File

@ -2,10 +2,11 @@ package build
import (
"context"
"github.com/filecoin-project/lotus/lib/addrutil"
"os"
"strings"
"github.com/filecoin-project/lotus/lib/addrutil"
rice "github.com/GeertJohan/go.rice"
"github.com/libp2p/go-libp2p-core/peer"
)

View File

@ -1 +0,0 @@
/ip4/147.75.80.17/tcp/1347/p2p/12D3KooWFCkQdiJEMBVA6RrWq22ZXVFfM41YX8soQ5QVvNFjMJT8

View File

@ -1 +0,0 @@
/ip4/147.75.80.29/tcp/1347/p2p/12D3KooWSw9h3e6YrYZfRWDcir8qMV7ctZG9VmtXwSaP2ntsKXYf

View File

@ -156,6 +156,8 @@ func doFetch(out string, info paramFile) error {
if err != nil {
return err
}
log.Infof("GET %s", url)
req := http.Request{
Method: "GET",
URL: url,

27
build/params_debug.go Normal file
View File

@ -0,0 +1,27 @@
// +build debug
package build
import "os"
// Seconds
const BlockDelay = 6
// FallbackPoStDelay is the number of epochs the miner needs to wait after
// ElectionPeriodStart before starting fallback post computation
//
// Epochs
const FallbackPoStDelay = 10
// SlashablePowerDelay is the number of epochs after ElectionPeriodStart, after
// which the miner is slashed
//
// Epochs
const SlashablePowerDelay = 20
// Epochs
const InteractivePoRepDelay = 2
func init() {
os.Setenv("TRUST_PARAMS", "1")
}

21
build/params_devnet.go Normal file
View File

@ -0,0 +1,21 @@
// +build !debug
package build
// Seconds
const BlockDelay = 12
// FallbackPoStDelay is the number of epochs the miner needs to wait after
// ElectionPeriodStart before starting fallback post computation
//
// Epochs
const FallbackPoStDelay = 1000
// SlashablePowerDelay is the number of epochs after ElectionPeriodStart, after
// which the miner is slashed
//
// Epochs
const SlashablePowerDelay = 2000
// Epochs
const InteractivePoRepDelay = 10

View File

@ -13,6 +13,7 @@ const UnixfsChunkSize uint64 = 1 << 20
const UnixfsLinksPerLevel = 1024
var SectorSizes = []uint64{
1 << 10,
16 << 20,
256 << 20,
1 << 30,
@ -30,25 +31,22 @@ func SupportedSectorSize(ssize uint64) bool {
// /////
// Payments
// Blocks
// Epochs
const PaymentChannelClosingDelay = 6 * 60 * 2 // six hours
// /////
// Consensus / Network
// Seconds
const BlockDelay = 2
// Seconds
const AllowableClockDrift = BlockDelay * 2
// Blocks
// Epochs
const ForkLengthThreshold = Finality
// Blocks (e)
const BlocksPerEpoch = 5
// Blocks
// Epochs
const Finality = 500
// constants for Weight calculation
@ -59,39 +57,27 @@ const WRatioDen = 2
// /////
// Proofs
// Blocks
const ProvingPeriodDuration uint64 = 30
// PoStChallangeTime sets the window in which post computation should happen
// Blocks
const PoStChallangeTime = ProvingPeriodDuration - 6
// PoStRandomnessLookback is additional randomness lookback for PoSt computation
// To compute randomness epoch in a given proving period:
// RandH = PPE - PoStChallangeTime - PoStRandomnessLookback
//
// Blocks
const PoStRandomnessLookback = 1
// Blocks
// Epochs
const SealRandomnessLookback = Finality
// Blocks
// Epochs
const SealRandomnessLookbackLimit = SealRandomnessLookback + 2000
// 1 / n
const SectorChallengeRatioDiv = 25
const MaxFallbackPostChallengeCount = 10
// /////
// Mining
// Blocks
// Epochs
const EcRandomnessLookback = 300
const PowerCollateralProportion = 5
const PerCapitaCollateralProportion = 1
const CollateralPrecision = 1000
// Blocks
const InteractivePoRepDelay = 10
// /////
// Devnet settings
@ -105,8 +91,8 @@ var InitialReward *big.Int
const FilecoinPrecision = 1_000_000_000_000_000_000
// six years
// Blocks
const HalvingPeriodBlocks = 6 * 365 * 24 * 60 * 2
// Epochs
const HalvingPeriodEpochs = 6 * 365 * 24 * 60 * 2
// TODO: Move other important consts here
@ -124,6 +110,6 @@ func init() {
// Sync
const BadBlockCacheSize = 1 << 15
// assuming 4000 blocks per round, this lets us not lose any messages across a
// assuming 4000 messages per round, this lets us not lose any messages across a
// 10 block reorg.
const BlsSignatureCacheSize = 40000

View File

@ -1,82 +1,82 @@
{
"v15-proof-of-spacetime-rational-535d1050e3adca2a0dfe6c3c0c4fa12097c9a7835fb969042f82a507b13310e0.params": {
"cid": "QmT22f1Np1GpW29NXD7Zrv3Ae4poMYhmkDjyscqL8QrJXY",
"digest": "989fd8d989e0f7f1fe21bb010cf1b231",
"sector_size": 16777216
},
"v15-proof-of-spacetime-rational-535d1050e3adca2a0dfe6c3c0c4fa12097c9a7835fb969042f82a507b13310e0.vk": {
"cid": "QmVqSdc23to4UwduCCb25223rpSccvtcgPMfRKY1qjucDc",
"digest": "c6d258c37243b8544238a98100e3e399",
"sector_size": 16777216
},
"v15-proof-of-spacetime-rational-b99f15d0bdaaf4ffb68b2ca72b69ea8d915f66a2a56f667430ad69d87aa5febd.params": {
"cid": "QmRTCqgokEGTMfWVaSr7qFXTNotmpd2QBEi8RsvSQKmPLz",
"digest": "ff77a5e270afc6e1c7fbc19e48348fac",
"sector_size": 1073741824
},
"v15-proof-of-spacetime-rational-b99f15d0bdaaf4ffb68b2ca72b69ea8d915f66a2a56f667430ad69d87aa5febd.vk": {
"cid": "QmRssVAXRN3xp9VdSpTq1pNjkob3QiikoFZiM5hqrmh1VU",
"digest": "b41f35ac26224258e366327716a835a4",
"sector_size": 1073741824
},
"v15-proof-of-spacetime-rational-ba14a058a9dea194f68596f8ecf6537074f038a15c8d1a8550e10e31d4728912.params": {
"cid": "QmYNVRVzjXkuxJfnHTU5vmEcUBQf8dabXZ4m53SzqMkBv5",
"digest": "d156b685e4a1fe3a1f7230b6a39b5ad4",
"sector_size": 1024
},
"v15-proof-of-spacetime-rational-ba14a058a9dea194f68596f8ecf6537074f038a15c8d1a8550e10e31d4728912.vk": {
"cid": "QmaCEcsCFVuepMKdC5WURbr5ucEyLMNGxQaB7HqSnr2KGh",
"digest": "06ff067ac78cdab5d7bbc82170882241",
"sector_size": 1024
},
"v15-proof-of-spacetime-rational-c2ae2b440e693ee69fd6da9e85c4294c5c70c1a46d5785ca5f2a676d6cd4c8de.params": {
"cid": "QmVuabRvJ797NwLisGKwRURASGxopBBgg4rfNsbZoSYzAc",
"digest": "0e1ceb79a459a60508f480e5b1fed7ac",
"v19-proof-of-spacetime-election-09ae025de08399327e14f0cb6b4c907b6fe1e8b77046e31de8921bde588de900.params": {
"cid": "QmZEKhzKbC7SPngjL85ghyuxabPmiEuUh4fpkC7CDK1J5q",
"digest": "1c81338b8afeaae514fd5d6c08c9c6e5",
"sector_size": 268435456
},
"v15-proof-of-spacetime-rational-c2ae2b440e693ee69fd6da9e85c4294c5c70c1a46d5785ca5f2a676d6cd4c8de.vk": {
"cid": "QmdWENZBAbuUty1vVNn9vmvj1XbJ5UC8qzpcVD35s5AJxG",
"digest": "1b755c74b9d6823c014f6a7ef76249f2",
"v19-proof-of-spacetime-election-09ae025de08399327e14f0cb6b4c907b6fe1e8b77046e31de8921bde588de900.vk": {
"cid": "Qmf5XQuM58jNmxudXeZMuZtGGiNzcd56Fiyn9h76wpX5dN",
"digest": "bb0f07b6071cd28e9348223c6a9c46d1",
"sector_size": 268435456
},
"v15-stacked-proof-of-replication-0c0b444c6f31d11c8e98003cc99a3b938db26b77a296d4253cda8945c234266d.params": {
"cid": "QmZDVpWTw5Eti5pE7N5z1Cmqsw8hPXhUcvG3cQuceK56LH",
"digest": "6aa80306018ea1328f2d6faf8c080734",
"sector_size": 16777216
},
"v15-stacked-proof-of-replication-0c0b444c6f31d11c8e98003cc99a3b938db26b77a296d4253cda8945c234266d.vk": {
"cid": "QmaoXV7iVSJcfZ5qubYy7NBcXDSdnTzxH85d7M4bdDtfGZ",
"digest": "f6832eb736faf2960e920d32e9780b12",
"sector_size": 16777216
},
"v15-stacked-proof-of-replication-967b11bb59be11b7dc6f2b627520ba450a3aa50846dbbf886cb8b735fe25c4e7.params": {
"cid": "QmbUW3a3q5DHBb7Ufk8iSbnSCZgbwpe3serqfwKmcTd11w",
"digest": "64024e461b07c869df2463d33dd28035",
"sector_size": 268435456
},
"v15-stacked-proof-of-replication-967b11bb59be11b7dc6f2b627520ba450a3aa50846dbbf886cb8b735fe25c4e7.vk": {
"cid": "Qme3QgBBE7hUgrK7G9ZfJhzkbvViN5HALFpFduYs5K1piv",
"digest": "32496f4dc434b0ed9ef49cb62497a7d1",
"sector_size": 268435456
},
"v15-stacked-proof-of-replication-d01cd22091627b721c60a3375b5219af653fb9f6928c70aa7400587d396bc07a.params": {
"cid": "QmZzgJmb8WXYDKxS22HDgnoBYcZzXDC7s2c2zsV7kouNZ9",
"digest": "cd91f7ccb2ff57a06f3375946dcbdc68",
"sector_size": 1073741824
},
"v15-stacked-proof-of-replication-d01cd22091627b721c60a3375b5219af653fb9f6928c70aa7400587d396bc07a.vk": {
"cid": "QmRUMVzFnENbvyNb6aN2AJ2dnnewr1ESGA1UQLMVZZdsJM",
"digest": "92fc84b76dbe69c731518aebcb82ac82",
"sector_size": 1073741824
},
"v15-stacked-proof-of-replication-f464b92d805d03de6e2c20e2530135b2c8ec96045ec58f342d6feb90282bff8a.params": {
"cid": "QmSixsGkxJXTAuFfWKy5aEXEDJEnpcb1GkdQVF8TCPWoHy",
"digest": "f8339ae93478ded3840d0bc7efa19953",
"v19-proof-of-spacetime-election-4a2342062706429612fac099694f77294e355c6c9265b80feaff12a0268b0a92.params": {
"cid": "QmaHs5CHcSD6QhaGAp4ysJP4HTZaxPxybCGmUVDk3TNocA",
"digest": "727fb2896a5668d04ba6e0ce71eb50d7",
"sector_size": 1024
},
"v15-stacked-proof-of-replication-f464b92d805d03de6e2c20e2530135b2c8ec96045ec58f342d6feb90282bff8a.vk": {
"cid": "QmTMC8hdZ2TkZ9BFuzHzRLM9SuR2PQdUrSAwABeCuHyV2f",
"digest": "f27f08ce1246ee6612c250bb12803ef1",
"v19-proof-of-spacetime-election-4a2342062706429612fac099694f77294e355c6c9265b80feaff12a0268b0a92.vk": {
"cid": "QmVg8mUXMb6MiZQseAyCmHzEgNkPbV72xQoRmdFr1yJA4w",
"digest": "3fdf4e65a7baf1a2bab5b8a717f3379a",
"sector_size": 1024
},
"v19-proof-of-spacetime-election-512f5e6dc00a37fa13c8b0e468188f85957b7bf1ab36d17fb9fe9ed49ae8d657.params": {
"cid": "QmYf1532WoeXhy8AoduWNxpBuwn5DEkpU6YFDGCXh1mqBX",
"digest": "983e641f9df01799bc33d5fb3c3020b2",
"sector_size": 1073741824
},
"v19-proof-of-spacetime-election-512f5e6dc00a37fa13c8b0e468188f85957b7bf1ab36d17fb9fe9ed49ae8d657.vk": {
"cid": "QmVig7LUpNSXUcfjkSxUKsFaxqYxEZdaEARWvi14sbihJ4",
"digest": "e1f7a46b60217f1dddf56671dd86e6a7",
"sector_size": 1073741824
},
"v19-proof-of-spacetime-election-6c7cbfe7eed40b6c0b23a213a70648770aed65d9ca03ae85451573c18532304b.params": {
"cid": "QmSTF7C6vQbV6qjEQknXpBDuixBkxYeMshX25NonjJxjbi",
"digest": "b434ece6a37e588ca11ed117f1c14325",
"sector_size": 16777216
},
"v19-proof-of-spacetime-election-6c7cbfe7eed40b6c0b23a213a70648770aed65d9ca03ae85451573c18532304b.vk": {
"cid": "QmaFV9n5scuYxKc9QpJnbBUf4sjhkUzpZ7QkoTqL8XsNQz",
"digest": "9c2e40b6635470d3674324b01c9a3976",
"sector_size": 16777216
},
"v19-stacked-proof-of-replication-5a438611c880423c4f5199787cd531b197846ef46af40af69222467ab9073226.params": {
"cid": "QmQb5mc3ksZh2K5GsNwJrkwuHoWXh8adBdJV3qTbFaRvGe",
"digest": "a187287b1d03cd7ec4f1fccd57f3f3d1",
"sector_size": 1024
},
"v19-stacked-proof-of-replication-5a438611c880423c4f5199787cd531b197846ef46af40af69222467ab9073226.vk": {
"cid": "QmYUjFHzeX22dfzv9wQxF4Qn8wS67bqBwr1Wcz2rga9rAZ",
"digest": "747792363f08d7b53be1a2f51f91582a",
"sector_size": 1024
},
"v19-stacked-proof-of-replication-6ae8ae8998ef393ffd171487bc5141fa3642e9fd39e3a7dbada4f6e7bacffb9b.params": {
"cid": "QmRUZqCwYdcVfQ49Z97g2xkJnaSh4b9SHWwfB3kgZiPo9L",
"digest": "b9494e0ae432a0ebde9c8c877c914583",
"sector_size": 16777216
},
"v19-stacked-proof-of-replication-6ae8ae8998ef393ffd171487bc5141fa3642e9fd39e3a7dbada4f6e7bacffb9b.vk": {
"cid": "QmXngrBy74h8LYhYrbBpefXsXQFWLU3WX3LTXnVQnu1Sdc",
"digest": "af2c0d6834fa581b6f507f8266244dfb",
"sector_size": 16777216
},
"v19-stacked-proof-of-replication-d2ca0f634aebcecba88904612ff82f2349b080b1290879f3fba73c1d9a13d84e.params": {
"cid": "QmfNstuJFKnBt4yJHsNfoKahn1LafBdpJju23U5UNZd9Xy",
"digest": "3911d84ca2b86f491bc7c6372d7d9285",
"sector_size": 268435456
},
"v19-stacked-proof-of-replication-d2ca0f634aebcecba88904612ff82f2349b080b1290879f3fba73c1d9a13d84e.vk": {
"cid": "QmQgSRQBbp7udHDp5pNA3GSCjSyXktUHBw15wx9meL4wgc",
"digest": "ecd2a9bdd178b0ebc9110f568fd70d07",
"sector_size": 268435456
},
"v19-stacked-proof-of-replication-f7b95455d6b7a5e967388a97c2ddc01807eff4c1736e84be4554853bf7783105.params": {
"cid": "QmV5mAkhohUHPRWoNtS3Uo4yvmF23CR2u8JxeeCqthMCdX",
"digest": "9306d91c3518b87016d5efc19428b25e",
"sector_size": 1073741824
},
"v19-stacked-proof-of-replication-f7b95455d6b7a5e967388a97c2ddc01807eff4c1736e84be4554853bf7783105.vk": {
"cid": "QmPjwPdUQJmqp2rQuJX2dy57AC9YCwYtMHdpZzW5BG9JWh",
"digest": "a2004fca043da423df51f6c4bb65788c",
"sector_size": 1073741824
}
}

3
build/testing_flags.go Normal file
View File

@ -0,0 +1,3 @@
package build
var InsecurePoStValidation = false

View File

@ -40,7 +40,6 @@ func init() {
type InitActor struct{}
type InitActorState struct {
// TODO: this needs to be a HAMT, its a dumb map for now
AddressMap cid.Cid
NextID uint64

View File

@ -6,6 +6,8 @@ import (
"encoding/binary"
"fmt"
ffi "github.com/filecoin-project/filecoin-ffi"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/address"
@ -29,12 +31,16 @@ type StorageMinerActorState struct {
PreCommittedSectors map[string]*PreCommittedSector
// All sectors this miner has committed.
//
// AMT[sectorID]ffi.PublicSectorInfo
Sectors cid.Cid
// TODO: Spec says 'StagedCommittedSectors', which one is it?
// Sectors this miner is currently mining. It is only updated
// when a PoSt is submitted (not as each new sector commitment is added).
//
// AMT[sectorID]ffi.PublicSectorInfo
ProvingSet cid.Cid
// TODO: these:
@ -54,12 +60,6 @@ type StorageMinerActorState struct {
// These become the currentFaultSet when a PoSt is submitted.
NextFaultSet types.BitField
// Sectors reported during the last PoSt submission as being 'done'.
// The collateral for them is still being held until
// the next PoSt submission in case early sector
// removal penalization is needed.
NextDoneSet types.BitField
// Amount of power this miner has.
Power types.BigInt
@ -69,7 +69,7 @@ type StorageMinerActorState struct {
// The height at which this miner was slashed at.
SlashedAt uint64
ProvingPeriodEnd uint64
ElectionPeriodStart uint64
}
type MinerInfo struct {
@ -117,7 +117,7 @@ type maMethods struct {
Constructor uint64
PreCommitSector uint64
ProveCommitSector uint64
SubmitPoSt uint64
SubmitFallbackPoSt uint64
SlashStorageFault uint64
GetCurrentProvingSet uint64
ArbitrateDeal uint64
@ -133,16 +133,17 @@ type maMethods struct {
CheckMiner uint64
DeclareFaults uint64
SlashConsensusFault uint64
SubmitElectionPoSt uint64
}
var MAMethods = maMethods{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}
var MAMethods = maMethods{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}
func (sma StorageMinerActor) Exports() []interface{} {
return []interface{}{
1: sma.StorageMinerConstructor,
2: sma.PreCommitSector,
3: sma.ProveCommitSector,
4: sma.SubmitPoSt,
4: sma.SubmitFallbackPoSt,
//5: sma.SlashStorageFault,
//6: sma.GetCurrentProvingSet,
//7: sma.ArbitrateDeal,
@ -158,6 +159,7 @@ func (sma StorageMinerActor) Exports() []interface{} {
17: sma.CheckMiner,
18: sma.DeclareFaults,
19: sma.SlashConsensusFault,
20: sma.SubmitElectionPoSt,
}
}
@ -345,7 +347,7 @@ func (sma StorageMinerActor) ProveCommitSector(act *types.Actor, vmctx types.VMC
// Note: There must exist a unique index in the miner's sector set for each
// sector ID. The `faults`, `recovered`, and `done` parameters of the
// SubmitPoSt method express indices into this sector set.
nssroot, err := AddToSectorSet(ctx, vmctx.Storage(), self.Sectors, params.SectorID, us.Info.CommR, commD)
nssroot, err := AddToSectorSet(ctx, types.WrapStorage(vmctx.Storage()), self.Sectors, params.SectorID, us.Info.CommR, commD)
if err != nil {
return nil, err
}
@ -366,7 +368,9 @@ func (sma StorageMinerActor) ProveCommitSector(act *types.Actor, vmctx types.VMC
if pss.Count == 0 {
self.ProvingSet = self.Sectors
self.ProvingPeriodEnd = vmctx.BlockHeight() + build.ProvingPeriodDuration
// TODO: probably want to wait until the miner is above a certain
// threshold before starting this
self.ElectionPeriodStart = vmctx.BlockHeight()
}
nstate, err := vmctx.Storage().Put(self)
@ -388,23 +392,12 @@ func (sma StorageMinerActor) ProveCommitSector(act *types.Actor, vmctx types.VMC
return nil, err
}
type SubmitPoStParams struct {
Proof []byte
DoneSet types.BitField
// TODO: once the spec changes finish, we have more work to do here...
type SubmitFallbackPoStParams struct {
Proof []byte
Candidates []types.EPostTicket
}
func ProvingPeriodEnd(setPeriodEnd, height uint64) (uint64, uint64) {
offset := setPeriodEnd % build.ProvingPeriodDuration
period := ((height - offset - 1) / build.ProvingPeriodDuration) + 1
end := (period * build.ProvingPeriodDuration) + offset
return end, period
}
// TODO: this is a dummy method that allows us to plumb in other parts of the
// system for now.
func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext, params *SubmitPoStParams) ([]byte, ActorError) {
func (sma StorageMinerActor) SubmitFallbackPoSt(act *types.Actor, vmctx types.VMContext, params *SubmitFallbackPoStParams) ([]byte, ActorError) {
oldstate, self, err := loadState(vmctx)
if err != nil {
return nil, err
@ -419,36 +412,28 @@ func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext,
return nil, aerrors.New(1, "not authorized to submit post for miner")
}
currentProvingPeriodEnd, _ := ProvingPeriodEnd(self.ProvingPeriodEnd, vmctx.BlockHeight())
feesRequired := types.NewInt(0)
if currentProvingPeriodEnd > self.ProvingPeriodEnd {
//TODO late fee calc
feesRequired = types.BigAdd(feesRequired, types.NewInt(1000))
}
//TODO temporary sector failure fees
msgVal := vmctx.Message().Value
if msgVal.LessThan(feesRequired) {
return nil, aerrors.New(2, "not enough funds to pay post submission fees")
}
if msgVal.GreaterThan(feesRequired) {
_, err := vmctx.Send(vmctx.Message().From, 0,
types.BigSub(msgVal, feesRequired), nil)
if err != nil {
return nil, aerrors.Wrap(err, "could not refund excess fees")
/*
// TODO: handle fees
msgVal := vmctx.Message().Value
if msgVal.LessThan(feesRequired) {
return nil, aerrors.New(2, "not enough funds to pay post submission fees")
}
}
if msgVal.GreaterThan(feesRequired) {
_, err := vmctx.Send(vmctx.Message().From, 0,
types.BigSub(msgVal, feesRequired), nil)
if err != nil {
return nil, aerrors.Wrap(err, "could not refund excess fees")
}
}
*/
var seed [sectorbuilder.CommLen]byte
{
randHeight := currentProvingPeriodEnd - build.PoStChallangeTime - build.PoStRandomnessLookback
randHeight := self.ElectionPeriodStart + build.FallbackPoStDelay
if vmctx.BlockHeight() <= randHeight {
// TODO: spec, retcode
return nil, aerrors.Newf(1, "submit PoSt called outside submission window (%d < %d)", vmctx.BlockHeight(), randHeight)
return nil, aerrors.Newf(1, "submit fallback PoSt called too early (%d < %d)", vmctx.BlockHeight(), randHeight)
}
rand, err := vmctx.GetRandomness(randHeight)
@ -468,13 +453,13 @@ func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext,
return nil, aerrors.HandleExternalError(lerr, "could not load proving set node")
}
var sectorInfos []sectorbuilder.SectorInfo
var sectorInfos []ffi.PublicSectorInfo
if err := pss.ForEach(func(id uint64, v *cbg.Deferred) error {
var comms [][]byte
if err := cbor.DecodeInto(v.Raw, &comms); err != nil {
return xerrors.New("could not decode comms")
}
si := sectorbuilder.SectorInfo{
si := ffi.PublicSectorInfo{
SectorID: id,
}
commR := comms[0]
@ -491,10 +476,23 @@ func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext,
}
faults := self.CurrentFaultSet.All()
_ = faults
if ok, lerr := sectorbuilder.VerifyPost(vmctx.Context(), mi.SectorSize,
sectorbuilder.NewSortedSectorInfo(sectorInfos), seed, params.Proof,
faults); !ok || lerr != nil {
proverID := vmctx.Message().To // TODO: normalize to ID address
var candidates []sectorbuilder.EPostCandidate
for _, t := range params.Candidates {
var partial [32]byte
copy(partial[:], t.Partial)
candidates = append(candidates, sectorbuilder.EPostCandidate{
PartialTicket: partial,
SectorID: t.SectorID,
SectorChallengeIndex: t.ChallengeIndex,
})
}
if ok, lerr := sectorbuilder.VerifyFallbackPost(vmctx.Context(), mi.SectorSize,
sectorbuilder.NewSortedPublicSectorInfo(sectorInfos), seed[:], params.Proof, candidates, proverID); !ok || lerr != nil {
if lerr != nil {
// TODO: study PoST errors
return nil, aerrors.Absorb(lerr, 4, "PoST error")
@ -503,60 +501,12 @@ func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext,
return nil, aerrors.New(4, "PoST invalid")
}
}
self.CurrentFaultSet = self.NextFaultSet
self.NextFaultSet = types.NewBitField()
ss, lerr := amt.LoadAMT(types.WrapStorage(vmctx.Storage()), self.ProvingSet)
if lerr != nil {
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.HandleExternalError(err, "failed to delete sectors in done set")
}
self.ProvingSet, lerr = ss.Flush()
if lerr != nil {
return nil, aerrors.HandleExternalError(lerr, "could not flush AMT")
}
oldPower := self.Power
self.Power = types.BigMul(types.NewInt(pss.Count-uint64(len(faults))),
types.NewInt(mi.SectorSize))
delta := types.BigSub(self.Power, oldPower)
if self.SlashedAt != 0 {
self.SlashedAt = 0
delta = self.Power
}
prevPE := self.ProvingPeriodEnd
if !self.Active {
self.Active = true
prevPE = 0
}
enc, err := SerializeParams(&UpdateStorageParams{
Delta: delta,
NextProvingPeriodEnd: currentProvingPeriodEnd + build.ProvingPeriodDuration,
PreviousProvingPeriodEnd: prevPE,
})
if err != nil {
// Post submission is successful!
if err := onSuccessfulPoSt(self, vmctx); err != nil {
return nil, err
}
_, err = vmctx.Send(StoragePowerAddress, SPAMethods.UpdateStorage, types.NewInt(0), enc)
if err != nil {
return nil, err
}
self.ProvingSet = self.Sectors
self.ProvingPeriodEnd = currentProvingPeriodEnd + build.ProvingPeriodDuration
self.NextDoneSet = params.DoneSet
c, err := vmctx.Storage().Put(self)
if err != nil {
return nil, err
@ -586,8 +536,8 @@ func SectorIsUnique(ctx context.Context, s types.Storage, sroot cid.Cid, sid uin
return !found, nil
}
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)
func AddToSectorSet(ctx context.Context, blks amt.Blocks, ss cid.Cid, sectorID uint64, commR, commD []byte) (cid.Cid, ActorError) {
ssr, err := amt.LoadAMT(blks, ss)
if err != nil {
return cid.Undef, aerrors.HandleExternalError(err, "could not load sector set node")
}
@ -749,7 +699,7 @@ func (sma StorageMinerActor) GetSectorSize(act *types.Actor, vmctx types.VMConte
}
func isLate(height uint64, self *StorageMinerActorState) bool {
return self.ProvingPeriodEnd > 0 && height >= self.ProvingPeriodEnd // TODO: review: maybe > ?
return self.ElectionPeriodStart > 0 && height >= self.ElectionPeriodStart+build.SlashablePowerDelay
}
func (sma StorageMinerActor) IsSlashed(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) {
@ -817,32 +767,34 @@ type DeclareFaultsParams struct {
}
func (sma StorageMinerActor) DeclareFaults(act *types.Actor, vmctx types.VMContext, params *DeclareFaultsParams) ([]byte, ActorError) {
oldstate, self, aerr := loadState(vmctx)
if aerr != nil {
return nil, aerr
}
challengeHeight := self.ProvingPeriodEnd - build.PoStChallangeTime
if vmctx.BlockHeight() < challengeHeight {
// TODO: optimized bitfield methods
for _, v := range params.Faults.All() {
self.CurrentFaultSet.Set(v)
/*
oldstate, self, aerr := loadState(vmctx)
if aerr != nil {
return nil, aerr
}
} else {
for _, v := range params.Faults.All() {
self.NextFaultSet.Set(v)
challengeHeight := self.ProvingPeriodEnd - build.PoStChallangeTime
if vmctx.BlockHeight() < challengeHeight {
// TODO: optimized bitfield methods
for _, v := range params.Faults.All() {
self.CurrentFaultSet.Set(v)
}
} else {
for _, v := range params.Faults.All() {
self.NextFaultSet.Set(v)
}
}
}
nstate, err := vmctx.Storage().Put(self)
if err != nil {
return nil, err
}
if err := vmctx.Storage().Commit(oldstate, nstate); err != nil {
return nil, err
}
nstate, err := vmctx.Storage().Put(self)
if err != nil {
return nil, err
}
if err := vmctx.Storage().Commit(oldstate, nstate); err != nil {
return nil, err
}
*/
return nil, nil
}
@ -892,6 +844,88 @@ func (sma StorageMinerActor) SlashConsensusFault(act *types.Actor, vmctx types.V
return nil, nil
}
func (sma StorageMinerActor) SubmitElectionPoSt(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, aerrors.ActorError) {
if vmctx.Message().From != NetworkAddress {
return nil, aerrors.Newf(1, "submit election post can only be called by the storage power actor")
}
oldstate, self, aerr := loadState(vmctx)
if aerr != nil {
return nil, aerr
}
if self.SlashedAt != 0 {
return nil, aerrors.New(1, "slashed miners can't perform election PoSt")
}
if err := onSuccessfulPoSt(self, vmctx); err != nil {
return nil, err
}
ncid, err := vmctx.Storage().Put(self)
if err != nil {
return nil, err
}
if err := vmctx.Storage().Commit(oldstate, ncid); err != nil {
return nil, err
}
return nil, nil
}
func onSuccessfulPoSt(self *StorageMinerActorState, vmctx types.VMContext) aerrors.ActorError {
// TODO: some sector upkeep stuff that is very haphazard and unclear in the spec
var mi MinerInfo
if err := vmctx.Storage().Get(self.Info, &mi); err != nil {
return err
}
pss, nerr := amt.LoadAMT(types.WrapStorage(vmctx.Storage()), self.ProvingSet)
if nerr != nil {
return aerrors.HandleExternalError(nerr, "failed to load proving set")
}
self.CurrentFaultSet = self.NextFaultSet
self.NextFaultSet = types.NewBitField()
faults := []uint64{} // TODO
oldPower := self.Power
self.Power = types.BigMul(types.NewInt(pss.Count-uint64(len(faults))),
types.NewInt(mi.SectorSize))
delta := types.BigSub(self.Power, oldPower)
if self.SlashedAt != 0 {
self.SlashedAt = 0
delta = self.Power
}
prevSlashingDeadline := self.ElectionPeriodStart + build.SlashablePowerDelay
if !self.Active {
self.Active = true
prevSlashingDeadline = 0
}
enc, err := SerializeParams(&UpdateStorageParams{
Delta: delta,
NextProvingPeriodEnd: vmctx.BlockHeight() + build.SlashablePowerDelay,
PreviousProvingPeriodEnd: prevSlashingDeadline,
})
if err != nil {
return err
}
_, err = vmctx.Send(StoragePowerAddress, SPAMethods.UpdateStorage, types.NewInt(0), enc)
if err != nil {
return err
}
self.ProvingSet = self.Sectors
self.ElectionPeriodStart = vmctx.BlockHeight()
return nil
}
func slasherShare(total types.BigInt, elapsed uint64) types.BigInt {
// [int(pow(1.26, n) * 10) for n in range(30)]
fracs := []uint64{10, 12, 15, 20, 25, 31, 40, 50, 63, 80, 100, 127, 160, 201, 254, 320, 403, 508, 640, 807, 1017, 1281, 1614, 2034, 2563, 3230, 4070, 5128, 6462, 8142}

View File

@ -3,16 +3,17 @@ package actors
import (
"bytes"
"context"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-amt-ipld"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-hamt-ipld"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/cborutil"
"github.com/filecoin-project/lotus/lib/sectorbuilder"
)
@ -110,6 +111,15 @@ func (sdp *StorageDealProposal) Sign(ctx context.Context, sign SignFunc) error {
return nil
}
func (sdp *StorageDealProposal) Cid() (cid.Cid, error) {
nd, err := cborutil.AsIpld(sdp)
if err != nil {
return cid.Undef, err
}
return nd.Cid(), nil
}
func (sdp *StorageDealProposal) Verify() error {
unsigned := *sdp
unsigned.ProposerSignature = nil
@ -538,9 +548,7 @@ func (sma StorageMarketActor) ProcessStorageDealsPayment(act *types.Actor, vmctx
return nil, nil
}
// todo: check math (written on a plane, also tired)
// TODO: division is hard, this more than likely has some off-by-one issue
toPay := types.BigMul(dealInfo.Deal.Proposal.StoragePricePerEpoch, types.NewInt(build.ProvingPeriodDuration))
toPay := types.BigMul(dealInfo.Deal.Proposal.StoragePricePerEpoch, types.NewInt(build.SlashablePowerDelay))
b, bnd, aerr := GetMarketBalances(vmctx.Context(), vmctx.Ipld(), self.Balances, dealInfo.Deal.Proposal.Client, providerWorker)
if aerr != nil {

View File

@ -289,8 +289,8 @@ func (spa StoragePowerActor) UpdateStorage(act *types.Actor, vmctx types.VMConte
self.TotalStorage = types.BigAdd(self.TotalStorage, params.Delta)
previousBucket := params.PreviousProvingPeriodEnd % build.ProvingPeriodDuration
nextBucket := params.NextProvingPeriodEnd % build.ProvingPeriodDuration
previousBucket := params.PreviousProvingPeriodEnd % build.SlashablePowerDelay
nextBucket := params.NextProvingPeriodEnd % build.SlashablePowerDelay
if previousBucket == nextBucket && params.PreviousProvingPeriodEnd != 0 {
nroot, err := vmctx.Storage().Put(&self)
@ -601,7 +601,7 @@ func (spa StoragePowerActor) CheckProofSubmissions(act *types.Actor, vmctx types
}
func checkProofSubmissionsAtH(vmctx types.VMContext, self *StoragePowerState, height uint64) aerrors.ActorError {
bucketID := height % build.ProvingPeriodDuration
bucketID := height % build.SlashablePowerDelay
buckets, eerr := amt.LoadAMT(types.WrapStorage(vmctx.Storage()), self.ProvingBuckets)
if eerr != nil {

View File

@ -170,5 +170,5 @@ func signBlock(t *testing.T, w *wallet.Wallet, worker address.Address, blk *type
t.Fatal(err)
}
blk.BlockSig = *sig
blk.BlockSig = sig
}

View File

@ -198,7 +198,7 @@ func (t *StorageMinerActorState) MarshalCBOR(w io.Writer) error {
_, err := w.Write(cbg.CborNull)
return err
}
if _, err := w.Write([]byte{139}); err != nil {
if _, err := w.Write([]byte{138}); err != nil {
return err
}
@ -258,11 +258,6 @@ func (t *StorageMinerActorState) MarshalCBOR(w io.Writer) error {
return err
}
// t.t.NextDoneSet (types.BitField) (struct)
if err := t.NextDoneSet.MarshalCBOR(w); err != nil {
return err
}
// t.t.Power (types.BigInt) (struct)
if err := t.Power.MarshalCBOR(w); err != nil {
return err
@ -278,8 +273,8 @@ func (t *StorageMinerActorState) MarshalCBOR(w io.Writer) error {
return err
}
// t.t.ProvingPeriodEnd (uint64) (uint64)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.ProvingPeriodEnd))); err != nil {
// t.t.ElectionPeriodStart (uint64) (uint64)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.ElectionPeriodStart))); err != nil {
return err
}
return nil
@ -296,7 +291,7 @@ func (t *StorageMinerActorState) UnmarshalCBOR(r io.Reader) error {
return fmt.Errorf("cbor input should be of type array")
}
if extra != 11 {
if extra != 10 {
return fmt.Errorf("cbor input had wrong number of fields")
}
@ -406,15 +401,6 @@ func (t *StorageMinerActorState) UnmarshalCBOR(r io.Reader) error {
return err
}
}
// t.t.NextDoneSet (types.BitField) (struct)
{
if err := t.NextDoneSet.UnmarshalCBOR(br); err != nil {
return err
}
}
// t.t.Power (types.BigInt) (struct)
@ -452,7 +438,7 @@ func (t *StorageMinerActorState) UnmarshalCBOR(r io.Reader) error {
return fmt.Errorf("wrong type for uint64 field")
}
t.SlashedAt = uint64(extra)
// t.t.ProvingPeriodEnd (uint64) (uint64)
// t.t.ElectionPeriodStart (uint64) (uint64)
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
@ -461,7 +447,7 @@ func (t *StorageMinerActorState) UnmarshalCBOR(r io.Reader) error {
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.ProvingPeriodEnd = uint64(extra)
t.ElectionPeriodStart = uint64(extra)
return nil
}
@ -827,7 +813,7 @@ func (t *MinerInfo) UnmarshalCBOR(r io.Reader) error {
return nil
}
func (t *SubmitPoStParams) MarshalCBOR(w io.Writer) error {
func (t *SubmitFallbackPoStParams) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)
return err
@ -844,14 +830,19 @@ func (t *SubmitPoStParams) MarshalCBOR(w io.Writer) error {
return err
}
// t.t.DoneSet (types.BitField) (struct)
if err := t.DoneSet.MarshalCBOR(w); err != nil {
// t.t.Candidates ([]types.EPostTicket) (slice)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Candidates)))); err != nil {
return err
}
for _, v := range t.Candidates {
if err := v.MarshalCBOR(w); err != nil {
return err
}
}
return nil
}
func (t *SubmitPoStParams) UnmarshalCBOR(r io.Reader) error {
func (t *SubmitFallbackPoStParams) UnmarshalCBOR(r io.Reader) error {
br := cbg.GetPeeker(r)
maj, extra, err := cbg.CborReadHeader(br)
@ -883,15 +874,32 @@ func (t *SubmitPoStParams) UnmarshalCBOR(r io.Reader) error {
if _, err := io.ReadFull(br, t.Proof); err != nil {
return err
}
// t.t.DoneSet (types.BitField) (struct)
// t.t.Candidates ([]types.EPostTicket) (slice)
{
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if extra > 8192 {
return fmt.Errorf("t.Candidates: array too large (%d)", extra)
}
if err := t.DoneSet.UnmarshalCBOR(br); err != nil {
if maj != cbg.MajArray {
return fmt.Errorf("expected cbor array")
}
if extra > 0 {
t.Candidates = make([]types.EPostTicket, extra)
}
for i := 0; i < int(extra); i++ {
var v types.EPostTicket
if err := v.UnmarshalCBOR(br); err != nil {
return err
}
t.Candidates[i] = v
}
return nil
}

View File

@ -7,7 +7,7 @@ import (
"io"
"strconv"
"github.com/filecoin-project/go-bls-sigs"
bls "github.com/filecoin-project/filecoin-ffi"
"github.com/filecoin-project/go-leb128"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/minio/blake2b-simd"
@ -389,3 +389,11 @@ func (a *Address) UnmarshalCBOR(br io.Reader) error {
return nil
}
func IDFromAddress(addr Address) (uint64, error) {
if addr.Protocol() != ID {
return 0, xerrors.Errorf("cannot get id from non id address")
}
return leb128.ToUInt64(addr.Payload()), nil
}

View File

@ -10,7 +10,7 @@ import (
"testing"
"time"
"github.com/filecoin-project/go-bls-sigs"
ffi "github.com/filecoin-project/filecoin-ffi"
"github.com/filecoin-project/go-leb128"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -285,7 +285,7 @@ func TestVectorActorAddress(t *testing.T) {
func TestRandomBLSAddress(t *testing.T) {
assert := assert.New(t)
pk := bls.PrivateKeyPublicKey(bls.PrivateKeyGenerate())
pk := ffi.PrivateKeyPublicKey(ffi.PrivateKeyGenerate())
addr, err := NewBLSAddress(pk[:])
assert.NoError(err)
@ -410,8 +410,8 @@ func TestInvalidByteAddresses(t *testing.T) {
{append([]byte{2}, make([]byte, PayloadHashLength+1)...), ErrInvalidPayload},
// BLS Protocol
{append([]byte{3}, make([]byte, bls.PublicKeyBytes-1)...), ErrInvalidPayload},
{append([]byte{3}, make([]byte, bls.PrivateKeyBytes+1)...), ErrInvalidPayload},
{append([]byte{3}, make([]byte, ffi.PublicKeyBytes-1)...), ErrInvalidPayload},
{append([]byte{3}, make([]byte, ffi.PrivateKeyBytes+1)...), ErrInvalidPayload},
}
for _, tc := range testCases {

View File

@ -2,9 +2,9 @@ package address
import (
"encoding/base32"
"errors"
"github.com/minio/blake2b-simd"
errors "github.com/pkg/errors"
)
func init() {

View File

@ -5,7 +5,7 @@ import (
"io"
"github.com/filecoin-project/lotus/chain/types"
cid "github.com/ipfs/go-cid"
"github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
xerrors "golang.org/x/xerrors"
)

View File

@ -24,6 +24,8 @@ import (
"github.com/filecoin-project/lotus/storage/sectorblocks"
)
var ProviderDsPrefix = "/deals/provider"
type MinerDeal struct {
Client peer.ID
Proposal actors.StorageDealProposal
@ -110,7 +112,7 @@ func NewProvider(ds dtypes.MetadataDS, sminer *storage.Miner, secb *sectorblocks
actor: minerAddress,
deals: statestore.New(namespace.Wrap(ds, datastore.NewKey("/deals/client"))),
deals: statestore.New(namespace.Wrap(ds, datastore.NewKey(ProviderDsPrefix))),
ds: ds,
}

View File

@ -6,7 +6,9 @@ import (
"sync"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
)
@ -302,9 +304,10 @@ func (e *calledEvents) Called(check CheckFunc, hnd CalledHandler, rev RevertHand
e.lk.Lock()
defer e.lk.Unlock()
done, more, err := check(e.tsc.best())
ts := e.tsc.best()
done, more, err := check(ts)
if err != nil {
return err
return xerrors.Errorf("called check error (h: %d): %w", ts.Height(), err)
}
if done {
timeout = NoTimeout
@ -335,6 +338,6 @@ func (e *calledEvents) Called(check CheckFunc, hnd CalledHandler, rev RevertHand
return nil
}
func (e *calledEvents) CalledMsg(ctx context.Context, hnd CalledHandler, rev RevertHandler, confidence int, timeout uint64, msg *types.Message) error {
return e.Called(e.CheckMsg(ctx, msg, hnd), hnd, rev, confidence, timeout, e.MatchMsg(msg))
func (e *calledEvents) CalledMsg(ctx context.Context, hnd CalledHandler, rev RevertHandler, confidence int, timeout uint64, msg store.ChainMsg) error {
return e.Called(e.CheckMsg(ctx, msg, hnd), hnd, rev, confidence, timeout, e.MatchMsg(msg.VMMessage()))
}

View File

@ -96,7 +96,7 @@ func (e *heightEvents) headChangeAt(rev, app []*types.TipSet) error {
span.End()
if err != nil {
log.Errorf("chain trigger (@H %d, called @ %d) failed: %s", triggerH, ts.Height(), err)
log.Errorf("chain trigger (@H %d, called @ %d) failed: %+v", triggerH, ts.Height(), err)
}
}
return nil

View File

@ -60,26 +60,26 @@ func makeTs(t *testing.T, h uint64, msgcid cid.Cid) *types.TipSet {
Height: h,
Miner: a,
Tickets: []*types.Ticket{{[]byte{byte(h % 2)}}},
Ticket: &types.Ticket{[]byte{byte(h % 2)}},
ParentStateRoot: dummyCid,
Messages: msgcid,
ParentMessageReceipts: dummyCid,
BlockSig: types.Signature{Type: types.KTBLS},
BlockSig: &types.Signature{Type: types.KTBLS},
BLSAggregate: types.Signature{Type: types.KTBLS},
},
{
Height: h,
Miner: b,
Tickets: []*types.Ticket{{[]byte{byte((h + 1) % 2)}}},
Ticket: &types.Ticket{[]byte{byte((h + 1) % 2)}},
ParentStateRoot: dummyCid,
Messages: msgcid,
ParentMessageReceipts: dummyCid,
BlockSig: types.Signature{Type: types.KTBLS},
BlockSig: &types.Signature{Type: types.KTBLS},
BLSAggregate: types.Signature{Type: types.KTBLS},
},
})

View File

@ -27,7 +27,7 @@ func TestTsCache(t *testing.T) {
ParentStateRoot: dummyCid,
Messages: dummyCid,
ParentMessageReceipts: dummyCid,
BlockSig: types.Signature{Type: types.KTBLS},
BlockSig: &types.Signature{Type: types.KTBLS},
BLSAggregate: types.Signature{Type: types.KTBLS},
}})
if err != nil {
@ -69,7 +69,7 @@ func TestTsCacheNulls(t *testing.T) {
ParentStateRoot: dummyCid,
Messages: dummyCid,
ParentMessageReceipts: dummyCid,
BlockSig: types.Signature{Type: types.KTBLS},
BlockSig: &types.Signature{Type: types.KTBLS},
BLSAggregate: types.Signature{Type: types.KTBLS},
}})
if err != nil {

View File

@ -5,28 +5,32 @@ import (
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
)
func (e *calledEvents) CheckMsg(ctx context.Context, msg *types.Message, hnd CalledHandler) CheckFunc {
func (e *calledEvents) CheckMsg(ctx context.Context, smsg store.ChainMsg, hnd CalledHandler) CheckFunc {
msg := smsg.VMMessage()
return func(ts *types.TipSet) (done bool, more bool, err error) {
fa, err := e.cs.StateGetActor(ctx, msg.From, ts)
if err != nil {
return false, true, err
}
// TODO: probably want to look at the chain to make sure it's
// the right message, but this is probably good enough for now
done = fa.Nonce >= msg.Nonce
// >= because actor nonce is actually the next nonce that is expected to appear on chain
if msg.Nonce >= fa.Nonce {
return false, true, nil
}
rec, err := e.cs.StateGetReceipt(ctx, msg.Cid(), ts)
rec, err := e.cs.StateGetReceipt(ctx, smsg.VMMessage().Cid(), ts)
if err != nil {
return false, true, err
return false, true, xerrors.Errorf("getting receipt in CheckMsg: %w", err)
}
more, err = hnd(msg, rec, ts, ts.Height())
return done, more, err
return true, more, err
}
}

View File

@ -3,14 +3,20 @@ package gen
import (
"bytes"
"context"
"crypto/sha256"
"encoding/binary"
"fmt"
"io/ioutil"
"sync/atomic"
ffi "github.com/filecoin-project/filecoin-ffi"
"github.com/ipfs/go-blockservice"
"github.com/ipfs/go-car"
offline "github.com/ipfs/go-ipfs-exchange-offline"
"github.com/ipfs/go-merkledag"
peer "github.com/libp2p/go-libp2p-peer"
"go.opencensus.io/trace"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/api"
@ -20,6 +26,9 @@ import (
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/wallet"
"github.com/filecoin-project/lotus/cmd/lotus-seed/seed"
"github.com/filecoin-project/lotus/genesis"
"github.com/filecoin-project/lotus/lib/sectorbuilder"
"github.com/filecoin-project/lotus/node/repo"
block "github.com/ipfs/go-block-format"
@ -46,10 +55,11 @@ type ChainGen struct {
genesis *types.BlockHeader
CurTipset *store.FullTipSet
Timestamper func(*types.TipSet, int) uint64
Timestamper func(*types.TipSet, uint64) uint64
w *wallet.Wallet
eppProvs map[address.Address]ElectionPoStProver
Miners []address.Address
mworkers []address.Address
receivers []address.Address
@ -102,16 +112,6 @@ func NewGenerator() (*ChainGen, error) {
return nil, xerrors.Errorf("creating memrepo wallet failed: %w", err)
}
worker1, err := w.GenerateKey(types.KTBLS)
if err != nil {
return nil, xerrors.Errorf("failed to generate worker key: %w", err)
}
worker2, err := w.GenerateKey(types.KTBLS)
if err != nil {
return nil, xerrors.Errorf("failed to generate worker key: %w", err)
}
banker, err := w.GenerateKey(types.KTSecp256k1)
if err != nil {
return nil, xerrors.Errorf("failed to generate banker key: %w", err)
@ -125,16 +125,60 @@ func NewGenerator() (*ChainGen, error) {
}
}
// TODO: this is really weird, we have to guess the miner addresses that
// will be created in order to preseal data for them
maddr1, err := address.NewFromString("t0300")
if err != nil {
return nil, err
}
m1temp, err := ioutil.TempDir("", "preseal")
if err != nil {
return nil, err
}
genm1, err := seed.PreSeal(maddr1, 1024, 1, m1temp, []byte("some randomness"))
if err != nil {
return nil, err
}
maddr2, err := address.NewFromString("t0301")
if err != nil {
return nil, err
}
m2temp, err := ioutil.TempDir("", "preseal")
if err != nil {
return nil, err
}
genm2, err := seed.PreSeal(maddr2, 1024, 1, m2temp, []byte("some randomness"))
if err != nil {
return nil, err
}
mk1, err := w.Import(&genm1.Key)
if err != nil {
return nil, err
}
mk2, err := w.Import(&genm2.Key)
if err != nil {
return nil, err
}
minercfg := &GenMinerCfg{
Workers: []address.Address{worker1, worker2},
Owners: []address.Address{worker1, worker2},
PeerIDs: []peer.ID{"peerID1", "peerID2"},
PreSeals: map[string]genesis.GenesisMiner{
maddr1.String(): *genm1,
maddr2.String(): *genm2,
},
MinerAddrs: []address.Address{maddr1, maddr2},
}
genb, err := MakeGenesisBlock(bs, map[address.Address]types.BigInt{
worker1: types.FromFil(40000),
worker2: types.FromFil(40000),
banker: types.FromFil(50000),
mk1: types.FromFil(40000),
mk2: types.FromFil(40000),
banker: types.FromFil(50000),
}, minercfg, 100000)
if err != nil {
return nil, xerrors.Errorf("make genesis block failed: %w", err)
@ -153,6 +197,11 @@ func NewGenerator() (*ChainGen, error) {
return nil, xerrors.Errorf("MakeGenesisBlock failed to set miner address")
}
mgen := make(map[address.Address]ElectionPoStProver)
for _, m := range minercfg.MinerAddrs {
mgen[m] = &eppProvider{}
}
sm := stmgr.NewStateManager(cs)
gen := &ChainGen{
@ -163,8 +212,9 @@ func NewGenerator() (*ChainGen, error) {
genesis: genb.Genesis,
w: w,
Miners: minercfg.MinerAddrs,
mworkers: minercfg.Workers,
Miners: minercfg.MinerAddrs,
eppProvs: mgen,
//mworkers: minercfg.Workers,
banker: banker,
receivers: receievers,
@ -189,20 +239,15 @@ func (cg *ChainGen) GenesisCar() ([]byte, error) {
out := new(bytes.Buffer)
if err := car.WriteCar(context.TODO(), dserv, []cid.Cid{cg.Genesis().Cid()}, out); err != nil {
return nil, err
return nil, xerrors.Errorf("genesis car write car failed: %w", err)
}
return out.Bytes(), nil
}
func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m address.Address, ticks []*types.Ticket) (types.ElectionProof, *types.Ticket, error) {
func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m address.Address, round int64) (*types.EPostProof, *types.Ticket, error) {
var lastTicket *types.Ticket
if len(ticks) == 0 {
lastTicket = pts.MinTicket()
} else {
lastTicket = ticks[len(ticks)-1]
}
lastTicket := pts.MinTicket()
st := pts.ParentState()
@ -211,7 +256,8 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add
return nil, nil, xerrors.Errorf("get miner worker: %w", err)
}
vrfout, err := ComputeVRF(ctx, cg.w.Sign, worker, lastTicket.VRFProof)
log.Warnf("compute VRF ROUND: %d %s %s", round, m, worker)
vrfout, err := ComputeVRF(ctx, cg.w.Sign, worker, m, DSepTicket, lastTicket.VRFProof)
if err != nil {
return nil, nil, xerrors.Errorf("compute VRF: %w", err)
}
@ -220,7 +266,7 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add
VRFProof: vrfout,
}
win, eproof, err := IsRoundWinner(ctx, pts, append(ticks, tick), m, &mca{w: cg.w, sm: cg.sm})
win, eproof, err := IsRoundWinner(ctx, pts, round, m, cg.eppProvs[m], &mca{w: cg.w, sm: cg.sm})
if err != nil {
return nil, nil, xerrors.Errorf("checking round winner failed: %w", err)
}
@ -248,23 +294,22 @@ func (cg *ChainGen) NextTipSet() (*MinedTipSet, error) {
func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Address) (*MinedTipSet, error) {
var blks []*types.FullBlock
ticketSets := make([][]*types.Ticket, len(miners))
msgs, err := cg.getRandomMessages()
if err != nil {
return nil, xerrors.Errorf("get random messages: %w", err)
}
for len(blks) == 0 {
for i, m := range miners {
proof, t, err := cg.nextBlockProof(context.TODO(), base, m, ticketSets[i])
for round := int64(base.Height() + 1); len(blks) == 0; round++ {
for _, m := range miners {
proof, t, err := cg.nextBlockProof(context.TODO(), base, m, round)
if err != nil {
return nil, xerrors.Errorf("next block proof: %w", err)
}
ticketSets[i] = append(ticketSets[i], t)
if proof != nil {
fblk, err := cg.makeBlock(base, m, proof, ticketSets[i], msgs)
log.Warn("making block, ticket: ", t.VRFProof)
fblk, err := cg.makeBlock(base, m, proof, t, uint64(round), msgs)
if err != nil {
return nil, xerrors.Errorf("making a block for next tipset failed: %w", err)
}
@ -286,16 +331,16 @@ func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Ad
}, nil
}
func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, eproof types.ElectionProof, tickets []*types.Ticket, msgs []*types.SignedMessage) (*types.FullBlock, error) {
func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, eproof *types.EPostProof, ticket *types.Ticket, height uint64, msgs []*types.SignedMessage) (*types.FullBlock, error) {
var ts uint64
if cg.Timestamper != nil {
ts = cg.Timestamper(parents, len(tickets))
ts = cg.Timestamper(parents, height-parents.Height())
} else {
ts = parents.MinTimestamp() + (uint64(len(tickets)) * build.BlockDelay)
ts = parents.MinTimestamp() + ((height - parents.Height()) * build.BlockDelay)
}
fblk, err := MinerCreateBlock(context.TODO(), cg.sm, cg.w, m, parents, tickets, eproof, msgs, ts)
fblk, err := MinerCreateBlock(context.TODO(), cg.sm, cg.w, m, parents, ticket, eproof, msgs, height, ts)
if err != nil {
return nil, err
}
@ -354,12 +399,16 @@ func (cg *ChainGen) YieldRepo() (repo.Repo, error) {
}
type MiningCheckAPI interface {
ChainGetRandomness(context.Context, types.TipSetKey, []*types.Ticket, int) ([]byte, error)
ChainGetRandomness(context.Context, types.TipSetKey, int64) ([]byte, error)
StateMinerPower(context.Context, address.Address, *types.TipSet) (api.MinerPower, error)
StateMinerWorker(context.Context, address.Address, *types.TipSet) (address.Address, error)
StateMinerSectorSize(context.Context, address.Address, *types.TipSet) (uint64, error)
StateMinerProvingSet(context.Context, address.Address, *types.TipSet) ([]*api.ChainSectorInfo, error)
WalletSign(context.Context, address.Address, []byte) (*types.Signature, error)
}
@ -368,8 +417,8 @@ type mca struct {
sm *stmgr.StateManager
}
func (mca mca) ChainGetRandomness(ctx context.Context, pts types.TipSetKey, ticks []*types.Ticket, lb int) ([]byte, error) {
return mca.sm.ChainStore().GetRandomness(ctx, pts.Cids(), ticks, int64(lb))
func (mca mca) ChainGetRandomness(ctx context.Context, pts types.TipSetKey, lb int64) ([]byte, error) {
return mca.sm.ChainStore().GetRandomness(ctx, pts.Cids(), int64(lb))
}
func (mca mca) StateMinerPower(ctx context.Context, maddr address.Address, ts *types.TipSet) (api.MinerPower, error) {
@ -388,12 +437,45 @@ func (mca mca) StateMinerWorker(ctx context.Context, maddr address.Address, ts *
return stmgr.GetMinerWorkerRaw(ctx, mca.sm, ts.ParentState(), maddr)
}
func (mca mca) StateMinerSectorSize(ctx context.Context, maddr address.Address, ts *types.TipSet) (uint64, error) {
return stmgr.GetMinerSectorSize(ctx, mca.sm, ts, maddr)
}
func (mca mca) StateMinerProvingSet(ctx context.Context, maddr address.Address, ts *types.TipSet) ([]*api.ChainSectorInfo, error) {
return stmgr.GetMinerProvingSet(ctx, mca.sm, ts, maddr)
}
func (mca mca) WalletSign(ctx context.Context, a address.Address, v []byte) (*types.Signature, error) {
return mca.w.Sign(ctx, a, v)
}
func IsRoundWinner(ctx context.Context, ts *types.TipSet, ticks []*types.Ticket, miner address.Address, a MiningCheckAPI) (bool, types.ElectionProof, error) {
r, err := a.ChainGetRandomness(ctx, ts.Key(), ticks, build.EcRandomnessLookback)
type ElectionPoStProver interface {
GenerateCandidates(context.Context, sectorbuilder.SortedPublicSectorInfo, []byte) ([]sectorbuilder.EPostCandidate, error)
ComputeProof(context.Context, sectorbuilder.SortedPublicSectorInfo, []byte, []sectorbuilder.EPostCandidate) ([]byte, error)
}
type eppProvider struct {
sectors []ffi.PublicSectorInfo
}
func (epp *eppProvider) GenerateCandidates(ctx context.Context, _ sectorbuilder.SortedPublicSectorInfo, eprand []byte) ([]sectorbuilder.EPostCandidate, error) {
return []sectorbuilder.EPostCandidate{
sectorbuilder.EPostCandidate{
SectorID: 1,
PartialTicket: [32]byte{},
Ticket: [32]byte{},
SectorChallengeIndex: 1,
},
}, nil
}
func (epp *eppProvider) ComputeProof(ctx context.Context, _ sectorbuilder.SortedPublicSectorInfo, eprand []byte, winners []sectorbuilder.EPostCandidate) ([]byte, error) {
return []byte("valid proof"), nil
}
func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner address.Address, epp ElectionPoStProver, a MiningCheckAPI) (bool, *types.EPostProof, error) {
r, err := a.ChainGetRandomness(ctx, ts.Key(), round-build.EcRandomnessLookback)
if err != nil {
return false, nil, xerrors.Errorf("chain get randomness: %w", err)
}
@ -403,30 +485,153 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, ticks []*types.Ticket,
return false, nil, xerrors.Errorf("failed to get miner worker: %w", err)
}
vrfout, err := ComputeVRF(ctx, a.WalletSign, mworker, r)
vrfout, err := ComputeVRF(ctx, a.WalletSign, mworker, miner, DSepElectionPost, r)
if err != nil {
return false, nil, xerrors.Errorf("failed to compute VRF: %w", err)
}
pset, err := a.StateMinerProvingSet(ctx, miner, ts)
if err != nil {
return false, nil, xerrors.Errorf("failed to load proving set for miner: %w", err)
}
if len(pset) == 0 {
return false, nil, nil
}
var sinfos []ffi.PublicSectorInfo
for _, s := range pset {
var commRa [32]byte
copy(commRa[:], s.CommR)
sinfos = append(sinfos, ffi.PublicSectorInfo{
SectorID: s.SectorID,
CommR: commRa,
})
}
sectors := sectorbuilder.NewSortedPublicSectorInfo(sinfos)
hvrf := sha256.Sum256(vrfout)
log.Info("Replicas: ", sectors)
candidates, err := epp.GenerateCandidates(ctx, sectors, hvrf[:])
if err != nil {
return false, nil, xerrors.Errorf("failed to generate electionPoSt candidates: %w", err)
}
pow, err := a.StateMinerPower(ctx, miner, ts)
if err != nil {
return false, nil, xerrors.Errorf("failed to check power: %w", err)
}
return types.PowerCmp(vrfout, pow.MinerPower, pow.TotalPower), vrfout, nil
ssize, err := a.StateMinerSectorSize(ctx, miner, ts)
if err != nil {
return false, nil, xerrors.Errorf("failed to look up miners sector size: %w", err)
}
var winners []sectorbuilder.EPostCandidate
for _, c := range candidates {
if types.IsTicketWinner(c.PartialTicket[:], ssize, pow.TotalPower, 1) {
winners = append(winners, c)
}
}
// no winners, sad
if len(winners) == 0 {
return false, nil, nil
}
proof, err := epp.ComputeProof(ctx, sectors, hvrf[:], winners)
if err != nil {
return false, nil, xerrors.Errorf("failed to compute snark for election proof: %w", err)
}
ept := types.EPostProof{
Proof: proof,
PostRand: vrfout,
}
for _, win := range winners {
ept.Candidates = append(ept.Candidates, types.EPostTicket{
Partial: win.PartialTicket[:],
SectorID: win.SectorID,
ChallengeIndex: win.SectorChallengeIndex,
})
}
return true, &ept, nil
}
type SignFunc func(context.Context, address.Address, []byte) (*types.Signature, error)
func ComputeVRF(ctx context.Context, sign SignFunc, w address.Address, input []byte) ([]byte, error) {
sig, err := sign(ctx, w, input)
const (
DSepTicket = 1
DSepElectionPost = 2
)
func hashVRFBase(personalization uint64, miner address.Address, input []byte) ([]byte, error) {
if miner.Protocol() != address.ID {
return nil, xerrors.Errorf("miner address for compute VRF must be an ID address")
}
var persbuf [8]byte
binary.LittleEndian.PutUint64(persbuf[:], personalization)
h := sha256.New()
h.Write(persbuf[:])
h.Write([]byte{0})
h.Write(input)
h.Write([]byte{0})
h.Write(miner.Bytes())
return h.Sum(nil), nil
}
func VerifyVRF(ctx context.Context, worker, miner address.Address, p uint64, input, vrfproof []byte) error {
ctx, span := trace.StartSpan(ctx, "VerifyVRF")
defer span.End()
vrfBase, err := hashVRFBase(p, miner, input)
if err != nil {
return xerrors.Errorf("computing vrf base failed: %w", err)
}
sig := &types.Signature{
Type: types.KTBLS,
Data: vrfproof,
}
if err := sig.Verify(worker, vrfBase); err != nil {
return xerrors.Errorf("vrf was invalid: %w", err)
}
return nil
}
func ComputeVRF(ctx context.Context, sign SignFunc, worker, miner address.Address, p uint64, input []byte) ([]byte, error) {
sigInput, err := hashVRFBase(p, miner, input)
if err != nil {
return nil, err
}
sig, err := sign(ctx, worker, sigInput)
if err != nil {
return nil, err
}
log.Warnf("making ticket: %x %s %s %x %x", sig.Data, worker, miner, input, sigInput)
if sig.Type != types.KTBLS {
return nil, fmt.Errorf("miner worker address was not a BLS key")
}
return sig.Data, nil
}
func TicketHash(t *types.Ticket, addr address.Address) []byte {
h := sha256.New()
h.Write(t.VRFProof)
// Field Delimeter
h.Write([]byte{0})
h.Write(addr.Bytes())
return h.Sum(nil)
}

View File

@ -12,18 +12,12 @@ func testGeneration(t testing.TB, n int, msgs int) {
g.msgsPerBlock = msgs
var height int
for i := 0; i < n; i++ {
mts, err := g.NextTipSet()
if err != nil {
t.Fatalf("error at H:%d, %s", i, err)
}
ts := mts.TipSet.TipSet()
if ts.Height() != uint64(height+len(ts.Blocks()[0].Tickets)) {
t.Fatal("wrong height", ts.Height(), i, len(ts.Blocks()[0].Tickets), len(ts.Blocks()))
}
height += len(ts.Blocks()[0].Tickets)
_ = mts
}
}

View File

@ -3,8 +3,8 @@ package gen
import (
"context"
bls "github.com/filecoin-project/filecoin-ffi"
amt "github.com/filecoin-project/go-amt-ipld"
bls "github.com/filecoin-project/go-bls-sigs"
cid "github.com/ipfs/go-cid"
hamt "github.com/ipfs/go-hamt-ipld"
cbg "github.com/whyrusleeping/cbor-gen"
@ -18,14 +18,12 @@ import (
"github.com/filecoin-project/lotus/chain/wallet"
)
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wallet, miner address.Address, parents *types.TipSet, tickets []*types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage, timestamp uint64) (*types.FullBlock, error) {
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wallet, miner address.Address, parents *types.TipSet, ticket *types.Ticket, proof *types.EPostProof, msgs []*types.SignedMessage, height, timestamp uint64) (*types.FullBlock, error) {
st, recpts, err := sm.TipSetState(ctx, parents)
if err != nil {
return nil, xerrors.Errorf("failed to load tipset state: %w", err)
}
height := parents.Height() + uint64(len(tickets))
worker, err := stmgr.GetMinerWorkerRaw(ctx, sm, st, miner)
if err != nil {
return nil, xerrors.Errorf("failed to get miner worker: %w", err)
@ -34,10 +32,10 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wal
next := &types.BlockHeader{
Miner: miner,
Parents: parents.Cids(),
Tickets: tickets,
Ticket: ticket,
Height: height,
Timestamp: timestamp,
ElectionProof: proof,
EPostProof: *proof,
ParentStateRoot: st,
ParentMessageReceipts: recpts,
}
@ -122,7 +120,7 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wal
return nil, xerrors.Errorf("failed to sign new block: %w", err)
}
next.BlockSig = *sig
next.BlockSig = sig
fullBlock := &types.FullBlock{
Header: next,

View File

@ -1,6 +1,7 @@
package gen
import (
"bytes"
"context"
"fmt"
@ -8,6 +9,7 @@ import (
"github.com/ipfs/go-cid"
"github.com/ipfs/go-datastore"
hamt "github.com/ipfs/go-hamt-ipld"
blockstore "github.com/ipfs/go-ipfs-blockstore"
bstore "github.com/ipfs/go-ipfs-blockstore"
peer "github.com/libp2p/go-libp2p-peer"
cbg "github.com/whyrusleeping/cbor-gen"
@ -20,8 +22,17 @@ import (
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/genesis"
)
var validSsizes = map[uint64]struct{}{}
func init() {
for _, size := range build.SectorSizes {
validSsizes[size] = struct{}{}
}
}
type GenesisBootstrap struct {
Genesis *types.BlockHeader
}
@ -98,15 +109,6 @@ func MakeInitialStateTree(bs bstore.Blockstore, actmap map[address.Address]types
return nil, xerrors.Errorf("set storage market actor: %w", err)
}
smact, err := SetupStorageMarketActor(bs)
if err != nil {
return nil, xerrors.Errorf("setup storage market actor: %w", err)
}
if err := state.SetActor(actors.StorageMarketAddress, smact); err != nil {
return nil, xerrors.Errorf("set storage market actor: %w", err)
}
netAmt := types.FromFil(build.TotalFilecoin)
for _, amt := range actmap {
netAmt = types.BigSub(netAmt, amt)
@ -177,46 +179,61 @@ func SetupStoragePowerActor(bs bstore.Blockstore) (*types.Actor, error) {
}, nil
}
func SetupStorageMarketActor(bs bstore.Blockstore) (*types.Actor, error) {
func SetupStorageMarketActor(bs bstore.Blockstore, sroot cid.Cid, deals []actors.StorageDeal) (cid.Cid, error) {
cst := hamt.CSTFromBstore(bs)
nd := hamt.NewNode(cst)
emptyHAMT, err := cst.Put(context.TODO(), nd)
if err != nil {
return nil, err
return cid.Undef, err
}
blks := amt.WrapBlockstore(bs)
emptyAMT, err := amt.FromArray(blks, nil)
cdeals := make([]cbg.CBORMarshaler, len(deals))
for i, deal := range deals {
cdeals[i] = &actors.OnChainDeal{
Deal: deal,
ActivationEpoch: 1,
}
}
dealAmt, err := amt.FromArray(blks, cdeals)
if err != nil {
return nil, xerrors.Errorf("amt build failed: %w", err)
return cid.Undef, xerrors.Errorf("amt build failed: %w", err)
}
sms := &actors.StorageMarketState{
Balances: emptyHAMT,
Deals: emptyAMT,
Deals: dealAmt,
NextDealID: 0,
}
stcid, err := cst.Put(context.TODO(), sms)
if err != nil {
return nil, err
return cid.Undef, err
}
return &types.Actor{
act := &types.Actor{
Code: actors.StorageMarketCodeCid,
Head: stcid,
Nonce: 0,
Balance: types.NewInt(0),
}, nil
}
state, err := state.LoadStateTree(cst, sroot)
if err != nil {
return cid.Undef, xerrors.Errorf("making new state tree: %w", err)
}
if err := state.SetActor(actors.StorageMarketAddress, act); err != nil {
return cid.Undef, xerrors.Errorf("set storage market actor: %w", err)
}
return state.Flush()
}
type GenMinerCfg struct {
Owners []address.Address
Workers []address.Address
// not quite generating real sectors yet, but this will be necessary
//SectorDir string
PreSeals map[string]genesis.GenesisMiner
// The addresses of the created miner, this is set by the genesis setup
MinerAddrs []address.Address
@ -232,78 +249,250 @@ func mustEnc(i cbg.CBORMarshaler) []byte {
return enc
}
func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid, gmcfg *GenMinerCfg) (cid.Cid, error) {
func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid, gmcfg *GenMinerCfg) (cid.Cid, []actors.StorageDeal, error) {
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)
return cid.Undef, nil, xerrors.Errorf("failed to create NewVM: %w", err)
}
for i := 0; i < len(gmcfg.Workers); i++ {
owner := gmcfg.Owners[i]
worker := gmcfg.Workers[i]
pid := gmcfg.PeerIDs[i]
if len(gmcfg.MinerAddrs) != len(gmcfg.PreSeals) {
return cid.Undef, nil, xerrors.Errorf("miner address list, and preseal count doesn't match (%d != %d)", len(gmcfg.MinerAddrs), len(gmcfg.PreSeals))
}
params := mustEnc(&actors.CreateStorageMinerParams{
Owner: owner,
Worker: worker,
SectorSize: build.SectorSizes[0],
PeerID: pid,
})
var deals []actors.StorageDeal
// TODO: hardcoding 7000000 here is a little fragile, it changes any
for i, maddr := range gmcfg.MinerAddrs {
ps, psok := gmcfg.PreSeals[maddr.String()]
if !psok {
return cid.Undef, nil, xerrors.Errorf("no preseal for miner %s", maddr)
}
minerParams := &actors.CreateStorageMinerParams{
Owner: ps.Owner,
Worker: ps.Worker,
SectorSize: ps.SectorSize,
PeerID: gmcfg.PeerIDs[i], // TODO: grab from preseal too
}
params := mustEnc(minerParams)
// TODO: hardcoding 6500 here is a little fragile, it changes any
// time anyone changes the initial account allocations
rval, err := doExecValue(ctx, vm, actors.StoragePowerAddress, owner, types.FromFil(6500), actors.SPAMethods.CreateStorageMiner, params)
rval, err := doExecValue(ctx, vm, actors.StoragePowerAddress, ps.Worker, types.FromFil(6500), actors.SPAMethods.CreateStorageMiner, params)
if err != nil {
return cid.Undef, xerrors.Errorf("failed to create genesis miner: %w", err)
return cid.Undef, nil, xerrors.Errorf("failed to create genesis miner: %w", err)
}
maddr, err := address.NewFromBytes(rval)
maddrret, err := address.NewFromBytes(rval)
if err != nil {
return cid.Undef, err
return cid.Undef, nil, err
}
gmcfg.MinerAddrs = append(gmcfg.MinerAddrs, maddr)
_, err = vm.Flush(ctx)
if err != nil {
return cid.Undef, nil, err
}
params = mustEnc(&actors.UpdateStorageParams{Delta: types.NewInt(5000)})
cst := hamt.CSTFromBstore(cs.Blockstore())
if err := reassignMinerActorAddress(vm, cst, maddrret, maddr); err != nil {
return cid.Undef, nil, err
}
power := types.BigMul(types.NewInt(minerParams.SectorSize), types.NewInt(uint64(len(ps.Sectors))))
params = mustEnc(&actors.UpdateStorageParams{Delta: power})
_, err = doExec(ctx, vm, actors.StoragePowerAddress, maddr, actors.SPAMethods.UpdateStorage, params)
if err != nil {
return cid.Undef, xerrors.Errorf("failed to update total storage: %w", err)
return cid.Undef, nil, xerrors.Errorf("failed to update total storage: %w", err)
}
// UGLY HACKY MODIFICATION OF MINER POWER
// we have to flush the vm here because it buffers stuff internally for perf reasons
if _, err := vm.Flush(ctx); err != nil {
return cid.Undef, xerrors.Errorf("vm.Flush failed: %w", err)
return cid.Undef, nil, xerrors.Errorf("vm.Flush failed: %w", err)
}
st := vm.StateTree()
mact, err := st.GetActor(maddr)
if err != nil {
return cid.Undef, xerrors.Errorf("get miner actor failed: %w", err)
return cid.Undef, nil, xerrors.Errorf("get miner actor failed: %w", err)
}
cst := hamt.CSTFromBstore(cs.Blockstore())
var mstate actors.StorageMinerActorState
if err := cst.Get(ctx, mact.Head, &mstate); err != nil {
return cid.Undef, xerrors.Errorf("getting miner actor state failed: %w", err)
return cid.Undef, nil, xerrors.Errorf("getting miner actor state failed: %w", err)
}
mstate.Power = types.NewInt(build.SectorSizes[0])
blks := amt.WrapBlockstore(cs.Blockstore())
for _, s := range ps.Sectors {
nssroot, err := actors.AddToSectorSet(ctx, blks, mstate.Sectors, s.SectorID, s.CommR[:], s.CommD[:])
if err != nil {
return cid.Undef, nil, xerrors.Errorf("failed to add fake sector to sector set: %w", err)
}
mstate.Sectors = nssroot
mstate.ProvingSet = nssroot
deals = append(deals, s.Deal)
}
mstate.Power = types.NewInt(5000)
nstate, err := cst.Put(ctx, &mstate)
if err != nil {
return cid.Undef, err
return cid.Undef, nil, err
}
mact.Head = nstate
if err := st.SetActor(maddr, mact); err != nil {
return cid.Undef, err
return cid.Undef, nil, err
}
// End of super haxx
}
return vm.Flush(ctx)
c, err := vm.Flush(ctx)
return c, deals, err
}
func reassignMinerActorAddress(vm *vm.VM, cst *hamt.CborIpldStore, from, to address.Address) error {
if from == to {
return nil
}
act, err := vm.StateTree().GetActor(from)
if err != nil {
return xerrors.Errorf("reassign: failed to get 'from' actor: %w", err)
}
_, err = vm.StateTree().GetActor(to)
if err == nil {
return xerrors.Errorf("cannot reassign actor, target address taken")
}
if err := vm.StateTree().SetActor(to, act); err != nil {
return xerrors.Errorf("failed to reassign actor: %w", err)
}
if err := adjustStorageMarketTracking(vm, cst, from, to); err != nil {
return xerrors.Errorf("adjusting storage market tracking: %w", err)
}
// Now, adjust the tracking in the init actor
return initActorReassign(vm, cst, from, to)
}
func adjustStorageMarketTracking(vm *vm.VM, cst *hamt.CborIpldStore, from, to address.Address) error {
ctx := context.TODO()
act, err := vm.StateTree().GetActor(actors.StoragePowerAddress)
if err != nil {
return xerrors.Errorf("loading storage power actor: %w", err)
}
var spst actors.StoragePowerState
if err := cst.Get(ctx, act.Head, &spst); err != nil {
return xerrors.Errorf("loading storage power actor state: %w", err)
}
miners, err := hamt.LoadNode(ctx, cst, spst.Miners)
if err != nil {
return xerrors.Errorf("loading miner set: %w", err)
}
if err := miners.Delete(ctx, string(from.Bytes())); err != nil {
return xerrors.Errorf("deleting from spa set: %w", err)
}
if err := miners.Set(ctx, string(to.Bytes()), uint64(1)); err != nil {
return xerrors.Errorf("failed setting miner: %w", err)
}
if err := miners.Flush(ctx); err != nil {
return err
}
nminerscid, err := cst.Put(ctx, miners)
if err != nil {
return err
}
spst.Miners = nminerscid
nhead, err := cst.Put(ctx, &spst)
if err != nil {
return err
}
act.Head = nhead
return nil
}
func initActorReassign(vm *vm.VM, cst *hamt.CborIpldStore, from, to address.Address) error {
ctx := context.TODO()
initact, err := vm.StateTree().GetActor(actors.InitAddress)
if err != nil {
return xerrors.Errorf("couldnt get init actor: %w", err)
}
var st actors.InitActorState
if err := cst.Get(ctx, initact.Head, &st); err != nil {
return xerrors.Errorf("reassign loading init actor state: %w", err)
}
amap, err := hamt.LoadNode(ctx, cst, st.AddressMap)
if err != nil {
return xerrors.Errorf("failed to load init actor map: %w", err)
}
target, err := address.IDFromAddress(from)
if err != nil {
return xerrors.Errorf("failed to extract ID: %w", err)
}
var out string
halt := xerrors.Errorf("halt")
err = amap.ForEach(ctx, func(k string, v interface{}) error {
_, val, err := cbg.CborReadHeader(bytes.NewReader(v.(*cbg.Deferred).Raw))
if err != nil {
return xerrors.Errorf("parsing int in map failed: %w", err)
}
if val == target {
out = k
return halt
}
return nil
})
if err == nil {
return xerrors.Errorf("could not find from address in init ID map")
}
if !xerrors.Is(err, halt) {
return xerrors.Errorf("finding address in ID map failed: %w", err)
}
if err := amap.Delete(ctx, out); err != nil {
return xerrors.Errorf("deleting 'from' entry in amap: %w", err)
}
if err := amap.Set(ctx, out, target); err != nil {
return xerrors.Errorf("setting 'to' entry in amap: %w", err)
}
if err := amap.Flush(ctx); err != nil {
return xerrors.Errorf("failed to flush amap: %w", err)
}
ncid, err := cst.Put(ctx, amap)
if err != nil {
return err
}
st.AddressMap = ncid
nacthead, err := cst.Put(ctx, &st)
if err != nil {
return err
}
initact.Head = nacthead
return nil
}
func doExec(ctx context.Context, vm *vm.VM, to, from address.Address, method uint64, params []byte) ([]byte, error) {
@ -352,11 +541,21 @@ func MakeGenesisBlock(bs bstore.Blockstore, balances map[address.Address]types.B
// temp chainstore
cs := store.NewChainStore(bs, datastore.NewMapDatastore())
stateroot, err = SetupStorageMiners(ctx, cs, stateroot, gmcfg)
stateroot, deals, err := SetupStorageMiners(ctx, cs, stateroot, gmcfg)
if err != nil {
return nil, xerrors.Errorf("setup storage miners failed: %w", err)
}
stateroot, err = SetupStorageMarketActor(bs, stateroot, deals)
if err != nil {
return nil, xerrors.Errorf("setup storage market actor: %w", err)
}
stateroot, err = AdjustInitActorStartID(ctx, bs, stateroot, 1000)
if err != nil {
return nil, xerrors.Errorf("failed to adjust init actor start ID: %w", err)
}
blks := amt.WrapBlockstore(bs)
emptyroot, err := amt.FromArray(blks, nil)
@ -383,9 +582,12 @@ func MakeGenesisBlock(bs bstore.Blockstore, balances map[address.Address]types.B
}
b := &types.BlockHeader{
Miner: actors.InitAddress,
Tickets: []*types.Ticket{genesisticket},
ElectionProof: []byte("the Genesis block"),
Miner: actors.InitAddress,
Ticket: genesisticket,
EPostProof: types.EPostProof{
Proof: []byte("not a real proof"),
PostRand: []byte("i guess this is kinda random"),
},
Parents: []cid.Cid{},
Height: 0,
ParentWeight: types.NewInt(0),
@ -393,7 +595,7 @@ func MakeGenesisBlock(bs bstore.Blockstore, balances map[address.Address]types.B
Messages: mmb.Cid(),
ParentMessageReceipts: emptyroot,
BLSAggregate: types.Signature{Type: types.KTBLS, Data: []byte("signatureeee")},
BlockSig: types.Signature{Type: types.KTBLS, Data: []byte("block signatureeee")},
BlockSig: &types.Signature{Type: types.KTBLS, Data: []byte("block signatureeee")},
Timestamp: ts,
}
@ -410,3 +612,37 @@ func MakeGenesisBlock(bs bstore.Blockstore, balances map[address.Address]types.B
Genesis: b,
}, nil
}
func AdjustInitActorStartID(ctx context.Context, bs blockstore.Blockstore, stateroot cid.Cid, val uint64) (cid.Cid, error) {
cst := hamt.CSTFromBstore(bs)
tree, err := state.LoadStateTree(cst, stateroot)
if err != nil {
return cid.Undef, err
}
act, err := tree.GetActor(actors.InitAddress)
if err != nil {
return cid.Undef, err
}
var st actors.InitActorState
if err := cst.Get(ctx, act.Head, &st); err != nil {
return cid.Undef, err
}
st.NextID = val
nstate, err := cst.Put(ctx, &st)
if err != nil {
return cid.Undef, err
}
act.Head = nstate
if err := tree.SetActor(actors.InitAddress, act); err != nil {
return cid.Undef, err
}
return tree.Flush()
}

View File

@ -1,6 +1,7 @@
package chain
import (
"bytes"
"context"
"errors"
"sort"
@ -8,6 +9,9 @@ import (
"time"
lru "github.com/hashicorp/golang-lru"
"github.com/ipfs/go-datastore"
"github.com/ipfs/go-datastore/namespace"
"github.com/ipfs/go-datastore/query"
pubsub "github.com/libp2p/go-libp2p-pubsub"
lps "github.com/whyrusleeping/pubsub"
"go.uber.org/multierr"
@ -18,6 +22,7 @@ import (
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/modules/dtypes"
)
var (
@ -35,6 +40,8 @@ var (
const (
msgTopic = "/fil/messages"
localMsgsDs = "/mpool/local"
localUpdates = "update"
)
@ -60,6 +67,8 @@ type MessagePool struct {
blsSigCache *lru.TwoQueueCache
changes *lps.PubSub
localMsgs datastore.Datastore
}
type msgSet struct {
@ -89,7 +98,7 @@ func (ms *msgSet) add(m *types.SignedMessage) error {
return nil
}
func NewMessagePool(sm *stmgr.StateManager, ps *pubsub.PubSub) *MessagePool {
func NewMessagePool(sm *stmgr.StateManager, ps *pubsub.PubSub, ds dtypes.MetadataDS) (*MessagePool, error) {
cache, _ := lru.New2Q(build.BlsSignatureCacheSize)
mp := &MessagePool{
closer: make(chan struct{}),
@ -99,10 +108,18 @@ func NewMessagePool(sm *stmgr.StateManager, ps *pubsub.PubSub) *MessagePool {
sm: sm,
ps: ps,
minGasPrice: types.NewInt(0),
maxTxPoolSize: 100000,
maxTxPoolSize: 5000,
blsSigCache: cache,
changes: lps.New(50),
localMsgs: namespace.Wrap(ds, datastore.NewKey(localMsgsDs)),
}
if err := mp.loadLocal(); err != nil {
return nil, xerrors.Errorf("loading local messages: %w", err)
}
go mp.repubLocal()
sm.ChainStore().SubscribeHeadChanges(func(rev, app []*types.TipSet) error {
err := mp.HeadChange(rev, app)
if err != nil {
@ -111,7 +128,7 @@ func NewMessagePool(sm *stmgr.StateManager, ps *pubsub.PubSub) *MessagePool {
return err
})
return mp
return mp, nil
}
func (mp *MessagePool) Close() error {
@ -134,13 +151,13 @@ func (mp *MessagePool) repubLocal() {
for _, msg := range msgs {
msgb, err := msg.Serialize()
if err != nil {
multierr.Append(errout, xerrors.Errorf("could not serialize: %w", err))
errout = multierr.Append(errout, xerrors.Errorf("could not serialize: %w", err))
continue
}
err = mp.ps.Publish(msgTopic, msgb)
if err != nil {
multierr.Append(errout, xerrors.Errorf("could not publish: %w", err))
errout = multierr.Append(errout, xerrors.Errorf("could not publish: %w", err))
continue
}
}
@ -156,8 +173,14 @@ func (mp *MessagePool) repubLocal() {
}
func (mp *MessagePool) addLocal(a address.Address) {
mp.localAddrs[a] = struct{}{}
func (mp *MessagePool) addLocal(m *types.SignedMessage, msgb []byte) error {
mp.localAddrs[m.Message.From] = struct{}{}
if err := mp.localMsgs.Put(datastore.NewKey(string(m.Cid().Bytes())), msgb); err != nil {
return xerrors.Errorf("persisting local message: %w", err)
}
return nil
}
func (mp *MessagePool) Push(m *types.SignedMessage) error {
@ -171,7 +194,10 @@ func (mp *MessagePool) Push(m *types.SignedMessage) error {
}
mp.lk.Lock()
mp.addLocal(m.Message.From)
if err := mp.addLocal(m, msgb); err != nil {
mp.lk.Unlock()
return err
}
mp.lk.Unlock()
return mp.ps.Publish(msgTopic, msgb)
@ -231,13 +257,20 @@ func (mp *MessagePool) addLocked(m *types.SignedMessage) error {
return err
}
if _, err := mp.sm.ChainStore().PutMessage(&m.Message); err != nil {
log.Warnf("mpooladd cs.PutMessage failed: %s", err)
return err
}
mset, ok := mp.pending[m.Message.From]
if !ok {
mset = newMsgSet()
mp.pending[m.Message.From] = mset
}
mset.add(m)
if err := mset.add(m); err != nil {
log.Error(err)
}
mp.changes.Pub(api.MpoolUpdate{
Type: api.MpoolAdd,
@ -254,12 +287,23 @@ func (mp *MessagePool) GetNonce(addr address.Address) (uint64, error) {
}
func (mp *MessagePool) getNonceLocked(addr address.Address) (uint64, error) {
stateNonce, err := mp.getStateNonce(addr) // sanity check
if err != nil {
return 0, err
}
mset, ok := mp.pending[addr]
if ok {
if stateNonce > mset.nextNonce {
log.Errorf("state nonce was larger than mset.nextNonce (%d > %d)", stateNonce, mset.nextNonce)
return stateNonce, nil
}
return mset.nextNonce, nil
}
return mp.getStateNonce(addr)
return stateNonce, nil
}
func (mp *MessagePool) getStateNonce(addr address.Address) (uint64, error) {
@ -302,7 +346,9 @@ func (mp *MessagePool) PushWithNonce(addr address.Address, cb func(uint64) (*typ
if err := mp.addLocked(msg); err != nil {
return nil, err
}
mp.addLocal(msg.Message.From)
if err := mp.addLocal(msg, msgb); err != nil {
log.Errorf("addLocal failed: %+v", err)
}
return msg, mp.ps.Publish(msgTopic, msgb)
}
@ -328,8 +374,7 @@ func (mp *MessagePool) Remove(from address.Address, nonce uint64) {
delete(mset.msgs, nonce)
if len(mset.msgs) == 0 {
// FIXME: This is racy
//delete(mp.pending, from)
delete(mp.pending, from)
} else {
var max uint64
for nonce := range mset.msgs {
@ -337,6 +382,10 @@ func (mp *MessagePool) Remove(from address.Address, nonce uint64) {
max = nonce
}
}
if max < nonce {
max = nonce // we could have not seen the removed message before
}
mset.nextNonce = max + 1
}
}
@ -380,7 +429,7 @@ func (mp *MessagePool) HeadChange(revert []*types.TipSet, apply []*types.TipSet)
}
for _, msg := range smsgs {
if err := mp.Add(msg); err != nil {
return err
log.Error(err) // TODO: probably lots of spam in multi-block tsets
}
}
@ -388,7 +437,7 @@ func (mp *MessagePool) HeadChange(revert []*types.TipSet, apply []*types.TipSet)
smsg := mp.RecoverSig(msg)
if smsg != nil {
if err := mp.Add(smsg); err != nil {
return err
log.Error(err) // TODO: probably lots of spam in multi-block tsets
}
} else {
log.Warnf("could not recover signature for bls message %s during a reorg revert", msg.Cid())
@ -423,7 +472,7 @@ func (mp *MessagePool) RecoverSig(msg *types.Message) *types.SignedMessage {
}
sig, ok := val.(types.Signature)
if !ok {
log.Warnf("value in signature cache was not a signature (got %T)", val)
log.Errorf("value in signature cache was not a signature (got %T)", val)
return nil
}
@ -456,3 +505,31 @@ func (mp *MessagePool) Updates(ctx context.Context) (<-chan api.MpoolUpdate, err
return out, nil
}
func (mp *MessagePool) loadLocal() error {
res, err := mp.localMsgs.Query(query.Query{})
if err != nil {
return xerrors.Errorf("query local messages: %w", err)
}
for r := range res.Next() {
if r.Error != nil {
return xerrors.Errorf("r.Error: %w", r.Error)
}
var sm types.SignedMessage
if err := sm.UnmarshalCBOR(bytes.NewReader(r.Value)); err != nil {
return xerrors.Errorf("unmarshaling local message: %w", err)
}
if err := mp.Add(&sm); err != nil {
if xerrors.Is(err, ErrNonceTooLow) {
continue // todo: drop the message from local cache (if above certain confidence threshold)
}
return xerrors.Errorf("adding local message: %w", err)
}
}
return nil
}

View File

@ -68,7 +68,7 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types.
state := ts.ParentState()
r := store.NewChainRand(sm.cs, ts.Cids(), ts.Height(), nil)
r := store.NewChainRand(sm.cs, ts.Cids(), ts.Height())
return sm.CallRaw(ctx, msg, state, r, ts.Height())
}

View File

@ -15,7 +15,7 @@ import (
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
bls "github.com/filecoin-project/go-bls-sigs"
bls "github.com/filecoin-project/filecoin-ffi"
"github.com/ipfs/go-cid"
hamt "github.com/ipfs/go-hamt-ipld"
logging "github.com/ipfs/go-log"
@ -102,7 +102,7 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
cids[i] = v.Cid()
}
r := store.NewChainRand(sm.cs, cids, blks[0].Height, nil)
r := store.NewChainRand(sm.cs, cids, blks[0].Height)
vmi, err := vm.NewVM(pstate, blks[0].Height, r, address.Undef, sm.cs.Blockstore())
if err != nil {
@ -113,9 +113,14 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
if err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("failed to get network actor: %w", err)
}
reward := vm.MiningReward(netact.Balance)
for _, b := range blks {
netact, err = vmi.StateTree().GetActor(actors.NetworkAddress)
if err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("failed to get network actor: %w", err)
}
vmi.SetBlockMiner(b.Miner)
owner, err := GetMinerOwner(ctx, sm, pstate, b.Miner)
if err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("failed to get owner for miner %s: %w", b.Miner, err)
@ -130,6 +135,23 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
return cid.Undef, cid.Undef, xerrors.Errorf("failed to deduct funds from network actor: %w", err)
}
// all block miners created a valid post, go update the actor state
postSubmitMsg := &types.Message{
From: actors.NetworkAddress,
Nonce: netact.Nonce,
To: b.Miner,
Method: actors.MAMethods.SubmitElectionPoSt,
GasPrice: types.NewInt(0),
GasLimit: types.NewInt(10000000000),
Value: types.NewInt(0),
}
ret, err := vmi.ApplyMessage(ctx, postSubmitMsg)
if err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("submit election post message invocation failed: %w", err)
}
if ret.ExitCode != 0 {
return cid.Undef, cid.Undef, xerrors.Errorf("submit election post invocation returned nonzero exit code: %d", ret.ExitCode)
}
}
// TODO: can't use method from chainstore because it doesnt let us know who the block miners were
@ -322,7 +344,12 @@ func (sm *StateManager) GetBlsPublicKey(ctx context.Context, addr address.Addres
}
func (sm *StateManager) GetReceipt(ctx context.Context, msg cid.Cid, ts *types.TipSet) (*types.MessageReceipt, error) {
r, err := sm.tipsetExecutedMessage(ts, msg)
m, err := sm.cs.GetCMessage(msg)
if err != nil {
return nil, fmt.Errorf("failed to load message: %w", err)
}
r, err := sm.tipsetExecutedMessage(ts, msg, m.VMMessage())
if err != nil {
return nil, err
}
@ -331,11 +358,6 @@ func (sm *StateManager) GetReceipt(ctx context.Context, msg cid.Cid, ts *types.T
return r, nil
}
m, err := sm.cs.GetCMessage(msg)
if err != nil {
return nil, fmt.Errorf("failed to load message: %w", err)
}
_, r, err = sm.searchBackForMsg(ctx, ts, m)
if err != nil {
return nil, fmt.Errorf("failed to look back through chain for message: %w", err)
@ -368,7 +390,7 @@ func (sm *StateManager) WaitForMessage(ctx context.Context, mcid cid.Cid) (*type
return nil, nil, fmt.Errorf("expected current head on SHC stream (got %s)", head[0].Type)
}
r, err := sm.tipsetExecutedMessage(head[0].Val, mcid)
r, err := sm.tipsetExecutedMessage(head[0].Val, mcid, msg.VMMessage())
if err != nil {
return nil, nil, err
}
@ -403,7 +425,7 @@ func (sm *StateManager) WaitForMessage(ctx context.Context, mcid cid.Cid) (*type
case store.HCRevert:
continue
case store.HCApply:
r, err := sm.tipsetExecutedMessage(val.Val, mcid)
r, err := sm.tipsetExecutedMessage(val.Val, mcid, msg.VMMessage())
if err != nil {
return nil, nil, err
}
@ -454,7 +476,7 @@ func (sm *StateManager) searchBackForMsg(ctx context.Context, from *types.TipSet
return nil, nil, fmt.Errorf("failed to load tipset during msg wait searchback: %w", err)
}
r, err := sm.tipsetExecutedMessage(ts, m.Cid())
r, err := sm.tipsetExecutedMessage(ts, m.Cid(), m.VMMessage())
if err != nil {
return nil, nil, fmt.Errorf("checking for message execution during lookback: %w", err)
}
@ -467,7 +489,7 @@ func (sm *StateManager) searchBackForMsg(ctx context.Context, from *types.TipSet
}
}
func (sm *StateManager) tipsetExecutedMessage(ts *types.TipSet, msg cid.Cid) (*types.MessageReceipt, error) {
func (sm *StateManager) tipsetExecutedMessage(ts *types.TipSet, msg cid.Cid, vmm *types.Message) (*types.MessageReceipt, error) {
// The genesis block did not execute any messages
if ts.Height() == 0 {
return nil, nil
@ -483,9 +505,24 @@ func (sm *StateManager) tipsetExecutedMessage(ts *types.TipSet, msg cid.Cid) (*t
return nil, err
}
for i, m := range cm {
if m.Cid() == msg {
return sm.cs.GetParentReceipt(ts.Blocks()[0], i)
for ii := range cm {
// iterate in reverse because we going backwards through the chain
i := len(cm) - ii - 1
m := cm[i]
if m.VMMessage().From == vmm.From { // cheaper to just check origin first
if m.VMMessage().Nonce == vmm.Nonce {
if m.Cid() == msg {
return sm.cs.GetParentReceipt(ts.Blocks()[0], i)
}
// this should be that message
return nil, xerrors.Errorf("found message with equal nonce as the one we are looking for (F:%s n %d, TS: %s n%d)",
msg, vmm.Nonce, m.Cid(), m.VMMessage().Nonce)
}
if m.VMMessage().Nonce < vmm.Nonce {
return nil, nil // don't bother looking further
}
}
}

View File

@ -3,10 +3,13 @@ package stmgr
import (
"context"
ffi "github.com/filecoin-project/filecoin-ffi"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/sectorbuilder"
amt "github.com/filecoin-project/go-amt-ipld"
cid "github.com/ipfs/go-cid"
@ -147,21 +150,21 @@ func GetMinerWorker(ctx context.Context, sm *StateManager, ts *types.TipSet, mad
return address.NewFromBytes(recp.Return)
}
func GetMinerProvingPeriodEnd(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (uint64, error) {
func GetMinerElectionPeriodStart(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (uint64, error) {
var mas actors.StorageMinerActorState
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil {
return 0, xerrors.Errorf("failed to load miner actor state: %w", err)
return 0, xerrors.Errorf("(get eps) failed to load miner actor state: %w", err)
}
return mas.ProvingPeriodEnd, nil
return mas.ElectionPeriodStart, nil
}
func GetMinerProvingSet(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) ([]*api.ChainSectorInfo, error) {
var mas actors.StorageMinerActorState
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil {
return nil, xerrors.Errorf("failed to load miner actor state: %w", err)
return nil, xerrors.Errorf("(get pset) failed to load miner actor state: %w", err)
}
return LoadSectorsFromSet(ctx, sm.ChainStore().Blockstore(), mas.ProvingSet)
@ -171,17 +174,37 @@ func GetMinerSectorSet(ctx context.Context, sm *StateManager, ts *types.TipSet,
var mas actors.StorageMinerActorState
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil {
return nil, xerrors.Errorf("failed to load miner actor state: %w", err)
return nil, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
}
return LoadSectorsFromSet(ctx, sm.ChainStore().Blockstore(), mas.Sectors)
}
func GetSectorsForElectionPost(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (*sectorbuilder.SortedPublicSectorInfo, error) {
sectors, err := GetMinerProvingSet(ctx, sm, ts, maddr)
if err != nil {
return nil, xerrors.Errorf("failed to get sector set for miner: %w", err)
}
var uselessOtherArray []ffi.PublicSectorInfo
for _, s := range sectors {
var uselessBuffer [32]byte
copy(uselessBuffer[:], s.CommR)
uselessOtherArray = append(uselessOtherArray, ffi.PublicSectorInfo{
SectorID: s.SectorID,
CommR: uselessBuffer,
})
}
ssi := sectorbuilder.NewSortedPublicSectorInfo(uselessOtherArray)
return &ssi, nil
}
func GetMinerSectorSize(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (uint64, error) {
var mas actors.StorageMinerActorState
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil {
return 0, xerrors.Errorf("failed to load miner actor state: %w", err)
return 0, xerrors.Errorf("(get ssize) failed to load miner actor state: %w", err)
}
cst := hamt.CSTFromBstore(sm.cs.Blockstore())
@ -197,7 +220,7 @@ func GetMinerSlashed(ctx context.Context, sm *StateManager, ts *types.TipSet, ma
var mas actors.StorageMinerActorState
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil {
return 0, xerrors.Errorf("failed to load miner actor state: %w", err)
return 0, xerrors.Errorf("(get mslash) failed to load miner actor state: %w", err)
}
return mas.SlashedAt, nil

View File

@ -3,8 +3,8 @@ package store
import (
"context"
"crypto/sha256"
"encoding/binary"
"encoding/json"
"fmt"
"sync"
"github.com/filecoin-project/lotus/build"
@ -12,7 +12,7 @@ import (
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/vm"
"go.opencensus.io/trace"
"go.uber.org/zap"
"go.uber.org/multierr"
amt "github.com/filecoin-project/go-amt-ipld"
"github.com/filecoin-project/lotus/chain/types"
@ -24,7 +24,6 @@ import (
hamt "github.com/ipfs/go-hamt-ipld"
bstore "github.com/ipfs/go-ipfs-blockstore"
logging "github.com/ipfs/go-log"
"github.com/pkg/errors"
cbg "github.com/whyrusleeping/cbor-gen"
pubsub "github.com/whyrusleeping/pubsub"
"golang.org/x/xerrors"
@ -100,12 +99,12 @@ func (cs *ChainStore) Load() error {
return nil
}
if err != nil {
return errors.Wrap(err, "failed to load chain state from datastore")
return xerrors.Errorf("failed to load chain state from datastore: %w", err)
}
var tscids []cid.Cid
if err := json.Unmarshal(head, &tscids); err != nil {
return errors.Wrap(err, "failed to unmarshal stored chain head")
return xerrors.Errorf("failed to unmarshal stored chain head: %w", err)
}
ts, err := cs.LoadTipSet(tscids)
@ -121,11 +120,11 @@ func (cs *ChainStore) Load() error {
func (cs *ChainStore) writeHead(ts *types.TipSet) error {
data, err := json.Marshal(ts.Cids())
if err != nil {
return errors.Wrap(err, "failed to marshal tipset")
return xerrors.Errorf("failed to marshal tipset: %w", err)
}
if err := cs.ds.Put(chainHeadKey, data); err != nil {
return errors.Wrap(err, "failed to write chain head to datastore")
return xerrors.Errorf("failed to write chain head to datastore: %w", err)
}
return nil
@ -209,7 +208,7 @@ func (cs *ChainStore) PutTipSet(ctx context.Context, ts *types.TipSet) error {
log.Debugf("expanded %s into %s\n", ts.Cids(), expanded.Cids())
if err := cs.MaybeTakeHeavierTipSet(ctx, expanded); err != nil {
return errors.Wrap(err, "MaybeTakeHeavierTipSet failed in PutTipSet")
return xerrors.Errorf("MaybeTakeHeavierTipSet failed in PutTipSet: %w", err)
}
return nil
}
@ -429,17 +428,32 @@ func (cs *ChainStore) AddToTipSetTracker(b *types.BlockHeader) error {
return nil
}
func (cs *ChainStore) PersistBlockHeaders(b ...*types.BlockHeader) (err error) {
func (cs *ChainStore) PersistBlockHeaders(b ...*types.BlockHeader) error {
sbs := make([]block.Block, len(b))
for i, header := range b {
var err error
sbs[i], err = header.ToStorageBlock()
if err != nil {
return err
}
}
return cs.bs.PutMany(sbs)
batchSize := 256
calls := len(b) / batchSize
var err error
for i := 0; i <= calls; i++ {
start := batchSize * i
end := start + batchSize
if end > len(b) {
end = len(b)
}
err = multierr.Append(err, cs.bs.PutMany(sbs[start:end]))
}
return err
}
type storable interface {
@ -507,7 +521,7 @@ func (cs *ChainStore) AddBlock(ctx context.Context, b *types.BlockHeader) error
}
if err := cs.MaybeTakeHeavierTipSet(ctx, ts); err != nil {
return errors.Wrap(err, "MaybeTakeHeavierTipSet failed")
return xerrors.Errorf("MaybeTakeHeavierTipSet failed: %w", err)
}
return nil
@ -537,6 +551,9 @@ func (cs *ChainStore) GetCMessage(c cid.Cid) (ChainMsg, error) {
if err == nil {
return m, nil
}
if err != bstore.ErrNotFound {
log.Warn("GetCMessage: unexpected error getting unsigned message: %s", err)
}
return cs.GetSignedMessage(c)
}
@ -667,12 +684,12 @@ func (cs *ChainStore) readMsgMetaCids(mmc cid.Cid) ([]cid.Cid, []cid.Cid, error)
blscids, err := cs.readAMTCids(msgmeta.BlsMessages)
if err != nil {
return nil, nil, errors.Wrap(err, "loading bls message cids for block")
return nil, nil, xerrors.Errorf("loading bls message cids for block: %w", err)
}
secpkcids, err := cs.readAMTCids(msgmeta.SecpkMessages)
if err != nil {
return nil, nil, errors.Wrap(err, "loading secpk message cids for block")
return nil, nil, xerrors.Errorf("loading secpk message cids for block: %w", err)
}
cs.mmCache.Add(mmc, &mmCids{
@ -691,12 +708,12 @@ func (cs *ChainStore) MessagesForBlock(b *types.BlockHeader) ([]*types.Message,
blsmsgs, err := cs.LoadMessagesFromCids(blscids)
if err != nil {
return nil, nil, errors.Wrap(err, "loading bls messages for block")
return nil, nil, xerrors.Errorf("loading bls messages for block: %w", err)
}
secpkmsgs, err := cs.LoadSignedMessagesFromCids(secpkcids)
if err != nil {
return nil, nil, errors.Wrap(err, "loading secpk messages for block")
return nil, nil, xerrors.Errorf("loading secpk messages for block: %w", err)
}
return blsmsgs, secpkmsgs, nil
@ -706,7 +723,7 @@ func (cs *ChainStore) GetParentReceipt(b *types.BlockHeader, i int) (*types.Mess
bs := amt.WrapBlockstore(cs.bs)
a, err := amt.LoadAMT(bs, b.ParentMessageReceipts)
if err != nil {
return nil, errors.Wrap(err, "amt load")
return nil, xerrors.Errorf("amt load: %w", err)
}
var r types.MessageReceipt
@ -722,7 +739,7 @@ func (cs *ChainStore) LoadMessagesFromCids(cids []cid.Cid) ([]*types.Message, er
for i, c := range cids {
m, err := cs.GetMessage(c)
if err != nil {
return nil, errors.Wrapf(err, "failed to get message: (%s):%d", c, i)
return nil, xerrors.Errorf("failed to get message: (%s):%d: %w", err, c, i)
}
msgs = append(msgs, m)
@ -736,7 +753,7 @@ func (cs *ChainStore) LoadSignedMessagesFromCids(cids []cid.Cid) ([]*types.Signe
for i, c := range cids {
m, err := cs.GetSignedMessage(c)
if err != nil {
return nil, errors.Wrapf(err, "failed to get message: (%s):%d", c, i)
return nil, xerrors.Errorf("failed to get message: (%s):%d: %w", err, c, i)
}
msgs = append(msgs, m)
@ -771,24 +788,21 @@ func (cs *ChainStore) TryFillTipSet(ts *types.TipSet) (*FullTipSet, error) {
return NewFullTipSet(out), nil
}
func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, tickets []*types.Ticket, lb int64) ([]byte, error) {
func drawRandomness(t *types.Ticket, round int64) []byte {
h := sha256.New()
var buf [8]byte
binary.LittleEndian.PutUint64(buf[:], uint64(round))
h.Write(t.VRFProof)
h.Write(buf[:])
return h.Sum(nil)
}
func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, round int64) ([]byte, error) {
ctx, span := trace.StartSpan(ctx, "store.GetRandomness")
defer span.End()
span.AddAttributes(trace.Int64Attribute("lb", lb))
if lb < 0 {
return nil, fmt.Errorf("negative lookback parameters are not valid (got %d)", lb)
}
lt := int64(len(tickets))
if lb < lt {
log.Desugar().Warn("self sampling randomness. this should be extremely rare, if you see this often it may be a bug", zap.Stack("stacktrace"))
t := tickets[lt-(1+lb)]
return t.VRFProof, nil
}
nv := lb - lt
span.AddAttributes(trace.Int64Attribute("round", round))
for {
nts, err := cs.LoadTipSet(blks)
@ -797,26 +811,21 @@ func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, tickets
}
mtb := nts.MinTicketBlock()
lt := int64(len(mtb.Tickets))
if nv < lt {
t := mtb.Tickets[lt-(1+nv)]
return t.VRFProof, nil
}
nv -= lt
if int64(nts.Height()) <= round {
return drawRandomness(nts.MinTicketBlock().Ticket, round), nil
}
// special case for lookback behind genesis block
// TODO(spec): this is not in the spec, need to sync that
if mtb.Height == 0 {
t := mtb.Tickets[0]
// round is negative
thash := drawRandomness(mtb.Ticket, round*-1)
rval := t.VRFProof
for i := int64(0); i < nv; i++ {
h := sha256.Sum256(rval)
rval = h[:]
}
return rval, nil
// for negative lookbacks, just use the hash of the positive tickethash value
h := sha256.Sum256(thash)
return h[:], nil
}
blks = mtb.Parents
@ -837,36 +846,33 @@ func (cs *ChainStore) GetTipsetByHeight(ctx context.Context, h uint64, ts *types
}
for {
mtb := ts.MinTicketBlock()
if h >= ts.Height()-uint64(len(mtb.Tickets)) {
return ts, nil
}
pts, err := cs.LoadTipSet(ts.Parents())
if err != nil {
return nil, err
}
if h > pts.Height() {
return ts, nil
}
ts = pts
}
}
type chainRand struct {
cs *ChainStore
blks []cid.Cid
bh uint64
tickets []*types.Ticket
cs *ChainStore
blks []cid.Cid
bh uint64
}
func NewChainRand(cs *ChainStore, blks []cid.Cid, bheight uint64, tickets []*types.Ticket) vm.Rand {
func NewChainRand(cs *ChainStore, blks []cid.Cid, bheight uint64) vm.Rand {
return &chainRand{
cs: cs,
blks: blks,
bh: bheight,
tickets: tickets,
cs: cs,
blks: blks,
bh: bheight,
}
}
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)
func (cr *chainRand) GetRandomness(ctx context.Context, round int64) ([]byte, error) {
return cr.cs.GetRandomness(ctx, cr.blks, round)
}

View File

@ -2,12 +2,13 @@ package store
import (
"context"
"math/big"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
"golang.org/x/xerrors"
"math/big"
)
var zero = types.NewInt(0)
@ -39,6 +40,7 @@ func (cs *ChainStore) Weight(ctx context.Context, ts *types.TipSet) (types.BigIn
log2P = int64(tpow.BitLen() - 1)
} else {
// Not really expect to be here ...
panic("where are we")
return types.EmptyInt, xerrors.Errorf("All power in the net is gone. You network might be disconnected, or the net is dead!")
}
@ -57,7 +59,7 @@ func (cs *ChainStore) Weight(ctx context.Context, ts *types.TipSet) (types.BigIn
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)
r := NewChainRand(cs, ts.Cids(), ts.Height())
vmi, err := vm.NewVM(bstate, ts.Height(), r, actors.NetworkAddress, cs.bs)
if err != nil {

View File

@ -3,14 +3,15 @@ package chain
import (
"bytes"
"context"
"crypto/sha256"
"errors"
"fmt"
"sync"
"time"
"github.com/Gurpartap/async"
bls "github.com/filecoin-project/filecoin-ffi"
amt "github.com/filecoin-project/go-amt-ipld"
"github.com/filecoin-project/go-bls-sigs"
"github.com/hashicorp/go-multierror"
"github.com/ipfs/go-cid"
dstore "github.com/ipfs/go-datastore"
@ -28,10 +29,12 @@ import (
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/blocksync"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/sectorbuilder"
)
var log = logging.Logger("chain")
@ -506,33 +509,8 @@ func (syncer *Syncer) minerIsValid(ctx context.Context, maddr address.Address, b
return nil
}
func (syncer *Syncer) validateTickets(ctx context.Context, mworker address.Address, tickets []*types.Ticket, base *types.TipSet) error {
ctx, span := trace.StartSpan(ctx, "validateTickets")
defer span.End()
span.AddAttributes(trace.Int64Attribute("tickets", int64(len(tickets))))
if len(tickets) == 0 {
return xerrors.Errorf("block had no tickets")
}
cur := base.MinTicket()
for i := 0; i < len(tickets); i++ {
next := tickets[i]
sig := &types.Signature{
Type: types.KTBLS,
Data: next.VRFProof,
}
// TODO: ticket signatures should also include miner address
if err := sig.Verify(mworker, cur.VRFProof); err != nil {
return xerrors.Errorf("invalid ticket, VRFProof invalid: %w", err)
}
cur = next
}
return nil
func (syncer *Syncer) validateTicket(ctx context.Context, maddr, mworker address.Address, ticket *types.Ticket, base *types.TipSet) error {
return gen.VerifyVRF(ctx, mworker, maddr, gen.DSepTicket, base.MinTicket().VRFProof, ticket.VRFProof)
}
var ErrTemporal = errors.New("temporal error")
@ -541,6 +519,9 @@ var ErrTemporal = errors.New("temporal error")
func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) error {
ctx, span := trace.StartSpan(ctx, "validateBlock")
defer span.End()
if build.InsecurePoStValidation {
log.Warn("insecure test validation is enabled, if you see this outside of a test, it is a severe bug!")
}
h := b.Header
@ -550,23 +531,34 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
}
// fast checks first
if h.BlockSig == nil {
return xerrors.Errorf("block had nil signature")
}
if h.Timestamp > uint64(time.Now().Unix()+build.AllowableClockDrift) {
return xerrors.Errorf("block was from the future")
}
if h.Timestamp < baseTs.MinTimestamp()+uint64(build.BlockDelay*len(h.Tickets)) {
log.Warn("timestamp funtimes: ", h.Timestamp, baseTs.MinTimestamp(), len(h.Tickets))
return xerrors.Errorf("block was generated too soon (h.ts:%d < base.mints:%d + BLOCK_DELAY:%d * tkts.len:%d)", h.Timestamp, baseTs.MinTimestamp(), build.BlockDelay, len(h.Tickets))
if h.Timestamp < baseTs.MinTimestamp()+(build.BlockDelay*(h.Height-baseTs.Height())) {
log.Warn("timestamp funtimes: ", h.Timestamp, baseTs.MinTimestamp(), h.Height, baseTs.Height())
return xerrors.Errorf("block was generated too soon (h.ts:%d < base.mints:%d + BLOCK_DELAY:%d * deltaH:%d)", h.Timestamp, baseTs.MinTimestamp(), build.BlockDelay, h.Height-baseTs.Height())
}
winnerCheck := async.Err(func() error {
mpow, tpow, err := stmgr.GetPower(ctx, syncer.sm, baseTs, h.Miner)
_, tpow, err := stmgr.GetPower(ctx, syncer.sm, baseTs, h.Miner)
if err != nil {
return xerrors.Errorf("failed getting power: %w", err)
}
if !types.PowerCmp(h.ElectionProof, mpow, tpow) {
return xerrors.Errorf("miner created a block but was not a winner")
ssize, err := stmgr.GetMinerSectorSize(ctx, syncer.sm, baseTs, h.Miner)
if err != nil {
return xerrors.Errorf("failed to get sector size for block miner: %w", err)
}
for _, t := range h.EPostProof.Candidates {
if !types.IsTicketWinner(t.Partial, ssize, tpow, 1) {
return xerrors.Errorf("miner created a block but was not a winner")
}
}
return nil
})
@ -623,20 +615,20 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
})
tktsCheck := async.Err(func() error {
if err := syncer.validateTickets(ctx, waddr, h.Tickets, baseTs); err != nil {
vrfBase := baseTs.MinTicket().VRFProof
err := gen.VerifyVRF(ctx, waddr, h.Miner, gen.DSepTicket, vrfBase, h.Ticket.VRFProof)
if err != nil {
log.Warnf("BAD TICKET: %d %x %x %s %s %x", h.Height, h.Ticket.VRFProof, vrfBase, waddr, h.Miner, baseTs.MinTicket().VRFProof)
return xerrors.Errorf("validating block tickets failed: %w", err)
}
return nil
})
eproofCheck := async.Err(func() error {
rand, err := syncer.sm.ChainStore().GetRandomness(ctx, baseTs.Cids(), h.Tickets, build.EcRandomnessLookback)
if err != nil {
return xerrors.Errorf("failed to get randomness for verifying election proof: %w", err)
}
if err := VerifyElectionProof(ctx, h.ElectionProof, rand, waddr); err != nil {
return xerrors.Errorf("checking eproof failed: %w", err)
if err := syncer.VerifyElectionPoStProof(ctx, h, baseTs, waddr); err != nil {
return xerrors.Errorf("invalid election post: %w", err)
}
return nil
})
@ -660,6 +652,56 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
return merr
}
func (syncer *Syncer) VerifyElectionPoStProof(ctx context.Context, h *types.BlockHeader, baseTs *types.TipSet, waddr address.Address) error {
rand, err := syncer.sm.ChainStore().GetRandomness(ctx, baseTs.Cids(), int64(h.Height-build.EcRandomnessLookback))
if err != nil {
return xerrors.Errorf("failed to get randomness for verifying election proof: %w", err)
}
if err := VerifyElectionPoStVRF(ctx, h.EPostProof.PostRand, rand, waddr, h.Miner); err != nil {
return xerrors.Errorf("checking eproof failed: %w", err)
}
ssize, err := stmgr.GetMinerSectorSize(ctx, syncer.sm, baseTs, h.Miner)
if err != nil {
return xerrors.Errorf("failed to get sector size for miner: %w", err)
}
var winners []sectorbuilder.EPostCandidate
for _, t := range h.EPostProof.Candidates {
var partial [32]byte
copy(partial[:], t.Partial)
winners = append(winners, sectorbuilder.EPostCandidate{
PartialTicket: partial,
SectorID: t.SectorID,
SectorChallengeIndex: t.ChallengeIndex,
})
}
sectorInfo, err := stmgr.GetSectorsForElectionPost(ctx, syncer.sm, baseTs, h.Miner)
if err != nil {
return xerrors.Errorf("getting election post sector set: %w", err)
}
if build.InsecurePoStValidation {
if string(h.EPostProof.Proof) == "valid proof" {
return nil
}
return xerrors.Errorf("[TESTING] election post was invalid")
}
hvrf := sha256.Sum256(h.EPostProof.PostRand)
ok, err := sectorbuilder.VerifyElectionPost(ctx, ssize, *sectorInfo, hvrf[:], h.EPostProof.Proof, winners, h.Miner)
if err != nil {
return xerrors.Errorf("failed to verify election post: %w", err)
}
if !ok {
return xerrors.Errorf("election post was invalid")
}
return nil
}
func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock, baseTs *types.TipSet) error {
nonces := make(map[address.Address]uint64)
balances := make(map[address.Address]types.BigInt)
@ -1103,14 +1145,9 @@ func (syncer *Syncer) collectChain(ctx context.Context, ts *types.TipSet) error
return nil
}
func VerifyElectionProof(ctx context.Context, eproof []byte, rand []byte, worker address.Address) error {
sig := types.Signature{
Data: eproof,
Type: types.KTBLS,
}
if err := sig.Verify(worker, rand); err != nil {
return xerrors.Errorf("failed to verify election proof signature: %w", err)
func VerifyElectionPoStVRF(ctx context.Context, evrf []byte, rand []byte, worker, miner address.Address) error {
if err := gen.VerifyVRF(ctx, worker, miner, gen.DSepElectionPost, rand, evrf); err != nil {
return xerrors.Errorf("failed to verify post_randomness vrf: %w", err)
}
return nil

View File

@ -23,6 +23,10 @@ import (
"github.com/filecoin-project/lotus/node/repo"
)
func init() {
build.InsecurePoStValidation = true
}
const source = 0
func (tu *syncTestUtil) repoWithChain(t testing.TB, h int) (repo.Repo, []byte, []*store.FullTipSet) {
@ -342,7 +346,7 @@ func (tu *syncTestUtil) waitUntilSyncTarget(to int, target *types.TipSet) {
}
func TestSyncSimple(t *testing.T) {
H := 50
H := 2
tu := prepSyncTest(t, H)
client := tu.addClientNode()
@ -390,7 +394,7 @@ func TestSyncBadTimestamp(t *testing.T) {
tu.waitUntilSync(0, client)
base := tu.g.CurTipset
tu.g.Timestamper = func(pts *types.TipSet, tl int) uint64 {
tu.g.Timestamper = func(pts *types.TipSet, tl uint64) uint64 {
return pts.MinTimestamp() + (build.BlockDelay / 2)
}

View File

@ -20,14 +20,24 @@ type Ticket struct {
VRFProof []byte
}
type ElectionProof []byte
type EPostTicket struct {
Partial []byte
SectorID uint64
ChallengeIndex uint64
}
type EPostProof struct {
Proof []byte
PostRand []byte
Candidates []EPostTicket
}
type BlockHeader struct {
Miner address.Address
Tickets []*Ticket
Ticket *Ticket
ElectionProof []byte
EPostProof EPostProof
Parents []cid.Cid
@ -45,7 +55,7 @@ type BlockHeader struct {
Timestamp uint64
BlockSig Signature
BlockSig *Signature
}
func (b *BlockHeader) ToStorageBlock() (block.Block, error) {
@ -91,12 +101,12 @@ func (blk *BlockHeader) Serialize() ([]byte, error) {
}
func (blk *BlockHeader) LastTicket() *Ticket {
return blk.Tickets[len(blk.Tickets)-1]
return blk.Ticket
}
func (blk *BlockHeader) SigningBytes() ([]byte, error) {
blkcopy := *blk
blkcopy.BlockSig = Signature{}
blkcopy.BlockSig = nil
return blkcopy.Serialize()
}
@ -162,29 +172,31 @@ func CidArrsEqual(a, b []cid.Cid) bool {
var blocksPerEpoch = NewInt(build.BlocksPerEpoch)
func PowerCmp(eproof ElectionProof, mpow, totpow BigInt) bool {
func IsTicketWinner(partialTicket []byte, ssizeI uint64, totpow BigInt, sampleRate int64) bool {
ssize := NewInt(ssizeI)
/*
Need to check that
(h(vrfout) + 1) / (max(h) + 1) <= e * minerPower / totalPower
(h(vrfout) + 1) / (max(h) + 1) <= e * sectorSize / totalPower
max(h) == 2^256-1
which in terms of integer math means:
(h(vrfout) + 1) * totalPower <= e * minerPower * 2^256
(h(vrfout) + 1) * totalPower <= e * sectorSize * 2^256
in 2^256 space, it is equivalent to:
h(vrfout) * totalPower < e * minerPower * 2^256
h(vrfout) * totalPower < e * sectorSize * 2^256
*/
h := sha256.Sum256(eproof)
h := sha256.Sum256(partialTicket)
lhs := BigFromBytes(h[:]).Int
lhs = lhs.Mul(lhs, totpow.Int)
lhs = lhs.Mul(lhs, big.NewInt(sampleRate))
// rhs = minerPower * 2^256
// rhs = minerPower << 256
rhs := new(big.Int).Lsh(mpow.Int, 256)
// rhs = sectorSize * 2^256
// rhs = sectorSize << 256
rhs := new(big.Int).Lsh(ssize.Int, 256)
rhs = rhs.Mul(rhs, blocksPerEpoch.Int)
// h(vrfout) * totalPower < e * minerPower * 2^256?
// h(vrfout) * totalPower < e * sectorSize * 2^256?
return lhs.Cmp(rhs) == -1
}

View File

@ -2,6 +2,7 @@ package types
import (
"bytes"
"fmt"
"reflect"
"testing"
@ -23,12 +24,13 @@ func testBlockHeader(t testing.TB) *BlockHeader {
}
return &BlockHeader{
Miner: addr,
ElectionProof: []byte("cats won the election"),
Tickets: []*Ticket{
&Ticket{
VRFProof: []byte("vrf proof0000000vrf proof0000000"),
},
Miner: addr,
EPostProof: EPostProof{
Proof: []byte("pruuf"),
PostRand: []byte("random"),
},
Ticket: &Ticket{
VRFProof: []byte("vrf proof0000000vrf proof0000000"),
},
Parents: []cid.Cid{c, c},
ParentMessageReceipts: c,
@ -37,7 +39,7 @@ func testBlockHeader(t testing.TB) *BlockHeader {
Messages: c,
Height: 85919298723,
ParentStateRoot: c,
BlockSig: Signature{Type: KTBLS, Data: []byte("boo! im a signature")},
BlockSig: &Signature{Type: KTBLS, Data: []byte("boo! im a signature")},
}
}
@ -55,6 +57,8 @@ func TestBlockHeaderSerialization(t *testing.T) {
}
if !reflect.DeepEqual(&out, bh) {
fmt.Printf("%#v\n", &out)
fmt.Printf("%#v\n", bh)
t.Fatal("not equal")
}
}

View File

@ -5,7 +5,7 @@ import (
"io"
"math"
cid "github.com/ipfs/go-cid"
"github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
xerrors "golang.org/x/xerrors"
)
@ -28,21 +28,13 @@ func (t *BlockHeader) MarshalCBOR(w io.Writer) error {
return err
}
// t.t.Tickets ([]*types.Ticket) (slice)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Tickets)))); err != nil {
// t.t.Ticket (types.Ticket) (struct)
if err := t.Ticket.MarshalCBOR(w); err != nil {
return err
}
for _, v := range t.Tickets {
if err := v.MarshalCBOR(w); err != nil {
return err
}
}
// t.t.ElectionProof ([]uint8) (slice)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.ElectionProof)))); err != nil {
return err
}
if _, err := w.Write(t.ElectionProof); err != nil {
// t.t.EPostProof (types.EPostProof) (struct)
if err := t.EPostProof.MarshalCBOR(w); err != nil {
return err
}
@ -125,48 +117,35 @@ func (t *BlockHeader) UnmarshalCBOR(r io.Reader) error {
}
}
// t.t.Tickets ([]*types.Ticket) (slice)
// t.t.Ticket (types.Ticket) (struct)
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if extra > 8192 {
return fmt.Errorf("t.Tickets: array too large (%d)", extra)
}
{
if maj != cbg.MajArray {
return fmt.Errorf("expected cbor array")
}
if extra > 0 {
t.Tickets = make([]*Ticket, extra)
}
for i := 0; i < int(extra); i++ {
pb, err := br.PeekByte()
if err != nil {
return err
}
if pb == cbg.CborNull[0] {
var nbuf [1]byte
if _, err := br.Read(nbuf[:]); err != nil {
return err
}
} else {
t.Ticket = new(Ticket)
if err := t.Ticket.UnmarshalCBOR(br); err != nil {
return err
}
}
var v Ticket
if err := v.UnmarshalCBOR(br); err != nil {
}
// t.t.EPostProof (types.EPostProof) (struct)
{
if err := t.EPostProof.UnmarshalCBOR(br); err != nil {
return err
}
t.Tickets[i] = &v
}
// t.t.ElectionProof ([]uint8) (slice)
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if extra > 8192 {
return fmt.Errorf("t.ElectionProof: array too large (%d)", extra)
}
if maj != cbg.MajByteString {
return fmt.Errorf("expected byte array")
}
t.ElectionProof = make([]byte, extra)
if _, err := io.ReadFull(br, t.ElectionProof); err != nil {
return err
}
// t.t.Parents ([]cid.Cid) (slice)
@ -271,9 +250,21 @@ func (t *BlockHeader) UnmarshalCBOR(r io.Reader) error {
{
if err := t.BlockSig.UnmarshalCBOR(br); err != nil {
pb, err := br.PeekByte()
if err != nil {
return err
}
if pb == cbg.CborNull[0] {
var nbuf [1]byte
if _, err := br.Read(nbuf[:]); err != nil {
return err
}
} else {
t.BlockSig = new(Signature)
if err := t.BlockSig.UnmarshalCBOR(br); err != nil {
return err
}
}
}
return nil
@ -333,6 +324,205 @@ func (t *Ticket) UnmarshalCBOR(r io.Reader) error {
return nil
}
func (t *EPostProof) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)
return err
}
if _, err := w.Write([]byte{131}); err != nil {
return err
}
// t.t.Proof ([]uint8) (slice)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Proof)))); err != nil {
return err
}
if _, err := w.Write(t.Proof); err != nil {
return err
}
// t.t.PostRand ([]uint8) (slice)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.PostRand)))); err != nil {
return err
}
if _, err := w.Write(t.PostRand); err != nil {
return err
}
// t.t.Candidates ([]types.EPostTicket) (slice)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Candidates)))); err != nil {
return err
}
for _, v := range t.Candidates {
if err := v.MarshalCBOR(w); err != nil {
return err
}
}
return nil
}
func (t *EPostProof) UnmarshalCBOR(r io.Reader) error {
br := cbg.GetPeeker(r)
maj, extra, err := cbg.CborReadHeader(br)
if err != nil {
return err
}
if maj != cbg.MajArray {
return fmt.Errorf("cbor input should be of type array")
}
if extra != 3 {
return fmt.Errorf("cbor input had wrong number of fields")
}
// t.t.Proof ([]uint8) (slice)
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if extra > 8192 {
return fmt.Errorf("t.Proof: array too large (%d)", extra)
}
if maj != cbg.MajByteString {
return fmt.Errorf("expected byte array")
}
t.Proof = make([]byte, extra)
if _, err := io.ReadFull(br, t.Proof); err != nil {
return err
}
// t.t.PostRand ([]uint8) (slice)
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if extra > 8192 {
return fmt.Errorf("t.PostRand: array too large (%d)", extra)
}
if maj != cbg.MajByteString {
return fmt.Errorf("expected byte array")
}
t.PostRand = make([]byte, extra)
if _, err := io.ReadFull(br, t.PostRand); err != nil {
return err
}
// t.t.Candidates ([]types.EPostTicket) (slice)
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if extra > 8192 {
return fmt.Errorf("t.Candidates: array too large (%d)", extra)
}
if maj != cbg.MajArray {
return fmt.Errorf("expected cbor array")
}
if extra > 0 {
t.Candidates = make([]EPostTicket, extra)
}
for i := 0; i < int(extra); i++ {
var v EPostTicket
if err := v.UnmarshalCBOR(br); err != nil {
return err
}
t.Candidates[i] = v
}
return nil
}
func (t *EPostTicket) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)
return err
}
if _, err := w.Write([]byte{131}); err != nil {
return err
}
// t.t.Partial ([]uint8) (slice)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Partial)))); err != nil {
return err
}
if _, err := w.Write(t.Partial); err != nil {
return err
}
// t.t.SectorID (uint64) (uint64)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.SectorID))); err != nil {
return err
}
// t.t.ChallengeIndex (uint64) (uint64)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.ChallengeIndex))); err != nil {
return err
}
return nil
}
func (t *EPostTicket) UnmarshalCBOR(r io.Reader) error {
br := cbg.GetPeeker(r)
maj, extra, err := cbg.CborReadHeader(br)
if err != nil {
return err
}
if maj != cbg.MajArray {
return fmt.Errorf("cbor input should be of type array")
}
if extra != 3 {
return fmt.Errorf("cbor input had wrong number of fields")
}
// t.t.Partial ([]uint8) (slice)
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if extra > 8192 {
return fmt.Errorf("t.Partial: array too large (%d)", extra)
}
if maj != cbg.MajByteString {
return fmt.Errorf("expected byte array")
}
t.Partial = make([]byte, extra)
if _, err := io.ReadFull(br, t.Partial); err != nil {
return err
}
// t.t.SectorID (uint64) (uint64)
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.SectorID = uint64(extra)
// t.t.ChallengeIndex (uint64) (uint64)
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.ChallengeIndex = uint64(extra)
return nil
}
func (t *Message) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)

View File

@ -34,12 +34,12 @@ func MkBlock(parents *types.TipSet, weightInc uint64, ticketNonce uint64) *types
}
return &types.BlockHeader{
Miner: addr,
ElectionProof: []byte("cats won the election"),
Tickets: []*types.Ticket{
{
VRFProof: []byte(fmt.Sprintf("====%d=====", ticketNonce)),
},
Miner: addr,
EPostProof: types.EPostProof{
Proof: []byte("election post proof proof"),
},
Ticket: &types.Ticket{
VRFProof: []byte(fmt.Sprintf("====%d=====", ticketNonce)),
},
Parents: pcids,
ParentMessageReceipts: c,
@ -48,7 +48,7 @@ func MkBlock(parents *types.TipSet, weightInc uint64, ticketNonce uint64) *types
Messages: c,
Height: height,
ParentStateRoot: c,
BlockSig: types.Signature{Type: types.KTBLS, Data: []byte("boo! im a signature")},
BlockSig: &types.Signature{Type: types.KTBLS, Data: []byte("boo! im a signature")},
}
}

View File

@ -5,7 +5,7 @@ package types
import (
"fmt"
bls "github.com/filecoin-project/go-bls-sigs"
bls "github.com/filecoin-project/filecoin-ffi"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/lib/crypto"
"github.com/minio/blake2b-simd"

View File

@ -165,8 +165,7 @@ func (t *Ticket) Less(o *Ticket) bool {
}
func (ts *TipSet) MinTicket() *Ticket {
b := ts.MinTicketBlock()
return b.Tickets[len(b.Tickets)-1]
return ts.MinTicketBlock().Ticket
}
func (ts *TipSet) MinTimestamp() uint64 {

View File

@ -3,7 +3,7 @@ package types
import (
"context"
amt "github.com/filecoin-project/go-amt-ipld"
"github.com/filecoin-project/go-amt-ipld"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/address"
cid "github.com/ipfs/go-cid"
@ -48,8 +48,8 @@ type storageWrapper struct {
s Storage
}
func (sw *storageWrapper) Put(i interface{}) (cid.Cid, error) {
c, err := sw.s.Put(i.(cbg.CBORMarshaler))
func (sw *storageWrapper) Put(i cbg.CBORMarshaler) (cid.Cid, error) {
c, err := sw.s.Put(i)
if err != nil {
return cid.Undef, err
}
@ -57,8 +57,8 @@ func (sw *storageWrapper) Put(i interface{}) (cid.Cid, error) {
return c, nil
}
func (sw *storageWrapper) Get(c cid.Cid, out interface{}) error {
if err := sw.s.Get(c, out.(cbg.CBORUnmarshaler)); err != nil {
func (sw *storageWrapper) Get(c cid.Cid, out cbg.CBORUnmarshaler) error {
if err := sw.s.Get(c, out); err != nil {
return err
}

View File

@ -3,11 +3,10 @@ package validation
import (
"context"
"github.com/pkg/errors"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/types"
"golang.org/x/xerrors"
"github.com/filecoin-project/chain-validation/pkg/chain"
"github.com/filecoin-project/chain-validation/pkg/state"
@ -43,7 +42,7 @@ func (mf *MessageFactory) MakeMessage(from, to state.Address, method chain.Metho
}
if int(method) >= len(methods) {
return nil, errors.Errorf("No method name for method %v", method)
return nil, xerrors.Errorf("No method name for method %v", method)
}
methodId := methods[method]
msg := &types.Message{

View File

@ -5,11 +5,10 @@ import (
"fmt"
"math/rand"
"github.com/pkg/errors"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/vm"
"golang.org/x/xerrors"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-datastore"
@ -109,7 +108,7 @@ func (s *StateWrapper) SetActor(addr vstate.Address, code vstate.ActorCodeID, ba
// The ID-based address is dropped here, but should be reported back to the caller.
_, err = tree.RegisterNewAddress(addrInt, &actr.Actor)
if err != nil {
return nil, nil, errors.Wrapf(err, "register new address for actor")
return nil, nil, xerrors.Errorf("register new address for actor: %w", err)
}
return actr, s.storage, s.flush(tree)
}
@ -131,17 +130,24 @@ func (s *StateWrapper) SetSingletonActor(addr vstate.SingletonActorID, balance v
return nil, nil, err
}
if err := tree.SetActor(actors.InitAddress, initact); err != nil {
return nil, nil, errors.Wrapf(err, "set init actor")
return nil, nil, xerrors.Errorf("set init actor: %w", err)
}
return &actorWrapper{*initact}, s.storage, s.flush(tree)
case actors.StorageMarketAddress:
smact, err := gen.SetupStorageMarketActor(s.bs)
nsroot, err := gen.SetupStorageMarketActor(s.bs, s.stateRoot, nil)
if err != nil {
return nil, nil, err
}
if err := tree.SetActor(actors.StorageMarketAddress, smact); err != nil {
return nil, nil, errors.Wrapf(err, "set network storage market actor")
s.stateRoot = nsroot
tree, err = state.LoadStateTree(s.cst, s.stateRoot)
if err != nil {
return nil, nil, err
}
smact, err := tree.GetActor(actors.StorageMarketAddress)
if err != nil {
return nil, nil, err
}
return &actorWrapper{*smact}, s.storage, s.flush(tree)
case actors.StoragePowerAddress:
@ -150,7 +156,7 @@ func (s *StateWrapper) SetSingletonActor(addr vstate.SingletonActorID, balance v
return nil, nil, err
}
if err := tree.SetActor(actors.StoragePowerAddress, spact); err != nil {
return nil, nil, errors.Wrapf(err, "set network storage market actor")
return nil, nil, xerrors.Errorf("set network storage market actor: %w", err)
}
return &actorWrapper{*spact}, s.storage, s.flush(tree)
case actors.NetworkAddress:
@ -160,7 +166,7 @@ func (s *StateWrapper) SetSingletonActor(addr vstate.SingletonActorID, balance v
Head: vm.EmptyObjectCid,
}
if err := tree.SetActor(actors.NetworkAddress, ntwkact); err != nil {
return nil, nil, errors.Wrapf(err, "set network actor")
return nil, nil, xerrors.Errorf("set network actor: %w", err)
}
return &actorWrapper{*ntwkact}, s.storage, s.flush(tree)
case actors.BurntFundsAddress:
@ -170,11 +176,11 @@ func (s *StateWrapper) SetSingletonActor(addr vstate.SingletonActorID, balance v
Head: vm.EmptyObjectCid,
}
if err := tree.SetActor(actors.BurntFundsAddress, ntwkact); err != nil {
return nil, nil, errors.Wrapf(err, "set network actor")
return nil, nil, xerrors.Errorf("set network actor: %w", err)
}
return &actorWrapper{*ntwkact}, s.storage, s.flush(tree)
default:
return nil, nil, errors.Errorf("%v is not a singleton actor address", addr)
return nil, nil, xerrors.Errorf("%v is not a singleton actor address", addr)
}
}

View File

@ -42,9 +42,13 @@ func newInvoker() *invoker {
func (inv *invoker) Invoke(act *types.Actor, vmctx types.VMContext, method uint64, params []byte) ([]byte, aerrors.ActorError) {
if act.Code == actors.AccountCodeCid {
return nil, aerrors.Newf(254, "cannot invoke methods on account actors")
}
code, ok := inv.builtInCode[act.Code]
if !ok {
log.Errorf("no code for actor %s", act.Code)
log.Errorf("no code for actor %s (Addr: %s)", act.Code, vmctx.Message().To)
return nil, aerrors.Newf(255, "no code for actor %s(%d)(%s)", act.Code, method, hex.EncodeToString(params))
}
if method >= uint64(len(code)) || code[method] == nil {
@ -159,7 +163,7 @@ func DumpActorState(code cid.Cid, b []byte) (interface{}, error) {
typ, ok := i.builtInState[code]
if !ok {
return nil, xerrors.New("state type for actor not found")
return nil, xerrors.Errorf("state type for actor %s not found", code)
}
rv := reflect.New(typ)

View File

@ -12,7 +12,7 @@ import (
func TestBlockReward(t *testing.T) {
coffer := types.FromFil(build.MiningRewardTotal).Int
sum := new(big.Int)
N := build.HalvingPeriodBlocks
N := build.HalvingPeriodEpochs
for i := 0; i < N; i++ {
a := MiningReward(types.BigInt{coffer})
sum = sum.Add(sum, a.Int)

View File

@ -7,7 +7,7 @@ import (
"strings"
"sync"
"github.com/filecoin-project/go-bls-sigs"
bls "github.com/filecoin-project/filecoin-ffi"
logging "github.com/ipfs/go-log"
"github.com/minio/blake2b-simd"
@ -41,6 +41,17 @@ func NewWallet(keystore types.KeyStore) (*Wallet, error) {
return w, nil
}
func KeyWallet(keys ...*Key) *Wallet {
m := make(map[address.Address]*Key)
for _, key := range keys {
m[key.Address] = key
}
return &Wallet{
keys: m,
}
}
func (w *Wallet) Sign(ctx context.Context, addr address.Address, msg []byte) (*types.Signature, error) {
ki, err := w.findKey(addr)
if err != nil {
@ -85,6 +96,11 @@ func (w *Wallet) findKey(addr address.Address) (*Key, error) {
if ok {
return k, nil
}
if w.keystore == nil {
log.Warn("findKey didn't find the key in in-memory wallet")
return nil, nil
}
ki, err := w.keystore.Get(KNamePrefix + addr.String())
if err != nil {
if xerrors.Is(err, types.ErrKeyInfoNotFound) {

View File

@ -143,7 +143,6 @@ var Commands = []*cli.Command{
sendCmd,
stateCmd,
syncCmd,
unregisterMinerCmd,
versionCmd,
walletCmd,
}

View File

@ -1,32 +0,0 @@
package cli
import (
"fmt"
"github.com/filecoin-project/lotus/chain/address"
"gopkg.in/urfave/cli.v2"
)
var unregisterMinerCmd = &cli.Command{
Name: "unregister-miner",
Usage: "Manually unregister miner actor",
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
if !cctx.Args().Present() {
return fmt.Errorf("must pass address of miner to unregister")
}
maddr, err := address.NewFromString(cctx.Args().First())
if err != nil {
return err
}
return api.MinerUnregister(ctx, maddr)
},
}

View File

@ -4,7 +4,11 @@ import (
"encoding/json"
"fmt"
"golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/types"
)
var mpoolCmd = &cli.Command{
@ -13,6 +17,7 @@ var mpoolCmd = &cli.Command{
Subcommands: []*cli.Command{
mpoolPending,
mpoolSub,
mpoolStat,
},
}
@ -76,3 +81,75 @@ var mpoolSub = &cli.Command{
}
},
}
type statBucket struct {
msgs map[uint64]*types.SignedMessage
}
var mpoolStat = &cli.Command{
Name: "stat",
Usage: "print mempool stats",
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
ts, err := api.ChainHead(ctx)
if err != nil {
return xerrors.Errorf("getting chain head: %w", err)
}
msgs, err := api.MpoolPending(ctx, nil)
if err != nil {
return err
}
buckets := map[address.Address]*statBucket{}
for _, v := range msgs {
bkt, ok := buckets[v.Message.From]
if !ok {
bkt = &statBucket{
msgs: map[uint64]*types.SignedMessage{},
}
buckets[v.Message.From] = bkt
}
bkt.msgs[v.Message.Nonce] = v
}
for a, bkt := range buckets {
act, err := api.StateGetActor(ctx, a, ts)
if err != nil {
return err
}
cur := act.Nonce
for {
_, ok := bkt.msgs[cur]
if !ok {
break
}
cur++
}
past := 0
future := 0
for _, m := range bkt.msgs {
if m.Message.Nonce < act.Nonce {
past++
}
if m.Message.Nonce > cur {
future++
}
}
fmt.Printf("%s, past: %d, cur: %d, future: %d\n", a, past, cur-act.Nonce, future)
}
return nil
},
}

264
cmd/lotus-bench/main.go Normal file
View File

@ -0,0 +1,264 @@
package main
import (
"bytes"
"context"
"crypto/sha256"
"fmt"
"io/ioutil"
"math/rand"
"os"
"path/filepath"
"time"
ffi "github.com/filecoin-project/filecoin-ffi"
"github.com/ipfs/go-datastore"
logging "github.com/ipfs/go-log"
"github.com/mitchellh/go-homedir"
"golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/lib/sectorbuilder"
)
var log = logging.Logger("lotus-bench")
type BenchResults struct {
SectorSize uint64
SealingResults []SealingResult
PostGenerateCandidates time.Duration
PostEProofCold time.Duration
PostEProofHot time.Duration
VerifyEPostCold time.Duration
VerifyEPostHot time.Duration
}
type SealingResult struct {
AddPiece time.Duration
PreCommit time.Duration
Commit time.Duration
Verify time.Duration
}
func main() {
logging.SetLogLevel("*", "INFO")
log.Info("Starting lotus-bench")
app := &cli.App{
Name: "lotus-bench",
Usage: "Benchmark performance of lotus on your hardware",
Version: build.Version,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "storage-dir",
Value: "~/.lotus-bench",
Usage: "Path to the storage directory that will store sectors long term",
},
&cli.Uint64Flag{
Name: "sector-size",
Value: 1024,
},
},
Action: func(c *cli.Context) error {
sdir, err := homedir.Expand(c.String("storage-dir"))
if err != nil {
return err
}
os.MkdirAll(sdir, 0775)
tsdir, err := ioutil.TempDir(sdir, "bench")
if err != nil {
return err
}
defer func() {
if err := os.RemoveAll(tsdir); err != nil {
log.Warn("remove all: ", err)
}
}()
maddr, err := address.NewFromString("t0101")
if err != nil {
return err
}
sectorSize := c.Uint64("sector-size")
mds := datastore.NewMapDatastore()
cfg := &sectorbuilder.Config{
Miner: maddr,
SectorSize: sectorSize,
WorkerThreads: 2,
CacheDir: filepath.Join(tsdir, "cache"),
SealedDir: filepath.Join(tsdir, "sealed"),
StagedDir: filepath.Join(tsdir, "staged"),
MetadataDir: filepath.Join(tsdir, "meta"),
}
for _, d := range []string{cfg.CacheDir, cfg.SealedDir, cfg.StagedDir, cfg.MetadataDir} {
if err := os.MkdirAll(d, 0775); err != nil {
return err
}
}
if err := build.GetParams(true, false); err != nil {
return xerrors.Errorf("getting params: %w", err)
}
sb, err := sectorbuilder.New(cfg, mds)
if err != nil {
return err
}
r := rand.New(rand.NewSource(101))
size := sectorbuilder.UserBytesForSectorSize(sectorSize)
var sealTimings []SealingResult
var sealedSectors []ffi.PublicSectorInfo
numSectors := uint64(1)
for i := uint64(1); i <= numSectors; i++ {
start := time.Now()
log.Info("Writing piece into sector...")
pi, err := sb.AddPiece(size, i, r, nil)
if err != nil {
return err
}
addpiece := time.Now()
trand := sha256.Sum256([]byte(c.String("ticket-preimage")))
ticket := sectorbuilder.SealTicket{
TicketBytes: trand,
}
log.Info("Running replication...")
pieces := []sectorbuilder.PublicPieceInfo{pi}
pco, err := sb.SealPreCommit(i, ticket, pieces)
if err != nil {
return xerrors.Errorf("commit: %w", err)
}
precommit := time.Now()
sealedSectors = append(sealedSectors, ffi.PublicSectorInfo{
CommR: pco.CommR,
SectorID: i,
})
seed := sectorbuilder.SealSeed{
BlockHeight: 101,
TicketBytes: [32]byte{1, 2, 3, 4, 5},
}
log.Info("Generating PoRep for sector")
proof, err := sb.SealCommit(i, ticket, seed, pieces, pco)
if err != nil {
return err
}
sealcommit := time.Now()
commD := pi.CommP
ok, err := sectorbuilder.VerifySeal(sectorSize, pco.CommR[:], commD[:], maddr, ticket.TicketBytes[:], seed.TicketBytes[:], i, proof)
if err != nil {
return err
}
if !ok {
return xerrors.Errorf("porep proof for sector %d was invalid", i)
}
verifySeal := time.Now()
sealTimings = append(sealTimings, SealingResult{
AddPiece: addpiece.Sub(start),
PreCommit: precommit.Sub(addpiece),
Commit: sealcommit.Sub(precommit),
Verify: verifySeal.Sub(sealcommit),
})
}
beforePost := time.Now()
var challenge [32]byte
rand.Read(challenge[:])
log.Info("generating election post candidates")
sinfos := sectorbuilder.NewSortedPublicSectorInfo(sealedSectors)
candidates, err := sb.GenerateEPostCandidates(sinfos, challenge, []uint64{})
if err != nil {
return err
}
gencandidates := time.Now()
log.Info("computing election post snark (cold)")
proof1, err := sb.ComputeElectionPoSt(sinfos, challenge[:], candidates[:1])
if err != nil {
return err
}
epost1 := time.Now()
log.Info("computing election post snark (hot)")
proof2, err := sb.ComputeElectionPoSt(sinfos, challenge[:], candidates[:1])
if err != nil {
return err
}
epost2 := time.Now()
if !bytes.Equal(proof1, proof2) {
log.Warn("separate epost calls returned different proof values (this might be bad)")
}
ok, err := sectorbuilder.VerifyElectionPost(context.TODO(), sectorSize, sinfos, challenge[:], proof1, candidates[:1], maddr)
if err != nil {
return err
}
if !ok {
log.Error("post verification failed")
}
verifypost1 := time.Now()
ok, err = sectorbuilder.VerifyElectionPost(context.TODO(), sectorSize, sinfos, challenge[:], proof2, candidates[:1], maddr)
if err != nil {
return err
}
if !ok {
log.Error("post verification failed")
}
verifypost2 := time.Now()
benchout := BenchResults{
SectorSize: cfg.SectorSize,
SealingResults: sealTimings,
PostGenerateCandidates: gencandidates.Sub(beforePost),
PostEProofCold: epost1.Sub(gencandidates),
PostEProofHot: epost2.Sub(epost1),
VerifyEPostCold: verifypost1.Sub(epost2),
VerifyEPostHot: verifypost2.Sub(verifypost1),
} // TODO: optionally write this as json to a file
fmt.Println("results")
fmt.Printf("seal: addPiece: %s\n", benchout.SealingResults[0].AddPiece) // TODO: average across multiple sealings
fmt.Printf("seal: preCommit: %s\n", benchout.SealingResults[0].PreCommit)
fmt.Printf("seal: Commit: %s\n", benchout.SealingResults[0].Commit)
fmt.Printf("seal: Verify: %s\n", benchout.SealingResults[0].Verify)
fmt.Printf("generate candidates: %s\n", benchout.PostGenerateCandidates)
fmt.Printf("compute epost proof (cold): %s\n", benchout.PostEProofCold)
fmt.Printf("compute epost proof (hot): %s\n", benchout.PostEProofHot)
fmt.Printf("verify epost proof (cold): %s\n", benchout.VerifyEPostCold)
fmt.Printf("verify epost proof (hot): %s\n", benchout.VerifyEPostHot)
return nil
},
}
if err := app.Run(os.Args); err != nil {
log.Warn(err)
return
}
}

View File

@ -252,7 +252,7 @@ func (st *storage) storeMiners(miners map[minerKey]*minerInfo) error {
i.info.SectorSize,
i.state.Power.String(),
i.state.Active,
i.state.ProvingPeriodEnd,
i.state.ElectionPeriodStart,
i.state.SlashedAt,
); err != nil {
return err

View File

@ -4,9 +4,10 @@ import (
"bytes"
"container/list"
"context"
"sync"
actors2 "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"sync"
"github.com/ipfs/go-cid"

89
cmd/lotus-seed/main.go Normal file
View File

@ -0,0 +1,89 @@
package main
import (
"os"
logging "github.com/ipfs/go-log"
"github.com/mitchellh/go-homedir"
"gopkg.in/urfave/cli.v2"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/cmd/lotus-seed/seed"
)
var log = logging.Logger("lotus-seed")
func main() {
logging.SetLogLevel("*", "INFO")
log.Info("Starting seed")
local := []*cli.Command{
preSealCmd,
}
app := &cli.App{
Name: "lotus-seed",
Usage: "Seal sectors for genesis miner",
Version: build.Version,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "sectorbuilder-dir",
Value: "~/.genesis-sectors",
},
},
Commands: local,
}
if err := app.Run(os.Args); err != nil {
log.Warn(err)
return
}
}
var preSealCmd = &cli.Command{
Name: "pre-seal",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "miner-addr",
Value: "t0101",
Usage: "specify the future address of your miner",
},
&cli.Uint64Flag{
Name: "sector-size",
Value: build.SectorSizes[0],
Usage: "specify size of sectors to pre-seal",
},
&cli.StringFlag{
Name: "ticket-preimage",
Value: "lotus is fire",
Usage: "set the ticket preimage for sealing randomness",
},
&cli.Uint64Flag{
Name: "num-sectors",
Value: 1,
Usage: "select number of sectors to pre-seal",
},
},
Action: func(c *cli.Context) error {
sdir := c.String("sectorbuilder-dir")
sbroot, err := homedir.Expand(sdir)
if err != nil {
return err
}
maddr, err := address.NewFromString(c.String("miner-addr"))
if err != nil {
return err
}
gm, err := seed.PreSeal(maddr, c.Uint64("sector-size"), c.Uint64("num-sectors"), sbroot, []byte(c.String("ticket-preimage")))
if err != nil {
return err
}
return seed.WriteGenesisMiner(maddr, sbroot, gm)
},
}

167
cmd/lotus-seed/seed/seed.go Normal file
View File

@ -0,0 +1,167 @@
package seed
import (
"context"
"crypto/sha256"
"encoding/json"
"fmt"
"io/ioutil"
"math/rand"
"os"
"path/filepath"
badger "github.com/ipfs/go-ds-badger"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/wallet"
"github.com/filecoin-project/lotus/genesis"
"github.com/filecoin-project/lotus/lib/sectorbuilder"
)
func PreSeal(maddr address.Address, ssize uint64, sectors uint64, sbroot string, preimage []byte) (*genesis.GenesisMiner, error) {
cfg := &sectorbuilder.Config{
Miner: maddr,
SectorSize: ssize,
CacheDir: filepath.Join(sbroot, "cache"),
SealedDir: filepath.Join(sbroot, "sealed"),
StagedDir: filepath.Join(sbroot, "staging"),
MetadataDir: filepath.Join(sbroot, "meta"),
WorkerThreads: 2,
}
for _, d := range []string{cfg.CacheDir, cfg.SealedDir, cfg.StagedDir, cfg.MetadataDir} {
if err := os.MkdirAll(d, 0775); err != nil {
return nil, err
}
}
mds, err := badger.NewDatastore(filepath.Join(sbroot, "badger"), nil)
if err != nil {
return nil, err
}
if err := build.GetParams(true, false); err != nil {
return nil, xerrors.Errorf("getting params: %w", err)
}
sb, err := sectorbuilder.New(cfg, mds)
if err != nil {
return nil, err
}
r := rand.New(rand.NewSource(101))
size := sectorbuilder.UserBytesForSectorSize(ssize)
var sealedSectors []*genesis.PreSeal
for i := uint64(1); i <= sectors; i++ {
sid, err := sb.AcquireSectorId()
if err != nil {
return nil, err
}
pi, err := sb.AddPiece(size, sid, r, nil)
if err != nil {
return nil, err
}
trand := sha256.Sum256(preimage)
ticket := sectorbuilder.SealTicket{
TicketBytes: trand,
}
fmt.Println("Piece info: ", pi)
pco, err := sb.SealPreCommit(sid, ticket, []sectorbuilder.PublicPieceInfo{pi})
if err != nil {
return nil, xerrors.Errorf("commit: %w", err)
}
sealedSectors = append(sealedSectors, &genesis.PreSeal{
CommR: pco.CommR,
CommD: pco.CommD,
SectorID: sid,
})
}
minerAddr, err := wallet.GenerateKey(types.KTBLS)
if err != nil {
return nil, err
}
miner := &genesis.GenesisMiner{
Owner: minerAddr.Address,
Worker: minerAddr.Address,
SectorSize: ssize,
Sectors: sealedSectors,
Key: minerAddr.KeyInfo,
}
if err := createDeals(miner, minerAddr, ssize); err != nil {
return nil, xerrors.Errorf("creating deals: %w", err)
}
if err := mds.Close(); err != nil {
return nil, xerrors.Errorf("closing datastore: %w", err)
}
return miner, nil
}
func WriteGenesisMiner(maddr address.Address, sbroot string, gm *genesis.GenesisMiner) error {
output := map[string]genesis.GenesisMiner{
maddr.String(): *gm,
}
out, err := json.MarshalIndent(output, "", " ")
if err != nil {
return err
}
if err := ioutil.WriteFile(filepath.Join(sbroot, "pre-seal-"+maddr.String()+".json"), out, 0664); err != nil {
return err
}
return nil
}
func createDeals(m *genesis.GenesisMiner, k *wallet.Key, ssize uint64) error {
for _, sector := range m.Sectors {
proposal := &actors.StorageDealProposal{
PieceRef: sector.CommD[:], // just one deal so this == CommP
PieceSize: ssize,
PieceSerialization: actors.SerializationUnixFSv0,
Client: k.Address,
Provider: k.Address,
ProposalExpiration: 9000, // TODO: allow setting
Duration: 9000,
StoragePricePerEpoch: types.NewInt(0),
StorageCollateral: types.NewInt(0),
ProposerSignature: nil,
}
if err := api.SignWith(context.TODO(), wallet.KeyWallet(k).Sign, k.Address, proposal); err != nil {
return err
}
deal := &actors.StorageDeal{
Proposal: *proposal,
CounterSignature: nil,
}
if err := api.SignWith(context.TODO(), wallet.KeyWallet(k).Sign, k.Address, deal); err != nil {
return err
}
sector.Deal = *deal
}
return nil
}

View File

@ -63,7 +63,7 @@ var infoCmd = &cli.Command{
fmt.Printf("\tLocal: %d / %d (+%d reserved)\n", wstat.LocalTotal-wstat.LocalReserved-wstat.LocalFree, wstat.LocalTotal-wstat.LocalReserved, wstat.LocalReserved)
fmt.Printf("\tRemote: %d / %d\n", wstat.RemotesTotal-wstat.RemotesFree, wstat.RemotesTotal)
ppe, err := api.StateMinerProvingPeriodEnd(ctx, maddr, nil)
ppe, err := api.StateMinerElectionPeriodStart(ctx, maddr, nil)
if err != nil {
return err
}

View File

@ -3,22 +3,36 @@ package main
import (
"context"
"crypto/rand"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strconv"
"github.com/ipfs/go-datastore"
badger "github.com/ipfs/go-ds-badger"
"github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/mitchellh/go-homedir"
"golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2"
"github.com/filecoin-project/lotus/api"
lapi "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/deals"
"github.com/filecoin-project/lotus/chain/types"
lcli "github.com/filecoin-project/lotus/cli"
"github.com/filecoin-project/lotus/genesis"
"github.com/filecoin-project/lotus/lib/cborutil"
"github.com/filecoin-project/lotus/lib/sectorbuilder"
"github.com/filecoin-project/lotus/miner"
"github.com/filecoin-project/lotus/node/modules"
"github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/filecoin-project/lotus/node/repo"
"github.com/filecoin-project/lotus/storage"
)
var initCmd = &cli.Command{
@ -53,6 +67,10 @@ var initCmd = &cli.Command{
Usage: "specify sector size to use",
Value: build.SectorSizes[0],
},
&cli.StringFlag{
Name: "pre-sealed-sectors",
Usage: "specify set of presealed sectors for starting as a genesis miner",
},
},
Action: func(cctx *cli.Context) error {
log.Info("Initializing lotus storage miner")
@ -104,6 +122,25 @@ var initCmd = &cli.Command{
return err
}
if pssb := cctx.String("pre-sealed-sectors"); pssb != "" {
log.Infof("moving pre-sealed-sectors from %s into newly created storage miner repo", pssb)
lr, err := r.Lock(repo.StorageMiner)
if err != nil {
return err
}
mds, err := lr.Datastore("/metadata")
if err != nil {
return err
}
if err := migratePreSealedSectors(pssb, repoPath, mds); err != nil {
return err
}
if err := lr.Close(); err != nil {
return xerrors.Errorf("unlocking repo after preseal migration: %w", err)
}
}
if err := storageMinerInit(ctx, cctx, api, r); err != nil {
log.Errorf("Failed to initialize lotus-storage-miner: %+v", err)
path, err := homedir.Expand(repoPath)
@ -124,7 +161,161 @@ var initCmd = &cli.Command{
},
}
func storageMinerInit(ctx context.Context, cctx *cli.Context, api api.FullNode, r repo.Repo) error {
// TODO: this method should be a lot more robust for mainnet. For testnet, its
// fine if we mess things up a few times
// Also probably makes sense for this method to be in the sectorbuilder package
func migratePreSealedSectors(presealsb string, repoPath string, mds dtypes.MetadataDS) error {
pspath, err := homedir.Expand(presealsb)
if err != nil {
return err
}
srcds, err := badger.NewDatastore(filepath.Join(pspath, "badger"), nil)
if err != nil {
return xerrors.Errorf("openning presealed sectors datastore: %w", err)
}
expRepo, err := homedir.Expand(repoPath)
if err != nil {
return err
}
if stat, err := os.Stat(pspath); err != nil {
return xerrors.Errorf("failed to stat presealed sectors directory: %w", err)
} else if !stat.IsDir() {
return xerrors.Errorf("given presealed sectors path was not a directory: %w", err)
}
for _, dir := range []string{"meta", "sealed", "staging", "cache"} {
from := filepath.Join(pspath, dir)
to := filepath.Join(expRepo, dir)
if err := os.Rename(from, to); err != nil {
return err
}
}
val, err := srcds.Get(sectorbuilder.LastSectorIdKey)
if err != nil {
return xerrors.Errorf("getting source last sector ID: %w", err)
}
if err := mds.Put(sectorbuilder.LastSectorIdKey, val); err != nil {
return xerrors.Errorf("failed to write last sector ID key to target datastore: %w", err)
}
return nil
}
func migratePreSealMeta(ctx context.Context, api lapi.FullNode, presealDir string, maddr address.Address, mds dtypes.MetadataDS) error {
b, err := ioutil.ReadFile(filepath.Join(presealDir, "pre-seal-"+maddr.String()+".json"))
if err != nil {
return xerrors.Errorf("reading preseal metadata: %w", err)
}
preseals := map[string]genesis.GenesisMiner{}
if err := json.Unmarshal(b, &preseals); err != nil {
return xerrors.Errorf("unmarshaling preseal metadata: %w", err)
}
meta, ok := preseals[maddr.String()]
if !ok {
return xerrors.New("got wrong preseal info")
}
for _, sector := range meta.Sectors {
sectorKey := datastore.NewKey(storage.SectorStorePrefix).ChildString(fmt.Sprint(sector.SectorID))
dealID, err := findMarketDealID(ctx, api, sector.Deal)
if err != nil {
return xerrors.Errorf("finding storage deal for pre-sealed sector %d: %w", sector.SectorID, err)
}
info := &storage.SectorInfo{
State: lapi.Proving,
SectorID: sector.SectorID,
Pieces: []storage.Piece{
{
DealID: dealID,
Ref: fmt.Sprintf("preseal-%d", sector.SectorID),
Size: meta.SectorSize,
CommP: sector.CommD[:],
},
},
CommC: nil,
CommD: sector.CommD[:],
CommR: sector.CommR[:],
CommRLast: nil,
Proof: nil,
Ticket: storage.SealTicket{},
PreCommitMessage: nil,
Seed: storage.SealSeed{},
CommitMessage: nil,
}
b, err := cborutil.Dump(info)
if err != nil {
return err
}
if err := mds.Put(sectorKey, b); err != nil {
return err
}
proposalCid, err := sector.Deal.Proposal.Cid()
if err != nil {
return err
}
dealKey := datastore.NewKey(deals.ProviderDsPrefix).ChildString(proposalCid.String())
deal := &deals.MinerDeal{
Proposal: sector.Deal.Proposal,
ProposalCid: proposalCid,
State: lapi.DealComplete,
Ref: proposalCid, // TODO: This is super wrong, but there
// are no params for CommP CIDs, we can't recover unixfs cid easily,
// and this isn't even used after the deal enters Complete state
DealID: dealID,
SectorID: sector.SectorID,
}
b, err = cborutil.Dump(deal)
if err != nil {
return err
}
if err := mds.Put(dealKey, b); err != nil {
return err
}
}
return nil
}
func findMarketDealID(ctx context.Context, api lapi.FullNode, deal actors.StorageDeal) (uint64, error) {
// TODO: find a better way
// (this is only used by genesis miners)
deals, err := api.StateMarketDeals(ctx, nil)
if err != nil {
return 0, xerrors.Errorf("getting market deals: %w", err)
}
for k, v := range deals {
eq, err := cborutil.Equals(&v.Deal, &deal)
if err != nil {
return 0, err
}
if eq {
return strconv.ParseUint(k, 10, 64)
}
}
return 0, xerrors.New("deal not found")
}
func storageMinerInit(ctx context.Context, cctx *cli.Context, api lapi.FullNode, r repo.Repo) error {
lr, err := r.Lock(repo.StorageMiner)
if err != nil {
return err
@ -143,6 +334,11 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api api.FullNode,
return xerrors.Errorf("peer ID from private key: %w", err)
}
mds, err := lr.Datastore("/metadata")
if err != nil {
return err
}
var addr address.Address
if act := cctx.String("actor"); act != "" {
a, err := address.NewFromString(act)
@ -150,8 +346,51 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api api.FullNode,
return xerrors.Errorf("failed parsing actor flag value (%q): %w", act, err)
}
if err := configureStorageMiner(ctx, api, a, peerid, cctx.Bool("genesis-miner")); err != nil {
return xerrors.Errorf("failed to configure storage miner: %w", err)
if cctx.Bool("genesis-miner") {
if err := mds.Put(datastore.NewKey("miner-address"), a.Bytes()); err != nil {
return err
}
sbcfg, err := modules.SectorBuilderConfig(lr.Path(), 2)(mds, api)
if err != nil {
return xerrors.Errorf("getting genesis miner sector builder config: %w", err)
}
sb, err := sectorbuilder.New(sbcfg, mds)
if err != nil {
return xerrors.Errorf("failed to set up sectorbuilder for genesis mining: %w", err)
}
epp := storage.NewElectionPoStProver(sb)
m := miner.NewMiner(api, epp)
{
if err := m.Register(a); err != nil {
return xerrors.Errorf("failed to start up genesis miner: %w", err)
}
defer func() {
if err := m.Unregister(ctx, a); err != nil {
log.Error("failed to shut down storage miner: ", err)
}
}()
if err := configureStorageMiner(ctx, api, a, peerid); err != nil {
return xerrors.Errorf("failed to configure storage miner: %w", err)
}
}
if pssb := cctx.String("pre-sealed-sectors"); pssb != "" {
log.Infof("Importing pre-sealed sector metadata for %s", a)
if err := migratePreSealMeta(ctx, api, cctx.String("pre-sealed-sectors"), a, mds); err != nil {
return xerrors.Errorf("migrating presealed sector metadata: %w", err)
}
}
return nil
} else {
if err := configureStorageMiner(ctx, api, a, peerid); err != nil {
return xerrors.Errorf("failed to configure storage miner: %w", err)
}
}
addr = a
@ -165,12 +404,7 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api api.FullNode,
}
log.Infof("Created new storage miner: %s", addr)
ds, err := lr.Datastore("/metadata")
if err != nil {
return err
}
if err := ds.Put(datastore.NewKey("miner-address"), addr.Bytes()); err != nil {
if err := mds.Put(datastore.NewKey("miner-address"), addr.Bytes()); err != nil {
return err
}
@ -203,22 +437,7 @@ func makeHostKey(lr repo.LockedRepo) (crypto.PrivKey, error) {
return pk, nil
}
func configureStorageMiner(ctx context.Context, api api.FullNode, addr address.Address, peerid peer.ID, genmine bool) error {
if genmine {
log.Warn("Starting genesis mining. This shouldn't happen when connecting to the real network.")
// We may be one of genesis miners, start mining before trying to do any chain operations
// (otherwise our messages won't be mined)
if err := api.MinerRegister(ctx, addr); err != nil {
return err
}
defer func() {
if err := api.MinerUnregister(ctx, addr); err != nil {
log.Errorf("failed to call api.MinerUnregister: %s", err)
}
}()
}
func configureStorageMiner(ctx context.Context, api lapi.FullNode, addr address.Address, peerid peer.ID) error {
// This really just needs to be an api call at this point...
recp, err := api.StateCall(ctx, &types.Message{
To: addr,
@ -271,7 +490,7 @@ func configureStorageMiner(ctx context.Context, api api.FullNode, addr address.A
return nil
}
func createStorageMiner(ctx context.Context, api api.FullNode, peerid peer.ID, cctx *cli.Context) (addr address.Address, err error) {
func createStorageMiner(ctx context.Context, api lapi.FullNode, peerid peer.ID, cctx *cli.Context) (addr address.Address, err error) {
log.Info("Creating StorageMarket.CreateStorageMiner message")
var owner address.Address

View File

@ -70,7 +70,7 @@ func main() {
}
if err := app.Run(os.Args); err != nil {
log.Warn(err)
log.Warnf("%+v", err)
os.Exit(1)
}
}

View File

@ -35,6 +35,7 @@ var runCmd = &cli.Command{
&cli.BoolFlag{
Name: "enable-gpu-proving",
Usage: "Enable use of GPU for mining operations",
Value: true,
},
},
Action: func(cctx *cli.Context) error {

View File

@ -21,7 +21,8 @@ import (
)
const (
makeGenFlag = "lotus-make-random-genesis"
makeGenFlag = "lotus-make-random-genesis"
preSealedSectorsFlag = "genesis-presealed-sectors"
)
// DaemonCmd is the `go-lotus daemon` command
@ -38,6 +39,10 @@ var DaemonCmd = &cli.Command{
Value: "",
Hidden: true,
},
&cli.StringFlag{
Name: preSealedSectorsFlag,
Hidden: true,
},
&cli.StringFlag{
Name: "genesis",
Usage: "genesis file to use for first node run",
@ -51,11 +56,11 @@ var DaemonCmd = &cli.Command{
ctx := context.Background()
r, err := repo.NewFS(cctx.String("repo"))
if err != nil {
return err
return xerrors.Errorf("opening fs repo: %w", err)
}
if err := r.Init(repo.FullNode); err != nil && err != repo.ErrRepoExists {
return err
return xerrors.Errorf("repo init error: %w", err)
}
if err := build.GetParams(false, false); err != nil {
@ -67,9 +72,8 @@ var DaemonCmd = &cli.Command{
if cctx.String("genesis") != "" {
genBytes, err = ioutil.ReadFile(cctx.String("genesis"))
if err != nil {
return err
return xerrors.Errorf("reading genesis: %w", err)
}
}
genesis := node.Options()
@ -77,7 +81,10 @@ var DaemonCmd = &cli.Command{
genesis = node.Override(new(modules.Genesis), modules.LoadGenesis(genBytes))
}
if cctx.String(makeGenFlag) != "" {
genesis = node.Override(new(modules.Genesis), testing.MakeGenesis(cctx.String(makeGenFlag)))
if cctx.String(preSealedSectorsFlag) == "" {
return xerrors.Errorf("must also pass file with miner preseal info to `--%s`", preSealedSectorsFlag)
}
genesis = node.Override(new(modules.Genesis), testing.MakeGenesis(cctx.String(makeGenFlag), cctx.String(preSealedSectorsFlag)))
}
var api api.FullNode
@ -105,12 +112,12 @@ var DaemonCmd = &cli.Command{
),
)
if err != nil {
return err
return xerrors.Errorf("initializing node: %w", err)
}
endpoint, err := r.APIEndpoint()
if err != nil {
return err
return xerrors.Errorf("getting api endpoint: %w", err)
}
// TODO: properly parse api endpoint (or make it a URL)

View File

@ -69,7 +69,7 @@ func main() {
Code: trace.StatusCodeFailedPrecondition,
Message: err.Error(),
})
log.Warn(err)
log.Warnf("%+v", err)
os.Exit(1)
}
return

1
extern/filecoin-ffi vendored Submodule

@ -0,0 +1 @@
Subproject commit 0e71b164cf4b2e1c0f53ca25145e3ea57cc53e90

1
extern/go-bls-sigs vendored

@ -1 +0,0 @@
Subproject commit 98479d3c79620f18783da0c2c6a15f8b8eb4fa2e

@ -1 +0,0 @@
Subproject commit 40278d4a6623e4c81003e20444871c9362bedd61

View File

@ -20,6 +20,8 @@ func main() {
err := gen.WriteTupleEncodersToFile("./chain/types/cbor_gen.go", "types",
types.BlockHeader{},
types.Ticket{},
types.EPostProof{},
types.EPostTicket{},
types.Message{},
types.SignedMessage{},
types.MsgMeta{},
@ -91,7 +93,7 @@ func main() {
actors.SectorPreCommitInfo{},
actors.PreCommittedSector{},
actors.MinerInfo{},
actors.SubmitPoStParams{},
actors.SubmitFallbackPoStParams{},
actors.PaymentVerifyParams{},
actors.UpdatePeerIDParams{},
actors.MultiSigActorState{},

25
genesis/types.go Normal file
View File

@ -0,0 +1,25 @@
package genesis
import (
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/types"
)
type PreSeal struct {
CommR [32]byte
CommD [32]byte
SectorID uint64
Deal actors.StorageDeal
}
type GenesisMiner struct {
Owner address.Address
Worker address.Address
SectorSize uint64
Sectors []*PreSeal
Key types.KeyInfo // TODO: separate file
}

37
go.mod
View File

@ -8,19 +8,17 @@ require (
github.com/GeertJohan/go.rice v1.0.0
github.com/Gurpartap/async v0.0.0-20180927173644-4f7f499dd9ee
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
github.com/btcsuite/btcd v0.0.0-20190807005414-4063feeff79a // indirect
github.com/fatih/color v1.7.0 // indirect
github.com/filecoin-project/chain-validation v0.0.0-20191106200742-11986803c0f7
github.com/filecoin-project/go-amt-ipld v0.0.0-20190919045431-3650716fff16
github.com/filecoin-project/go-bls-sigs v0.0.0-20190718224239-4bc4b8a7bbf8
github.com/filecoin-project/filecoin-ffi v0.0.0-00010101000000-000000000000
github.com/filecoin-project/go-amt-ipld v0.0.0-20191122035745-59b9dfc0efc7
github.com/filecoin-project/go-leb128 v0.0.0-20190212224330-8d79a5489543
github.com/filecoin-project/go-sectorbuilder v0.0.0-00010101000000-000000000000
github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1
github.com/go-ole/go-ole v1.2.4 // indirect
github.com/google/go-cmp v0.3.1 // indirect
github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f // indirect
github.com/gorilla/mux v1.7.3
github.com/gorilla/websocket v1.4.0
github.com/gorilla/websocket v1.4.1
github.com/hashicorp/go-multierror v1.0.0
github.com/hashicorp/golang-lru v0.5.3
github.com/influxdata/influxdb1-client v0.0.0-20190809212627-fc22c7df067e
@ -44,17 +42,16 @@ require (
github.com/ipfs/go-ipfs-routing v0.1.0
github.com/ipfs/go-ipld-cbor v0.0.3
github.com/ipfs/go-ipld-format v0.0.2
github.com/ipfs/go-log v0.0.2-0.20190920042044-a609c1ae5144
github.com/ipfs/go-log v1.0.0
github.com/ipfs/go-merkledag v0.2.4
github.com/ipfs/go-unixfs v0.2.2-0.20190827150610-868af2e9e5cb
github.com/ipld/go-ipld-prime v0.0.2-0.20191025154717-8dff1cbec43b
github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52
github.com/libp2p/go-eventbus v0.1.0 // indirect
github.com/libp2p/go-libp2p v0.3.0
github.com/libp2p/go-libp2p-circuit v0.1.1
github.com/libp2p/go-libp2p-connmgr v0.1.0
github.com/libp2p/go-libp2p-core v0.2.2
github.com/libp2p/go-libp2p-discovery v0.1.0
github.com/libp2p/go-libp2p-core v0.2.4
github.com/libp2p/go-libp2p-discovery v0.2.0
github.com/libp2p/go-libp2p-host v0.1.0
github.com/libp2p/go-libp2p-kad-dht v0.1.1
github.com/libp2p/go-libp2p-mplex v0.2.1
@ -62,31 +59,30 @@ require (
github.com/libp2p/go-libp2p-peerstore v0.1.3
github.com/libp2p/go-libp2p-pnet v0.1.0
github.com/libp2p/go-libp2p-protocol v0.1.0
github.com/libp2p/go-libp2p-pubsub v0.1.0
github.com/libp2p/go-libp2p-pubsub v0.2.3
github.com/libp2p/go-libp2p-quic-transport v0.1.1
github.com/libp2p/go-libp2p-record v0.1.1
github.com/libp2p/go-libp2p-routing-helpers v0.1.0
github.com/libp2p/go-libp2p-secio v0.2.0
github.com/libp2p/go-libp2p-swarm v0.2.1 // indirect
github.com/libp2p/go-libp2p-tls v0.1.0
github.com/libp2p/go-libp2p-yamux v0.2.1
github.com/libp2p/go-maddr-filter v0.0.5
github.com/libp2p/go-ws-transport v0.1.2 // indirect
github.com/mattn/go-isatty v0.0.9 // indirect
github.com/mattn/go-runewidth v0.0.4 // indirect
github.com/mattn/go-sqlite3 v1.12.0
github.com/miekg/dns v1.1.16 // indirect
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1
github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771
github.com/minio/sha256-simd v0.1.1
github.com/mitchellh/go-homedir v1.1.0
github.com/multiformats/go-base32 v0.0.3
github.com/multiformats/go-multiaddr v0.0.4
github.com/multiformats/go-multiaddr-dns v0.0.3
github.com/multiformats/go-multiaddr-net v0.0.1
github.com/multiformats/go-multiaddr v0.1.1
github.com/multiformats/go-multiaddr-dns v0.2.0
github.com/multiformats/go-multiaddr-net v0.1.0
github.com/multiformats/go-multihash v0.0.9
github.com/onsi/ginkgo v1.9.0 // indirect
github.com/onsi/gomega v1.6.0 // indirect
github.com/opentracing/opentracing-go v1.1.0
github.com/pkg/errors v0.8.1
github.com/polydawn/refmt v0.0.0-20190809202753-05966cbd336a
github.com/smartystreets/assertions v1.0.1 // indirect
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 // indirect
@ -95,16 +91,15 @@ require (
github.com/whyrusleeping/cbor-gen v0.0.0-20191116002219-891f55cd449d
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7
github.com/whyrusleeping/pubsub v0.0.0-20131020042734-02de8aa2db3d
go.opencensus.io v0.22.0
go.opencensus.io v0.22.1
go.uber.org/dig v1.7.0 // indirect
go.uber.org/fx v1.9.0
go.uber.org/goleak v0.10.0 // indirect
go.uber.org/multierr v1.1.0
go.uber.org/zap v1.10.0
go4.org v0.0.0-20190313082347-94abd6928b1d // indirect
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 // indirect
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898
google.golang.org/api v0.9.0 // indirect
gopkg.in/cheggaaa/pb.v1 v1.0.28
gopkg.in/urfave/cli.v2 v2.0.0-20180128182452-d3ae77c26ac8
@ -114,6 +109,4 @@ require (
replace github.com/golangci/golangci-lint => github.com/golangci/golangci-lint v1.18.0
replace github.com/filecoin-project/go-bls-sigs => ./extern/go-bls-sigs
replace github.com/filecoin-project/go-sectorbuilder => ./extern/go-sectorbuilder
replace github.com/filecoin-project/filecoin-ffi => ./extern/filecoin-ffi

78
go.sum
View File

@ -33,8 +33,8 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8=
github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
github.com/btcsuite/btcd v0.0.0-20190605094302-a0d1e3e36d50/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
github.com/btcsuite/btcd v0.0.0-20190807005414-4063feeff79a h1:We35J+0yvVFrEXbtViYUW8H/wNOhqjIF3PsrW4yYmGw=
github.com/btcsuite/btcd v0.0.0-20190807005414-4063feeff79a/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3 h1:A/EVblehb75cUgXA5njHPn0kLAsykn6mJGz7rnmW5W0=
github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
@ -78,8 +78,8 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv
github.com/fd/go-nat v1.0.0/go.mod h1:BTBu/CKvMmOMUPkKVef1pngt2WFH/lg7E6yQnulfp6E=
github.com/filecoin-project/chain-validation v0.0.0-20191106200742-11986803c0f7 h1:Ags/z6ZubzKonQ9PsY9fO439yGdVg07qpdxfv/AEUno=
github.com/filecoin-project/chain-validation v0.0.0-20191106200742-11986803c0f7/go.mod h1:0/0/QUNqpF/jVzLHFncGeT3NvGPODBhGzQlNgzmoZew=
github.com/filecoin-project/go-amt-ipld v0.0.0-20190919045431-3650716fff16 h1:NzojcJU1VbS6zdLG13JMYis/cQy/MrN3rxmZRq56jKA=
github.com/filecoin-project/go-amt-ipld v0.0.0-20190919045431-3650716fff16/go.mod h1:lKjJYPg2kwbav5f78i5YA8kGccnZn18IySbpneXvaQs=
github.com/filecoin-project/go-amt-ipld v0.0.0-20191122035745-59b9dfc0efc7 h1:lKSMm8Go6qI7+Dk3rWCNIh57wBOqVNJ21re/p7D58gc=
github.com/filecoin-project/go-amt-ipld v0.0.0-20191122035745-59b9dfc0efc7/go.mod h1:lKjJYPg2kwbav5f78i5YA8kGccnZn18IySbpneXvaQs=
github.com/filecoin-project/go-leb128 v0.0.0-20190212224330-8d79a5489543 h1:aMJGfgqe1QDhAVwxRg5fjCRF533xHidiKsugk7Vvzug=
github.com/filecoin-project/go-leb128 v0.0.0-20190212224330-8d79a5489543/go.mod h1:mjrHv1cDGJWDlGmC0eDc1E5VJr8DmL9XMUcaFwiuKg8=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
@ -97,7 +97,12 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
@ -127,6 +132,8 @@ github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU=
github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48=
github.com/gxed/pubsub v0.0.0-20180201040156-26ebdf44f824/go.mod h1:OiEWyHgK+CWrmOlVquHaIK1vhpUJydC9m0Je6mhaiNE=
@ -220,8 +227,8 @@ github.com/ipfs/go-ipld-format v0.0.1/go.mod h1:kyJtbkDALmFHv3QR6et67i35QzO3S0dC
github.com/ipfs/go-ipld-format v0.0.2 h1:OVAGlyYT6JPZ0pEfGntFPS40lfrDmaDbQwNHEY2G9Zs=
github.com/ipfs/go-ipld-format v0.0.2/go.mod h1:4B6+FM2u9OJ9zCV+kSbgFAZlOrv1Hqbf0INGQgiKf9k=
github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM=
github.com/ipfs/go-log v0.0.2-0.20190920042044-a609c1ae5144 h1:5WM8S1nwquWQ3zEuNhK82NE5Di6Pd41qz9JxxvxTAIA=
github.com/ipfs/go-log v0.0.2-0.20190920042044-a609c1ae5144/go.mod h1:azGN5dH7ailfREknDDNYB0Eq4qZ/4I4Y3gO0ivjJNyM=
github.com/ipfs/go-log v1.0.0 h1:BW3LQIiZzpNyolt84yvKNCd3FU+AK4VDw1hnHR+1aiI=
github.com/ipfs/go-log v1.0.0/go.mod h1:JO7RzlMK6rA+CIxFMLOuB6Wf5b81GDiKElL7UPSIKjA=
github.com/ipfs/go-merkledag v0.1.0/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk=
github.com/ipfs/go-merkledag v0.2.3/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk=
github.com/ipfs/go-merkledag v0.2.4 h1:ZSHQSe9BENfixUjT+MaLeHEeZGxrZQfgo3KT3SLosF8=
@ -265,6 +272,7 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@ -298,6 +306,8 @@ github.com/libp2p/go-libp2p-autonat v0.1.0/go.mod h1:1tLf2yXxiE/oKGtDwPYWTSYG3Pt
github.com/libp2p/go-libp2p-blankhost v0.1.1/go.mod h1:pf2fvdLJPsC1FsVrNP3DUUvMzUts2dsLLBEpo1vW1ro=
github.com/libp2p/go-libp2p-blankhost v0.1.3 h1:0KycuXvPDhmehw0ASsg+s1o3IfXgCUDqfzAl94KEBOg=
github.com/libp2p/go-libp2p-blankhost v0.1.3/go.mod h1:KML1//wiKR8vuuJO0y3LUd1uLv+tlkGTAr3jC0S5cLg=
github.com/libp2p/go-libp2p-blankhost v0.1.4 h1:I96SWjR4rK9irDHcHq3XHN6hawCRTPUADzkJacgZLvk=
github.com/libp2p/go-libp2p-blankhost v0.1.4/go.mod h1:oJF0saYsAXQCSfDq254GMNmLNz6ZTHTOvtF4ZydUvwU=
github.com/libp2p/go-libp2p-circuit v0.1.0/go.mod h1:Ahq4cY3V9VJcHcn1SBXjr78AbFkZeIRmfunbA7pmFh8=
github.com/libp2p/go-libp2p-circuit v0.1.1 h1:eopfG9fAg6rEHWQO1TSrLosXDgYbbbu/RTva/tBANus=
github.com/libp2p/go-libp2p-circuit v0.1.1/go.mod h1:Ahq4cY3V9VJcHcn1SBXjr78AbFkZeIRmfunbA7pmFh8=
@ -311,11 +321,15 @@ github.com/libp2p/go-libp2p-core v0.0.6/go.mod h1:0d9xmaYAVY5qmbp/fcgxHT3ZJsLjYe
github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI=
github.com/libp2p/go-libp2p-core v0.2.2 h1:Sv1ggdoMx9c7v7FOFkR7agraHCnAgqYsXrU1ARSRUMs=
github.com/libp2p/go-libp2p-core v0.2.2/go.mod h1:8fcwTbsG2B+lTgRJ1ICZtiM5GWCWZVoVrLaDRvIRng0=
github.com/libp2p/go-libp2p-core v0.2.4 h1:Et6ykkTwI6PU44tr8qUF9k43vP0aduMNniShAbUJJw8=
github.com/libp2p/go-libp2p-core v0.2.4/go.mod h1:STh4fdfa5vDYr0/SzYYeqnt+E6KfEV5VxfIrm0bcI0g=
github.com/libp2p/go-libp2p-crypto v0.0.1/go.mod h1:yJkNyDmO341d5wwXxDUGO0LykUVT72ImHNUqh5D/dBE=
github.com/libp2p/go-libp2p-crypto v0.1.0 h1:k9MFy+o2zGDNGsaoZl0MA3iZ75qXxr9OOoAZF+sD5OQ=
github.com/libp2p/go-libp2p-crypto v0.1.0/go.mod h1:sPUokVISZiy+nNuTTH/TY+leRSxnFj/2GLjtOTW90hI=
github.com/libp2p/go-libp2p-discovery v0.1.0 h1:j+R6cokKcGbnZLf4kcNwpx6mDEUPF3N6SrqMymQhmvs=
github.com/libp2p/go-libp2p-discovery v0.1.0/go.mod h1:4F/x+aldVHjHDHuX85x1zWoFTGElt8HnoDzwkFZm29g=
github.com/libp2p/go-libp2p-discovery v0.2.0 h1:1p3YSOq7VsgaL+xVHPi8XAmtGyas6D2J6rWBEfz/aiY=
github.com/libp2p/go-libp2p-discovery v0.2.0/go.mod h1:s4VGaxYMbw4+4+tsoQTqh7wfxg97AEdo4GYBt6BadWg=
github.com/libp2p/go-libp2p-host v0.0.1/go.mod h1:qWd+H1yuU0m5CwzAkvbSjqKairayEHdR5MMl7Cwa7Go=
github.com/libp2p/go-libp2p-host v0.1.0 h1:OZwENiFm6JOK3YR5PZJxkXlJE8a5u8g4YvAUrEV2MjM=
github.com/libp2p/go-libp2p-host v0.1.0/go.mod h1:5+fWuLbDn8OxoxPN3CV0vsLe1hAKScSMbT84qRfxum8=
@ -348,8 +362,8 @@ github.com/libp2p/go-libp2p-pnet v0.1.0/go.mod h1:ZkyZw3d0ZFOex71halXRihWf9WH/j3
github.com/libp2p/go-libp2p-protocol v0.0.1/go.mod h1:Af9n4PiruirSDjHycM1QuiMi/1VZNHYcK8cLgFJLZ4s=
github.com/libp2p/go-libp2p-protocol v0.1.0 h1:HdqhEyhg0ToCaxgMhnOmUO8snQtt/kQlcjVk3UoJU3c=
github.com/libp2p/go-libp2p-protocol v0.1.0/go.mod h1:KQPHpAabB57XQxGrXCNvbL6UEXfQqUgC/1adR2Xtflk=
github.com/libp2p/go-libp2p-pubsub v0.1.0 h1:SmQeMa7IUv5vadh0fYgYsafWCBA1sCy5d/68kIYqGcU=
github.com/libp2p/go-libp2p-pubsub v0.1.0/go.mod h1:ZwlKzRSe1eGvSIdU5bD7+8RZN/Uzw0t1Bp9R1znpR/Q=
github.com/libp2p/go-libp2p-pubsub v0.2.3 h1:qJRnRnM7Z4xnHb4i6EBb3DKQXRPgtFWlKP4AmfJudLQ=
github.com/libp2p/go-libp2p-pubsub v0.2.3/go.mod h1:Jscj3fk23R5mCrOwb625xjVs5ZEyTZcx/OlTwMDqU+g=
github.com/libp2p/go-libp2p-quic-transport v0.1.1 h1:MFMJzvsxIEDEVKzO89BnB/FgvMj9WI4GDGUW2ArDPUA=
github.com/libp2p/go-libp2p-quic-transport v0.1.1/go.mod h1:wqG/jzhF3Pu2NrhJEvE+IE0NTHNXslOPn9JQzyCAxzU=
github.com/libp2p/go-libp2p-record v0.1.0/go.mod h1:ujNc8iuE5dlKWVy6wuL6dd58t0n7xI4hAIl8pE6wu5Q=
@ -365,8 +379,8 @@ github.com/libp2p/go-libp2p-secio v0.2.0 h1:ywzZBsWEEz2KNTn5RtzauEDq5RFEefPsttXY
github.com/libp2p/go-libp2p-secio v0.2.0/go.mod h1:2JdZepB8J5V9mBp79BmwsaPQhRPNN2NrnB2lKQcdy6g=
github.com/libp2p/go-libp2p-swarm v0.1.0/go.mod h1:wQVsCdjsuZoc730CgOvh5ox6K8evllckjebkdiY5ta4=
github.com/libp2p/go-libp2p-swarm v0.2.0/go.mod h1:x07b4zkMFo2EvgPV2bMTlNmdQc8i+74Jjio7xGvsTgU=
github.com/libp2p/go-libp2p-swarm v0.2.1 h1:9A8oQqPIZvbaRyrjViHeDYS7fE7fNtP7BRWdJrBHbe8=
github.com/libp2p/go-libp2p-swarm v0.2.1/go.mod h1:x07b4zkMFo2EvgPV2bMTlNmdQc8i+74Jjio7xGvsTgU=
github.com/libp2p/go-libp2p-swarm v0.2.2 h1:T4hUpgEs2r371PweU3DuH7EOmBIdTBCwWs+FLcgx3bQ=
github.com/libp2p/go-libp2p-swarm v0.2.2/go.mod h1:fvmtQ0T1nErXym1/aa1uJEyN7JzaTNyBcHImCxRpPKU=
github.com/libp2p/go-libp2p-testing v0.0.2/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E=
github.com/libp2p/go-libp2p-testing v0.0.3/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E=
github.com/libp2p/go-libp2p-testing v0.0.4/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E=
@ -394,6 +408,8 @@ github.com/libp2p/go-nat v0.0.3 h1:l6fKV+p0Xa354EqQOQP+d8CivdLM4kl5GxC1hSc/UeI=
github.com/libp2p/go-nat v0.0.3/go.mod h1:88nUEt0k0JD45Bk93NIwDqjlhiOwOoV36GchpcVc1yI=
github.com/libp2p/go-openssl v0.0.2 h1:9pP2d3Ubaxkv7ZisLjx9BFwgOGnQdQYnfcH29HNY3ls=
github.com/libp2p/go-openssl v0.0.2/go.mod h1:v8Zw2ijCSWBQi8Pq5GAixw6DbFfa9u6VIYDXnvOXkc0=
github.com/libp2p/go-openssl v0.0.3 h1:wjlG7HvQkt4Fq4cfH33Ivpwp0omaElYEi9z26qaIkIk=
github.com/libp2p/go-openssl v0.0.3/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc=
github.com/libp2p/go-reuseport v0.0.1 h1:7PhkfH73VXfPJYKQ6JwS5I/eVcoyYi9IMNGc6FWpFLw=
github.com/libp2p/go-reuseport v0.0.1/go.mod h1:jn6RmB1ufnQwl0Q1f+YxAj8isJgDCQzaaxIFYDhcYEA=
github.com/libp2p/go-reuseport-transport v0.0.2 h1:WglMwyXyBu61CMkjCCtnmqNqnjib0GIEjMiHTwR/KN4=
@ -403,9 +419,13 @@ github.com/libp2p/go-stream-muxer-multistream v0.2.0 h1:714bRJ4Zy9mdhyTLJ+ZKiROm
github.com/libp2p/go-stream-muxer-multistream v0.2.0/go.mod h1:j9eyPol/LLRqT+GPLSxvimPhNph4sfYfMoDPd7HkzIc=
github.com/libp2p/go-tcp-transport v0.1.0 h1:IGhowvEqyMFknOar4FWCKSWE0zL36UFKQtiRQD60/8o=
github.com/libp2p/go-tcp-transport v0.1.0/go.mod h1:oJ8I5VXryj493DEJ7OsBieu8fcg2nHGctwtInJVpipc=
github.com/libp2p/go-tcp-transport v0.1.1 h1:yGlqURmqgNA2fvzjSgZNlHcsd/IulAnKM8Ncu+vlqnw=
github.com/libp2p/go-tcp-transport v0.1.1/go.mod h1:3HzGvLbx6etZjnFlERyakbaYPdfjg2pWP97dFZworkY=
github.com/libp2p/go-testutil v0.1.0/go.mod h1:81b2n5HypcVyrCg/MJx4Wgfp/VHojytjVe/gLzZ2Ehc=
github.com/libp2p/go-ws-transport v0.1.0 h1:F+0OvvdmPTDsVc4AjPHjV7L7Pk1B7D5QwtDcKE2oag4=
github.com/libp2p/go-ws-transport v0.1.0/go.mod h1:rjw1MG1LU9YDC6gzmwObkPd/Sqwhw7yT74kj3raBFuo=
github.com/libp2p/go-ws-transport v0.1.2 h1:VnxQcLfSGtqupqPpBNu8fUiCv+IN1RJ2BcVqQEM+z8E=
github.com/libp2p/go-ws-transport v0.1.2/go.mod h1:dsh2Ld8F+XNmzpkaAijmg5Is+e9l6/1tK/6VFOdN69Y=
github.com/libp2p/go-yamux v1.2.2/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow=
github.com/libp2p/go-yamux v1.2.3 h1:xX8A36vpXb59frIzWFdEgptLMsOANMFq2K7fPRlunYI=
github.com/libp2p/go-yamux v1.2.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow=
@ -417,9 +437,8 @@ github.com/marten-seemann/qtls v0.2.3 h1:0yWJ43C62LsZt08vuQJDK1uC1czUc3FJeCLPoNA
github.com/marten-seemann/qtls v0.2.3/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
@ -441,6 +460,8 @@ github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+
github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U=
github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771 h1:MHkK1uRtFbVqvAgvWxafZe54+5uBxLluGylDiKgdhwo=
github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU=
github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
@ -454,18 +475,26 @@ github.com/multiformats/go-multiaddr v0.0.1/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lg
github.com/multiformats/go-multiaddr v0.0.2/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44=
github.com/multiformats/go-multiaddr v0.0.4 h1:WgMSI84/eRLdbptXMkMWDXPjPq7SPLIgGUVm2eroyU4=
github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44=
github.com/multiformats/go-multiaddr v0.1.0/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44=
github.com/multiformats/go-multiaddr v0.1.1 h1:rVAztJYMhCQ7vEFr8FvxW3mS+HF2eY/oPbOMeS0ZDnE=
github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo=
github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q=
github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q=
github.com/multiformats/go-multiaddr-dns v0.0.3 h1:P19q/k9jwmtgh+qXFkKfgFM7rCg/9l5AVqh7VNxSXhs=
github.com/multiformats/go-multiaddr-dns v0.0.3/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q=
github.com/multiformats/go-multiaddr-dns v0.2.0 h1:YWJoIDwLePniH7OU5hBnDZV6SWuvJqJ0YtN6pLeH9zA=
github.com/multiformats/go-multiaddr-dns v0.2.0/go.mod h1:TJ5pr5bBO7Y1B18djPuRsVkduhQH2YqYSbxWJzYGdK0=
github.com/multiformats/go-multiaddr-fmt v0.0.1 h1:5YjeOIzbX8OTKVaN72aOzGIYW7PnrZrnkDyOfAWRSMA=
github.com/multiformats/go-multiaddr-fmt v0.0.1/go.mod h1:aBYjqL4T/7j4Qx+R73XSv/8JsgnRFlf0w2KGLCmXl3Q=
github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E=
github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo=
github.com/multiformats/go-multiaddr-net v0.0.1 h1:76O59E3FavvHqNg7jvzWzsPSW5JSi/ek0E4eiDVbg9g=
github.com/multiformats/go-multiaddr-net v0.0.1/go.mod h1:nw6HSxNmCIQH27XPGBuX+d1tnvM7ihcFwHMSstNAVUU=
github.com/multiformats/go-multiaddr-net v0.1.0 h1:ZepO8Ezwovd+7b5XPPDhQhayk1yt0AJpzQBpq9fejx4=
github.com/multiformats/go-multiaddr-net v0.1.0/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ=
github.com/multiformats/go-multibase v0.0.1 h1:PN9/v21eLywrFWdFNsFKaU04kLJzuYzmrJR+ubhT9qA=
github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs=
github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U=
github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po=
github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
github.com/multiformats/go-multihash v0.0.9 h1:aoijQXYYl7Xtb2pUUP68R+ys1TlnlR3eX6wmozr0Hp4=
github.com/multiformats/go-multihash v0.0.9/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
github.com/multiformats/go-multistream v0.0.1/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg=
@ -540,6 +569,7 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
@ -581,8 +611,8 @@ github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7V
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.1 h1:8dP3SGL7MPB94crU3bEPplMPe83FI4EouesJUeFHv50=
go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA=
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/dig v1.7.0 h1:E5/L92iQTNJTjfgJF2KgU+/JpMaiuvK2DHLBj0+kSZk=
@ -611,8 +641,8 @@ golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 h1:Gv7RPwsi3eZ2Fgewe3CBsuOebPwO27PoXzRpJPsvSSM=
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@ -632,13 +662,11 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190611141213-3f473d35a33a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -668,9 +696,8 @@ golang.org/x/sys v0.0.0-20190526052359-791d8a0f4d09/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456 h1:ng0gs1AKnRRuEMZoTLLlbOd+C17zUDepwGQBb/n+JVg=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69 h1:rOhMmluY6kLMhdnrivzec6lLgaVbMHMn2ISQXJeJ5EM=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
@ -681,6 +708,7 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181130052023-1c3d964395ce/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
@ -691,6 +719,8 @@ golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/api v0.3.2/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
@ -710,6 +740,7 @@ google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@ -724,6 +755,7 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD
gopkg.in/urfave/cli.v2 v2.0.0-20180128182452-d3ae77c26ac8 h1:Ggy3mWN4l3PUFPfSG0YB3n5fVYggzysUmiUQ89SnX6Y=
gopkg.in/urfave/cli.v2 v2.0.0-20180128182452-d3ae77c26ac8/go.mod h1:cKXr3E0k4aosgycml1b5z33BVV6hai1Kh7uDgFOkbcs=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@ -4,7 +4,7 @@ import (
"io"
"math/bits"
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
sectorbuilder "github.com/filecoin-project/filecoin-ffi"
)
func PaddedSize(size uint64) uint64 {

View File

@ -1,8 +1,9 @@
package padreader
import (
"gotest.tools/assert"
"testing"
"gotest.tools/assert"
)
func TestComputePaddedSize(t *testing.T) {

View File

@ -17,8 +17,6 @@ func TempSectorbuilder(sectorSize uint64, ds dtypes.MetadataDS) (*SectorBuilder,
sb, err := TempSectorbuilderDir(dir, sectorSize, ds)
return sb, func() {
sb.Destroy()
if err := os.RemoveAll(dir); err != nil {
log.Warn("failed to clean up temp sectorbuilder: ", err)
}

View File

@ -0,0 +1 @@
package sectorbuilder

View File

@ -7,13 +7,13 @@ import (
"strconv"
"sync"
"sync/atomic"
"unsafe"
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
sectorbuilder "github.com/filecoin-project/filecoin-ffi"
"github.com/ipfs/go-datastore"
logging "github.com/ipfs/go-log"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/node/modules/dtypes"
)
@ -21,17 +21,12 @@ import (
const PoStReservedWorkers = 1
const PoRepProofPartitions = 2
var lastSectorIdKey = datastore.NewKey("/sectorbuilder/last")
var LastSectorIdKey = datastore.NewKey("/sectorbuilder/last")
var log = logging.Logger("sectorbuilder")
type SectorSealingStatus = sectorbuilder.SectorSealingStatus
type StagedSectorMetadata = sectorbuilder.StagedSectorMetadata
type SortedSectorInfo = sectorbuilder.SortedSectorInfo
type SectorInfo = sectorbuilder.SectorInfo
type SortedPublicSectorInfo = sectorbuilder.SortedPublicSectorInfo
type SortedPrivateSectorInfo = sectorbuilder.SortedPrivateSectorInfo
type SealTicket = sectorbuilder.SealTicket
@ -45,14 +40,16 @@ type PublicPieceInfo = sectorbuilder.PublicPieceInfo
type RawSealPreCommitOutput sectorbuilder.RawSealPreCommitOutput
type EPostCandidate = sectorbuilder.Candidate
const CommLen = sectorbuilder.CommitmentBytesLen
type SectorBuilder struct {
handle unsafe.Pointer
ds dtypes.MetadataDS
idLk sync.Mutex
ds dtypes.MetadataDS
idLk sync.Mutex
ssize uint64
ssize uint64
lastID uint64
Miner address.Address
@ -130,8 +127,6 @@ func New(cfg *Config, ds dtypes.MetadataDS) (*SectorBuilder, error) {
return nil, xerrors.Errorf("minimum worker threads is %d, specified %d", PoStReservedWorkers, cfg.WorkerThreads)
}
proverId := addressToProverID(cfg.Miner)
for _, dir := range []string{cfg.StagedDir, cfg.SealedDir, cfg.CacheDir, cfg.MetadataDir} {
if err := os.Mkdir(dir, 0755); err != nil {
if os.IsExist(err) {
@ -142,7 +137,7 @@ func New(cfg *Config, ds dtypes.MetadataDS) (*SectorBuilder, error) {
}
var lastUsedID uint64
b, err := ds.Get(lastSectorIdKey)
b, err := ds.Get(LastSectorIdKey)
switch err {
case nil:
i, err := strconv.ParseInt(string(b), 10, 64)
@ -155,11 +150,6 @@ func New(cfg *Config, ds dtypes.MetadataDS) (*SectorBuilder, error) {
return nil, err
}
sbp, err := sectorbuilder.InitSectorBuilder(cfg.SectorSize, PoRepProofPartitions, lastUsedID, cfg.MetadataDir, proverId, cfg.SealedDir, cfg.StagedDir, cfg.CacheDir, 16, cfg.WorkerThreads)
if err != nil {
return nil, err
}
rlimit := cfg.WorkerThreads - PoStReservedWorkers
sealLocal := rlimit > 0
@ -169,10 +159,10 @@ func New(cfg *Config, ds dtypes.MetadataDS) (*SectorBuilder, error) {
}
sb := &SectorBuilder{
handle: sbp,
ds: ds,
ds: ds,
ssize: cfg.SectorSize,
ssize: cfg.SectorSize,
lastID: lastUsedID,
stagedDir: cfg.StagedDir,
sealedDir: cfg.SealedDir,
@ -205,9 +195,10 @@ func NewStandalone(cfg *Config) (*SectorBuilder, error) {
}
return &SectorBuilder{
handle: nil,
ds: nil,
ssize: cfg.SectorSize,
Miner: cfg.Miner,
stagedDir: cfg.StagedDir,
sealedDir: cfg.SealedDir,
@ -272,19 +263,14 @@ func addressToProverID(a address.Address) [32]byte {
return proverId
}
func (sb *SectorBuilder) Destroy() {
sectorbuilder.DestroySectorBuilder(sb.handle)
}
func (sb *SectorBuilder) AcquireSectorId() (uint64, error) {
sb.idLk.Lock()
defer sb.idLk.Unlock()
id, err := sectorbuilder.AcquireSectorId(sb.handle)
if err != nil {
return 0, err
}
err = sb.ds.Put(lastSectorIdKey, []byte(fmt.Sprint(id)))
sb.lastID++
id := sb.lastID
err := sb.ds.Put(LastSectorIdKey, []byte(fmt.Sprint(id)))
if err != nil {
return 0, err
}
@ -305,7 +291,7 @@ func (sb *SectorBuilder) AddPiece(pieceSize uint64, sectorId uint64, file io.Rea
return PublicPieceInfo{}, err
}
_, _, commP, err := sectorbuilder.StandaloneWriteWithAlignment(f, pieceSize, stagedFile, existingPieceSizes)
_, _, commP, err := sectorbuilder.WriteWithAlignment(f, pieceSize, stagedFile, existingPieceSizes)
if err != nil {
return PublicPieceInfo{}, err
}
@ -329,7 +315,8 @@ func (sb *SectorBuilder) ReadPieceFromSealedSector(pieceKey string) ([]byte, err
ret := sb.RateLimit()
defer ret()
return sectorbuilder.ReadPieceFromSealedSector(sb.handle, pieceKey)
panic("fixme")
//return sectorbuilder.Unseal(sb.handle, pieceKey)
}
func (sb *SectorBuilder) sealPreCommitRemote(call workerCall) (RawSealPreCommitOutput, error) {
@ -394,7 +381,7 @@ func (sb *SectorBuilder) SealPreCommit(sectorID uint64, ticket SealTicket, piece
stagedPath := sb.StagedSectorPath(sectorID)
rspco, err := sectorbuilder.StandaloneSealPreCommit(
rspco, err := sectorbuilder.SealPreCommit(
sb.ssize,
PoRepProofPartitions,
cacheDir,
@ -431,7 +418,7 @@ func (sb *SectorBuilder) sealCommitLocal(sectorID uint64, ticket SealTicket, see
return nil, err
}
proof, err = sectorbuilder.StandaloneSealCommit(
proof, err = sectorbuilder.SealCommit(
sb.ssize,
PoRepProofPartitions,
cacheDir,
@ -452,7 +439,7 @@ func (sb *SectorBuilder) sealCommitLocal(sectorID uint64, ticket SealTicket, see
return proof, nil
}
func (sb *SectorBuilder) SealCommit(sectorID uint64, ticket SealTicket, seed SealSeed, pieces []PublicPieceInfo, pieceKeys []string, rspco RawSealPreCommitOutput) (proof []byte, err error) {
func (sb *SectorBuilder) SealCommit(sectorID uint64, ticket SealTicket, seed SealSeed, pieces []PublicPieceInfo, rspco RawSealPreCommitOutput) (proof []byte, err error) {
call := workerCall{
task: WorkerTask{
Type: WorkerCommit,
@ -484,49 +471,91 @@ func (sb *SectorBuilder) SealCommit(sectorID uint64, ticket SealTicket, seed Sea
return nil, xerrors.Errorf("commit: %w", err)
}
if pieceKeys == nil {
return
}
pmeta := make([]sectorbuilder.PieceMetadata, len(pieces))
for i, piece := range pieces {
pmeta[i] = sectorbuilder.PieceMetadata{
Key: pieceKeys[i],
Size: piece.Size,
CommP: piece.CommP,
}
}
sealedPath, err := sb.SealedSectorPath(sectorID)
if err != nil {
return nil, err
}
cacheDir, err := sb.sectorCacheDir(sectorID)
if err != nil {
return nil, err
}
err = sectorbuilder.ImportSealedSector(
sb.handle,
sectorID,
cacheDir,
sealedPath,
ticket,
seed,
rspco.CommR,
rspco.CommD,
rspco.CommC,
rspco.CommRLast,
proof,
pmeta,
)
if err != nil {
return nil, xerrors.Errorf("ImportSealedSector: %w", err)
}
return proof, nil
}
func (sb *SectorBuilder) ComputeElectionPoSt(sectorInfo SortedPublicSectorInfo, challengeSeed []byte, winners []EPostCandidate) ([]byte, error) {
if len(challengeSeed) != CommLen {
return nil, xerrors.Errorf("given challenge seed was the wrong length: %d != %d", len(challengeSeed), CommLen)
}
var cseed [CommLen]byte
copy(cseed[:], challengeSeed)
privsects, err := sb.pubSectorToPriv(sectorInfo)
if err != nil {
return nil, err
}
proverID := addressToProverID(sb.Miner)
return sectorbuilder.GeneratePoSt(sb.ssize, proverID, privsects, cseed, winners)
}
func (sb *SectorBuilder) GenerateEPostCandidates(sectorInfo SortedPublicSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]EPostCandidate, error) {
privsectors, err := sb.pubSectorToPriv(sectorInfo)
if err != nil {
return nil, err
}
challengeCount := electionPostChallengeCount(uint64(len(sectorInfo.Values())))
proverID := addressToProverID(sb.Miner)
return sectorbuilder.GenerateCandidates(sb.ssize, proverID, challengeSeed, challengeCount, privsectors)
}
func (sb *SectorBuilder) pubSectorToPriv(sectorInfo SortedPublicSectorInfo) (SortedPrivateSectorInfo, error) {
var out []sectorbuilder.PrivateSectorInfo
for _, s := range sectorInfo.Values() {
cachePath, err := sb.sectorCacheDir(s.SectorID)
if err != nil {
return SortedPrivateSectorInfo{}, xerrors.Errorf("getting cache path for sector %d: %w", s.SectorID, err)
}
sealedPath, err := sb.SealedSectorPath(s.SectorID)
if err != nil {
return SortedPrivateSectorInfo{}, xerrors.Errorf("getting sealed path for sector %d: %w", s.SectorID, err)
}
out = append(out, sectorbuilder.PrivateSectorInfo{
SectorID: s.SectorID,
CommR: s.CommR,
CacheDirPath: cachePath,
SealedSectorPath: sealedPath,
})
}
return NewSortedPrivateSectorInfo(out), nil
}
func (sb *SectorBuilder) GenerateFallbackPoSt(sectorInfo SortedPublicSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]EPostCandidate, []byte, error) {
privsectors, err := sb.pubSectorToPriv(sectorInfo)
if err != nil {
return nil, nil, err
}
challengeCount := fallbackPostChallengeCount(uint64(len(sectorInfo.Values())))
proverID := addressToProverID(sb.Miner)
candidates, err := sectorbuilder.GenerateCandidates(sb.ssize, proverID, challengeSeed, challengeCount, privsectors)
if err != nil {
return nil, nil, err
}
proof, err := sectorbuilder.GeneratePoSt(sb.ssize, proverID, privsectors, challengeSeed, candidates)
return candidates, proof, err
}
func (sb *SectorBuilder) Stop() {
close(sb.stopping)
}
func electionPostChallengeCount(sectors uint64) uint64 {
// ceil(sectors / build.SectorChallengeRatioDiv)
return (sectors + build.SectorChallengeRatioDiv - 1) / build.SectorChallengeRatioDiv
}
func fallbackPostChallengeCount(sectors uint64) uint64 {
challengeCount := electionPostChallengeCount(sectors)
if challengeCount > build.MaxFallbackPostChallengeCount {
return build.MaxFallbackPostChallengeCount
}
return challengeCount
}

View File

@ -2,6 +2,7 @@ package sectorbuilder_test
import (
"context"
"fmt"
"io"
"io/ioutil"
"math/rand"
@ -15,6 +16,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
ffi "github.com/filecoin-project/filecoin-ffi"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/lib/sectorbuilder"
)
@ -59,7 +61,7 @@ func (s *seal) commit(t *testing.T, sb *sectorbuilder.SectorBuilder, done func()
TicketBytes: [32]byte{0, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 9, 8, 7, 6, 45, 3, 2, 1, 0, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 9},
}
proof, err := sb.SealCommit(s.sid, s.ticket, seed, []sectorbuilder.PublicPieceInfo{s.ppi}, []string{"foo"}, s.pco)
proof, err := sb.SealCommit(s.sid, s.ticket, seed, []sectorbuilder.PublicPieceInfo{s.ppi}, s.pco)
if err != nil {
t.Fatalf("%+v", err)
}
@ -76,26 +78,44 @@ func (s *seal) commit(t *testing.T, sb *sectorbuilder.SectorBuilder, done func()
done()
}
func (s *seal) post(t *testing.T, sb *sectorbuilder.SectorBuilder) {
func post(t *testing.T, sb *sectorbuilder.SectorBuilder, seals ...seal) time.Time {
cSeed := [32]byte{0, 9, 2, 7, 6, 5, 4, 3, 2, 1, 0, 9, 8, 7, 6, 45, 3, 2, 1, 0, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 9}
ssi := sectorbuilder.NewSortedSectorInfo([]sectorbuilder.SectorInfo{{
SectorID: s.sid,
CommR: s.pco.CommR,
}})
ppi := make([]ffi.PublicSectorInfo, len(seals))
for i, s := range seals {
ppi[i] = ffi.PublicSectorInfo{
SectorID: s.sid,
CommR: s.pco.CommR,
}
}
postProof, err := sb.GeneratePoSt(ssi, cSeed, []uint64{})
ssi := sectorbuilder.NewSortedPublicSectorInfo(ppi)
candndates, err := sb.GenerateEPostCandidates(ssi, cSeed, []uint64{})
if err != nil {
t.Fatalf("%+v", err)
}
ok, err := sectorbuilder.VerifyPost(context.TODO(), sb.SectorSize(), ssi, cSeed, postProof, []uint64{})
genCandidates := time.Now()
if len(candndates) != 1 {
t.Fatal("expected 1 candidate")
}
postProof, err := sb.ComputeElectionPoSt(ssi, cSeed[:], candndates)
if err != nil {
t.Fatalf("%+v", err)
}
ok, err := sectorbuilder.VerifyElectionPost(context.TODO(), sb.SectorSize(), ssi, cSeed[:], postProof, candndates, sb.Miner)
if err != nil {
t.Fatalf("%+v", err)
}
if !ok {
t.Fatal("bad post")
}
return genCandidates
}
func TestSealAndVerify(t *testing.T) {
@ -123,7 +143,10 @@ func TestSealAndVerify(t *testing.T) {
t.Fatalf("%+v", err)
}
cleanup := func() {
sb.Destroy()
if t.Failed() {
fmt.Printf("not removing %s\n", dir)
return
}
if err := os.RemoveAll(dir); err != nil {
t.Error(err)
}
@ -137,20 +160,95 @@ func TestSealAndVerify(t *testing.T) {
s := seal{sid: si}
start := time.Now()
s.precommit(t, sb, 1, func() {})
precommit := time.Now()
s.commit(t, sb, func() {})
s.post(t, sb)
commit := time.Now()
genCandidiates := post(t, sb, s)
epost := time.Now()
// Restart sectorbuilder, re-run post
sb.Destroy()
sb, err = sectorbuilder.TempSectorbuilderDir(dir, sectorSize, ds)
if err != nil {
t.Fatalf("%+v", err)
}
s.post(t, sb)
post(t, sb, s)
fmt.Printf("PreCommit: %s\n", precommit.Sub(start).String())
fmt.Printf("Commit: %s\n", commit.Sub(precommit).String())
fmt.Printf("GenCandidates: %s\n", genCandidiates.Sub(commit).String())
fmt.Printf("EPoSt: %s\n", epost.Sub(genCandidiates).String())
}
func TestSealPoStNoCommit(t *testing.T) {
if runtime.NumCPU() < 10 && os.Getenv("CI") == "" { // don't bother on slow hardware
t.Skip("this is slow")
}
os.Setenv("BELLMAN_NO_GPU", "1")
os.Setenv("RUST_LOG", "info")
build.SectorSizes = []uint64{sectorSize}
if err := build.GetParams(true, true); err != nil {
t.Fatalf("%+v", err)
}
ds := datastore.NewMapDatastore()
dir, err := ioutil.TempDir("", "sbtest")
if err != nil {
t.Fatal(err)
}
sb, err := sectorbuilder.TempSectorbuilderDir(dir, sectorSize, ds)
if err != nil {
t.Fatalf("%+v", err)
}
cleanup := func() {
if t.Failed() {
fmt.Printf("not removing %s\n", dir)
return
}
if err := os.RemoveAll(dir); err != nil {
t.Error(err)
}
}
defer cleanup()
si, err := sb.AcquireSectorId()
if err != nil {
t.Fatalf("%+v", err)
}
s := seal{sid: si}
start := time.Now()
s.precommit(t, sb, 1, func() {})
precommit := time.Now()
// Restart sectorbuilder, re-run post
sb, err = sectorbuilder.TempSectorbuilderDir(dir, sectorSize, ds)
if err != nil {
t.Fatalf("%+v", err)
}
genCandidiates := post(t, sb, s)
epost := time.Now()
fmt.Printf("PreCommit: %s\n", precommit.Sub(start).String())
fmt.Printf("GenCandidates: %s\n", genCandidiates.Sub(precommit).String())
fmt.Printf("EPoSt: %s\n", epost.Sub(genCandidiates).String())
}
func TestSealAndVerify2(t *testing.T) {
@ -178,7 +276,6 @@ func TestSealAndVerify2(t *testing.T) {
t.Fatalf("%+v", err)
}
cleanup := func() {
sb.Destroy()
if err := os.RemoveAll(dir); err != nil {
t.Error(err)
}
@ -210,6 +307,8 @@ func TestSealAndVerify2(t *testing.T) {
go s1.commit(t, sb, wg.Done)
go s2.commit(t, sb, wg.Done)
wg.Wait()
post(t, sb, s1, s2)
}
func TestAcquireID(t *testing.T) {
@ -235,8 +334,6 @@ func TestAcquireID(t *testing.T) {
assertAcquire(2)
assertAcquire(3)
sb.Destroy()
sb, err = sectorbuilder.TempSectorbuilderDir(dir, sectorSize, ds)
if err != nil {
t.Fatalf("%+v", err)
@ -246,7 +343,6 @@ func TestAcquireID(t *testing.T) {
assertAcquire(5)
assertAcquire(6)
sb.Destroy()
if err := os.RemoveAll(dir); err != nil {
t.Error(err)
}

View File

@ -4,18 +4,12 @@ import (
"context"
"io"
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
sectorbuilder "github.com/filecoin-project/filecoin-ffi"
"go.opencensus.io/trace"
"github.com/filecoin-project/lotus/chain/address"
)
func (sb *SectorBuilder) GeneratePoSt(sectorInfo SortedSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]byte, error) {
// Wait, this is a blocking method with no way of interrupting it?
// does it checkpoint itself?
return sectorbuilder.GeneratePoSt(sb.handle, sectorInfo, challengeSeed, faults)
}
func (sb *SectorBuilder) SectorSize() uint64 {
return sb.ssize
}
@ -33,14 +27,37 @@ func VerifySeal(sectorSize uint64, commR, commD []byte, proverID address.Address
return sectorbuilder.VerifySeal(sectorSize, commRa, commDa, proverIDa, ticketa, seeda, sectorID, proof)
}
func NewSortedSectorInfo(sectors []SectorInfo) SortedSectorInfo {
return sectorbuilder.NewSortedSectorInfo(sectors...)
func NewSortedPrivateSectorInfo(sectors []sectorbuilder.PrivateSectorInfo) SortedPrivateSectorInfo {
return sectorbuilder.NewSortedPrivateSectorInfo(sectors...)
}
func VerifyPost(ctx context.Context, sectorSize uint64, sectorInfo SortedSectorInfo, challengeSeed [CommLen]byte, proof []byte, faults []uint64) (bool, error) {
func NewSortedPublicSectorInfo(sectors []sectorbuilder.PublicSectorInfo) SortedPublicSectorInfo {
return sectorbuilder.NewSortedPublicSectorInfo(sectors...)
}
func VerifyElectionPost(ctx context.Context, sectorSize uint64, sectorInfo SortedPublicSectorInfo, challengeSeed []byte, proof []byte, candidates []EPostCandidate, proverID address.Address) (bool, error) {
challengeCount := electionPostChallengeCount(uint64(len(sectorInfo.Values())))
return verifyPost(ctx, sectorSize, sectorInfo, challengeCount, challengeSeed, proof, candidates, proverID)
}
func VerifyFallbackPost(ctx context.Context, sectorSize uint64, sectorInfo SortedPublicSectorInfo, challengeSeed []byte, proof []byte, candidates []EPostCandidate, proverID address.Address) (bool, error) {
challengeCount := fallbackPostChallengeCount(uint64(len(sectorInfo.Values())))
return verifyPost(ctx, sectorSize, sectorInfo, challengeCount, challengeSeed, proof, candidates, proverID)
}
func verifyPost(ctx context.Context, sectorSize uint64, sectorInfo SortedPublicSectorInfo, challengeCount uint64, challengeSeed []byte, proof []byte, candidates []EPostCandidate, proverID address.Address) (bool, error) {
if challengeCount != uint64(len(candidates)) {
log.Warnf("verifyPost with wrong candidate count: expected %d, got %d", challengeCount, len(candidates))
return false, nil // user input, dont't error
}
var challengeSeeda [CommLen]byte
copy(challengeSeeda[:], challengeSeed)
_, span := trace.StartSpan(ctx, "VerifyPoSt")
defer span.End()
return sectorbuilder.VerifyPoSt(sectorSize, sectorInfo, challengeSeed, proof, faults)
prover := addressToProverID(proverID)
return sectorbuilder.VerifyPoSt(sectorSize, sectorInfo, challengeSeeda, challengeCount, proof, candidates, prover)
}
func GeneratePieceCommitment(piece io.Reader, pieceSize uint64) (commP [CommLen]byte, err error) {
@ -57,6 +74,6 @@ func GeneratePieceCommitment(piece io.Reader, pieceSize uint64) (commP [CommLen]
return commP, werr()
}
func GenerateDataCommitment(ssize uint64, pieces []PublicPieceInfo) ([CommLen]byte, error) {
func GenerateDataCommitment(ssize uint64, pieces []sectorbuilder.PublicPieceInfo) ([CommLen]byte, error) {
return sectorbuilder.GenerateDataCommitment(ssize, pieces)
}
}

View File

@ -2,14 +2,15 @@ package main
import (
"crypto/rand"
"github.com/filecoin-project/lotus/lib/jsonrpc"
"github.com/filecoin-project/lotus/node/repo"
"io"
"io/ioutil"
"os"
"sync"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/lib/jsonrpc"
"github.com/filecoin-project/lotus/node/repo"
)
type NodeState int

View File

@ -45,8 +45,6 @@ class FullNode extends React.Component {
return this.props.client.call('Filecoin.PaychVoucherList', [paych])
}))
let minerList = await this.props.client.call('Filecoin.MinerAddresses', [])
let mpoolPending = (await this.props.client.call('Filecoin.MpoolPending', [tipset])).length
this.setState(() => ({
@ -62,8 +60,6 @@ class FullNode extends React.Component {
vouchers: vouchers,
defaultAddr: defaultAddr,
minerList: minerList,
}))
}
@ -110,11 +106,6 @@ class FullNode extends React.Component {
)
}
let miners = <span/>
if(this.state.minerList.length > 0) {
miners = this.state.minerList.map((a, k) => <div key={k}><Address miner={true} client={this.props.client} addr={a} mountWindow={this.props.mountWindow}/></div>)
}
let storageMine = <a href="#" onClick={this.startStorageMiner} hidden={!this.props.spawnStorageNode}>[Spawn Storage Miner]</a>
let addresses = this.state.addrs.map((addr) => {
@ -153,7 +144,6 @@ class FullNode extends React.Component {
<div>
<div>Balances: [New <a href="#" onClick={this.newSecpAddr}>[Secp256k1]</a> <a href="#" onClick={this.newBLSAddr}>[BLS]</a>]</div>
<div>{addresses}</div>
<div>{miners}</div>
<div>{paychannels}</div>
</div>

View File

@ -181,7 +181,7 @@ class MinerState extends React.Component {
<div>Worker: <Address addr={this.state.worker} client={this.props.client} mountWindow={this.props.mountWindow}/></div>
<div>Sector Size: <b>{this.state.sectorSize/1024}</b> KiB</div>
<div>Power: <b>{state.Power}</b> (<b>{state.Power/this.state.networkPower*100}</b>%)</div>
<div>Proving Period End: <b>{state.ProvingPeriodEnd}</b></div>
<div>Election Period Start: <b>{state.ElectionPeriodStart}</b></div>
<div>Slashed: <b>{state.SlashedAt === 0 ? "NO" : state.SlashedAt}</b></div>
<div>
<div>----</div>

View File

@ -120,7 +120,7 @@ class StorageNode extends React.Component {
</div>
<div>
<Address client={this.props.fullConn} addr={this.state.actor} mountWindow={this.props.mountWindow}/>
<span>&nbsp;<abbr title="Proving period end">PPE:</abbr> <b>{this.state.actorState.State.ProvingPeriodEnd}</b></span>
<span>&nbsp;<abbr title="Proving period end">EPS:</abbr> <b>{this.state.actorState.State.ElectionPeriodStart}</b></span>
</div>
<div>{this.state.statusCounts.map((c, i) => <span key={i}>{sealCodes[i]}: {c} | </span>)}</div>
<div>

View File

@ -3,12 +3,13 @@ package main
import (
"bufio"
"fmt"
"github.com/gorilla/websocket"
"github.com/opentracing/opentracing-go/log"
"io"
"net/http"
"strings"
"sync"
"github.com/gorilla/websocket"
"github.com/opentracing/opentracing-go/log"
)
type outmux struct {

View File

@ -11,6 +11,10 @@ import (
"time"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/cmd/lotus-seed/seed"
)
func (api *api) Spawn() (nodeInfo, error) {
@ -19,9 +23,29 @@ func (api *api) Spawn() (nodeInfo, error) {
return nodeInfo{}, err
}
params := []string{"daemon", "--bootstrap=false"}
genParam := "--genesis=" + api.genesis
id := atomic.AddInt32(&api.cmds, 1)
if id == 1 {
// preseal
genMiner, err := address.NewIDAddress(101)
if err != nil {
return nodeInfo{}, err
}
sbroot := filepath.Join(dir, "preseal")
genm, err := seed.PreSeal(genMiner, build.SectorSizes[0], 1, sbroot, []byte("8"))
if err != nil {
return nodeInfo{}, xerrors.Errorf("preseal failed: %w", err)
}
if err := seed.WriteGenesisMiner(genMiner, sbroot, genm); err != nil {
return nodeInfo{}, xerrors.Errorf("failed to write genminer info: %w", err)
}
params = append(params, "--genesis-presealed-sectors="+filepath.Join(dir, "preseal", "pre-seal-t0101.json"))
// make genesis
genf, err := ioutil.TempFile(os.TempDir(), "lotus-genesis-")
if err != nil {
@ -54,7 +78,7 @@ func (api *api) Spawn() (nodeInfo, error) {
return nodeInfo{}, err
}
cmd := exec.Command("./lotus", "daemon", "--bootstrap=false", genParam)
cmd := exec.Command("./lotus", append(params, genParam)...)
cmd.Stderr = io.MultiWriter(os.Stderr, errlogfile, mux.errpw)
cmd.Stdout = io.MultiWriter(os.Stdout, logfile, mux.outpw)
@ -114,7 +138,7 @@ func (api *api) SpawnStorage(fullNodeRepo string) (nodeInfo, error) {
initArgs := []string{"init"}
if fullNodeRepo == api.running[1].meta.Repo {
initArgs = []string{"init", "--actor=t0101", "--genesis-miner"}
initArgs = []string{"init", "--actor=t0101", "--genesis-miner", "--pre-sealed-sectors=" + filepath.Join(fullNodeRepo, "preseal")}
}
id := atomic.AddInt32(&api.cmds, 1)

View File

@ -5,17 +5,15 @@ import (
"sync"
"time"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/impl/full"
logging "github.com/ipfs/go-log"
"github.com/pkg/errors"
"go.opencensus.io/trace"
"go.uber.org/fx"
"golang.org/x/xerrors"
)
@ -23,19 +21,10 @@ var log = logging.Logger("miner")
type waitFunc func(ctx context.Context) error
type api struct {
fx.In
full.ChainAPI
full.SyncAPI
full.MpoolAPI
full.WalletAPI
full.StateAPI
}
func NewMiner(api api) *Miner {
func NewMiner(api api.FullNode, epp gen.ElectionPoStProver) *Miner {
return &Miner{
api: api,
epp: epp,
waitFunc: func(ctx context.Context) error {
// Wait around for half the block time in case other parents come in
time.Sleep(build.BlockDelay * time.Second / 2)
@ -45,7 +34,9 @@ func NewMiner(api api) *Miner {
}
type Miner struct {
api api
api api.FullNode
epp gen.ElectionPoStProver
lk sync.Mutex
addresses []address.Address
@ -161,8 +152,8 @@ eventLoop:
log.Errorf("failed to get best mining candidate: %s", err)
continue
}
if base.ts.Equals(lastBase.ts) && len(lastBase.tickets) == len(base.tickets) {
log.Errorf("BestMiningCandidate from the previous round: %s (tkts:%d)", lastBase.ts.Cids(), len(lastBase.tickets))
if base.ts.Equals(lastBase.ts) && lastBase.nullRounds == base.nullRounds {
log.Errorf("BestMiningCandidate from the previous round: %s (nulls:%d)", lastBase.ts.Cids(), lastBase.nullRounds)
time.Sleep(build.BlockDelay * time.Second)
continue
}
@ -173,7 +164,7 @@ eventLoop:
for _, addr := range addrs {
b, err := m.mineOne(ctx, addr, base)
if err != nil {
log.Errorf("mining block failed: %s", err)
log.Errorf("mining block failed: %+v", err)
continue
}
if b != nil {
@ -205,15 +196,15 @@ eventLoop:
}
}
} else {
nextRound := time.Unix(int64(base.ts.MinTimestamp()+uint64(build.BlockDelay*len(base.tickets))), 0)
nextRound := time.Unix(int64(base.ts.MinTimestamp()+uint64(build.BlockDelay*base.nullRounds)), 0)
time.Sleep(time.Until(nextRound))
}
}
}
type MiningBase struct {
ts *types.TipSet
tickets []*types.Ticket
ts *types.TipSet
nullRounds uint64
}
func (m *Miner) GetBestMiningCandidate(ctx context.Context) (*MiningBase, error) {
@ -246,35 +237,54 @@ func (m *Miner) GetBestMiningCandidate(ctx context.Context) (*MiningBase, error)
}, nil
}
func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningBase) (*types.BlockMsg, error) {
log.Debugw("attempting to mine a block", "tipset", types.LogCids(base.ts.Cids()))
ticket, err := m.scratchTicket(ctx, addr, base)
func (m *Miner) isSlashed(ctx context.Context, addr address.Address, ts *types.TipSet) (bool, error) {
power, err := m.api.StateMinerPower(ctx, addr, ts)
if err != nil {
return nil, errors.Wrap(err, "scratching ticket failed")
return false, err
}
win, proof, err := gen.IsRoundWinner(ctx, base.ts, append(base.tickets, ticket), addr, &m.api)
return power.MinerPower.Equals(types.NewInt(0)), nil
}
func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningBase) (*types.BlockMsg, error) {
log.Debugw("attempting to mine a block", "tipset", types.LogCids(base.ts.Cids()))
start := time.Now()
slashed, err := m.isSlashed(ctx, addr, base.ts)
if err != nil {
return nil, errors.Wrap(err, "failed to check if we win next round")
return nil, xerrors.Errorf("checking if miner is slashed: %w", err)
}
if slashed {
log.Warnf("Slashed at epoch %d, not attempting to mine a block", base.ts.Height()+base.nullRounds)
base.nullRounds++
return nil, nil
}
ticket, err := m.computeTicket(ctx, addr, base)
if err != nil {
return nil, xerrors.Errorf("scratching ticket failed: %w", err)
}
win, proof, err := gen.IsRoundWinner(ctx, base.ts, int64(base.ts.Height()+base.nullRounds+1), addr, m.epp, m.api)
if err != nil {
return nil, xerrors.Errorf("failed to check if we win next round: %w", err)
}
if !win {
m.submitNullTicket(base, ticket)
base.nullRounds++
return nil, nil
}
b, err := m.createBlock(base, addr, ticket, proof)
if err != nil {
return nil, errors.Wrap(err, "failed to create block")
return nil, xerrors.Errorf("failed to create block: %w", err)
}
log.Infow("mined new block", "cid", b.Cid())
return b, nil
}
dur := time.Now().Sub(start)
log.Infof("Creating block took %s", dur)
func (m *Miner) submitNullTicket(base *MiningBase, ticket *types.Ticket) {
base.tickets = append(base.tickets, ticket)
m.lastWork = base
return b, nil
}
func (m *Miner) computeVRF(ctx context.Context, addr address.Address, input []byte) ([]byte, error) {
@ -283,7 +293,7 @@ func (m *Miner) computeVRF(ctx context.Context, addr address.Address, input []by
return nil, err
}
return gen.ComputeVRF(ctx, m.api.WalletSign, w, input)
return gen.ComputeVRF(ctx, m.api.WalletSign, w, addr, gen.DSepTicket, input)
}
func (m *Miner) getMinerWorker(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
@ -308,15 +318,11 @@ func (m *Miner) getMinerWorker(ctx context.Context, addr address.Address, ts *ty
return w, nil
}
func (m *Miner) scratchTicket(ctx context.Context, addr address.Address, base *MiningBase) (*types.Ticket, error) {
var lastTicket *types.Ticket
if len(base.tickets) > 0 {
lastTicket = base.tickets[len(base.tickets)-1]
} else {
lastTicket = base.ts.MinTicket()
}
func (m *Miner) computeTicket(ctx context.Context, addr address.Address, base *MiningBase) (*types.Ticket, error) {
vrfOut, err := m.computeVRF(ctx, addr, lastTicket.VRFProof)
vrfBase := base.ts.MinTicket().VRFProof
vrfOut, err := m.computeVRF(ctx, addr, vrfBase)
if err != nil {
return nil, err
}
@ -326,11 +332,11 @@ func (m *Miner) scratchTicket(ctx context.Context, addr address.Address, base *M
}, nil
}
func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *types.Ticket, proof types.ElectionProof) (*types.BlockMsg, error) {
func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *types.Ticket, proof *types.EPostProof) (*types.BlockMsg, error) {
pending, err := m.api.MpoolPending(context.TODO(), base.ts)
if err != nil {
return nil, errors.Wrapf(err, "failed to get pending messages")
return nil, xerrors.Errorf("failed to get pending messages: %w", err)
}
msgs, err := selectMessages(context.TODO(), m.api.StateGetActor, base, pending)
@ -338,10 +344,12 @@ func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *type
return nil, xerrors.Errorf("message filtering failed: %w", err)
}
uts := base.ts.MinTimestamp() + uint64(build.BlockDelay*(len(base.tickets)+1))
uts := base.ts.MinTimestamp() + uint64(build.BlockDelay*(base.nullRounds+1))
nheight := base.ts.Height() + base.nullRounds + 1
// why even return this? that api call could just submit it for us
return m.api.MinerCreateBlock(context.TODO(), addr, base.ts, append(base.tickets, ticket), proof, msgs, uint64(uts))
return m.api.MinerCreateBlock(context.TODO(), addr, base.ts, ticket, proof, msgs, nheight, uint64(uts))
}
type actorLookup func(context.Context, address.Address, *types.TipSet) (*types.Actor, error)
@ -378,7 +386,7 @@ func selectMessages(ctx context.Context, al actorLookup, base *MiningBase, msgs
}
if msg.Message.Nonce < inclNonces[from] {
log.Warnf("message in mempool has already used nonce (%d < %d) %s", msg.Message.Nonce, inclNonces[from], msg.Cid())
log.Warnf("message in mempool has already used nonce (%d < %d), from %s, to %s, %s", msg.Message.Nonce, inclNonces[from], msg.Message.From, msg.Message.To, msg.Cid())
continue
}

View File

@ -2,10 +2,12 @@ package miner
import (
"context"
"github.com/filecoin-project/lotus/api"
)
func NewTestMiner(nextCh <-chan struct{}) func(api api) *Miner {
return func(api api) *Miner {
func NewTestMiner(nextCh <-chan struct{}) func(api api.FullNode) *Miner {
return func(api api.FullNode) *Miner {
return &Miner{
api: api,
waitFunc: chanWaiter(nextCh),

View File

@ -22,6 +22,7 @@ import (
"github.com/filecoin-project/lotus/chain"
"github.com/filecoin-project/lotus/chain/blocksync"
"github.com/filecoin-project/lotus/chain/deals"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/market"
"github.com/filecoin-project/lotus/chain/metrics"
"github.com/filecoin-project/lotus/chain/stmgr"
@ -92,7 +93,6 @@ const (
HandleDealsKey
HandleRetrievalKey
RunSectorServiceKey
RegisterMinerKey
RegisterProviderValidatorKey
// daemon
@ -231,8 +231,6 @@ func Online() Option {
Override(new(*paych.Store), paych.NewStore),
Override(new(*paych.Manager), paych.NewManager),
Override(new(*market.FundMgr), market.NewFundMgr),
Override(new(*miner.Miner), miner.NewMiner),
),
// Storage miner
@ -252,7 +250,8 @@ func Online() Option {
Override(RegisterProviderValidatorKey, modules.RegisterProviderValidator),
Override(HandleRetrievalKey, modules.HandleRetrieval),
Override(HandleDealsKey, modules.HandleDeals),
Override(RegisterMinerKey, modules.RegisterMiner),
Override(new(gen.ElectionPoStProver), storage.NewElectionPoStProver),
Override(new(*miner.Miner), modules.SetupBlockProducer),
),
)
}
@ -312,6 +311,9 @@ func ConfigFullNode(c interface{}) Option {
return Options(
ConfigCommon(&cfg.Common),
Override(HeadMetricsKey, metrics.SendHeadNotifs(cfg.Metrics.Nickname)),
If(cfg.Metrics.PubsubTracing,
Override(new(*pubsub.PubSub), lp2p.GossipSub(lp2p.PubsubTracer())),
),
)
}

View File

@ -41,7 +41,8 @@ type Libp2p struct {
// // Full Node
type Metrics struct {
Nickname string
Nickname string
PubsubTracing bool
}
// // Storage Miner

View File

@ -1,8 +1,6 @@
package impl
import (
"context"
logging "github.com/ipfs/go-log"
"github.com/filecoin-project/lotus/node/impl/client"
@ -10,8 +8,6 @@ import (
"github.com/filecoin-project/lotus/node/impl/paych"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/miner"
"github.com/filecoin-project/lotus/node/impl/full"
)
@ -27,20 +23,6 @@ type FullNodeAPI struct {
full.StateAPI
full.WalletAPI
full.SyncAPI
Miner *miner.Miner
}
func (a *FullNodeAPI) MinerAddresses(context.Context) ([]address.Address, error) {
return a.Miner.Addresses()
}
func (a *FullNodeAPI) MinerRegister(ctx context.Context, addr address.Address) error {
return a.Miner.Register(addr)
}
func (a *FullNodeAPI) MinerUnregister(ctx context.Context, addr address.Address) error {
return a.Miner.Unregister(ctx, addr)
}
var _ api.FullNode = &FullNodeAPI{}

View File

@ -28,8 +28,8 @@ func (a *ChainAPI) ChainHead(context.Context) (*types.TipSet, error) {
return a.Chain.GetHeaviestTipSet(), nil
}
func (a *ChainAPI) ChainGetRandomness(ctx context.Context, pts types.TipSetKey, tickets []*types.Ticket, lb int) ([]byte, error) {
return a.Chain.GetRandomness(ctx, pts.Cids(), tickets, int64(lb))
func (a *ChainAPI) ChainGetRandomness(ctx context.Context, pts types.TipSetKey, round int64) ([]byte, error) {
return a.Chain.GetRandomness(ctx, pts.Cids(), round)
}
func (a *ChainAPI) ChainGetBlock(ctx context.Context, msg cid.Cid) (*types.BlockHeader, error) {

View File

@ -76,8 +76,8 @@ func (a *StateAPI) StateMinerPeerID(ctx context.Context, m address.Address, ts *
return stmgr.GetMinerPeerID(ctx, a.StateManager, ts, m)
}
func (a *StateAPI) StateMinerProvingPeriodEnd(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error) {
return stmgr.GetMinerProvingPeriodEnd(ctx, a.StateManager, ts, actor)
func (a *StateAPI) StateMinerElectionPeriodStart(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error) {
return stmgr.GetMinerElectionPeriodStart(ctx, a.StateManager, ts, actor)
}
func (a *StateAPI) StateMinerSectorSize(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error) {
@ -186,8 +186,8 @@ func (a *StateAPI) StateReadState(ctx context.Context, act *types.Actor, ts *typ
}
// This is on StateAPI because miner.Miner requires this, and MinerAPI requires miner.Miner
func (a *StateAPI) MinerCreateBlock(ctx context.Context, addr address.Address, parents *types.TipSet, tickets []*types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage, ts uint64) (*types.BlockMsg, error) {
fblk, err := gen.MinerCreateBlock(ctx, a.StateManager, a.Wallet, addr, parents, tickets, proof, msgs, ts)
func (a *StateAPI) MinerCreateBlock(ctx context.Context, addr address.Address, parents *types.TipSet, ticket *types.Ticket, proof *types.EPostProof, msgs []*types.SignedMessage, height, ts uint64) (*types.BlockMsg, error) {
fblk, err := gen.MinerCreateBlock(ctx, a.StateManager, a.Wallet, addr, parents, ticket, proof, msgs, height, ts)
if err != nil {
return nil, err
}

View File

@ -11,6 +11,7 @@ import (
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/lib/sectorbuilder"
"github.com/filecoin-project/lotus/miner"
"github.com/filecoin-project/lotus/storage"
"github.com/filecoin-project/lotus/storage/sectorblocks"
)
@ -22,8 +23,9 @@ type StorageMinerAPI struct {
SectorBuilder *sectorbuilder.SectorBuilder
SectorBlocks *sectorblocks.SectorBlocks
Miner *storage.Miner
Full api.FullNode
Miner *storage.Miner
BlockMiner *miner.Miner
Full api.FullNode
}
func (sm *StorageMinerAPI) ServeRemote(w http.ResponseWriter, r *http.Request) {

View File

@ -41,14 +41,17 @@ func ChainExchange(mctx helpers.MetricsCtx, lc fx.Lifecycle, host host.Host, rt
return exch
}
func MessagePool(lc fx.Lifecycle, sm *stmgr.StateManager, ps *pubsub.PubSub) *chain.MessagePool {
mp := chain.NewMessagePool(sm, ps)
func MessagePool(lc fx.Lifecycle, sm *stmgr.StateManager, ps *pubsub.PubSub, ds dtypes.MetadataDS) (*chain.MessagePool, error) {
mp, err := chain.NewMessagePool(sm, ps, ds)
if err != nil {
return nil, xerrors.Errorf("constructing mpool: %w", err)
}
lc.Append(fx.Hook{
OnStop: func(_ context.Context) error {
return mp.Close()
},
})
return mp
return mp, nil
}
func ChainBlockstore(r repo.LockedRepo) (dtypes.ChainBlockstore, error) {

View File

@ -3,6 +3,9 @@ package modules
import (
"context"
"crypto/rand"
"io"
"io/ioutil"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/types"
@ -14,8 +17,6 @@ import (
"github.com/libp2p/go-libp2p-core/peerstore"
record "github.com/libp2p/go-libp2p-record"
"golang.org/x/xerrors"
"io"
"io/ioutil"
)
var log = logging.Logger("modules")

Some files were not shown because too many files have changed in this diff Show More