Merge pull request #1243 from filecoin-project/feat/specs-actors

Spec Actors integration
This commit is contained in:
Łukasz Magiera 2020-02-26 00:31:59 +01:00 committed by GitHub
commit 1b6646b55a
184 changed files with 4908 additions and 12037 deletions

View File

@ -6,11 +6,16 @@ import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-fil-markets/storagemarket"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
"github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-filestore"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
)
@ -19,19 +24,21 @@ import (
type FullNode interface {
Common
// TODO: TipSetKeys
// chain
// ChainNotify returns channel with chain head updates
// First message is guaranteed to be of len == 1, and type == 'current'
ChainNotify(context.Context) (<-chan []*store.HeadChange, error)
ChainHead(context.Context) (*types.TipSet, error)
ChainGetRandomness(context.Context, types.TipSetKey, int64) ([]byte, error)
ChainGetRandomness(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error)
ChainGetBlock(context.Context, cid.Cid) (*types.BlockHeader, error)
ChainGetTipSet(context.Context, types.TipSetKey) (*types.TipSet, error)
ChainGetBlockMessages(context.Context, cid.Cid) (*BlockMessages, error)
ChainGetParentReceipts(context.Context, cid.Cid) ([]*types.MessageReceipt, error)
ChainGetParentMessages(context.Context, cid.Cid) ([]Message, error)
ChainGetTipSetByHeight(context.Context, uint64, types.TipSetKey) (*types.TipSet, error)
ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error)
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
ChainHasObj(context.Context, cid.Cid) (bool, error)
ChainSetHead(context.Context, types.TipSetKey) error
@ -60,17 +67,17 @@ type FullNode interface {
// miner
MinerCreateBlock(context.Context, address.Address, types.TipSetKey, *types.Ticket, *types.EPostProof, []*types.SignedMessage, uint64, uint64) (*types.BlockMsg, error)
MinerCreateBlock(context.Context, address.Address, types.TipSetKey, *types.Ticket, *types.EPostProof, []*types.SignedMessage, abi.ChainEpoch, uint64) (*types.BlockMsg, error)
// // UX ?
// wallet
WalletNew(context.Context, string) (address.Address, error)
WalletNew(context.Context, crypto.SigType) (address.Address, error)
WalletHas(context.Context, address.Address) (bool, error)
WalletList(context.Context) ([]address.Address, error)
WalletBalance(context.Context, address.Address) (types.BigInt, error)
WalletSign(context.Context, address.Address, []byte) (*types.Signature, error)
WalletSign(context.Context, address.Address, []byte) (*crypto.Signature, error)
WalletSignMessage(context.Context, address.Address, *types.Message) (*types.SignedMessage, error)
WalletDefaultAddress(context.Context) (address.Address, error)
WalletSetDefault(context.Context, address.Address) error
@ -87,7 +94,7 @@ type FullNode interface {
ClientHasLocal(ctx context.Context, root cid.Cid) (bool, error)
ClientFindData(ctx context.Context, root cid.Cid) ([]QueryOffer, error)
ClientRetrieve(ctx context.Context, order RetrievalOrder, path string) error
ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Address) (*types.SignedStorageAsk, error)
ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.SignedStorageAsk, error)
// ClientUnimport removes references to the specified file from filestore
//ClientUnimport(path string)
@ -102,29 +109,29 @@ type FullNode interface {
StateReplay(context.Context, types.TipSetKey, cid.Cid) (*ReplayResults, error)
StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error)
StateReadState(ctx context.Context, act *types.Actor, tsk types.TipSetKey) (*ActorState, error)
StateListMessages(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht uint64) ([]cid.Cid, error)
StateListMessages(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error)
StateMinerSectors(context.Context, address.Address, types.TipSetKey) ([]*ChainSectorInfo, error)
StateMinerProvingSet(context.Context, address.Address, types.TipSetKey) ([]*ChainSectorInfo, error)
StateMinerPower(context.Context, address.Address, types.TipSetKey) (MinerPower, error)
StateMinerWorker(context.Context, address.Address, types.TipSetKey) (address.Address, error)
StateMinerPeerID(ctx context.Context, m address.Address, tsk types.TipSetKey) (peer.ID, error)
StateMinerElectionPeriodStart(ctx context.Context, actor address.Address, tsk types.TipSetKey) (uint64, error)
StateMinerSectorSize(context.Context, address.Address, types.TipSetKey) (uint64, error)
StateMinerFaults(context.Context, address.Address, types.TipSetKey) ([]uint64, error)
StateMinerPostState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*miner.PoStState, error)
StateMinerSectorSize(context.Context, address.Address, types.TipSetKey) (abi.SectorSize, error)
StateMinerFaults(context.Context, address.Address, types.TipSetKey) ([]abi.SectorNumber, error)
StatePledgeCollateral(context.Context, types.TipSetKey) (types.BigInt, error)
StateWaitMsg(context.Context, cid.Cid) (*MsgWait, error)
StateListMiners(context.Context, types.TipSetKey) ([]address.Address, error)
StateListActors(context.Context, types.TipSetKey) ([]address.Address, error)
StateMarketBalance(context.Context, address.Address, types.TipSetKey) (actors.StorageParticipantBalance, error)
StateMarketParticipants(context.Context, types.TipSetKey) (map[string]actors.StorageParticipantBalance, error)
StateMarketDeals(context.Context, types.TipSetKey) (map[string]actors.OnChainDeal, error)
StateMarketStorageDeal(context.Context, uint64, types.TipSetKey) (*actors.OnChainDeal, error)
StateMarketBalance(context.Context, address.Address, types.TipSetKey) (MarketBalance, error)
StateMarketParticipants(context.Context, types.TipSetKey) (map[string]MarketBalance, error)
StateMarketDeals(context.Context, types.TipSetKey) (map[string]MarketDeal, error)
StateMarketStorageDeal(context.Context, abi.DealID, types.TipSetKey) (*MarketDeal, error)
StateLookupID(context.Context, address.Address, types.TipSetKey) (address.Address, error)
StateChangedActors(context.Context, cid.Cid, cid.Cid) (map[string]types.Actor, error)
StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error)
StateMinerSectorCount(context.Context, address.Address, types.TipSetKey) (MinerSectors, error)
StateCompute(context.Context, uint64, []*types.Message, types.TipSetKey) (cid.Cid, error)
StateCompute(context.Context, abi.ChainEpoch, []*types.Message, types.TipSetKey) (cid.Cid, error)
MsigGetAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error)
@ -137,12 +144,12 @@ type FullNode interface {
PaychClose(context.Context, address.Address) (cid.Cid, error)
PaychAllocateLane(ctx context.Context, ch address.Address) (uint64, error)
PaychNewPayment(ctx context.Context, from, to address.Address, vouchers []VoucherSpec) (*PaymentInfo, error)
PaychVoucherCheckValid(context.Context, address.Address, *types.SignedVoucher) error
PaychVoucherCheckSpendable(context.Context, address.Address, *types.SignedVoucher, []byte, []byte) (bool, error)
PaychVoucherCreate(context.Context, address.Address, types.BigInt, uint64) (*types.SignedVoucher, error)
PaychVoucherAdd(context.Context, address.Address, *types.SignedVoucher, []byte, types.BigInt) (types.BigInt, error)
PaychVoucherList(context.Context, address.Address) ([]*types.SignedVoucher, error)
PaychVoucherSubmit(context.Context, address.Address, *types.SignedVoucher) (cid.Cid, error)
PaychVoucherCheckValid(context.Context, address.Address, *paych.SignedVoucher) error
PaychVoucherCheckSpendable(context.Context, address.Address, *paych.SignedVoucher, []byte, []byte) (bool, error)
PaychVoucherCreate(context.Context, address.Address, types.BigInt, uint64) (*paych.SignedVoucher, error)
PaychVoucherAdd(context.Context, address.Address, *paych.SignedVoucher, []byte, types.BigInt) (types.BigInt, error)
PaychVoucherList(context.Context, address.Address) ([]*paych.SignedVoucher, error)
PaychVoucherSubmit(context.Context, address.Address, *paych.SignedVoucher) (cid.Cid, error)
}
type MinerSectors struct {
@ -187,9 +194,8 @@ type Message struct {
}
type ChainSectorInfo struct {
SectorID uint64
CommD []byte
CommR []byte
Info miner.SectorOnChainInfo
ID abi.SectorNumber
}
type ActorState struct {
@ -218,15 +224,15 @@ type ChannelInfo struct {
type PaymentInfo struct {
Channel address.Address
ChannelMessage *cid.Cid
Vouchers []*types.SignedVoucher
Vouchers []*paych.SignedVoucher
}
type VoucherSpec struct {
Amount types.BigInt
TimeLock uint64
MinClose uint64
Amount types.BigInt
TimeLock abi.ChainEpoch
MinSettle abi.ChainEpoch
Extra *types.ModVerifyParams
Extra *paych.ModVerifyParams
}
type MinerPower struct {
@ -261,6 +267,16 @@ func (o *QueryOffer) Order(client address.Address) RetrievalOrder {
}
}
type MarketBalance struct {
Escrow big.Int
Locked big.Int
}
type MarketDeal struct {
Proposal market.DealProposal
State market.DealState
}
type RetrievalOrder struct {
// TODO: make this less unixfs specific
Root cid.Cid
@ -290,7 +306,7 @@ type ActiveSync struct {
Target *types.TipSet
Stage SyncStateStage
Height uint64
Height abi.ChainEpoch
Start time.Time
End time.Time

View File

@ -4,6 +4,8 @@ import (
"context"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/go-sectorbuilder"
)
@ -86,20 +88,20 @@ type StorageMiner interface {
ActorAddress(context.Context) (address.Address, error)
ActorSectorSize(context.Context, address.Address) (uint64, error)
ActorSectorSize(context.Context, address.Address) (abi.SectorSize, error)
// Temp api for testing
PledgeSector(context.Context) error
// Get the status of a given sector by ID
SectorsStatus(context.Context, uint64) (SectorInfo, error)
SectorsStatus(context.Context, abi.SectorNumber) (SectorInfo, error)
// List all staged sectors
SectorsList(context.Context) ([]uint64, error)
SectorsList(context.Context) ([]abi.SectorNumber, error)
SectorsRefs(context.Context) (map[string][]SealedRef, error)
SectorsUpdate(context.Context, uint64, SectorState) error
SectorsUpdate(context.Context, abi.SectorNumber, SectorState) error
WorkerStats(context.Context) (sectorbuilder.WorkerStats, error)
@ -119,12 +121,12 @@ type SectorLog struct {
}
type SectorInfo struct {
SectorID uint64
SectorID abi.SectorNumber
State SectorState
CommD []byte
CommR []byte
Proof []byte
Deals []uint64
Deals []abi.DealID
Ticket sectorbuilder.SealTicket
Seed sectorbuilder.SealSeed
Retries uint64
@ -135,9 +137,9 @@ type SectorInfo struct {
}
type SealedRef struct {
SectorID uint64
SectorID abi.SectorNumber
Offset uint64
Size uint64
Size abi.UnpaddedPieceSize
}
type SealedRefs struct {

View File

@ -3,15 +3,20 @@ package apistruct
import (
"context"
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
"github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-fil-markets/storagemarket"
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
"github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
)
@ -44,24 +49,24 @@ 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, 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) (*api.BlockMessages, error) `perm:"read"`
ChainGetParentReceipts func(context.Context, cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"`
ChainGetParentMessages func(context.Context, cid.Cid) ([]api.Message, error) `perm:"read"`
ChainGetTipSetByHeight func(context.Context, uint64, types.TipSetKey) (*types.TipSet, error) `perm:"read"`
ChainReadObj func(context.Context, cid.Cid) ([]byte, error) `perm:"read"`
ChainHasObj func(context.Context, cid.Cid) (bool, error) `perm:"read"`
ChainSetHead func(context.Context, types.TipSetKey) error `perm:"admin"`
ChainGetGenesis func(context.Context) (*types.TipSet, error) `perm:"read"`
ChainTipSetWeight func(context.Context, types.TipSetKey) (types.BigInt, error) `perm:"read"`
ChainGetNode func(ctx context.Context, p string) (interface{}, error) `perm:"read"`
ChainGetMessage func(context.Context, cid.Cid) (*types.Message, error) `perm:"read"`
ChainGetPath func(context.Context, types.TipSetKey, types.TipSetKey) ([]*store.HeadChange, error) `perm:"read"`
ChainExport func(context.Context, types.TipSetKey) (<-chan []byte, 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, crypto.DomainSeparationTag, abi.ChainEpoch, []byte) (abi.Randomness, 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) (*api.BlockMessages, error) `perm:"read"`
ChainGetParentReceipts func(context.Context, cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"`
ChainGetParentMessages func(context.Context, cid.Cid) ([]api.Message, error) `perm:"read"`
ChainGetTipSetByHeight func(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) `perm:"read"`
ChainReadObj func(context.Context, cid.Cid) ([]byte, error) `perm:"read"`
ChainHasObj func(context.Context, cid.Cid) (bool, error) `perm:"read"`
ChainSetHead func(context.Context, types.TipSetKey) error `perm:"admin"`
ChainGetGenesis func(context.Context) (*types.TipSet, error) `perm:"read"`
ChainTipSetWeight func(context.Context, types.TipSetKey) (types.BigInt, error) `perm:"read"`
ChainGetNode func(ctx context.Context, p string) (interface{}, error) `perm:"read"`
ChainGetMessage func(context.Context, cid.Cid) (*types.Message, error) `perm:"read"`
ChainGetPath func(context.Context, types.TipSetKey, types.TipSetKey) ([]*store.HeadChange, error) `perm:"read"`
ChainExport func(context.Context, types.TipSetKey) (<-chan []byte, error) `perm:"read"`
SyncState func(context.Context) (*api.SyncState, error) `perm:"read"`
SyncSubmitBlock func(ctx context.Context, blk *types.BlockMsg) error `perm:"write"`
@ -70,18 +75,18 @@ type FullNodeStruct struct {
SyncCheckBad func(ctx context.Context, bcid cid.Cid) (string, error) `perm:"read"`
MpoolPending func(context.Context, types.TipSetKey) ([]*types.SignedMessage, error) `perm:"read"`
MpoolPush func(context.Context, *types.SignedMessage) (cid.Cid, error) `perm:"write"`
MpoolPushMessage func(context.Context, *types.Message) (*types.SignedMessage, error) `perm:"sign"`
MpoolGetNonce func(context.Context, address.Address) (uint64, error) `perm:"read"`
MpoolSub func(context.Context) (<-chan api.MpoolUpdate, error) `perm:"read"`
MpoolPush func(context.Context, *types.SignedMessage) (cid.Cid, error) `perm:"write"`
MpoolPushMessage func(context.Context, *types.Message) (*types.SignedMessage, error) `perm:"sign"`
MpoolGetNonce func(context.Context, address.Address) (uint64, error) `perm:"read"`
MpoolSub func(context.Context) (<-chan api.MpoolUpdate, error) `perm:"read"`
MinerCreateBlock func(context.Context, address.Address, types.TipSetKey, *types.Ticket, *types.EPostProof, []*types.SignedMessage, uint64, uint64) (*types.BlockMsg, error) `perm:"write"`
MinerCreateBlock func(context.Context, address.Address, types.TipSetKey, *types.Ticket, *types.EPostProof, []*types.SignedMessage, abi.ChainEpoch, uint64) (*types.BlockMsg, error) `perm:"write"`
WalletNew func(context.Context, string) (address.Address, error) `perm:"write"`
WalletNew func(context.Context, crypto.SigType) (address.Address, error) `perm:"write"`
WalletHas func(context.Context, address.Address) (bool, error) `perm:"write"`
WalletList func(context.Context) ([]address.Address, error) `perm:"write"`
WalletBalance func(context.Context, address.Address) (types.BigInt, error) `perm:"read"`
WalletSign func(context.Context, address.Address, []byte) (*types.Signature, error) `perm:"sign"`
WalletSign func(context.Context, address.Address, []byte) (*crypto.Signature, error) `perm:"sign"`
WalletSignMessage func(context.Context, address.Address, *types.Message) (*types.SignedMessage, error) `perm:"sign"`
WalletDefaultAddress func(context.Context) (address.Address, error) `perm:"write"`
WalletSetDefault func(context.Context, address.Address) error `perm:"admin"`
@ -96,34 +101,34 @@ type FullNodeStruct struct {
ClientGetDealInfo func(context.Context, cid.Cid) (*api.DealInfo, error) `perm:"read"`
ClientListDeals func(ctx context.Context) ([]api.DealInfo, error) `perm:"write"`
ClientRetrieve func(ctx context.Context, order api.RetrievalOrder, path string) error `perm:"admin"`
ClientQueryAsk func(ctx context.Context, p peer.ID, miner address.Address) (*types.SignedStorageAsk, error) `perm:"read"`
ClientQueryAsk func(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.SignedStorageAsk, error) `perm:"read"`
StateMinerSectors func(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"`
StateMinerProvingSet func(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"`
StateMinerPower func(context.Context, address.Address, types.TipSetKey) (api.MinerPower, error) `perm:"read"`
StateMinerWorker func(context.Context, address.Address, types.TipSetKey) (address.Address, error) `perm:"read"`
StateMinerPeerID func(ctx context.Context, m address.Address, tsk types.TipSetKey) (peer.ID, error) `perm:"read"`
StateMinerElectionPeriodStart func(ctx context.Context, actor address.Address, tsk types.TipSetKey) (uint64, error) `perm:"read"`
StateMinerSectorSize func(context.Context, address.Address, types.TipSetKey) (uint64, error) `perm:"read"`
StateMinerFaults func(context.Context, address.Address, types.TipSetKey) ([]uint64, error) `perm:"read"`
StateCall func(context.Context, *types.Message, types.TipSetKey) (*api.MethodCall, error) `perm:"read"`
StateReplay func(context.Context, types.TipSetKey, cid.Cid) (*api.ReplayResults, error) `perm:"read"`
StateGetActor func(context.Context, address.Address, types.TipSetKey) (*types.Actor, error) `perm:"read"`
StateReadState func(context.Context, *types.Actor, types.TipSetKey) (*api.ActorState, error) `perm:"read"`
StatePledgeCollateral func(context.Context, types.TipSetKey) (types.BigInt, error) `perm:"read"`
StateWaitMsg func(context.Context, cid.Cid) (*api.MsgWait, error) `perm:"read"`
StateListMiners func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"`
StateListActors func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"`
StateMarketBalance func(context.Context, address.Address, types.TipSetKey) (actors.StorageParticipantBalance, error) `perm:"read"`
StateMarketParticipants func(context.Context, types.TipSetKey) (map[string]actors.StorageParticipantBalance, error) `perm:"read"`
StateMarketDeals func(context.Context, types.TipSetKey) (map[string]actors.OnChainDeal, error) `perm:"read"`
StateMarketStorageDeal func(context.Context, uint64, types.TipSetKey) (*actors.OnChainDeal, error) `perm:"read"`
StateLookupID func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (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.TipSetKey) (*types.MessageReceipt, error) `perm:"read"`
StateMinerSectorCount func(context.Context, address.Address, types.TipSetKey) (api.MinerSectors, error) `perm:"read"`
StateListMessages func(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht uint64) ([]cid.Cid, error) `perm:"read"`
StateCompute func(context.Context, uint64, []*types.Message, types.TipSetKey) (cid.Cid, error) `perm:"read"`
StateMinerSectors func(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"`
StateMinerProvingSet func(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"`
StateMinerPower func(context.Context, address.Address, types.TipSetKey) (api.MinerPower, error) `perm:"read"`
StateMinerWorker func(context.Context, address.Address, types.TipSetKey) (address.Address, error) `perm:"read"`
StateMinerPeerID func(ctx context.Context, m address.Address, tsk types.TipSetKey) (peer.ID, error) `perm:"read"`
StateMinerPostState func(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*miner.PoStState, error) `perm:"read"`
StateMinerSectorSize func(context.Context, address.Address, types.TipSetKey) (abi.SectorSize, error) `perm:"read"`
StateMinerFaults func(context.Context, address.Address, types.TipSetKey) ([]abi.SectorNumber, error) `perm:"read"`
StateCall func(context.Context, *types.Message, types.TipSetKey) (*api.MethodCall, error) `perm:"read"`
StateReplay func(context.Context, types.TipSetKey, cid.Cid) (*api.ReplayResults, error) `perm:"read"`
StateGetActor func(context.Context, address.Address, types.TipSetKey) (*types.Actor, error) `perm:"read"`
StateReadState func(context.Context, *types.Actor, types.TipSetKey) (*api.ActorState, error) `perm:"read"`
StatePledgeCollateral func(context.Context, types.TipSetKey) (types.BigInt, error) `perm:"read"`
StateWaitMsg func(context.Context, cid.Cid) (*api.MsgWait, error) `perm:"read"`
StateListMiners func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"`
StateListActors func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"`
StateMarketBalance func(context.Context, address.Address, types.TipSetKey) (api.MarketBalance, error) `perm:"read"`
StateMarketParticipants func(context.Context, types.TipSetKey) (map[string]api.MarketBalance, error) `perm:"read"`
StateMarketDeals func(context.Context, types.TipSetKey) (map[string]api.MarketDeal, error) `perm:"read"`
StateMarketStorageDeal func(context.Context, abi.DealID, types.TipSetKey) (*api.MarketDeal, error) `perm:"read"`
StateLookupID func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (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.TipSetKey) (*types.MessageReceipt, error) `perm:"read"`
StateMinerSectorCount func(context.Context, address.Address, types.TipSetKey) (api.MinerSectors, error) `perm:"read"`
StateListMessages func(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) `perm:"read"`
StateCompute func(context.Context, abi.ChainEpoch, []*types.Message, types.TipSetKey) (cid.Cid, error) `perm:"read"`
MsigGetAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"`
@ -135,13 +140,13 @@ type FullNodeStruct struct {
PaychClose func(context.Context, address.Address) (cid.Cid, error) `perm:"sign"`
PaychAllocateLane func(context.Context, address.Address) (uint64, error) `perm:"sign"`
PaychNewPayment func(ctx context.Context, from, to address.Address, vouchers []api.VoucherSpec) (*api.PaymentInfo, error) `perm:"sign"`
PaychVoucherCheck func(context.Context, *types.SignedVoucher) error `perm:"read"`
PaychVoucherCheckValid func(context.Context, address.Address, *types.SignedVoucher) error `perm:"read"`
PaychVoucherCheckSpendable func(context.Context, address.Address, *types.SignedVoucher, []byte, []byte) (bool, error) `perm:"read"`
PaychVoucherAdd func(context.Context, address.Address, *types.SignedVoucher, []byte, types.BigInt) (types.BigInt, error) `perm:"write"`
PaychVoucherCreate func(context.Context, address.Address, types.BigInt, uint64) (*types.SignedVoucher, error) `perm:"sign"`
PaychVoucherList func(context.Context, address.Address) ([]*types.SignedVoucher, error) `perm:"write"`
PaychVoucherSubmit func(context.Context, address.Address, *types.SignedVoucher) (cid.Cid, error) `perm:"sign"`
PaychVoucherCheck func(context.Context, *paych.SignedVoucher) error `perm:"read"`
PaychVoucherCheckValid func(context.Context, address.Address, *paych.SignedVoucher) error `perm:"read"`
PaychVoucherCheckSpendable func(context.Context, address.Address, *paych.SignedVoucher, []byte, []byte) (bool, error) `perm:"read"`
PaychVoucherAdd func(context.Context, address.Address, *paych.SignedVoucher, []byte, types.BigInt) (types.BigInt, error) `perm:"write"`
PaychVoucherCreate func(context.Context, address.Address, big.Int, uint64) (*paych.SignedVoucher, error) `perm:"sign"`
PaychVoucherList func(context.Context, address.Address) ([]*paych.SignedVoucher, error) `perm:"write"`
PaychVoucherSubmit func(context.Context, address.Address, *paych.SignedVoucher) (cid.Cid, error) `perm:"sign"`
}
}
@ -153,15 +158,15 @@ type StorageMinerStruct struct {
CommonStruct
Internal struct {
ActorAddress func(context.Context) (address.Address, error) `perm:"read"`
ActorSectorSize func(context.Context, address.Address) (uint64, error) `perm:"read"`
ActorAddress func(context.Context) (address.Address, error) `perm:"read"`
ActorSectorSize func(context.Context, address.Address) (abi.SectorSize, error) `perm:"read"`
PledgeSector func(context.Context) error `perm:"write"`
SectorsStatus func(context.Context, uint64) (api.SectorInfo, error) `perm:"read"`
SectorsList func(context.Context) ([]uint64, error) `perm:"read"`
SectorsRefs func(context.Context) (map[string][]api.SealedRef, error) `perm:"read"`
SectorsUpdate func(context.Context, uint64, api.SectorState) error `perm:"write"`
SectorsStatus func(context.Context, abi.SectorNumber) (api.SectorInfo, error) `perm:"read"`
SectorsList func(context.Context) ([]abi.SectorNumber, error) `perm:"read"`
SectorsRefs func(context.Context) (map[string][]api.SealedRef, error) `perm:"read"`
SectorsUpdate func(context.Context, abi.SectorNumber, api.SectorState) error `perm:"write"`
WorkerStats func(context.Context) (sectorbuilder.WorkerStats, error) `perm:"read"`
@ -251,7 +256,7 @@ func (c *FullNodeStruct) ClientRetrieve(ctx context.Context, order api.Retrieval
return c.Internal.ClientRetrieve(ctx, order, path)
}
func (c *FullNodeStruct) ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Address) (*types.SignedStorageAsk, error) {
func (c *FullNodeStruct) ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.SignedStorageAsk, error) {
return c.Internal.ClientQueryAsk(ctx, p, miner)
}
@ -271,7 +276,7 @@ func (c *FullNodeStruct) MpoolSub(ctx context.Context) (<-chan api.MpoolUpdate,
return c.Internal.MpoolSub(ctx)
}
func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, addr address.Address, base types.TipSetKey, ticket *types.Ticket, eproof *types.EPostProof, msgs []*types.SignedMessage, height, ts uint64) (*types.BlockMsg, error) {
func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, addr address.Address, base types.TipSetKey, ticket *types.Ticket, eproof *types.EPostProof, msgs []*types.SignedMessage, height abi.ChainEpoch, ts uint64) (*types.BlockMsg, error) {
return c.Internal.MinerCreateBlock(ctx, addr, base, ticket, eproof, msgs, height, ts)
}
@ -279,15 +284,15 @@ 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, round int64) ([]byte, error) {
return c.Internal.ChainGetRandomness(ctx, pts, round)
func (c *FullNodeStruct) ChainGetRandomness(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error) {
return c.Internal.ChainGetRandomness(ctx, tsk, personalization, randEpoch, entropy)
}
func (c *FullNodeStruct) ChainGetTipSetByHeight(ctx context.Context, h uint64, tsk types.TipSetKey) (*types.TipSet, error) {
func (c *FullNodeStruct) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) {
return c.Internal.ChainGetTipSetByHeight(ctx, h, tsk)
}
func (c *FullNodeStruct) WalletNew(ctx context.Context, typ string) (address.Address, error) {
func (c *FullNodeStruct) WalletNew(ctx context.Context, typ crypto.SigType) (address.Address, error) {
return c.Internal.WalletNew(ctx, typ)
}
@ -303,7 +308,7 @@ func (c *FullNodeStruct) WalletBalance(ctx context.Context, a address.Address) (
return c.Internal.WalletBalance(ctx, a)
}
func (c *FullNodeStruct) WalletSign(ctx context.Context, k address.Address, msg []byte) (*types.Signature, error) {
func (c *FullNodeStruct) WalletSign(ctx context.Context, k address.Address, msg []byte) (*crypto.Signature, error) {
return c.Internal.WalletSign(ctx, k, msg)
}
@ -431,15 +436,15 @@ func (c *FullNodeStruct) StateMinerPeerID(ctx context.Context, m address.Address
return c.Internal.StateMinerPeerID(ctx, m, tsk)
}
func (c *FullNodeStruct) StateMinerElectionPeriodStart(ctx context.Context, actor address.Address, tsk types.TipSetKey) (uint64, error) {
return c.Internal.StateMinerElectionPeriodStart(ctx, actor, tsk)
func (c *FullNodeStruct) StateMinerPostState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*miner.PoStState, error) {
return c.Internal.StateMinerPostState(ctx, actor, tsk)
}
func (c *FullNodeStruct) StateMinerSectorSize(ctx context.Context, actor address.Address, tsk types.TipSetKey) (uint64, error) {
func (c *FullNodeStruct) StateMinerSectorSize(ctx context.Context, actor address.Address, tsk types.TipSetKey) (abi.SectorSize, error) {
return c.Internal.StateMinerSectorSize(ctx, actor, tsk)
}
func (c *FullNodeStruct) StateMinerFaults(ctx context.Context, actor address.Address, tsk types.TipSetKey) ([]uint64, error) {
func (c *FullNodeStruct) StateMinerFaults(ctx context.Context, actor address.Address, tsk types.TipSetKey) ([]abi.SectorNumber, error) {
return c.Internal.StateMinerFaults(ctx, actor, tsk)
}
@ -474,19 +479,19 @@ func (c *FullNodeStruct) StateListActors(ctx context.Context, tsk types.TipSetKe
return c.Internal.StateListActors(ctx, tsk)
}
func (c *FullNodeStruct) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (actors.StorageParticipantBalance, error) {
func (c *FullNodeStruct) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) {
return c.Internal.StateMarketBalance(ctx, addr, tsk)
}
func (c *FullNodeStruct) StateMarketParticipants(ctx context.Context, tsk types.TipSetKey) (map[string]actors.StorageParticipantBalance, error) {
func (c *FullNodeStruct) StateMarketParticipants(ctx context.Context, tsk types.TipSetKey) (map[string]api.MarketBalance, error) {
return c.Internal.StateMarketParticipants(ctx, tsk)
}
func (c *FullNodeStruct) StateMarketDeals(ctx context.Context, tsk types.TipSetKey) (map[string]actors.OnChainDeal, error) {
func (c *FullNodeStruct) StateMarketDeals(ctx context.Context, tsk types.TipSetKey) (map[string]api.MarketDeal, error) {
return c.Internal.StateMarketDeals(ctx, tsk)
}
func (c *FullNodeStruct) StateMarketStorageDeal(ctx context.Context, dealid uint64, tsk types.TipSetKey) (*actors.OnChainDeal, error) {
func (c *FullNodeStruct) StateMarketStorageDeal(ctx context.Context, dealid abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) {
return c.Internal.StateMarketStorageDeal(ctx, dealid, tsk)
}
@ -502,11 +507,11 @@ func (c *FullNodeStruct) StateGetReceipt(ctx context.Context, msg cid.Cid, tsk t
return c.Internal.StateGetReceipt(ctx, msg, tsk)
}
func (c *FullNodeStruct) StateListMessages(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht uint64) ([]cid.Cid, error) {
func (c *FullNodeStruct) StateListMessages(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) {
return c.Internal.StateListMessages(ctx, match, tsk, toht)
}
func (c *FullNodeStruct) StateCompute(ctx context.Context, height uint64, msgs []*types.Message, tsk types.TipSetKey) (cid.Cid, error) {
func (c *FullNodeStruct) StateCompute(ctx context.Context, height abi.ChainEpoch, msgs []*types.Message, tsk types.TipSetKey) (cid.Cid, error) {
return c.Internal.StateCompute(ctx, height, msgs, tsk)
}
@ -530,23 +535,23 @@ func (c *FullNodeStruct) PaychStatus(ctx context.Context, pch address.Address) (
return c.Internal.PaychStatus(ctx, pch)
}
func (c *FullNodeStruct) PaychVoucherCheckValid(ctx context.Context, addr address.Address, sv *types.SignedVoucher) error {
func (c *FullNodeStruct) PaychVoucherCheckValid(ctx context.Context, addr address.Address, sv *paych.SignedVoucher) error {
return c.Internal.PaychVoucherCheckValid(ctx, addr, sv)
}
func (c *FullNodeStruct) PaychVoucherCheckSpendable(ctx context.Context, addr address.Address, sv *types.SignedVoucher, secret []byte, proof []byte) (bool, error) {
func (c *FullNodeStruct) PaychVoucherCheckSpendable(ctx context.Context, addr address.Address, sv *paych.SignedVoucher, secret []byte, proof []byte) (bool, error) {
return c.Internal.PaychVoucherCheckSpendable(ctx, addr, sv, secret, proof)
}
func (c *FullNodeStruct) PaychVoucherAdd(ctx context.Context, addr address.Address, sv *types.SignedVoucher, proof []byte, minDelta types.BigInt) (types.BigInt, error) {
func (c *FullNodeStruct) PaychVoucherAdd(ctx context.Context, addr address.Address, sv *paych.SignedVoucher, proof []byte, minDelta types.BigInt) (types.BigInt, error) {
return c.Internal.PaychVoucherAdd(ctx, addr, sv, proof, minDelta)
}
func (c *FullNodeStruct) PaychVoucherCreate(ctx context.Context, pch address.Address, amt types.BigInt, lane uint64) (*types.SignedVoucher, error) {
func (c *FullNodeStruct) PaychVoucherCreate(ctx context.Context, pch address.Address, amt types.BigInt, lane uint64) (*paych.SignedVoucher, error) {
return c.Internal.PaychVoucherCreate(ctx, pch, amt, lane)
}
func (c *FullNodeStruct) PaychVoucherList(ctx context.Context, pch address.Address) ([]*types.SignedVoucher, error) {
func (c *FullNodeStruct) PaychVoucherList(ctx context.Context, pch address.Address) ([]*paych.SignedVoucher, error) {
return c.Internal.PaychVoucherList(ctx, pch)
}
@ -562,7 +567,7 @@ func (c *FullNodeStruct) PaychNewPayment(ctx context.Context, from, to address.A
return c.Internal.PaychNewPayment(ctx, from, to, vouchers)
}
func (c *FullNodeStruct) PaychVoucherSubmit(ctx context.Context, ch address.Address, sv *types.SignedVoucher) (cid.Cid, error) {
func (c *FullNodeStruct) PaychVoucherSubmit(ctx context.Context, ch address.Address, sv *paych.SignedVoucher) (cid.Cid, error) {
return c.Internal.PaychVoucherSubmit(ctx, ch, sv)
}
@ -570,7 +575,7 @@ func (c *StorageMinerStruct) ActorAddress(ctx context.Context) (address.Address,
return c.Internal.ActorAddress(ctx)
}
func (c *StorageMinerStruct) ActorSectorSize(ctx context.Context, addr address.Address) (uint64, error) {
func (c *StorageMinerStruct) ActorSectorSize(ctx context.Context, addr address.Address) (abi.SectorSize, error) {
return c.Internal.ActorSectorSize(ctx, addr)
}
@ -579,12 +584,12 @@ func (c *StorageMinerStruct) PledgeSector(ctx context.Context) error {
}
// Get the status of a given sector by ID
func (c *StorageMinerStruct) SectorsStatus(ctx context.Context, sid uint64) (api.SectorInfo, error) {
func (c *StorageMinerStruct) SectorsStatus(ctx context.Context, sid abi.SectorNumber) (api.SectorInfo, error) {
return c.Internal.SectorsStatus(ctx, sid)
}
// List all staged sectors
func (c *StorageMinerStruct) SectorsList(ctx context.Context) ([]uint64, error) {
func (c *StorageMinerStruct) SectorsList(ctx context.Context) ([]abi.SectorNumber, error) {
return c.Internal.SectorsList(ctx)
}
@ -592,7 +597,7 @@ func (c *StorageMinerStruct) SectorsRefs(ctx context.Context) (map[string][]api.
return c.Internal.SectorsRefs(ctx)
}
func (c *StorageMinerStruct) SectorsUpdate(ctx context.Context, id uint64, state api.SectorState) error {
func (c *StorageMinerStruct) SectorsUpdate(ctx context.Context, id abi.SectorNumber, state api.SectorState) error {
return c.Internal.SectorsUpdate(ctx, id, state)
}

View File

@ -6,7 +6,8 @@ import (
"fmt"
"io"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
cbg "github.com/whyrusleeping/cbor-gen"
xerrors "golang.org/x/xerrors"
)
@ -60,7 +61,7 @@ func (t *PaymentInfo) MarshalCBOR(w io.Writer) error {
}
}
// t.Vouchers ([]*types.SignedVoucher) (slice)
// t.Vouchers ([]*paych.SignedVoucher) (slice)
if len("Vouchers") > cbg.MaxLength {
return xerrors.Errorf("Value in field \"Vouchers\" was too long")
}
@ -152,7 +153,7 @@ func (t *PaymentInfo) UnmarshalCBOR(r io.Reader) error {
}
}
// t.Vouchers ([]*types.SignedVoucher) (slice)
// t.Vouchers ([]*paych.SignedVoucher) (slice)
case "Vouchers":
maj, extra, err = cbg.CborReadHeader(br)
@ -168,11 +169,11 @@ func (t *PaymentInfo) UnmarshalCBOR(r io.Reader) error {
return fmt.Errorf("expected cbor array")
}
if extra > 0 {
t.Vouchers = make([]*types.SignedVoucher, extra)
t.Vouchers = make([]*paych.SignedVoucher, extra)
}
for i := 0; i < int(extra); i++ {
var v types.SignedVoucher
var v paych.SignedVoucher
if err := v.UnmarshalCBOR(br); err != nil {
return err
}
@ -196,7 +197,7 @@ func (t *SealedRef) MarshalCBOR(w io.Writer) error {
return err
}
// t.SectorID (uint64) (uint64)
// t.SectorID (abi.SectorNumber) (uint64)
if len("SectorID") > cbg.MaxLength {
return xerrors.Errorf("Value in field \"SectorID\" was too long")
}
@ -228,7 +229,7 @@ func (t *SealedRef) MarshalCBOR(w io.Writer) error {
return err
}
// t.Size (uint64) (uint64)
// t.Size (abi.UnpaddedPieceSize) (uint64)
if len("Size") > cbg.MaxLength {
return xerrors.Errorf("Value in field \"Size\" was too long")
}
@ -243,6 +244,7 @@ func (t *SealedRef) MarshalCBOR(w io.Writer) error {
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.Size))); err != nil {
return err
}
return nil
}
@ -276,39 +278,51 @@ func (t *SealedRef) UnmarshalCBOR(r io.Reader) error {
}
switch name {
// t.SectorID (uint64) (uint64)
// t.SectorID (abi.SectorNumber) (uint64)
case "SectorID":
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
{
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 = abi.SectorNumber(extra)
}
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.SectorID = uint64(extra)
// t.Offset (uint64) (uint64)
case "Offset":
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
{
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.Offset = uint64(extra)
}
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.Offset = uint64(extra)
// t.Size (uint64) (uint64)
// t.Size (abi.UnpaddedPieceSize) (uint64)
case "Size":
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
{
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.Size = abi.UnpaddedPieceSize(extra)
}
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.Size = uint64(extra)
default:
return fmt.Errorf("unknown struct field %d: '%s'", i, name)

View File

@ -74,9 +74,9 @@ func TestDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration) {
if err != nil {
t.Fatal(err)
}
deal, err := client.ClientStartDeal(ctx, fcid, addr, maddr, types.NewInt(40000000), 100)
deal, err := client.ClientStartDeal(ctx, fcid, addr, maddr, types.NewInt(1000000), 100)
if err != nil {
t.Fatal(err)
t.Fatalf("%+v", err)
}
// TODO: this sleep is only necessary because deals don't immediately get logged in the dealstore, we should fix this

View File

@ -4,12 +4,12 @@ import (
"context"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/specs-actors/actors/crypto"
)
type SignFunc = func(context.Context, []byte) (*types.Signature, error)
type SignFunc = func(context.Context, []byte) (*crypto.Signature, error)
type Signer func(context.Context, address.Address, []byte) (*types.Signature, error)
type Signer func(context.Context, address.Address, []byte) (*crypto.Signature, error)
type Signable interface {
Sign(context.Context, SignFunc) error
@ -17,7 +17,7 @@ type Signable interface {
func SignWith(ctx context.Context, signer Signer, addr address.Address, signable ...Signable) error {
for _, s := range signable {
err := s.Sign(ctx, func(ctx context.Context, b []byte) (*types.Signature, error) {
err := s.Sign(ctx, func(ctx context.Context, b []byte) (*crypto.Signature, error) {
return signer(ctx, addr, b)
})
if err != nil {

View File

@ -1,177 +0,0 @@
#!/bin/sh
GOCC=${GOCC=go}
die() {
echo "$@" >&2
exit 1
}
have_binary() {
type "$1" > /dev/null 2> /dev/null
}
check_writable() {
printf "" > "$1" && rm "$1"
}
try_download() {
url="$1"
output="$2"
command="$3"
util_name="$(set -- $command; echo "$1")"
if ! have_binary "$util_name"; then
return 1
fi
printf '==> Using %s to download "%s" to "%s"\n' "$util_name" "$url" "$output"
if eval "$command"; then
echo "==> Download complete!"
return
else
echo "error: couldn't download with $util_name ($?)"
return 1
fi
}
download() {
dl_url="$1"
dl_output="$2"
test "$#" -eq "2" || die "download requires exactly two arguments, was given $@"
if ! check_writable "$dl_output"; then
die "download error: cannot write to $dl_output"
fi
try_download "$dl_url" "$dl_output" "wget '$dl_url' -O '$dl_output'" && return
try_download "$dl_url" "$dl_output" "curl --silent --fail --output '$dl_output' '$dl_url'" && return
try_download "$dl_url" "$dl_output" "fetch '$dl_url' -o '$dl_output'" && return
try_download "$dl_url" "$dl_output" "http '$dl_url' > '$dl_output'" && return
try_download "$dl_url" "$dl_output" "ftp -o '$dl_output' '$dl_url'" && return
die "Unable to download $dl_url. exiting."
}
unarchive() {
ua_archivetype="$1"
ua_infile="$2"
ua_outfile="$3"
ua_distname="$4"
ua_binpostfix=""
ua_os=$(uname -o)
if [ "$ua_os" = "Msys" ] || [ "$ua_os" = "Cygwin" ] ; then
ua_binpostfix=".exe"
fi
ua_outfile="$ua_outfile$ua_binpostfix"
if ! check_writable "$ua_outfile"; then
die "unarchive error: cannot write to $ua_outfile"
fi
case "$ua_archivetype" in
tar.gz)
if have_binary tar; then
echo "==> using 'tar' to extract binary from archive"
< "$ua_infile" tar -Ozxf - "$ua_distname/$ua_distname$ua_binpostfix" > "$ua_outfile" \
|| die "tar has failed"
else
die "no binary on system for extracting tar files"
fi
;;
zip)
if have_binary unzip; then
echo "==> using 'unzip' to extract binary from archive"
unzip -p "$ua_infile" "$ua_distname/$ua_distname$ua_binpostfix" > "$ua_outfile" \
|| die "unzip has failed"
else
die "no installed method for extracting .zip archives"
fi
;;
*)
die "unrecognized archive type '$ua_archivetype'"
esac
chmod +x "$ua_outfile" || die "chmod has failed"
}
get_go_vars() {
if [ ! -z "$GOOS" ] && [ ! -z "$GOARCH" ]; then
printf "%s-%s" "$GOOS" "$GOARCH"
elif have_binary go; then
printf "%s-%s" "$($GOCC env GOOS)" "$($GOCC env GOARCH)"
else
die "no way of determining system GOOS and GOARCH\nPlease manually set GOOS and GOARCH then retry."
fi
}
mkurl() {
m_root="$1"
m_name="$2"
m_vers="$3"
m_archive="$4"
m_govars=$(get_go_vars) || die "could not get go env vars"
echo "https://ipfs.io$m_root/$m_name/$m_vers/${m_name}_${m_vers}_$m_govars.$m_archive"
}
distroot="$1"
distname="$2"
outpath="$3"
version="$4"
if [ -z "$distroot" ] || [ -z "$distname" ] || [ -z "$outpath" ] || [ -z "$version" ]; then
die "usage: dist_get <distroot> <distname> <outpath> <version>"
fi
case $version in
v*)
# correct input
;;
*)
echo "invalid version '$version'" >&2
die "versions must begin with 'v', for example: v0.4.0"
;;
esac
# TODO: don't depend on the go tool being installed to detect this
goenv=$(get_go_vars) || die "could not get go env vars"
case $goenv in
linux-*)
archive="tar.gz"
;;
darwin-*)
archive="tar.gz"
;;
windows-*)
archive="zip"
;;
freebsd-*)
archive="tar.gz"
;;
openbsd-*)
archive="tar.gz"
;;
*)
echo "unrecognized system environment: $goenv" >&2
die "currently only linux, darwin, windows and freebsd are supported by this script"
esac
mkdir -p bin/tmp
url=$(mkurl "$distroot" "$distname" "$version" "$archive")
tmpfi="bin/tmp/$distname.$archive"
download "$url" "$tmpfi"
if [ $? -ne 0 ]; then
die "failed to download $url to $tmpfi"
fi
unarchive "$archive" "$tmpfi" "$outpath" "$distname"
if [ $? -ne 0 ]; then
die "failed to extract archive $tmpfi"
fi

View File

@ -2,11 +2,15 @@
package build
import (
"github.com/filecoin-project/specs-actors/actors/abi"
)
func init() {
InsecurePoStValidation = true
}
var SectorSizes = []uint64{1024}
var SectorSizes = []abi.SectorSize{1024}
// Seconds
const BlockDelay = 6

View File

@ -2,6 +2,8 @@ package build
import (
"math/big"
"github.com/filecoin-project/specs-actors/actors/abi"
)
// Core network constants
@ -12,7 +14,7 @@ import (
const UnixfsChunkSize uint64 = 1 << 20
const UnixfsLinksPerLevel = 1024
func SupportedSectorSize(ssize uint64) bool {
func SupportedSectorSize(ssize abi.SectorSize) bool {
for _, ss := range SectorSizes {
if ssize == ss {
return true

View File

@ -2,7 +2,12 @@
package build
var SectorSizes = []uint64{
import (
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
)
var SectorSizes = []abi.SectorSize{
32 << 30,
}
@ -15,16 +20,13 @@ const PropagationDelay = 6
// ElectionPeriodStart before starting fallback post computation
//
// Epochs
const FallbackPoStDelay = 30
const FallbackPoStDelay = miner.ProvingPeriod
// SlashablePowerDelay is the number of epochs after ElectionPeriodStart, after
// which the miner is slashed
//
// Epochs
const SlashablePowerDelay = 200
// Epochs
const InteractivePoRepDelay = 8
const SlashablePowerDelay = miner.ProvingPeriod * 3 // TODO: remove
// Epochs
const InteractivePoRepConfidence = 6

View File

@ -5,7 +5,7 @@ import "fmt"
var CurrentCommit string
// BuildVersion is the local build version, set by build system
const BuildVersion = "0.2.8"
const BuildVersion = "0.3.0"
var UserVersion = BuildVersion + CurrentCommit
@ -31,7 +31,7 @@ func (ve Version) EqMajorMinor(v2 Version) bool {
}
// APIVersion is a semver version of the rpc api exposed
var APIVersion Version = newVer(0, 1, 6)
var APIVersion Version = newVer(0, 2, 0)
const (
majorMask = 0xff0000

View File

@ -1,48 +0,0 @@
package actors
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/types"
)
type CronActor struct{}
type callTuple struct {
addr address.Address
method uint64
}
var CronActors = []callTuple{
{StoragePowerAddress, SPAMethods.CheckProofSubmissions},
}
type CronActorState struct{}
type cAMethods struct {
EpochTick uint64
}
var CAMethods = cAMethods{2}
func (ca CronActor) Exports() []interface{} {
return []interface{}{
1: nil,
2: ca.EpochTick,
}
}
func (ca CronActor) EpochTick(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) {
if vmctx.Message().From != CronAddress {
return nil, aerrors.New(1, "EpochTick is only callable as a part of tipset state computation")
}
for _, call := range CronActors {
_, err := vmctx.Send(call.addr, call.method, types.NewInt(0), nil)
if err != nil {
return nil, err // todo: this very bad?
}
}
return nil, nil
}

View File

@ -1,239 +0,0 @@
package actors
import (
"bytes"
"context"
"encoding/binary"
"fmt"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/types"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-hamt-ipld"
cbor "github.com/ipfs/go-ipld-cbor"
logging "github.com/ipfs/go-log/v2"
mh "github.com/multiformats/go-multihash"
)
var log = logging.Logger("actors")
var EmptyCBOR cid.Cid
const (
GasCreateActor = 100
)
var BuiltInActors map[cid.Cid]bool
func init() {
n, err := cbor.WrapObject(map[string]string{}, mh.SHA2_256, -1)
if err != nil {
panic(err) // ok
}
EmptyCBOR = n.Cid()
}
type InitActor struct{}
type InitActorState struct {
AddressMap cid.Cid
NextID uint64
}
type iAMethods struct {
Exec uint64
}
var IAMethods = iAMethods{2}
func (ia InitActor) Exports() []interface{} {
return []interface{}{
1: nil,
2: ia.Exec,
}
}
type ExecParams struct {
Code cid.Cid
Params []byte
}
func CreateExecParams(act cid.Cid, obj cbg.CBORMarshaler) ([]byte, aerrors.ActorError) {
encparams, err := SerializeParams(obj)
if err != nil {
return nil, aerrors.Wrap(err, "creating ExecParams")
}
return SerializeParams(&ExecParams{
Code: act,
Params: encparams,
})
}
func (ia InitActor) Exec(act *types.Actor, vmctx types.VMContext, p *ExecParams) ([]byte, aerrors.ActorError) {
beginState := vmctx.Storage().GetHead()
var self InitActorState
if err := vmctx.Storage().Get(beginState, &self); err != nil {
return nil, err
}
if err := vmctx.ChargeGas(GasCreateActor); err != nil {
return nil, aerrors.Wrap(err, "run out of gas")
}
// Make sure that only the actors defined in the spec can be launched.
if !IsBuiltinActor(p.Code) {
return nil, aerrors.New(1,
"cannot launch actor instance that is not a builtin actor")
}
// Ensure that singletons can be only launched once.
// TODO: do we want to enforce this? If so how should actors be marked as such?
if IsSingletonActor(p.Code) {
return nil, aerrors.New(1, "cannot launch another actor of this type")
}
// This generates a unique address for this actor that is stable across message
// reordering
creator := vmctx.Message().From
nonce := vmctx.Message().Nonce
addr, err := ComputeActorAddress(creator, nonce)
if err != nil {
return nil, err
}
// Set up the actor itself
actor := types.Actor{
Code: p.Code,
Balance: types.NewInt(0),
Head: EmptyCBOR,
Nonce: 0,
}
// The call to the actors constructor will set up the initial state
// from the given parameters, setting `actor.Head` to a new value when successful.
// TODO: can constructors fail?
//actor.Constructor(p.Params)
// Store the mapping of address to actor ID.
idAddr, nerr := self.AddActor(vmctx.Ipld(), addr)
if nerr != nil {
return nil, aerrors.Escalate(err, "adding new actor mapping")
}
// NOTE: This is a privileged call that only the init actor is allowed to make
// FIXME: Had to comment this because state is not in interface
state, err := vmctx.StateTree()
if err != nil {
return nil, err
}
if err := state.SetActor(idAddr, &actor); err != nil {
if xerrors.Is(err, types.ErrActorNotFound) {
return nil, aerrors.Absorb(err, 1, "SetActor, actor not found")
}
return nil, aerrors.Escalate(err, "inserting new actor into state tree")
}
// '1' is reserved for constructor methods
_, err = vmctx.Send(idAddr, 1, vmctx.Message().Value, p.Params)
if err != nil {
return nil, err
}
c, err := vmctx.Storage().Put(&self)
if err != nil {
return nil, err
}
if err := vmctx.Storage().Commit(beginState, c); err != nil {
return nil, err
}
return idAddr.Bytes(), nil
}
func IsBuiltinActor(code cid.Cid) bool {
return BuiltInActors[code]
}
func IsSingletonActor(code cid.Cid) bool {
return code == StoragePowerCodeCid || code == StorageMarketCodeCid || code == InitCodeCid || code == CronCodeCid
}
func (ias *InitActorState) AddActor(cst cbor.IpldStore, addr address.Address) (address.Address, error) {
nid := ias.NextID
amap, err := hamt.LoadNode(context.TODO(), cst, ias.AddressMap)
if err != nil {
return address.Undef, err
}
if err := amap.Set(context.TODO(), string(addr.Bytes()), nid); err != nil {
return address.Undef, err
}
if err := amap.Flush(context.TODO()); err != nil {
return address.Undef, err
}
ncid, err := cst.Put(context.TODO(), amap)
if err != nil {
return address.Undef, err
}
ias.AddressMap = ncid
ias.NextID++
return NewIDAddress(nid)
}
func (ias *InitActorState) Lookup(cst cbor.IpldStore, addr address.Address) (address.Address, error) {
amap, err := hamt.LoadNode(context.TODO(), cst, ias.AddressMap)
if err != nil {
return address.Undef, xerrors.Errorf("ias lookup failed loading hamt node: %w", err)
}
var val interface{}
err = amap.Find(context.TODO(), string(addr.Bytes()), &val)
if err != nil {
return address.Undef, xerrors.Errorf("ias lookup failed to do find: %w", err)
}
ival, ok := val.(uint64)
if !ok {
return address.Undef, fmt.Errorf("invalid value in init actor state, expected uint64, got %T", val)
}
return address.NewIDAddress(ival)
}
type AccountActorState struct {
Address address.Address
}
func ComputeActorAddress(creator address.Address, nonce uint64) (address.Address, ActorError) {
buf := new(bytes.Buffer)
_, err := buf.Write(creator.Bytes())
if err != nil {
return address.Undef, aerrors.Escalate(err, "could not write address")
}
err = binary.Write(buf, binary.BigEndian, nonce)
if err != nil {
return address.Undef, aerrors.Escalate(err, "could not write nonce")
}
addr, err := address.NewActorAddress(buf.Bytes())
if err != nil {
return address.Undef, aerrors.Escalate(err, "could not create address")
}
return addr, nil
}

File diff suppressed because it is too large Load Diff

View File

@ -1,281 +0,0 @@
package actors_test
import (
"bytes"
"context"
"math"
"math/rand"
"testing"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-sectorbuilder"
"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/actors/aerrors"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/rlepluslazy"
blockstore "github.com/ipfs/go-ipfs-blockstore"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/stretchr/testify/assert"
cbg "github.com/whyrusleeping/cbor-gen"
)
func TestMinerCommitSectors(t *testing.T) {
var worker, client address.Address
var minerAddr address.Address
opts := []HarnessOpt{
HarnessAddr(&worker, 1000000),
HarnessAddr(&client, 1000000),
HarnessActor(&minerAddr, &worker, actors.StorageMinerCodeCid,
func() cbg.CBORMarshaler {
return &actors.StorageMinerConstructorParams{
Owner: worker,
Worker: worker,
SectorSize: 1024,
PeerID: "fakepeerid",
}
}),
}
h := NewHarness(t, opts...)
h.vm.Syscalls.ValidatePoRep = func(ctx context.Context, maddr address.Address, ssize uint64, commD, commR, ticket, proof, seed []byte, sectorID uint64) (bool, aerrors.ActorError) {
// all proofs are valid
return true, nil
}
ret, _ := h.SendFunds(t, worker, minerAddr, types.NewInt(100000))
ApplyOK(t, ret)
ret, _ = h.InvokeWithValue(t, client, actors.StorageMarketAddress, actors.SMAMethods.AddBalance, types.NewInt(2000), nil)
ApplyOK(t, ret)
addSectorToMiner(h, t, minerAddr, worker, client, 1)
assertSectorIDs(h, t, minerAddr, []uint64{1})
}
type badRuns struct {
done bool
}
func (br *badRuns) HasNext() bool {
return !br.done
}
func (br *badRuns) NextRun() (rlepluslazy.Run, error) {
br.done = true
return rlepluslazy.Run{true, math.MaxInt64}, nil
}
var _ rlepluslazy.RunIterator = (*badRuns)(nil)
func TestMinerSubmitBadFault(t *testing.T) {
oldSS, oldMin := build.SectorSizes, build.MinimumMinerPower
build.SectorSizes, build.MinimumMinerPower = []uint64{1024}, 1024
defer func() {
build.SectorSizes, build.MinimumMinerPower = oldSS, oldMin
}()
var worker, client address.Address
var minerAddr address.Address
opts := []HarnessOpt{
HarnessAddr(&worker, 1000000),
HarnessAddr(&client, 1000000),
HarnessAddMiner(&minerAddr, &worker),
}
h := NewHarness(t, opts...)
h.vm.Syscalls.ValidatePoRep = func(ctx context.Context, maddr address.Address, ssize uint64, commD, commR, ticket, proof, seed []byte, sectorID uint64) (bool, aerrors.ActorError) {
// all proofs are valid
return true, nil
}
ret, _ := h.SendFunds(t, worker, minerAddr, types.NewInt(100000))
ApplyOK(t, ret)
ret, _ = h.InvokeWithValue(t, client, actors.StorageMarketAddress, actors.SMAMethods.AddBalance, types.NewInt(2000), nil)
ApplyOK(t, ret)
addSectorToMiner(h, t, minerAddr, worker, client, 1)
assertSectorIDs(h, t, minerAddr, []uint64{1})
bf := types.NewBitField()
bf.Set(6)
ret, _ = h.Invoke(t, worker, minerAddr, actors.MAMethods.DeclareFaults, &actors.DeclareFaultsParams{bf})
ApplyOK(t, ret)
ret, _ = h.Invoke(t, actors.NetworkAddress, minerAddr, actors.MAMethods.SubmitElectionPoSt, nil)
ApplyOK(t, ret)
assertSectorIDs(h, t, minerAddr, []uint64{1})
st, err := getMinerState(context.TODO(), h.vm.StateTree(), h.bs, minerAddr)
assert.NoError(t, err)
expectedPower := st.Power
if types.BigCmp(expectedPower, types.NewInt(1024)) != 0 {
t.Errorf("Expected power of 1024, got %s", expectedPower)
}
badnum := uint64(0)
badnum--
bf = types.NewBitField()
bf.Set(badnum)
bf.Set(badnum - 1)
ret, _ = h.Invoke(t, worker, minerAddr, actors.MAMethods.DeclareFaults, &actors.DeclareFaultsParams{bf})
ApplyOK(t, ret)
ret, _ = h.Invoke(t, actors.NetworkAddress, minerAddr, actors.MAMethods.SubmitElectionPoSt, nil)
ApplyOK(t, ret)
assertSectorIDs(h, t, minerAddr, []uint64{1})
st, err = getMinerState(context.TODO(), h.vm.StateTree(), h.bs, minerAddr)
assert.NoError(t, err)
currentPower := st.Power
if types.BigCmp(expectedPower, currentPower) != 0 {
t.Errorf("power changed and shouldn't have: %s != %s", expectedPower, currentPower)
}
bf.Set(badnum - 2)
ret, _ = h.Invoke(t, worker, minerAddr, actors.MAMethods.DeclareFaults, &actors.DeclareFaultsParams{bf})
if ret.ExitCode != 3 {
t.Errorf("expected exit code 3, got %d: %+v", ret.ExitCode, ret.ActorErr)
}
assertSectorIDs(h, t, minerAddr, []uint64{1})
rle, err := rlepluslazy.EncodeRuns(&badRuns{}, []byte{})
assert.NoError(t, err)
bf, err = types.NewBitFieldFromBytes(rle)
assert.NoError(t, err)
ret, _ = h.Invoke(t, worker, minerAddr, actors.MAMethods.DeclareFaults, &actors.DeclareFaultsParams{bf})
if ret.ExitCode != 3 {
t.Errorf("expected exit code 3, got %d: %+v", ret.ExitCode, ret.ActorErr)
}
assertSectorIDs(h, t, minerAddr, []uint64{1})
bf = types.NewBitField()
bf.Set(1)
ret, _ = h.Invoke(t, worker, minerAddr, actors.MAMethods.DeclareFaults, &actors.DeclareFaultsParams{bf})
ApplyOK(t, ret)
ret, _ = h.Invoke(t, actors.NetworkAddress, minerAddr, actors.MAMethods.SubmitElectionPoSt, nil)
ApplyOK(t, ret)
assertSectorIDs(h, t, minerAddr, []uint64{})
}
func addSectorToMiner(h *Harness, t *testing.T, minerAddr, worker, client address.Address, sid uint64) {
t.Helper()
s := sectorbuilder.UserBytesForSectorSize(1024)
deal := h.makeFakeDeal(t, minerAddr, worker, client, s)
ret, _ := h.Invoke(t, worker, actors.StorageMarketAddress, actors.SMAMethods.PublishStorageDeals,
&actors.PublishStorageDealsParams{
Deals: []actors.StorageDealProposal{*deal},
})
ApplyOK(t, ret)
var dealIds actors.PublishStorageDealResponse
if err := dealIds.UnmarshalCBOR(bytes.NewReader(ret.Return)); err != nil {
t.Fatal(err)
}
dealid := dealIds.DealIDs[0]
ret, _ = h.Invoke(t, worker, minerAddr, actors.MAMethods.PreCommitSector,
&actors.SectorPreCommitInfo{
SectorNumber: sid,
CommR: []byte("cats"),
SealEpoch: 10,
DealIDs: []uint64{dealid},
})
ApplyOK(t, ret)
h.BlockHeight += 100
ret, _ = h.Invoke(t, worker, minerAddr, actors.MAMethods.ProveCommitSector,
&actors.SectorProveCommitInfo{
Proof: []byte("prooofy"),
SectorID: sid,
DealIDs: []uint64{dealid}, // TODO: weird that i have to pass this again
})
ApplyOK(t, ret)
}
func assertSectorIDs(h *Harness, t *testing.T, maddr address.Address, ids []uint64) {
t.Helper()
sectors, err := getMinerSectorSet(context.TODO(), h.vm.StateTree(), h.bs, maddr)
if err != nil {
t.Fatal(err)
}
if len(sectors) != len(ids) {
t.Fatal("miner has wrong number of sectors in their sector set")
}
all := make(map[uint64]bool)
for _, s := range sectors {
all[s.SectorID] = true
}
for _, id := range ids {
if !all[id] {
t.Fatal("expected to find sector ID: ", id)
}
}
}
func getMinerState(ctx context.Context, st types.StateTree, bs blockstore.Blockstore, maddr address.Address) (*actors.StorageMinerActorState, error) {
mact, err := st.GetActor(maddr)
if err != nil {
return nil, err
}
cst := cbor.NewCborStore(bs)
var mstate actors.StorageMinerActorState
if err := cst.Get(ctx, mact.Head, &mstate); err != nil {
return nil, err
}
return &mstate, nil
}
func getMinerSectorSet(ctx context.Context, st types.StateTree, bs blockstore.Blockstore, maddr address.Address) ([]*api.ChainSectorInfo, error) {
mstate, err := getMinerState(ctx, st, bs, maddr)
if err != nil {
return nil, err
}
return stmgr.LoadSectorsFromSet(ctx, bs, mstate.Sectors)
}
func (h *Harness) makeFakeDeal(t *testing.T, miner, worker, client address.Address, size uint64) *actors.StorageDealProposal {
data := make([]byte, size)
rand.Read(data)
commP, err := sectorbuilder.GeneratePieceCommitment(bytes.NewReader(data), size)
if err != nil {
t.Fatal(err)
}
prop := actors.StorageDealProposal{
PieceRef: commP[:],
PieceSize: size,
Client: client,
Provider: miner,
ProposalExpiration: 10000,
Duration: 150,
StoragePricePerEpoch: types.NewInt(1),
StorageCollateral: types.NewInt(0),
}
if err := api.SignWith(context.TODO(), h.w.Sign, client, &prop); err != nil {
t.Fatal(err)
}
return &prop
}

View File

@ -1,302 +0,0 @@
package actors
import (
"bytes"
"fmt"
"github.com/ipfs/go-cid"
"github.com/minio/blake2b-simd"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/types"
)
type PaymentChannelActor struct{}
type PaymentInfo struct {
PayChActor address.Address
Payer address.Address
ChannelMessage *cid.Cid
Vouchers []*types.SignedVoucher
}
type LaneState struct {
Closed bool
Redeemed types.BigInt
Nonce uint64
}
type PaymentChannelActorState struct {
From address.Address
To address.Address
ToSend types.BigInt
ClosingAt uint64
MinCloseHeight uint64
// TODO: needs to be map[uint64]*laneState
// waiting on refmt#35 to be fixed
LaneStates map[string]*LaneState
}
func (pca PaymentChannelActor) Exports() []interface{} {
return []interface{}{
1: pca.Constructor,
2: pca.UpdateChannelState,
3: pca.Close,
4: pca.Collect,
5: pca.GetOwner,
6: pca.GetToSend,
}
}
type pcaMethods struct {
Constructor uint64
UpdateChannelState uint64
Close uint64
Collect uint64
GetOwner uint64
GetToSend uint64
}
var PCAMethods = pcaMethods{1, 2, 3, 4, 5, 6}
type PCAConstructorParams struct {
To address.Address
}
func (pca PaymentChannelActor) Constructor(act *types.Actor, vmctx types.VMContext, params *PCAConstructorParams) ([]byte, ActorError) {
var self PaymentChannelActorState
self.From = vmctx.Origin()
self.To = params.To
self.LaneStates = make(map[string]*LaneState)
storage := vmctx.Storage()
c, err := storage.Put(&self)
if err != nil {
return nil, err
}
if err := storage.Commit(EmptyCBOR, c); err != nil {
return nil, err
}
return nil, nil
}
type PCAUpdateChannelStateParams struct {
Sv types.SignedVoucher
Secret []byte
Proof []byte
}
func hash(b []byte) []byte {
s := blake2b.Sum256(b)
return s[:]
}
type PaymentVerifyParams struct {
Extra []byte
Proof []byte
}
func (pca PaymentChannelActor) UpdateChannelState(act *types.Actor, vmctx types.VMContext, params *PCAUpdateChannelStateParams) ([]byte, ActorError) {
var self PaymentChannelActorState
oldstate := vmctx.Storage().GetHead()
storage := vmctx.Storage()
if err := storage.Get(oldstate, &self); err != nil {
return nil, err
}
sv := params.Sv
vb, nerr := sv.SigningBytes()
if nerr != nil {
return nil, aerrors.Absorb(nerr, 1, "failed to serialize signedvoucher")
}
if err := vmctx.VerifySignature(sv.Signature, self.From, vb); err != nil {
return nil, err
}
if vmctx.BlockHeight() < sv.TimeLock {
return nil, aerrors.New(2, "cannot use this voucher yet!")
}
if len(sv.SecretPreimage) > 0 {
if !bytes.Equal(hash(params.Secret), sv.SecretPreimage) {
return nil, aerrors.New(3, "incorrect secret!")
}
}
if sv.Extra != nil {
encoded, err := SerializeParams(&PaymentVerifyParams{sv.Extra.Data, params.Proof})
if err != nil {
return nil, err
}
_, err = vmctx.Send(sv.Extra.Actor, sv.Extra.Method, types.NewInt(0), encoded)
if err != nil {
return nil, aerrors.Newf(4, "spend voucher verification failed: %s", err)
}
}
ls, ok := self.LaneStates[fmt.Sprint(sv.Lane)]
if !ok {
ls = new(LaneState)
ls.Redeemed = types.NewInt(0) // TODO: kinda annoying that this doesnt default to a usable value
self.LaneStates[fmt.Sprint(sv.Lane)] = ls
}
if ls.Closed {
return nil, aerrors.New(5, "cannot redeem a voucher on a closed lane")
}
if ls.Nonce > sv.Nonce {
return nil, aerrors.New(6, "voucher has an outdated nonce, cannot redeem")
}
mergeValue := types.NewInt(0)
for _, merge := range sv.Merges {
if merge.Lane == sv.Lane {
return nil, aerrors.New(7, "voucher cannot merge its own lane")
}
ols := self.LaneStates[fmt.Sprint(merge.Lane)]
if ols.Nonce >= merge.Nonce {
return nil, aerrors.New(8, "merge in voucher has outdated nonce, cannot redeem")
}
mergeValue = types.BigAdd(mergeValue, ols.Redeemed)
ols.Nonce = merge.Nonce
}
ls.Nonce = sv.Nonce
balanceDelta := types.BigSub(sv.Amount, types.BigAdd(mergeValue, ls.Redeemed))
ls.Redeemed = sv.Amount
newSendBalance := types.BigAdd(self.ToSend, balanceDelta)
if newSendBalance.LessThan(types.NewInt(0)) {
// TODO: is this impossible?
return nil, aerrors.New(9, "voucher would leave channel balance negative")
}
if newSendBalance.GreaterThan(act.Balance) {
return nil, aerrors.New(10, "not enough funds in channel to cover voucher")
}
log.Info("vals: ", newSendBalance, sv.Amount, balanceDelta, mergeValue, ls.Redeemed)
self.ToSend = newSendBalance
if sv.MinCloseHeight != 0 {
if self.ClosingAt != 0 && self.ClosingAt < sv.MinCloseHeight {
self.ClosingAt = sv.MinCloseHeight
}
if self.MinCloseHeight < sv.MinCloseHeight {
self.MinCloseHeight = sv.MinCloseHeight
}
}
ncid, err := storage.Put(&self)
if err != nil {
return nil, err
}
if err := storage.Commit(oldstate, ncid); err != nil {
return nil, err
}
return nil, nil
}
func (pca PaymentChannelActor) Close(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, aerrors.ActorError) {
var self PaymentChannelActorState
storage := vmctx.Storage()
oldstate := storage.GetHead()
if err := storage.Get(oldstate, &self); err != nil {
return nil, err
}
if vmctx.Message().From != self.From && vmctx.Message().From != self.To {
return nil, aerrors.New(1, "not authorized to close channel")
}
if self.ClosingAt != 0 {
return nil, aerrors.New(2, "channel already closing")
}
self.ClosingAt = vmctx.BlockHeight() + build.PaymentChannelClosingDelay
if self.ClosingAt < self.MinCloseHeight {
self.ClosingAt = self.MinCloseHeight
}
ncid, err := storage.Put(&self)
if err != nil {
return nil, err
}
if err := storage.Commit(oldstate, ncid); err != nil {
return nil, err
}
return nil, nil
}
func (pca PaymentChannelActor) Collect(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, aerrors.ActorError) {
var self PaymentChannelActorState
storage := vmctx.Storage()
oldstate := storage.GetHead()
if err := storage.Get(oldstate, &self); err != nil {
return nil, err
}
if self.ClosingAt == 0 {
return nil, aerrors.New(1, "payment channel not closing or closed")
}
if vmctx.BlockHeight() < self.ClosingAt {
return nil, aerrors.New(2, "payment channel not closed yet")
}
_, err := vmctx.Send(self.From, 0, types.BigSub(act.Balance, self.ToSend), nil)
if err != nil {
return nil, err
}
_, err = vmctx.Send(self.To, 0, self.ToSend, nil)
if err != nil {
return nil, err
}
self.ToSend = types.NewInt(0)
ncid, err := storage.Put(&self)
if err != nil {
return nil, err
}
if err := storage.Commit(oldstate, ncid); err != nil {
return nil, err
}
return nil, nil
}
func (pca PaymentChannelActor) GetOwner(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, aerrors.ActorError) {
var self PaymentChannelActorState
storage := vmctx.Storage()
if err := storage.Get(storage.GetHead(), &self); err != nil {
return nil, err
}
return self.From.Bytes(), nil
}
func (pca PaymentChannelActor) GetToSend(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, aerrors.ActorError) {
var self PaymentChannelActorState
storage := vmctx.Storage()
if err := storage.Get(storage.GetHead(), &self); err != nil {
return nil, err
}
return self.ToSend.Bytes(), nil
}

View File

@ -1,681 +0,0 @@
package actors
import (
"bytes"
"context"
"sort"
"go.opencensus.io/trace"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-amt-ipld/v2"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-hamt-ipld"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/filecoin-project/go-address"
cborutil "github.com/filecoin-project/go-cbor-util"
"github.com/filecoin-project/go-sectorbuilder"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/sigs"
)
type StorageMarketActor struct{}
type smaMethods struct {
Constructor uint64
WithdrawBalance uint64
AddBalance uint64
CheckLockedBalance uint64
PublishStorageDeals uint64
HandleCronAction uint64
SettleExpiredDeals uint64
ProcessStorageDealsPayment uint64
SlashStorageDealCollateral uint64
GetLastExpirationFromDealIDs uint64
ActivateStorageDeals uint64
ComputeDataCommitment uint64
}
var SMAMethods = smaMethods{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}
func (sma StorageMarketActor) Exports() []interface{} {
return []interface{}{
2: sma.WithdrawBalance,
3: sma.AddBalance,
// 4: sma.CheckLockedBalance,
5: sma.PublishStorageDeals,
// 6: sma.HandleCronAction,
// 7: sma.SettleExpiredDeals,
// 8: sma.ProcessStorageDealsPayment,
// 9: sma.SlashStorageDealCollateral,
// 10: sma.GetLastExpirationFromDealIDs,
11: sma.ActivateStorageDeals, // TODO: move under PublishStorageDeals after specs team approves
12: sma.ComputeDataCommitment,
}
}
type StorageParticipantBalance struct {
Locked types.BigInt
Available types.BigInt
}
type StorageMarketState struct {
Balances cid.Cid // hamt<addr, StorageParticipantBalance>
Deals cid.Cid // amt<StorageDeal>
NextDealID uint64 // TODO: spec
}
// TODO: Drop in favour of car storage
type SerializationMode = uint64
const (
SerializationUnixFSv0 = iota
// IPLD / car
)
type StorageDealProposal struct {
PieceRef []byte // cid bytes // TODO: spec says to use cid.Cid, probably not a good idea
PieceSize uint64
Client address.Address
Provider address.Address
ProposalExpiration uint64
Duration uint64 // TODO: spec
StoragePricePerEpoch types.BigInt
StorageCollateral types.BigInt
ProposerSignature *types.Signature
}
func (sdp *StorageDealProposal) TotalStoragePrice() types.BigInt {
return types.BigMul(sdp.StoragePricePerEpoch, types.NewInt(sdp.Duration))
}
type SignFunc = func(context.Context, []byte) (*types.Signature, error)
func (sdp *StorageDealProposal) Sign(ctx context.Context, sign SignFunc) error {
if sdp.ProposerSignature != nil {
return xerrors.New("signature already present in StorageDealProposal")
}
var buf bytes.Buffer
if err := sdp.MarshalCBOR(&buf); err != nil {
return err
}
sig, err := sign(ctx, buf.Bytes())
if err != nil {
return err
}
sdp.ProposerSignature = sig
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(worker address.Address) error {
if sdp.Client != worker || worker == address.Undef {
unsigned := *sdp
unsigned.ProposerSignature = nil
var buf bytes.Buffer
if err := unsigned.MarshalCBOR(&buf); err != nil {
return err
}
if err := sigs.Verify(sdp.ProposerSignature, sdp.Client, buf.Bytes()); err != nil {
return err
}
}
return nil
}
type OnChainDeal struct {
PieceRef []byte // cid bytes // TODO: spec says to use cid.Cid, probably not a good idea
PieceSize uint64
Client address.Address
Provider address.Address
ProposalExpiration uint64
Duration uint64 // TODO: spec
StoragePricePerEpoch types.BigInt
StorageCollateral types.BigInt
ActivationEpoch uint64 // 0 = inactive
}
type WithdrawBalanceParams struct {
Balance types.BigInt
}
func (sma StorageMarketActor) WithdrawBalance(act *types.Actor, vmctx types.VMContext, params *WithdrawBalanceParams) ([]byte, ActorError) {
// TODO: (spec) this should be 2-stage
var self StorageMarketState
old := vmctx.Storage().GetHead()
if err := vmctx.Storage().Get(old, &self); err != nil {
return nil, err
}
b, bnd, err := GetMarketBalances(vmctx.Context(), vmctx.Ipld(), self.Balances, vmctx.Message().From)
if err != nil {
return nil, aerrors.Wrap(err, "could not get balance")
}
balance := b[0]
if balance.Available.LessThan(params.Balance) {
return nil, aerrors.Newf(1, "can not withdraw more funds than available: %s > %s", params.Balance, b[0].Available)
}
balance.Available = types.BigSub(balance.Available, params.Balance)
_, err = vmctx.Send(vmctx.Message().From, 0, params.Balance, nil)
if err != nil {
return nil, aerrors.Wrap(err, "sending funds failed")
}
bcid, err := setMarketBalances(vmctx, bnd, map[address.Address]StorageParticipantBalance{
vmctx.Message().From: balance,
})
if err != nil {
return nil, err
}
self.Balances = bcid
nroot, err := vmctx.Storage().Put(&self)
if err != nil {
return nil, err
}
return nil, vmctx.Storage().Commit(old, nroot)
}
func (sma StorageMarketActor) AddBalance(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) {
var self StorageMarketState
old := vmctx.Storage().GetHead()
if err := vmctx.Storage().Get(old, &self); err != nil {
return nil, err
}
b, bnd, err := GetMarketBalances(vmctx.Context(), vmctx.Ipld(), self.Balances, vmctx.Message().From)
if err != nil {
return nil, aerrors.Wrap(err, "could not get balance")
}
balance := b[0]
balance.Available = types.BigAdd(balance.Available, vmctx.Message().Value)
bcid, err := setMarketBalances(vmctx, bnd, map[address.Address]StorageParticipantBalance{
vmctx.Message().From: balance,
})
if err != nil {
return nil, err
}
self.Balances = bcid
nroot, err := vmctx.Storage().Put(&self)
if err != nil {
return nil, err
}
return nil, vmctx.Storage().Commit(old, nroot)
}
func setMarketBalances(vmctx types.VMContext, nd *hamt.Node, set map[address.Address]StorageParticipantBalance) (cid.Cid, ActorError) {
keys := make([]address.Address, 0, len(set))
for k := range set {
keys = append(keys, k)
}
sort.Slice(keys, func(i, j int) bool {
return bytes.Compare(keys[i].Bytes(), keys[j].Bytes()) < 0
})
for _, addr := range keys {
balance := set[addr]
if err := nd.Set(vmctx.Context(), string(addr.Bytes()), &balance); err != nil {
return cid.Undef, aerrors.HandleExternalError(err, "setting new balance")
}
}
if err := nd.Flush(vmctx.Context()); err != nil {
return cid.Undef, aerrors.HandleExternalError(err, "flushing balance hamt")
}
c, err := vmctx.Ipld().Put(vmctx.Context(), nd)
if err != nil {
return cid.Undef, aerrors.HandleExternalError(err, "failed to balances storage")
}
return c, nil
}
func GetMarketBalances(ctx context.Context, store cbor.IpldStore, rcid cid.Cid, addrs ...address.Address) ([]StorageParticipantBalance, *hamt.Node, ActorError) {
ctx, span := trace.StartSpan(ctx, "GetMarketBalances")
defer span.End()
nd, err := hamt.LoadNode(ctx, store, rcid)
if err != nil {
return nil, nil, aerrors.HandleExternalError(err, "failed to load miner set")
}
out := make([]StorageParticipantBalance, len(addrs))
for i, a := range addrs {
var balance StorageParticipantBalance
err = nd.Find(ctx, string(a.Bytes()), &balance)
switch err {
case hamt.ErrNotFound:
out[i] = StorageParticipantBalance{
Locked: types.NewInt(0),
Available: types.NewInt(0),
}
case nil:
out[i] = balance
default:
return nil, nil, aerrors.HandleExternalError(err, "failed to do set lookup")
}
}
return out, nd, nil
}
/*
func (sma StorageMarketActor) CheckLockedBalance(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) {
}
*/
type PublishStorageDealsParams struct {
Deals []StorageDealProposal
}
type PublishStorageDealResponse struct {
DealIDs []uint64
}
func (sma StorageMarketActor) PublishStorageDeals(act *types.Actor, vmctx types.VMContext, params *PublishStorageDealsParams) ([]byte, ActorError) {
var self StorageMarketState
old := vmctx.Storage().GetHead()
if err := vmctx.Storage().Get(old, &self); err != nil {
return nil, err
}
deals, err := amt.LoadAMT(vmctx.Context(), vmctx.Ipld(), self.Deals)
if err != nil {
return nil, aerrors.HandleExternalError(err, "loading deals amt")
}
// todo: handle duplicate deals
if len(params.Deals) == 0 {
return nil, aerrors.New(1, "no storage deals in params.Deals")
}
out := PublishStorageDealResponse{
DealIDs: make([]uint64, len(params.Deals)),
}
workerBytes, aerr := vmctx.Send(params.Deals[0].Provider, MAMethods.GetWorkerAddr, types.NewInt(0), nil)
if aerr != nil {
return nil, aerr
}
providerWorker, err := address.NewFromBytes(workerBytes)
if err != nil {
return nil, aerrors.HandleExternalError(err, "parsing provider worker address bytes")
}
// TODO: REVIEW: Do we want to check if provider exists in the power actor?
for i, deal := range params.Deals {
if err := self.validateDeal(vmctx, deal, providerWorker); err != nil {
return nil, err
}
err := deals.Set(vmctx.Context(), self.NextDealID, &OnChainDeal{
PieceRef: deal.PieceRef,
PieceSize: deal.PieceSize,
Client: deal.Client,
Provider: deal.Provider,
ProposalExpiration: deal.ProposalExpiration,
Duration: deal.Duration,
StoragePricePerEpoch: deal.StoragePricePerEpoch,
StorageCollateral: deal.StorageCollateral,
ActivationEpoch: 0,
})
if err != nil {
return nil, aerrors.HandleExternalError(err, "setting deal in deal AMT")
}
out.DealIDs[i] = self.NextDealID
self.NextDealID++
}
dealsCid, err := deals.Flush(vmctx.Context())
if err != nil {
return nil, aerrors.HandleExternalError(err, "saving deals AMT")
}
self.Deals = dealsCid
nroot, err := vmctx.Storage().Put(&self)
if err != nil {
return nil, aerrors.HandleExternalError(err, "storing state failed")
}
aerr = vmctx.Storage().Commit(old, nroot)
if aerr != nil {
return nil, aerr
}
var outBuf bytes.Buffer
if err := out.MarshalCBOR(&outBuf); err != nil {
return nil, aerrors.HandleExternalError(err, "serialising output")
}
return outBuf.Bytes(), nil
}
func (st *StorageMarketState) validateDeal(vmctx types.VMContext, deal StorageDealProposal, providerWorker address.Address) aerrors.ActorError {
ctx, span := trace.StartSpan(vmctx.Context(), "validateDeal")
defer span.End()
if vmctx.BlockHeight() > deal.ProposalExpiration {
return aerrors.New(1, "deal proposal already expired")
}
if vmctx.Message().From != providerWorker {
return aerrors.New(2, "Deals must be submitted by the miner worker")
}
if err := deal.Verify(providerWorker); err != nil {
return aerrors.Absorb(err, 3, "verifying proposer signature")
}
// TODO: do some caching (changes gas so needs to be in spec too)
b, bnd, aerr := GetMarketBalances(ctx, vmctx.Ipld(), st.Balances, deal.Client, providerWorker)
if aerr != nil {
return aerrors.Wrap(aerr, "getting client, and provider balances")
}
clientBalance := b[0]
providerBalance := b[1]
totalPrice := deal.TotalStoragePrice()
if clientBalance.Available.LessThan(totalPrice) {
return aerrors.Newf(5, "client doesn't have enough available funds to cover storage price; %d < %d", clientBalance.Available, totalPrice)
}
clientBalance = lockFunds(clientBalance, totalPrice)
// TODO: REVIEW: Not clear who pays for this
if providerBalance.Available.LessThan(deal.StorageCollateral) {
return aerrors.Newf(6, "provider doesn't have enough available funds to cover StorageCollateral; %d < %d", providerBalance.Available, deal.StorageCollateral)
}
providerBalance = lockFunds(providerBalance, deal.StorageCollateral)
// TODO: piece checks (e.g. size > sectorSize)?
bcid, aerr := setMarketBalances(vmctx, bnd, map[address.Address]StorageParticipantBalance{
deal.Client: clientBalance,
providerWorker: providerBalance,
})
if aerr != nil {
return aerr
}
st.Balances = bcid
return nil
}
type ActivateStorageDealsParams struct {
Deals []uint64
}
func (sma StorageMarketActor) ActivateStorageDeals(act *types.Actor, vmctx types.VMContext, params *ActivateStorageDealsParams) ([]byte, ActorError) {
ctx := vmctx.Context()
var self StorageMarketState
old := vmctx.Storage().GetHead()
if err := vmctx.Storage().Get(old, &self); err != nil {
return nil, err
}
deals, err := amt.LoadAMT(ctx, vmctx.Ipld(), self.Deals)
if err != nil {
return nil, aerrors.HandleExternalError(err, "loading deals amt")
}
for _, deal := range params.Deals {
var dealInfo OnChainDeal
if err := deals.Get(ctx, deal, &dealInfo); err != nil {
if _, is := err.(*amt.ErrNotFound); is {
return nil, aerrors.New(3, "deal not found")
}
return nil, aerrors.HandleExternalError(err, "getting deal info failed")
}
if vmctx.Message().From != dealInfo.Provider {
return nil, aerrors.New(1, "ActivateStorageDeals can only be called by the deal provider")
}
if vmctx.BlockHeight() > dealInfo.ProposalExpiration {
return nil, aerrors.New(2, "deal cannot be activated: proposal expired")
}
if dealInfo.ActivationEpoch > 0 {
// this probably can't happen in practice
return nil, aerrors.New(3, "deal already active")
}
dealInfo.ActivationEpoch = vmctx.BlockHeight()
if err := deals.Set(ctx, deal, &dealInfo); err != nil {
return nil, aerrors.HandleExternalError(err, "setting deal info in AMT failed")
}
}
dealsCid, err := deals.Flush(ctx)
if err != nil {
return nil, aerrors.HandleExternalError(err, "saving deals AMT")
}
self.Deals = dealsCid
nroot, err := vmctx.Storage().Put(&self)
if err != nil {
return nil, aerrors.HandleExternalError(err, "storing state failed")
}
aerr := vmctx.Storage().Commit(old, nroot)
if aerr != nil {
return nil, aerr
}
return nil, nil
}
type ProcessStorageDealsPaymentParams struct {
DealIDs []uint64
}
func (sma StorageMarketActor) ProcessStorageDealsPayment(act *types.Actor, vmctx types.VMContext, params *ProcessStorageDealsPaymentParams) ([]byte, ActorError) {
ctx := vmctx.Context()
var self StorageMarketState
old := vmctx.Storage().GetHead()
if err := vmctx.Storage().Get(old, &self); err != nil {
return nil, err
}
deals, err := amt.LoadAMT(ctx, vmctx.Ipld(), self.Deals)
if err != nil {
return nil, aerrors.HandleExternalError(err, "loading deals amt")
}
// TODO: Would be nice if send could assert actor type
workerBytes, aerr := vmctx.Send(vmctx.Message().From, MAMethods.GetWorkerAddr, types.NewInt(0), nil)
if aerr != nil {
return nil, aerr
}
providerWorker, err := address.NewFromBytes(workerBytes)
if err != nil {
return nil, aerrors.HandleExternalError(err, "parsing provider worker address bytes")
}
for _, deal := range params.DealIDs {
var dealInfo OnChainDeal
if err := deals.Get(ctx, deal, &dealInfo); err != nil {
if _, is := err.(*amt.ErrNotFound); is {
return nil, aerrors.New(2, "deal not found")
}
return nil, aerrors.HandleExternalError(err, "getting deal info failed")
}
if dealInfo.Provider != vmctx.Message().From {
return nil, aerrors.New(3, "ProcessStorageDealsPayment can only be called by deal provider")
}
if vmctx.BlockHeight() < dealInfo.ActivationEpoch {
// TODO: This is probably fatal
return nil, aerrors.New(4, "ActivationEpoch lower than block height")
}
if vmctx.BlockHeight() > dealInfo.ActivationEpoch+dealInfo.Duration {
// Deal expired, miner should drop it
// TODO: process payment for the remainder of last proving period
return nil, nil
}
toPay := types.BigMul(dealInfo.StoragePricePerEpoch, types.NewInt(build.SlashablePowerDelay))
b, bnd, aerr := GetMarketBalances(vmctx.Context(), vmctx.Ipld(), self.Balances, dealInfo.Client, providerWorker)
if aerr != nil {
return nil, aerr
}
clientBal := b[0]
providerBal := b[1]
clientBal.Locked, providerBal.Available = transferFunds(clientBal.Locked, providerBal.Available, toPay)
// TODO: call set once
bcid, aerr := setMarketBalances(vmctx, bnd, map[address.Address]StorageParticipantBalance{
dealInfo.Client: clientBal,
providerWorker: providerBal,
})
if aerr != nil {
return nil, aerr
}
self.Balances = bcid
}
nroot, err := vmctx.Storage().Put(&self)
if err != nil {
return nil, aerrors.HandleExternalError(err, "storing state failed")
}
aerr = vmctx.Storage().Commit(old, nroot)
if aerr != nil {
return nil, aerr
}
return nil, nil
}
func lockFunds(p StorageParticipantBalance, amt types.BigInt) StorageParticipantBalance {
p.Available, p.Locked = transferFunds(p.Available, p.Locked, amt)
return p
}
func transferFunds(from, to, amt types.BigInt) (types.BigInt, types.BigInt) {
// TODO: some asserts
return types.BigSub(from, amt), types.BigAdd(to, amt)
}
type ComputeDataCommitmentParams struct {
DealIDs []uint64
SectorSize uint64
}
func (sma StorageMarketActor) ComputeDataCommitment(act *types.Actor, vmctx types.VMContext, params *ComputeDataCommitmentParams) ([]byte, ActorError) {
ctx := vmctx.Context()
var self StorageMarketState
old := vmctx.Storage().GetHead()
if err := vmctx.Storage().Get(old, &self); err != nil {
return nil, err
}
deals, err := amt.LoadAMT(ctx, vmctx.Ipld(), self.Deals)
if err != nil {
return nil, aerrors.HandleExternalError(err, "loading deals amt")
}
if len(params.DealIDs) == 0 {
return nil, aerrors.New(3, "no deal IDs")
}
var pieces []sectorbuilder.PublicPieceInfo
for _, deal := range params.DealIDs {
var dealInfo OnChainDeal
if err := deals.Get(ctx, deal, &dealInfo); err != nil {
if _, is := err.(*amt.ErrNotFound); is {
return nil, aerrors.New(4, "deal not found")
}
return nil, aerrors.HandleExternalError(err, "getting deal info failed")
}
if dealInfo.Provider != vmctx.Message().From {
return nil, aerrors.New(5, "referenced deal was not from caller")
}
var commP [32]byte
copy(commP[:], dealInfo.PieceRef)
pieces = append(pieces, sectorbuilder.PublicPieceInfo{
Size: dealInfo.PieceSize,
CommP: commP,
})
}
commd, err := sectorbuilder.GenerateDataCommitment(params.SectorSize, pieces)
if err != nil {
return nil, aerrors.Absorb(err, 6, "failed to generate data commitment from pieces")
}
return commd[:], nil
}
/*
func (sma StorageMarketActor) HandleCronAction(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) {
}
func (sma StorageMarketActor) SettleExpiredDeals(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) {
}
func (sma StorageMarketActor) SlashStorageDealCollateral(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) {
}
func (sma StorageMarketActor) GetLastExpirationFromDealIDs(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) {
}
*/

View File

@ -1,845 +0,0 @@
package actors
import (
"bytes"
"context"
"io"
"github.com/filecoin-project/go-amt-ipld/v2"
cid "github.com/ipfs/go-cid"
hamt "github.com/ipfs/go-hamt-ipld"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/libp2p/go-libp2p-core/peer"
cbg "github.com/whyrusleeping/cbor-gen"
"go.opencensus.io/trace"
xerrors "golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/sigs"
)
type StoragePowerActor struct{}
type spaMethods struct {
Constructor uint64
CreateStorageMiner uint64
ArbitrateConsensusFault uint64
UpdateStorage uint64
GetTotalStorage uint64
PowerLookup uint64
IsValidMiner uint64
PledgeCollateralForSize uint64
CheckProofSubmissions uint64
}
var SPAMethods = spaMethods{1, 2, 3, 4, 5, 6, 7, 8, 9}
func (spa StoragePowerActor) Exports() []interface{} {
return []interface{}{
//1: spa.StoragePowerConstructor,
2: spa.CreateStorageMiner,
3: spa.ArbitrateConsensusFault,
4: spa.UpdateStorage,
5: spa.GetTotalStorage,
6: spa.PowerLookup,
7: spa.IsValidMiner,
8: spa.PledgeCollateralForSize,
9: spa.CheckProofSubmissions,
}
}
type StoragePowerState struct {
Miners cid.Cid
ProvingBuckets cid.Cid // amt[ProvingPeriodBucket]hamt[minerAddress]struct{}
MinerCount uint64
LastMinerCheck uint64
TotalStorage types.BigInt
}
type CreateStorageMinerParams struct {
Owner address.Address
Worker address.Address
SectorSize uint64
PeerID peer.ID
}
func (spa StoragePowerActor) CreateStorageMiner(act *types.Actor, vmctx types.VMContext, params *CreateStorageMinerParams) ([]byte, ActorError) {
if !build.SupportedSectorSize(params.SectorSize) {
return nil, aerrors.Newf(1, "Unsupported sector size: %d", params.SectorSize)
}
var self StoragePowerState
old := vmctx.Storage().GetHead()
if err := vmctx.Storage().Get(old, &self); err != nil {
return nil, err
}
reqColl, err := pledgeCollateralForSize(vmctx, types.NewInt(0), self.TotalStorage, self.MinerCount+1)
if err != nil {
return nil, err
}
if vmctx.Message().Value.LessThan(reqColl) {
return nil, aerrors.Newf(1, "not enough funds passed to cover required miner collateral (needed %s, got %s)", reqColl, vmctx.Message().Value)
}
minerCid := StorageMinerCodeCid
encoded, err := CreateExecParams(minerCid, &StorageMinerConstructorParams{
Owner: params.Owner,
Worker: params.Worker,
SectorSize: params.SectorSize,
PeerID: params.PeerID,
})
if err != nil {
return nil, err
}
ret, err := vmctx.Send(InitAddress, IAMethods.Exec, vmctx.Message().Value, encoded)
if err != nil {
return nil, err
}
naddr, nerr := address.NewFromBytes(ret)
if nerr != nil {
return nil, aerrors.Absorb(nerr, 2, "could not read address of new actor")
}
ncid, err := MinerSetAdd(context.TODO(), vmctx, self.Miners, naddr)
if err != nil {
return nil, err
}
self.Miners = ncid
self.MinerCount++
nroot, err := vmctx.Storage().Put(&self)
if err != nil {
return nil, err
}
if err := vmctx.Storage().Commit(old, nroot); err != nil {
return nil, err
}
return naddr.Bytes(), nil
}
type ArbitrateConsensusFaultParams struct {
Block1 *types.BlockHeader
Block2 *types.BlockHeader
}
func (spa StoragePowerActor) ArbitrateConsensusFault(act *types.Actor, vmctx types.VMContext, params *ArbitrateConsensusFaultParams) ([]byte, ActorError) {
if params == nil || params.Block1 == nil || params.Block2 == nil {
return nil, aerrors.New(1, "failed to parse params")
}
if params.Block1.Miner != params.Block2.Miner {
return nil, aerrors.New(2, "blocks must be from the same miner")
}
if params.Block1.Cid() == params.Block2.Cid() {
return nil, aerrors.New(3, "blocks must be different")
}
rval, err := vmctx.Send(params.Block1.Miner, MAMethods.GetWorkerAddr, types.NewInt(0), nil)
if err != nil {
return nil, aerrors.Wrap(err, "failed to get miner worker")
}
worker, oerr := address.NewFromBytes(rval)
if oerr != nil {
// REVIEW: should this be fatal? i can't think of a real situation that would get us here
return nil, aerrors.Absorb(oerr, 3, "response from 'GetWorkerAddr' was not a valid address")
}
if err := sigs.CheckBlockSignature(params.Block1, vmctx.Context(), worker); err != nil {
return nil, aerrors.Absorb(err, 4, "block1 did not have valid signature")
}
if err := sigs.CheckBlockSignature(params.Block2, vmctx.Context(), worker); err != nil {
return nil, aerrors.Absorb(err, 5, "block2 did not have valid signature")
}
// see the "Consensus Faults" section of the faults spec (faults.md)
// for details on these slashing conditions.
if !shouldSlash(params.Block1, params.Block2) {
return nil, aerrors.New(6, "blocks do not prove a slashable offense")
}
var self StoragePowerState
old := vmctx.Storage().GetHead()
if err := vmctx.Storage().Get(old, &self); err != nil {
return nil, err
}
if types.BigCmp(self.TotalStorage, types.NewInt(0)) == 0 {
return nil, aerrors.Fatal("invalid state, storage power actor has zero total storage")
}
miner := params.Block1.Miner
if has, err := MinerSetHas(vmctx, self.Miners, miner); err != nil {
return nil, aerrors.Wrapf(err, "failed to check miner in set")
} else if !has {
return nil, aerrors.New(7, "either already slashed or not a miner")
}
minerPower, err := powerLookup(context.TODO(), vmctx, &self, miner)
if err != nil {
return nil, err
}
slashedCollateral, err := pledgeCollateralForSize(vmctx, minerPower, self.TotalStorage, self.MinerCount)
if err != nil {
return nil, err
}
enc, err := SerializeParams(&MinerSlashConsensusFault{
Slasher: vmctx.Message().From,
AtHeight: params.Block1.Height,
SlashedCollateral: slashedCollateral,
})
if err != nil {
return nil, err
}
_, err = vmctx.Send(miner, MAMethods.SlashConsensusFault, types.NewInt(0), enc)
if err != nil {
return nil, err
}
// Remove the miner from the list of network miners
ncid, err := MinerSetRemove(context.TODO(), vmctx, self.Miners, miner)
if err != nil {
return nil, err
}
self.Miners = ncid
self.MinerCount--
self.TotalStorage = types.BigSub(self.TotalStorage, minerPower)
nroot, err := vmctx.Storage().Put(&self)
if err != nil {
return nil, err
}
if err := vmctx.Storage().Commit(old, nroot); err != nil {
return nil, err
}
return nil, nil
}
func cidArrContains(a []cid.Cid, b cid.Cid) bool {
for _, c := range a {
if b == c {
return true
}
}
return false
}
func shouldSlash(block1, block2 *types.BlockHeader) bool {
// First slashing condition, blocks have the same ticket round
if block1.Height == block2.Height {
return true
}
/* Second slashing condition requires having access to the parent tipset blocks
// This might not always be available, needs some thought on the best way to deal with this
// Second slashing condition, miner ignored own block when mining
// Case A: block2 could have been in block1's parent set but is not
b1ParentHeight := block1.Height - len(block1.Tickets)
block1ParentTipSet := block1.Parents
if !cidArrContains(block1.Parents, block2.Cid()) &&
b1ParentHeight == block2.Height &&
block1ParentTipSet.ParentCids == block2.ParentCids {
return true
}
// Case B: block1 could have been in block2's parent set but is not
block2ParentTipSet := parentOf(block2)
if !block2Parent.contains(block1) &&
block2ParentTipSet.Height == block1.Height &&
block2ParentTipSet.ParentCids == block1.ParentCids {
return true
}
*/
return false
}
type UpdateStorageParams struct {
Delta types.BigInt
NextSlashDeadline uint64
PreviousSlashDeadline uint64
}
func (spa StoragePowerActor) UpdateStorage(act *types.Actor, vmctx types.VMContext, params *UpdateStorageParams) ([]byte, ActorError) {
ctx := vmctx.Context()
var self StoragePowerState
old := vmctx.Storage().GetHead()
if err := vmctx.Storage().Get(old, &self); err != nil {
return nil, err
}
has, err := MinerSetHas(vmctx, self.Miners, vmctx.Message().From)
if err != nil {
return nil, err
}
if !has {
return nil, aerrors.New(1, "update storage must only be called by a miner actor")
}
self.TotalStorage = types.BigAdd(self.TotalStorage, params.Delta)
previousBucket := params.PreviousSlashDeadline % build.SlashablePowerDelay
nextBucket := params.NextSlashDeadline % build.SlashablePowerDelay
if previousBucket == nextBucket && params.PreviousSlashDeadline != 0 {
nroot, err := vmctx.Storage().Put(&self)
if err != nil {
return nil, err
}
if err := vmctx.Storage().Commit(old, nroot); err != nil {
return nil, err
}
return nil, nil // Nothing to do
}
buckets, eerr := amt.LoadAMT(ctx, vmctx.Ipld(), self.ProvingBuckets)
if eerr != nil {
return nil, aerrors.HandleExternalError(eerr, "loading proving buckets amt")
}
if params.PreviousSlashDeadline != 0 { // delete from previous bucket
err := deleteMinerFromBucket(vmctx, buckets, previousBucket)
if err != nil {
return nil, aerrors.Wrapf(err, "delete from bucket %d, next %d", previousBucket, nextBucket)
}
}
err = addMinerToBucket(vmctx, buckets, nextBucket)
if err != nil {
return nil, err
}
self.ProvingBuckets, eerr = buckets.Flush(ctx)
if eerr != nil {
return nil, aerrors.HandleExternalError(eerr, "flushing proving buckets")
}
nroot, err := vmctx.Storage().Put(&self)
if err != nil {
return nil, err
}
if err := vmctx.Storage().Commit(old, nroot); err != nil {
return nil, err
}
return nil, nil
}
func deleteMinerFromBucket(vmctx types.VMContext, buckets *amt.Root, previousBucket uint64) aerrors.ActorError {
ctx := vmctx.Context()
var bucket cid.Cid
err := buckets.Get(ctx, previousBucket, &bucket)
switch err.(type) {
case *amt.ErrNotFound:
return aerrors.HandleExternalError(err, "proving bucket missing")
case nil: // noop
default:
return aerrors.HandleExternalError(err, "getting proving bucket")
}
bhamt, err := hamt.LoadNode(vmctx.Context(), vmctx.Ipld(), bucket)
if err != nil {
return aerrors.HandleExternalError(err, "failed to load proving bucket")
}
err = bhamt.Delete(vmctx.Context(), string(vmctx.Message().From.Bytes()))
if err != nil {
return aerrors.HandleExternalError(err, "deleting miner from proving bucket")
}
err = bhamt.Flush(vmctx.Context())
if err != nil {
return aerrors.HandleExternalError(err, "flushing previous proving bucket")
}
bucket, err = vmctx.Ipld().Put(vmctx.Context(), bhamt)
if err != nil {
return aerrors.HandleExternalError(err, "putting previous proving bucket hamt")
}
err = buckets.Set(ctx, previousBucket, bucket)
if err != nil {
return aerrors.HandleExternalError(err, "setting previous proving bucket cid in amt")
}
return nil
}
func addMinerToBucket(vmctx types.VMContext, buckets *amt.Root, nextBucket uint64) aerrors.ActorError {
ctx := vmctx.Context()
var bhamt *hamt.Node
var bucket cid.Cid
err := buckets.Get(ctx, nextBucket, &bucket)
switch err.(type) {
case *amt.ErrNotFound:
bhamt = hamt.NewNode(vmctx.Ipld())
case nil:
bhamt, err = hamt.LoadNode(vmctx.Context(), vmctx.Ipld(), bucket)
if err != nil {
return aerrors.HandleExternalError(err, "failed to load proving bucket")
}
default:
return aerrors.HandleExternalError(err, "getting proving bucket")
}
err = bhamt.Set(vmctx.Context(), string(vmctx.Message().From.Bytes()), CborNull)
if err != nil {
return aerrors.HandleExternalError(err, "setting miner in proving bucket")
}
err = bhamt.Flush(vmctx.Context())
if err != nil {
return aerrors.HandleExternalError(err, "flushing previous proving bucket")
}
bucket, err = vmctx.Ipld().Put(vmctx.Context(), bhamt)
if err != nil {
return aerrors.HandleExternalError(err, "putting previous proving bucket hamt")
}
err = buckets.Set(ctx, nextBucket, bucket)
if err != nil {
return aerrors.HandleExternalError(err, "setting previous proving bucket cid in amt")
}
return nil
}
func (spa StoragePowerActor) GetTotalStorage(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) {
var self StoragePowerState
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
return nil, err
}
return self.TotalStorage.Bytes(), nil
}
type PowerLookupParams struct {
Miner address.Address
}
func (spa StoragePowerActor) PowerLookup(act *types.Actor, vmctx types.VMContext, params *PowerLookupParams) ([]byte, ActorError) {
var self StoragePowerState
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
return nil, aerrors.Wrap(err, "getting head")
}
pow, err := powerLookup(context.TODO(), vmctx, &self, params.Miner)
if err != nil {
return nil, err
}
return pow.Bytes(), nil
}
func powerLookup(ctx context.Context, vmctx types.VMContext, self *StoragePowerState, miner address.Address) (types.BigInt, ActorError) {
has, err := MinerSetHas(vmctx, self.Miners, miner)
if err != nil {
return types.EmptyInt, err
}
if !has {
// A miner could be registered with storage power actor, but removed for some reasons, e.g. consensus fault
return types.EmptyInt, aerrors.New(1, "miner not registered with storage power actor, or removed already")
}
// TODO: Use local amt
ret, err := vmctx.Send(miner, MAMethods.GetPower, types.NewInt(0), nil)
if err != nil {
return types.EmptyInt, aerrors.Wrap(err, "invoke Miner.GetPower")
}
return types.BigFromBytes(ret), nil
}
type IsValidMinerParam struct {
Addr address.Address
}
func (spa StoragePowerActor) IsValidMiner(act *types.Actor, vmctx types.VMContext, param *IsValidMinerParam) ([]byte, ActorError) {
var self StoragePowerState
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
return nil, err
}
has, err := MinerSetHas(vmctx, self.Miners, param.Addr)
if err != nil {
return nil, err
}
if !has {
log.Warnf("Miner INVALID: not in set: %s", param.Addr)
return cbg.CborBoolFalse, nil
}
ret, err := vmctx.Send(param.Addr, MAMethods.IsSlashed, types.NewInt(0), nil)
if err != nil {
return nil, err
}
slashed := bytes.Equal(ret, cbg.CborBoolTrue)
if slashed {
log.Warnf("Miner INVALID: /SLASHED/ : %s", param.Addr)
}
return cbg.EncodeBool(!slashed), nil
}
type PledgeCollateralParams struct {
Size types.BigInt
}
func (spa StoragePowerActor) PledgeCollateralForSize(act *types.Actor, vmctx types.VMContext, param *PledgeCollateralParams) ([]byte, ActorError) {
var self StoragePowerState
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
return nil, err
}
totalCollateral, err := pledgeCollateralForSize(vmctx, param.Size, self.TotalStorage, self.MinerCount)
if err != nil {
return nil, err
}
return totalCollateral.Bytes(), nil
}
func pledgeCollateralForSize(vmctx types.VMContext, size, totalStorage types.BigInt, minerCount uint64) (types.BigInt, aerrors.ActorError) {
netBalance, err := vmctx.GetBalance(NetworkAddress)
if err != nil {
return types.EmptyInt, err
}
// TODO: the spec says to also grab 'total vested filecoin' and include it as available
// If we don't factor that in, we effectively assume all of the locked up filecoin is 'available'
// the blocker on that right now is that its hard to tell how much filecoin is unlocked
availableFilecoin := types.BigSub(
types.BigMul(types.NewInt(build.TotalFilecoin), types.NewInt(build.FilecoinPrecision)),
netBalance,
)
totalPowerCollateral := types.BigDiv(
types.BigMul(
availableFilecoin,
types.NewInt(build.PowerCollateralProportion),
),
types.NewInt(build.CollateralPrecision),
)
totalPerCapitaCollateral := types.BigDiv(
types.BigMul(
availableFilecoin,
types.NewInt(build.PerCapitaCollateralProportion),
),
types.NewInt(build.CollateralPrecision),
)
// REVIEW: for bootstrapping purposes, we skip the power portion of the
// collateral if there is no collateral in the network yet
powerCollateral := types.NewInt(0)
if types.BigCmp(totalStorage, types.NewInt(0)) != 0 {
powerCollateral = types.BigDiv(
types.BigMul(
totalPowerCollateral,
size,
),
totalStorage,
)
}
perCapCollateral := types.BigDiv(
totalPerCapitaCollateral,
types.NewInt(minerCount),
)
return types.BigAdd(powerCollateral, perCapCollateral), nil
}
func (spa StoragePowerActor) CheckProofSubmissions(act *types.Actor, vmctx types.VMContext, param *struct{}) ([]byte, ActorError) {
if vmctx.Message().From != CronAddress {
return nil, aerrors.New(1, "CheckProofSubmissions is only callable from the cron actor")
}
var self StoragePowerState
old := vmctx.Storage().GetHead()
if err := vmctx.Storage().Get(old, &self); err != nil {
return nil, err
}
for i := self.LastMinerCheck; i < vmctx.BlockHeight(); i++ {
height := i + 1
err := checkProofSubmissionsAtH(vmctx, &self, height)
if err != nil {
return nil, err
}
}
self.LastMinerCheck = vmctx.BlockHeight()
nroot, aerr := vmctx.Storage().Put(&self)
if aerr != nil {
return nil, aerr
}
if err := vmctx.Storage().Commit(old, nroot); err != nil {
return nil, err
}
return nil, nil
}
func checkProofSubmissionsAtH(vmctx types.VMContext, self *StoragePowerState, height uint64) aerrors.ActorError {
ctx := vmctx.Context()
bucketID := height % build.SlashablePowerDelay
buckets, eerr := amt.LoadAMT(ctx, vmctx.Ipld(), self.ProvingBuckets)
if eerr != nil {
return aerrors.HandleExternalError(eerr, "loading proving buckets amt")
}
var bucket cid.Cid
err := buckets.Get(ctx, bucketID, &bucket)
switch err.(type) {
case *amt.ErrNotFound:
return nil // nothing to do
case nil:
default:
return aerrors.HandleExternalError(err, "getting proving bucket")
}
bhamt, err := hamt.LoadNode(vmctx.Context(), vmctx.Ipld(), bucket)
if err != nil {
return aerrors.HandleExternalError(err, "failed to load proving bucket")
}
forRemoval := make([]address.Address, 0)
err = bhamt.ForEach(vmctx.Context(), func(k string, val interface{}) error {
_, span := trace.StartSpan(vmctx.Context(), "StoragePowerActor.CheckProofSubmissions.loop")
defer span.End()
maddr, err := address.NewFromBytes([]byte(k))
if err != nil {
return aerrors.Escalate(err, "parsing miner address")
}
has, aerr := MinerSetHas(vmctx, self.Miners, maddr)
if aerr != nil {
return aerr
}
if !has {
forRemoval = append(forRemoval, maddr)
}
span.AddAttributes(trace.StringAttribute("miner", maddr.String()))
params, err := SerializeParams(&CheckMinerParams{NetworkPower: self.TotalStorage})
if err != nil {
return err
}
ret, err := vmctx.Send(maddr, MAMethods.CheckMiner, types.NewInt(0), params)
if err != nil {
return err
}
if len(ret) == 0 {
return nil // miner is fine
}
var power types.BigInt
if err := power.UnmarshalCBOR(bytes.NewReader(ret)); err != nil {
return xerrors.Errorf("unmarshaling CheckMiner response (%x): %w", ret, err)
}
if power.GreaterThan(types.NewInt(0)) {
log.Warnf("slashing miner %s for missed PoSt (%s B, H: %d, Bucket: %d)", maddr, power, height, bucketID)
self.TotalStorage = types.BigSub(self.TotalStorage, power)
}
return nil
})
if err != nil {
return aerrors.HandleExternalError(err, "iterating miners in proving bucket")
}
if len(forRemoval) > 0 {
nBucket, err := MinerSetRemove(vmctx.Context(), vmctx, bucket, forRemoval...)
if err != nil {
return aerrors.Wrap(err, "could not remove miners from set")
}
eerr := buckets.Set(ctx, bucketID, nBucket)
if err != nil {
return aerrors.HandleExternalError(eerr, "could not set the bucket")
}
ncid, eerr := buckets.Flush(ctx)
if err != nil {
return aerrors.HandleExternalError(eerr, "could not flush buckets")
}
self.ProvingBuckets = ncid
}
return nil
}
func MinerSetHas(vmctx types.VMContext, rcid cid.Cid, maddr address.Address) (bool, aerrors.ActorError) {
nd, err := hamt.LoadNode(vmctx.Context(), vmctx.Ipld(), rcid)
if err != nil {
return false, aerrors.HandleExternalError(err, "failed to load miner set")
}
err = nd.Find(vmctx.Context(), string(maddr.Bytes()), nil)
switch err {
case hamt.ErrNotFound:
return false, nil
case nil:
return true, nil
default:
return false, aerrors.HandleExternalError(err, "failed to do set lookup")
}
}
func MinerSetList(ctx context.Context, cst cbor.IpldStore, rcid cid.Cid) ([]address.Address, error) {
nd, err := hamt.LoadNode(ctx, cst, rcid)
if err != nil {
return nil, xerrors.Errorf("failed to load miner set: %w", err)
}
var out []address.Address
err = nd.ForEach(ctx, func(k string, val interface{}) error {
addr, err := address.NewFromBytes([]byte(k))
if err != nil {
return err
}
out = append(out, addr)
return nil
})
if err != nil {
return nil, err
}
return out, nil
}
func MinerSetAdd(ctx context.Context, vmctx types.VMContext, rcid cid.Cid, maddr address.Address) (cid.Cid, aerrors.ActorError) {
nd, err := hamt.LoadNode(ctx, vmctx.Ipld(), rcid)
if err != nil {
return cid.Undef, aerrors.HandleExternalError(err, "failed to load miner set")
}
mkey := string(maddr.Bytes())
err = nd.Find(ctx, mkey, nil)
if err == nil {
return cid.Undef, aerrors.New(20, "miner already in set")
}
if !xerrors.Is(err, hamt.ErrNotFound) {
return cid.Undef, aerrors.HandleExternalError(err, "failed to do miner set check")
}
if err := nd.Set(ctx, mkey, uint64(1)); err != nil {
return cid.Undef, aerrors.HandleExternalError(err, "adding miner address to set failed")
}
if err := nd.Flush(ctx); err != nil {
return cid.Undef, aerrors.HandleExternalError(err, "failed to flush miner set")
}
c, err := vmctx.Ipld().Put(ctx, nd)
if err != nil {
return cid.Undef, aerrors.HandleExternalError(err, "failed to persist miner set to storage")
}
return c, nil
}
func MinerSetRemove(ctx context.Context, vmctx types.VMContext, rcid cid.Cid, maddrs ...address.Address) (cid.Cid, aerrors.ActorError) {
nd, err := hamt.LoadNode(ctx, vmctx.Ipld(), rcid)
if err != nil {
return cid.Undef, aerrors.HandleExternalError(err, "failed to load miner set")
}
for _, maddr := range maddrs {
mkey := string(maddr.Bytes())
switch nd.Delete(ctx, mkey) {
default:
return cid.Undef, aerrors.HandleExternalError(err, "failed to delete miner from set")
case hamt.ErrNotFound:
return cid.Undef, aerrors.New(1, "miner not found in set on delete")
case nil:
}
}
if err := nd.Flush(ctx); err != nil {
return cid.Undef, aerrors.HandleExternalError(err, "failed to flush miner set")
}
c, err := vmctx.Ipld().Put(ctx, nd)
if err != nil {
return cid.Undef, aerrors.HandleExternalError(err, "failed to persist miner set to storage")
}
return c, nil
}
type cbgNull struct{}
var CborNull = &cbgNull{}
func (cbgNull) MarshalCBOR(w io.Writer) error {
n, err := w.Write(cbg.CborNull)
if err != nil {
return err
}
if n != 1 {
return xerrors.New("expected to write 1 byte")
}
return nil
}
func (cbgNull) UnmarshalCBOR(r io.Reader) error {
b := [1]byte{}
n, err := r.Read(b[:])
if err != nil {
return err
}
if n != 1 {
return xerrors.New("expected 1 byte")
}
if !bytes.Equal(b[:], cbg.CborNull) {
return xerrors.New("expected cbor null")
}
return nil
}

View File

@ -1,66 +0,0 @@
package actors
import (
"github.com/filecoin-project/go-address"
"github.com/ipfs/go-cid"
mh "github.com/multiformats/go-multihash"
)
var AccountCodeCid cid.Cid
var CronCodeCid cid.Cid
var StoragePowerCodeCid cid.Cid
var StorageMarketCodeCid cid.Cid
var StorageMinerCodeCid cid.Cid
var MultisigCodeCid cid.Cid
var InitCodeCid cid.Cid
var PaymentChannelCodeCid cid.Cid
var SystemAddress = mustIDAddress(0)
var InitAddress = mustIDAddress(1)
var RewardActor = mustIDAddress(2)
var CronAddress = mustIDAddress(3)
var StoragePowerAddress = mustIDAddress(4)
var StorageMarketAddress = mustIDAddress(5)
var NetworkAddress = mustIDAddress(17) // TODO: needs to be removed in favor of reward actor
var BurntFundsAddress = mustIDAddress(99)
func mustIDAddress(i uint64) address.Address {
a, err := address.NewIDAddress(i)
if err != nil {
panic(err) // ok
}
return a
}
func init() {
pref := cid.NewPrefixV1(cid.Raw, mh.IDENTITY)
mustSum := func(s string) cid.Cid {
c, err := pref.Sum([]byte(s))
if err != nil {
panic(err) // ok
}
return c
}
AccountCodeCid = mustSum("fil/1/account") // TODO: spec
CronCodeCid = mustSum("fil/1/cron")
StoragePowerCodeCid = mustSum("fil/1/power")
StorageMarketCodeCid = mustSum("fil/1/market")
StorageMinerCodeCid = mustSum("fil/1/miner")
MultisigCodeCid = mustSum("fil/1/multisig")
InitCodeCid = mustSum("fil/1/init")
PaymentChannelCodeCid = mustSum("fil/1/paych")
BuiltInActors = map[cid.Cid]bool{
StorageMarketCodeCid: true,
StoragePowerCodeCid: true,
StorageMinerCodeCid: true,
AccountCodeCid: true,
InitCodeCid: true,
MultisigCodeCid: true,
PaymentChannelCodeCid: true,
}
}

View File

@ -7,15 +7,16 @@ import (
"testing"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/gen/genesis"
"github.com/filecoin-project/go-address"
dstore "github.com/ipfs/go-datastore"
bstore "github.com/ipfs/go-ipfs-blockstore"
. "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
dstore "github.com/ipfs/go-datastore"
bstore "github.com/ipfs/go-ipfs-blockstore"
)
func blsaddr(n uint64) address.Address {
@ -40,7 +41,7 @@ func setupVMTestEnv(t *testing.T) (*vm.VM, []address.Address, bstore.Blockstore)
from: types.NewInt(1000000),
maddr: types.NewInt(0),
}
st, err := gen.MakeInitialStateTree(bs, actors)
st, err := genesis.MakeInitialStateTree(bs, actors)
if err != nil {
t.Fatal(err)
}

View File

@ -1,14 +0,0 @@
package actors
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
)
func NewIDAddress(id uint64) (address.Address, ActorError) {
a, err := address.NewIDAddress(id)
if err != nil {
return address.Undef, aerrors.Escalate(err, "could not create ID Address")
}
return a, nil
}

View File

@ -48,6 +48,26 @@ func Newf(retCode uint8, format string, args ...interface{}) ActorError {
}
}
// todo: bit hacky
func NewfSkip(skip int, retCode uint8, format string, args ...interface{}) ActorError {
if retCode == 0 {
return &actorError{
fatal: true,
retCode: 0,
msg: "tried creating an error and setting RetCode to 0",
frame: xerrors.Caller(skip),
err: fmt.Errorf(format, args...),
}
}
return &actorError{
retCode: retCode,
msg: fmt.Sprintf(format, args...),
frame: xerrors.Caller(skip),
}
}
func Fatal(message string, args ...interface{}) ActorError {
return &actorError{
fatal: true,

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +0,0 @@
package actors
import "github.com/filecoin-project/lotus/chain/actors/aerrors"
type ActorError = aerrors.ActorError

View File

@ -1,46 +0,0 @@
package actors
import (
"reflect"
"sort"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/types"
)
type update struct {
start uint64
method interface{}
}
func withUpdates(updates ...update) interface{} {
sort.Slice(updates, func(i, j int) bool { // so we iterate from newest below
return updates[i].start > updates[j].start
})
// <script type="application/javascript">
typ := reflect.TypeOf(updates[0].method)
out := reflect.MakeFunc(typ, func(args []reflect.Value) (results []reflect.Value) {
vmctx := args[1].Interface().(types.VMContext)
for _, u := range updates {
if vmctx.BlockHeight() > u.start {
return reflect.ValueOf(u.method).Call(args)
}
}
return reflect.ValueOf(notFound(vmctx)).Call([]reflect.Value{})
})
return out.Interface()
// </script>
}
func notFound(vmctx types.VMContext) func() ([]byte, ActorError) {
return func() ([]byte, ActorError) {
return nil, aerrors.Fatal("no code for method %d at height %d", vmctx.Message().Method, vmctx.BlockHeight())
}
}

View File

@ -6,6 +6,8 @@ import (
"math/rand"
"testing"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/go-sectorbuilder"
"github.com/ipfs/go-cid"
@ -17,8 +19,9 @@ import (
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/gen/genesis"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
@ -49,7 +52,7 @@ type Harness struct {
Nonces map[address.Address]uint64
GasCharges map[address.Address]types.BigInt
Rand vm.Rand
BlockHeight uint64
BlockHeight abi.ChainEpoch
lastBalanceCheck map[address.Address]types.BigInt
@ -181,7 +184,7 @@ func NewHarness(t *testing.T, options ...HarnessOpt) *Harness {
}
}
st, err := gen.MakeInitialStateTree(h.bs, h.HI.Addrs)
st, err := genesis.MakeInitialStateTree(h.bs, h.HI.Addrs)
if err != nil {
t.Fatal(err)
}
@ -191,7 +194,7 @@ func NewHarness(t *testing.T, options ...HarnessOpt) *Harness {
t.Fatal(err)
}
stateroot, err = gen.SetupStorageMarketActor(h.bs, stateroot, nil)
stateroot, err = genesis.SetupStorageMarketActor(h.bs, stateroot, nil)
if err != nil {
t.Fatal(err)
}

View File

@ -7,10 +7,6 @@ import (
cbg "github.com/whyrusleeping/cbor-gen"
)
var (
EmptyStructCBOR = []byte{0xa0}
)
func SerializeParams(i cbg.CBORMarshaler) ([]byte, aerrors.ActorError) {
buf := new(bytes.Buffer)
if err := i.MarshalCBOR(buf); err != nil {

View File

@ -22,8 +22,8 @@ import (
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
incrt "github.com/filecoin-project/lotus/lib/increadtimeout"
"github.com/filecoin-project/lotus/lib/peermgr"
"github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/filecoin-project/lotus/peermgr"
)
type BlockSync struct {

View File

@ -7,7 +7,7 @@ import (
"io"
"github.com/filecoin-project/lotus/chain/types"
"github.com/ipfs/go-cid"
cid "github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
xerrors "golang.org/x/xerrors"
)
@ -38,14 +38,17 @@ func (t *BlockSyncRequest) MarshalCBOR(w io.Writer) error {
}
// t.RequestLength (uint64) (uint64)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.RequestLength))); err != nil {
return err
}
// t.Options (uint64) (uint64)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.Options))); err != nil {
return err
}
return nil
}
@ -92,24 +95,32 @@ func (t *BlockSyncRequest) UnmarshalCBOR(r io.Reader) error {
// t.RequestLength (uint64) (uint64)
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
{
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.RequestLength = uint64(extra)
}
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.RequestLength = uint64(extra)
// t.Options (uint64) (uint64)
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
{
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.Options = uint64(extra)
}
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.Options = uint64(extra)
return nil
}
@ -137,6 +148,7 @@ func (t *BlockSyncResponse) MarshalCBOR(w io.Writer) error {
}
// t.Status (uint64) (uint64)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.Status))); err != nil {
return err
}
@ -199,14 +211,18 @@ func (t *BlockSyncResponse) UnmarshalCBOR(r io.Reader) error {
// t.Status (uint64) (uint64)
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
{
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.Status = uint64(extra)
}
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.Status = uint64(extra)
// t.Message (string) (string)
{

View File

@ -5,6 +5,7 @@ import (
"sync"
"time"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/ipfs/go-cid"
logging "github.com/ipfs/go-log/v2"
"golang.org/x/xerrors"
@ -19,7 +20,7 @@ import (
var log = logging.Logger("events")
// `curH`-`ts.Height` = `confidence`
type HeightHandler func(ctx context.Context, ts *types.TipSet, curH uint64) error
type HeightHandler func(ctx context.Context, ts *types.TipSet, curH abi.ChainEpoch) error
type RevertHandler func(ctx context.Context, ts *types.TipSet) error
type heightHandler struct {
@ -33,7 +34,7 @@ type heightHandler struct {
type eventApi interface {
ChainNotify(context.Context) (<-chan []*store.HeadChange, error)
ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error)
ChainGetTipSetByHeight(context.Context, uint64, types.TipSetKey) (*types.TipSet, error)
ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error)
StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error)
StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) // optional / for CalledMsg
@ -65,11 +66,11 @@ func NewEvents(ctx context.Context, api eventApi) *Events {
heightEvents: heightEvents{
tsc: tsc,
ctx: ctx,
gcConfidence: uint64(gcConfidence),
gcConfidence: abi.ChainEpoch(gcConfidence),
heightTriggers: map[uint64]*heightHandler{},
htTriggerHeights: map[uint64][]uint64{},
htHeights: map[uint64][]uint64{},
htTriggerHeights: map[abi.ChainEpoch][]uint64{},
htHeights: map[abi.ChainEpoch][]uint64{},
},
calledEvents: calledEvents{
@ -82,7 +83,7 @@ func NewEvents(ctx context.Context, api eventApi) *Events {
revertQueue: map[msgH][]triggerH{},
triggers: map[triggerId]*callHandler{},
matchers: map[triggerId][]MatchFunc{},
timeouts: map[uint64]map[triggerId]int{},
timeouts: map[abi.ChainEpoch]map[triggerId]int{},
},
}

View File

@ -5,6 +5,7 @@ import (
"math"
"sync"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
@ -12,20 +13,20 @@ import (
"github.com/filecoin-project/lotus/chain/types"
)
const NoTimeout = math.MaxUint64
const NoTimeout = math.MaxInt64
type triggerId = uint64
// msgH is the block height at which a message was present / event has happened
type msgH = uint64
type msgH = abi.ChainEpoch
// triggerH is the block height at which the listener will be notified about the
// message (msgH+confidence)
type triggerH = uint64
type triggerH = abi.ChainEpoch
// `ts` is the tipset, in which the `msg` is included.
// `curH`-`ts.Height` = `confidence`
type CalledHandler func(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH uint64) (more bool, err error)
type CalledHandler func(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH abi.ChainEpoch) (more bool, err error)
// CheckFunc is used for atomicity guarantees. If the condition the callbacks
// wait for has already happened in tipset `ts`
@ -39,7 +40,7 @@ type MatchFunc func(msg *types.Message) (bool, error)
type callHandler struct {
confidence int
timeout uint64
timeout abi.ChainEpoch
disabled bool // TODO: GC after gcConfidence reached
@ -50,7 +51,7 @@ type callHandler struct {
type queuedEvent struct {
trigger triggerId
h uint64
h abi.ChainEpoch
msg *types.Message
called bool
@ -77,7 +78,7 @@ type calledEvents struct {
revertQueue map[msgH][]triggerH
// [timeoutH+confidence][triggerId]{calls}
timeouts map[uint64]map[triggerId]int
timeouts map[abi.ChainEpoch]map[triggerId]int
}
func (e *calledEvents) headChangeCalled(rev, app []*types.TipSet) error {
@ -129,7 +130,7 @@ func (e *calledEvents) checkNewCalls(ts *types.TipSet) {
for _, matchFn := range matchFns {
ok, err := matchFn(msg)
if err != nil {
log.Warnf("event matcher failed: %s")
log.Warnf("event matcher failed: %s", err)
continue
}
matched = ok
@ -153,11 +154,11 @@ func (e *calledEvents) queueForConfidence(triggerId uint64, msg *types.Message,
// messages are not applied in the tipset they are included in
appliedH := ts.Height() + 1
triggerH := appliedH + uint64(trigger.confidence)
triggerH := appliedH + abi.ChainEpoch(trigger.confidence)
byOrigH, ok := e.confQueue[triggerH]
if !ok {
byOrigH = map[uint64][]*queuedEvent{}
byOrigH = map[abi.ChainEpoch][]*queuedEvent{}
e.confQueue[triggerH] = byOrigH
}
@ -231,9 +232,9 @@ func (e *calledEvents) applyTimeouts(ts *types.TipSet) {
continue
}
timeoutTs, err := e.tsc.get(ts.Height() - uint64(trigger.confidence))
timeoutTs, err := e.tsc.get(ts.Height() - abi.ChainEpoch(trigger.confidence))
if err != nil {
log.Errorf("events: applyTimeouts didn't find tipset for event; wanted %d; current %d", ts.Height()-uint64(trigger.confidence), ts.Height())
log.Errorf("events: applyTimeouts didn't find tipset for event; wanted %d; current %d", ts.Height()-abi.ChainEpoch(trigger.confidence), ts.Height())
}
more, err := trigger.handle(nil, nil, timeoutTs, ts.Height())
@ -304,7 +305,7 @@ func (e *calledEvents) messagesForTs(ts *types.TipSet, consume func(*types.Messa
// containing the message. The tipset passed as the argument is the tipset
// that is being dropped. Note that the message dropped may be re-applied
// in a different tipset in small amount of time.
func (e *calledEvents) Called(check CheckFunc, hnd CalledHandler, rev RevertHandler, confidence int, timeout uint64, mf MatchFunc) error {
func (e *calledEvents) Called(check CheckFunc, hnd CalledHandler, rev RevertHandler, confidence int, timeout abi.ChainEpoch, mf MatchFunc) error {
e.lk.Lock()
defer e.lk.Unlock()
@ -322,7 +323,7 @@ func (e *calledEvents) Called(check CheckFunc, hnd CalledHandler, rev RevertHand
e.triggers[id] = &callHandler{
confidence: confidence,
timeout: timeout + uint64(confidence),
timeout: timeout + abi.ChainEpoch(confidence),
disabled: !more,
@ -333,15 +334,15 @@ func (e *calledEvents) Called(check CheckFunc, hnd CalledHandler, rev RevertHand
e.matchers[id] = append(e.matchers[id], mf)
if timeout != NoTimeout {
if e.timeouts[timeout+uint64(confidence)] == nil {
e.timeouts[timeout+uint64(confidence)] = map[uint64]int{}
if e.timeouts[timeout+abi.ChainEpoch(confidence)] == nil {
e.timeouts[timeout+abi.ChainEpoch(confidence)] = map[uint64]int{}
}
e.timeouts[timeout+uint64(confidence)][id] = 0
e.timeouts[timeout+abi.ChainEpoch(confidence)][id] = 0
}
return nil
}
func (e *calledEvents) CalledMsg(ctx context.Context, hnd CalledHandler, rev RevertHandler, confidence int, timeout uint64, msg store.ChainMsg) error {
func (e *calledEvents) CalledMsg(ctx context.Context, hnd CalledHandler, rev RevertHandler, confidence int, timeout abi.ChainEpoch, msg store.ChainMsg) error {
return e.Called(e.CheckMsg(ctx, msg, hnd), hnd, rev, confidence, timeout, e.MatchMsg(msg.VMMessage()))
}

View File

@ -4,6 +4,7 @@ import (
"context"
"sync"
"github.com/filecoin-project/specs-actors/actors/abi"
"go.opencensus.io/trace"
"github.com/filecoin-project/lotus/chain/types"
@ -12,7 +13,7 @@ import (
type heightEvents struct {
lk sync.Mutex
tsc *tipSetCache
gcConfidence uint64
gcConfidence abi.ChainEpoch
ctr triggerId
@ -35,7 +36,7 @@ func (e *heightEvents) headChangeAt(rev, app []*types.TipSet) error {
// TODO: log error if h below gcconfidence
// revert height-based triggers
revert := func(h uint64, ts *types.TipSet) {
revert := func(h abi.ChainEpoch, ts *types.TipSet) {
for _, tid := range e.htHeights[h] {
ctx, span := trace.StartSpan(ctx, "events.HeightRevert")
@ -80,7 +81,7 @@ func (e *heightEvents) headChangeAt(rev, app []*types.TipSet) error {
// height triggers
apply := func(h uint64, ts *types.TipSet) error {
apply := func(h abi.ChainEpoch, ts *types.TipSet) error {
for _, tid := range e.htTriggerHeights[h] {
hnd := e.heightTriggers[tid]
if hnd.called {
@ -88,7 +89,7 @@ func (e *heightEvents) headChangeAt(rev, app []*types.TipSet) error {
}
hnd.called = true
triggerH := h - uint64(hnd.confidence)
triggerH := h - abi.ChainEpoch(hnd.confidence)
incTs, err := e.tsc.getNonNull(triggerH)
if err != nil {
@ -139,13 +140,13 @@ func (e *heightEvents) headChangeAt(rev, app []*types.TipSet) error {
// specified height, `RevertHandler` will be called.
//
// ts passed to handlers is the tipset at the specified, or above, if lower tipsets were null
func (e *heightEvents) ChainAt(hnd HeightHandler, rev RevertHandler, confidence int, h uint64) error {
func (e *heightEvents) ChainAt(hnd HeightHandler, rev RevertHandler, confidence int, h abi.ChainEpoch) error {
e.lk.Lock() // Tricky locking, check your locks if you modify this function!
bestH := e.tsc.best().Height()
if bestH >= h+uint64(confidence) {
if bestH >= h+abi.ChainEpoch(confidence) {
ts, err := e.tsc.getNonNull(h)
if err != nil {
log.Warnf("events.ChainAt: calling HandleFunc with nil tipset, not found in cache: %s", err)
@ -168,11 +169,11 @@ func (e *heightEvents) ChainAt(hnd HeightHandler, rev RevertHandler, confidence
defer e.lk.Unlock()
if bestH >= h+uint64(confidence)+e.gcConfidence {
if bestH >= h+abi.ChainEpoch(confidence)+e.gcConfidence {
return nil
}
triggerAt := h + uint64(confidence)
triggerAt := h + abi.ChainEpoch(confidence)
id := e.ctr
e.ctr++

View File

@ -6,6 +6,9 @@ import (
"testing"
"time"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/store"
@ -31,7 +34,7 @@ type fakeMsg struct {
type fakeCS struct {
t *testing.T
h uint64
h abi.ChainEpoch
tsc *tipSetCache
msgs map[cid.Cid]fakeMsg
@ -48,11 +51,11 @@ func (fcs *fakeCS) StateGetActor(ctx context.Context, actor address.Address, tsk
panic("Not Implemented")
}
func (fcs *fakeCS) ChainGetTipSetByHeight(context.Context, uint64, types.TipSetKey) (*types.TipSet, error) {
func (fcs *fakeCS) ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) {
panic("Not Implemented")
}
func makeTs(t *testing.T, h uint64, msgcid cid.Cid) *types.TipSet {
func makeTs(t *testing.T, h abi.ChainEpoch, msgcid cid.Cid) *types.TipSet {
a, _ := address.NewFromString("t00")
b, _ := address.NewFromString("t02")
var ts, err = types.NewTipSet([]*types.BlockHeader{
@ -66,8 +69,8 @@ func makeTs(t *testing.T, h uint64, msgcid cid.Cid) *types.TipSet {
Messages: msgcid,
ParentMessageReceipts: dummyCid,
BlockSig: &types.Signature{Type: types.KTBLS},
BLSAggregate: types.Signature{Type: types.KTBLS},
BlockSig: &crypto.Signature{Type: crypto.SigTypeBLS},
BLSAggregate: crypto.Signature{Type: crypto.SigTypeBLS},
},
{
Height: h,
@ -79,8 +82,8 @@ func makeTs(t *testing.T, h uint64, msgcid cid.Cid) *types.TipSet {
Messages: msgcid,
ParentMessageReceipts: dummyCid,
BlockSig: &types.Signature{Type: types.KTBLS},
BLSAggregate: types.Signature{Type: types.KTBLS},
BlockSig: &crypto.Signature{Type: crypto.SigTypeBLS},
BLSAggregate: crypto.Signature{Type: crypto.SigTypeBLS},
},
})
@ -206,7 +209,7 @@ func TestAt(t *testing.T) {
var applied bool
var reverted bool
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH uint64) error {
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH abi.ChainEpoch) error {
require.Equal(t, 5, int(ts.Height()))
require.Equal(t, 8, int(curH))
applied = true
@ -271,7 +274,7 @@ func TestAtDoubleTrigger(t *testing.T) {
var applied bool
var reverted bool
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH uint64) error {
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH abi.ChainEpoch) error {
require.Equal(t, 5, int(ts.Height()))
require.Equal(t, 8, int(curH))
applied = true
@ -313,8 +316,8 @@ func TestAtNullTrigger(t *testing.T) {
var applied bool
var reverted bool
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH uint64) error {
require.Equal(t, uint64(6), ts.Height())
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH abi.ChainEpoch) error {
require.Equal(t, abi.ChainEpoch(6), ts.Height())
require.Equal(t, 8, int(curH))
applied = true
return nil
@ -347,7 +350,7 @@ func TestAtNullConf(t *testing.T) {
var applied bool
var reverted bool
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH uint64) error {
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH abi.ChainEpoch) error {
require.Equal(t, 5, int(ts.Height()))
require.Equal(t, 8, int(curH))
applied = true
@ -388,7 +391,7 @@ func TestAtStart(t *testing.T) {
var applied bool
var reverted bool
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH uint64) error {
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH abi.ChainEpoch) error {
require.Equal(t, 5, int(ts.Height()))
require.Equal(t, 8, int(curH))
applied = true
@ -422,7 +425,7 @@ func TestAtStartConfidence(t *testing.T) {
var applied bool
var reverted bool
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH uint64) error {
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH abi.ChainEpoch) error {
require.Equal(t, 5, int(ts.Height()))
require.Equal(t, 11, int(curH))
applied = true
@ -450,8 +453,8 @@ func TestAtChained(t *testing.T) {
var applied bool
var reverted bool
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH uint64) error {
return events.ChainAt(func(_ context.Context, ts *types.TipSet, curH uint64) error {
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH abi.ChainEpoch) error {
return events.ChainAt(func(_ context.Context, ts *types.TipSet, curH abi.ChainEpoch) error {
require.Equal(t, 10, int(ts.Height()))
applied = true
return nil
@ -486,8 +489,8 @@ func TestAtChainedConfidence(t *testing.T) {
var applied bool
var reverted bool
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH uint64) error {
return events.ChainAt(func(_ context.Context, ts *types.TipSet, curH uint64) error {
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH abi.ChainEpoch) error {
return events.ChainAt(func(_ context.Context, ts *types.TipSet, curH abi.ChainEpoch) error {
require.Equal(t, 10, int(ts.Height()))
applied = true
return nil
@ -520,7 +523,7 @@ func TestAtChainedConfidenceNull(t *testing.T) {
var applied bool
var reverted bool
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH uint64) error {
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH abi.ChainEpoch) error {
applied = true
require.Equal(t, 6, int(ts.Height()))
return nil
@ -534,7 +537,7 @@ func TestAtChainedConfidenceNull(t *testing.T) {
require.Equal(t, false, reverted)
}
func matchAddrMethod(to address.Address, m uint64) func(msg *types.Message) (bool, error) {
func matchAddrMethod(to address.Address, m abi.MethodNum) func(msg *types.Message) (bool, error) {
return func(msg *types.Message) (bool, error) {
return to == msg.To && m == msg.Method, nil
}
@ -560,11 +563,11 @@ func TestCalled(t *testing.T) {
var applied, reverted bool
var appliedMsg *types.Message
var appliedTs *types.TipSet
var appliedH uint64
var appliedH abi.ChainEpoch
err = events.Called(func(ts *types.TipSet) (d bool, m bool, e error) {
return false, true, nil
}, func(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH uint64) (bool, error) {
}, func(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH abi.ChainEpoch) (bool, error) {
require.Equal(t, false, applied)
applied = true
appliedMsg = msg
@ -610,12 +613,12 @@ func TestCalled(t *testing.T) {
require.Equal(t, false, applied)
require.Equal(t, false, reverted)
require.Equal(t, uint64(7), appliedTs.Height())
require.Equal(t, abi.ChainEpoch(7), appliedTs.Height())
require.Equal(t, "bafkqaaa", appliedTs.Blocks()[0].Messages.String())
require.Equal(t, uint64(10), appliedH)
require.Equal(t, abi.ChainEpoch(10), appliedH)
require.Equal(t, t0123, appliedMsg.To)
require.Equal(t, uint64(1), appliedMsg.Nonce)
require.Equal(t, uint64(5), appliedMsg.Method)
require.Equal(t, abi.MethodNum(5), appliedMsg.Method)
// revert some blocks, keep the message
@ -647,12 +650,12 @@ func TestCalled(t *testing.T) {
require.Equal(t, false, reverted)
applied = false
require.Equal(t, uint64(9), appliedTs.Height())
require.Equal(t, abi.ChainEpoch(9), appliedTs.Height())
require.Equal(t, "bafkqaaa", appliedTs.Blocks()[0].Messages.String())
require.Equal(t, uint64(12), appliedH)
require.Equal(t, abi.ChainEpoch(12), appliedH)
require.Equal(t, t0123, appliedMsg.To)
require.Equal(t, uint64(2), appliedMsg.Nonce)
require.Equal(t, uint64(5), appliedMsg.Method)
require.Equal(t, abi.MethodNum(5), appliedMsg.Method)
// revert and apply at different height
@ -668,12 +671,12 @@ func TestCalled(t *testing.T) {
reverted = false
applied = false
require.Equal(t, uint64(11), appliedTs.Height())
require.Equal(t, abi.ChainEpoch(11), appliedTs.Height())
require.Equal(t, "bafkqaaa", appliedTs.Blocks()[0].Messages.String())
require.Equal(t, uint64(14), appliedH)
require.Equal(t, abi.ChainEpoch(14), appliedH)
require.Equal(t, t0123, appliedMsg.To)
require.Equal(t, uint64(2), appliedMsg.Nonce)
require.Equal(t, uint64(5), appliedMsg.Method)
require.Equal(t, abi.MethodNum(5), appliedMsg.Method)
// call method again
@ -765,11 +768,11 @@ func TestCalledTimeout(t *testing.T) {
err = events.Called(func(ts *types.TipSet) (d bool, m bool, e error) {
return false, true, nil
}, func(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH uint64) (bool, error) {
}, func(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH abi.ChainEpoch) (bool, error) {
called = true
require.Nil(t, msg)
require.Equal(t, uint64(20), ts.Height())
require.Equal(t, uint64(23), curH)
require.Equal(t, abi.ChainEpoch(20), ts.Height())
require.Equal(t, abi.ChainEpoch(23), curH)
return false, nil
}, func(_ context.Context, ts *types.TipSet) error {
t.Fatal("revert on timeout")
@ -800,11 +803,11 @@ func TestCalledTimeout(t *testing.T) {
err = events.Called(func(ts *types.TipSet) (d bool, m bool, e error) {
return true, true, nil
}, func(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH uint64) (bool, error) {
}, func(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH abi.ChainEpoch) (bool, error) {
called = true
require.Nil(t, msg)
require.Equal(t, uint64(20), ts.Height())
require.Equal(t, uint64(23), curH)
require.Equal(t, abi.ChainEpoch(20), ts.Height())
require.Equal(t, abi.ChainEpoch(23), curH)
return false, nil
}, func(_ context.Context, ts *types.TipSet) error {
t.Fatal("revert on timeout")
@ -839,14 +842,14 @@ func TestCalledOrder(t *testing.T) {
err = events.Called(func(ts *types.TipSet) (d bool, m bool, e error) {
return false, true, nil
}, func(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH uint64) (bool, error) {
}, func(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH abi.ChainEpoch) (bool, error) {
switch at {
case 0:
require.Equal(t, uint64(1), msg.Nonce)
require.Equal(t, uint64(4), ts.Height())
require.Equal(t, abi.ChainEpoch(4), ts.Height())
case 1:
require.Equal(t, uint64(2), msg.Nonce)
require.Equal(t, uint64(5), ts.Height())
require.Equal(t, abi.ChainEpoch(5), ts.Height())
default:
t.Fatal("apply should only get called twice, at: ", at)
}
@ -855,9 +858,9 @@ func TestCalledOrder(t *testing.T) {
}, func(_ context.Context, ts *types.TipSet) error {
switch at {
case 2:
require.Equal(t, uint64(5), ts.Height())
require.Equal(t, abi.ChainEpoch(5), ts.Height())
case 3:
require.Equal(t, uint64(4), ts.Height())
require.Equal(t, abi.ChainEpoch(4), ts.Height())
default:
t.Fatal("revert should only get called twice, at: ", at)
}

View File

@ -3,12 +3,13 @@ package events
import (
"context"
"github.com/filecoin-project/specs-actors/actors/abi"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/types"
)
type tsByHFunc func(context.Context, uint64, types.TipSetKey) (*types.TipSet, error)
type tsByHFunc func(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error)
// tipSetCache implements a simple ring-buffer cache to keep track of recent
// tipsets
@ -77,7 +78,7 @@ func (tsc *tipSetCache) revert(ts *types.TipSet) error {
return nil
}
func (tsc *tipSetCache) getNonNull(height uint64) (*types.TipSet, error) {
func (tsc *tipSetCache) getNonNull(height abi.ChainEpoch) (*types.TipSet, error) {
for {
ts, err := tsc.get(height)
if err != nil {
@ -90,7 +91,7 @@ func (tsc *tipSetCache) getNonNull(height uint64) (*types.TipSet, error) {
}
}
func (tsc *tipSetCache) get(height uint64) (*types.TipSet, error) {
func (tsc *tipSetCache) get(height abi.ChainEpoch) (*types.TipSet, error) {
if tsc.len == 0 {
log.Warnf("tipSetCache.get: cache is empty, requesting from storage (h=%d)", height)
return tsc.storage(context.TODO(), height, types.EmptyTSK)

View File

@ -4,6 +4,8 @@ import (
"context"
"testing"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/stretchr/testify/require"
"github.com/filecoin-project/go-address"
@ -11,12 +13,12 @@ import (
)
func TestTsCache(t *testing.T) {
tsc := newTSCache(50, func(context.Context, uint64, types.TipSetKey) (*types.TipSet, error) {
tsc := newTSCache(50, func(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) {
t.Fatal("storage call")
return &types.TipSet{}, nil
})
h := uint64(75)
h := abi.ChainEpoch(75)
a, _ := address.NewFromString("t00")
@ -27,8 +29,8 @@ func TestTsCache(t *testing.T) {
ParentStateRoot: dummyCid,
Messages: dummyCid,
ParentMessageReceipts: dummyCid,
BlockSig: &types.Signature{Type: types.KTBLS},
BLSAggregate: types.Signature{Type: types.KTBLS},
BlockSig: &types.Signature{Type: crypto.SigTypeBLS},
BLSAggregate: types.Signature{Type: crypto.SigTypeBLS},
}})
if err != nil {
t.Fatal(err)
@ -54,12 +56,12 @@ func TestTsCache(t *testing.T) {
}
func TestTsCacheNulls(t *testing.T) {
tsc := newTSCache(50, func(context.Context, uint64, types.TipSetKey) (*types.TipSet, error) {
tsc := newTSCache(50, func(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) {
t.Fatal("storage call")
return &types.TipSet{}, nil
})
h := uint64(75)
h := abi.ChainEpoch(75)
a, _ := address.NewFromString("t00")
add := func() {
@ -69,8 +71,8 @@ func TestTsCacheNulls(t *testing.T) {
ParentStateRoot: dummyCid,
Messages: dummyCid,
ParentMessageReceipts: dummyCid,
BlockSig: &types.Signature{Type: types.KTBLS},
BLSAggregate: types.Signature{Type: types.KTBLS},
BlockSig: &types.Signature{Type: crypto.SigTypeBLS},
BLSAggregate: types.Signature{Type: crypto.SigTypeBLS},
}})
if err != nil {
t.Fatal(err)

View File

@ -4,26 +4,29 @@ import (
"bytes"
"context"
"crypto/sha256"
"encoding/binary"
"fmt"
"io/ioutil"
"sync/atomic"
"github.com/filecoin-project/go-address"
commcid "github.com/filecoin-project/go-fil-commcid"
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/crypto"
block "github.com/ipfs/go-block-format"
"github.com/ipfs/go-blockservice"
"github.com/ipfs/go-car"
"github.com/ipfs/go-cid"
blockstore "github.com/ipfs/go-ipfs-blockstore"
offline "github.com/ipfs/go-ipfs-exchange-offline"
format "github.com/ipfs/go-ipld-format"
logging "github.com/ipfs/go-log/v2"
"github.com/ipfs/go-merkledag"
peer "github.com/libp2p/go-libp2p-core/peer"
ffi "github.com/filecoin-project/filecoin-ffi"
"github.com/filecoin-project/go-address"
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
genesis2 "github.com/filecoin-project/lotus/chain/gen/genesis"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
@ -33,6 +36,7 @@ import (
"github.com/filecoin-project/lotus/genesis"
"github.com/filecoin-project/lotus/lib/sigs"
"github.com/filecoin-project/lotus/node/repo"
"github.com/filecoin-project/lotus/storage/sbmock"
"go.opencensus.io/trace"
"golang.org/x/xerrors"
@ -54,7 +58,7 @@ type ChainGen struct {
genesis *types.BlockHeader
CurTipset *store.FullTipSet
Timestamper func(*types.TipSet, uint64) uint64
Timestamper func(*types.TipSet, abi.ChainEpoch) uint64
GetMessages func(*ChainGen) ([]*types.SignedMessage, error)
@ -112,74 +116,81 @@ func NewGenerator() (*ChainGen, error) {
return nil, xerrors.Errorf("creating memrepo wallet failed: %w", err)
}
banker, err := w.GenerateKey(types.KTSecp256k1)
banker, err := w.GenerateKey(crypto.SigTypeSecp256k1)
if err != nil {
return nil, xerrors.Errorf("failed to generate banker key: %w", err)
}
receievers := make([]address.Address, msgsPerBlock)
for r := range receievers {
receievers[r], err = w.GenerateKey(types.KTBLS)
receievers[r], err = w.GenerateKey(crypto.SigTypeBLS)
if err != nil {
return nil, xerrors.Errorf("failed to generate receiver key: %w", err)
}
}
maddr1, err := address.NewFromString("t0300")
if err != nil {
return nil, err
}
maddr1 := genesis2.MinerAddress(0)
m1temp, err := ioutil.TempDir("", "preseal")
if err != nil {
return nil, err
}
genm1, err := seed.PreSeal(maddr1, 1024, 0, 1, m1temp, []byte("some randomness"))
genm1, k1, err := seed.PreSeal(maddr1, 1024, 0, 1, m1temp, []byte("some randomness"), nil)
if err != nil {
return nil, err
}
maddr2, err := address.NewFromString("t0301")
if err != nil {
return nil, err
}
maddr2 := genesis2.MinerAddress(1)
m2temp, err := ioutil.TempDir("", "preseal")
if err != nil {
return nil, err
}
genm2, err := seed.PreSeal(maddr2, 1024, 0, 1, m2temp, []byte("some randomness"))
genm2, k2, err := seed.PreSeal(maddr2, 1024, 0, 1, m2temp, []byte("some randomness"), nil)
if err != nil {
return nil, err
}
mk1, err := w.Import(&genm1.Key)
mk1, err := w.Import(k1)
if err != nil {
return nil, err
}
mk2, err := w.Import(&genm2.Key)
mk2, err := w.Import(k2)
if err != nil {
return nil, err
}
minercfg := &GenMinerCfg{
PeerIDs: []peer.ID{"peerID1", "peerID2"},
PreSeals: map[string]genesis.GenesisMiner{
maddr1.String(): *genm1,
maddr2.String(): *genm2,
sys := vm.Syscalls(&genFakeVerifier{})
tpl := genesis.Template{
Accounts: []genesis.Actor{
{
Type: genesis.TAccount,
Balance: types.FromFil(40000),
Meta: (&genesis.AccountMeta{Owner: mk1}).ActorMeta(),
},
{
Type: genesis.TAccount,
Balance: types.FromFil(40000),
Meta: (&genesis.AccountMeta{Owner: mk2}).ActorMeta(),
},
{
Type: genesis.TAccount,
Balance: types.FromFil(50000),
Meta: (&genesis.AccountMeta{Owner: banker}).ActorMeta(),
},
},
MinerAddrs: []address.Address{maddr1, maddr2},
Miners: []genesis.Miner{
*genm1,
*genm2,
},
NetworkName: "",
Timestamp: 100000,
}
sys := vm.Syscalls(sectorbuilder.ProofVerifier)
genb, err := MakeGenesisBlock(bs, sys, map[address.Address]types.BigInt{
mk1: types.FromFil(40000),
mk2: types.FromFil(40000),
banker: types.FromFil(50000),
}, minercfg, 100000)
genb, err := genesis2.MakeGenesisBlock(context.TODO(), bs, sys, tpl)
if err != nil {
return nil, xerrors.Errorf("make genesis block failed: %w", err)
}
@ -193,17 +204,15 @@ func NewGenerator() (*ChainGen, error) {
return nil, xerrors.Errorf("set genesis failed: %w", err)
}
if len(minercfg.MinerAddrs) == 0 {
return nil, xerrors.Errorf("MakeGenesisBlock failed to set miner address")
}
mgen := make(map[address.Address]ElectionPoStProver)
for _, m := range minercfg.MinerAddrs {
mgen[m] = &eppProvider{}
for i := range tpl.Miners {
mgen[genesis2.MinerAddress(uint64(i))] = &eppProvider{}
}
sm := stmgr.NewStateManager(cs)
miners := []address.Address{maddr1, maddr2}
gen := &ChainGen{
bs: bs,
cs: cs,
@ -213,7 +222,7 @@ func NewGenerator() (*ChainGen, error) {
w: w,
GetMessages: getRandomMessages,
Miners: minercfg.MinerAddrs,
Miners: miners,
eppProvs: mgen,
banker: banker,
receivers: receievers,
@ -246,16 +255,32 @@ 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 {
if err := car.WriteCarWithWalker(context.TODO(), dserv, []cid.Cid{cg.Genesis().Cid()}, out, CarWalkFunc); err != nil {
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, round int64) (*types.EPostProof, *types.Ticket, error) {
func CarWalkFunc(nd format.Node) (out []*format.Link, err error) {
for _, link := range nd.Links() {
if link.Cid.Prefix().MhType == uint64(commcid.FC_SEALED_V1) || link.Cid.Prefix().MhType == uint64(commcid.FC_UNSEALED_V1) {
continue
}
out = append(out, link)
}
lastTicket := pts.MinTicket()
return out, nil
}
func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m address.Address, round int64) (*types.EPostProof, *types.Ticket, error) {
mc := &mca{w: cg.w, sm: cg.sm}
// TODO: REVIEW: Am I doing this correctly?
ticketRand, err := mc.ChainGetRandomness(ctx, pts.Key(), crypto.DomainSeparationTag_TicketProduction, pts.Height(), m.Bytes())
if err != nil {
return nil, nil, err
}
st := pts.ParentState()
@ -264,7 +289,7 @@ 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, m, DSepTicket, lastTicket.VRFProof)
vrfout, err := ComputeVRF(ctx, cg.w.Sign, worker, ticketRand)
if err != nil {
return nil, nil, xerrors.Errorf("compute VRF: %w", err)
}
@ -273,7 +298,7 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add
VRFProof: vrfout,
}
eproofin, err := IsRoundWinner(ctx, pts, round, m, cg.eppProvs[m], &mca{w: cg.w, sm: cg.sm})
eproofin, err := IsRoundWinner(ctx, pts, round, m, cg.eppProvs[m], mc)
if err != nil {
return nil, nil, xerrors.Errorf("checking round winner failed: %w", err)
}
@ -319,7 +344,7 @@ func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Ad
}
if proof != nil {
fblk, err := cg.makeBlock(base, m, proof, t, uint64(round), msgs)
fblk, err := cg.makeBlock(base, m, proof, t, abi.ChainEpoch(round), msgs)
if err != nil {
return nil, xerrors.Errorf("making a block for next tipset failed: %w", err)
}
@ -341,13 +366,13 @@ func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Ad
}, nil
}
func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, eproof *types.EPostProof, ticket *types.Ticket, height uint64, msgs []*types.SignedMessage) (*types.FullBlock, error) {
func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, eproof *types.EPostProof, ticket *types.Ticket, height abi.ChainEpoch, msgs []*types.SignedMessage) (*types.FullBlock, error) {
var ts uint64
if cg.Timestamper != nil {
ts = cg.Timestamper(parents, height-parents.Height())
} else {
ts = parents.MinTimestamp() + ((height - parents.Height()) * build.BlockDelay)
ts = parents.MinTimestamp() + uint64((height-parents.Height())*build.BlockDelay)
}
fblk, err := MinerCreateBlock(context.TODO(), cg.sm, cg.w, m, parents, ticket, eproof, msgs, height, ts)
@ -417,17 +442,17 @@ func (cg *ChainGen) YieldRepo() (repo.Repo, error) {
}
type MiningCheckAPI interface {
ChainGetRandomness(context.Context, types.TipSetKey, int64) ([]byte, error)
ChainGetRandomness(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error)
StateMinerPower(context.Context, address.Address, types.TipSetKey) (api.MinerPower, error)
StateMinerWorker(context.Context, address.Address, types.TipSetKey) (address.Address, error)
StateMinerSectorSize(context.Context, address.Address, types.TipSetKey) (uint64, error)
StateMinerSectorSize(context.Context, address.Address, types.TipSetKey) (abi.SectorSize, error)
StateMinerProvingSet(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error)
WalletSign(context.Context, address.Address, []byte) (*types.Signature, error)
WalletSign(context.Context, address.Address, []byte) (*crypto.Signature, error)
}
type mca struct {
@ -435,8 +460,13 @@ type mca struct {
sm *stmgr.StateManager
}
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) ChainGetRandomness(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error) {
pts, err := mca.sm.ChainStore().LoadTipSet(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset key: %w", err)
}
return mca.sm.ChainStore().GetRandomness(ctx, pts.Cids(), personalization, int64(randEpoch), entropy)
}
func (mca mca) StateMinerPower(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (api.MinerPower, error) {
@ -463,7 +493,7 @@ func (mca mca) StateMinerWorker(ctx context.Context, maddr address.Address, tsk
return stmgr.GetMinerWorkerRaw(ctx, mca.sm, ts.ParentState(), maddr)
}
func (mca mca) StateMinerSectorSize(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (uint64, error) {
func (mca mca) StateMinerSectorSize(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (abi.SectorSize, error) {
ts, err := mca.sm.ChainStore().LoadTipSet(tsk)
if err != nil {
return 0, xerrors.Errorf("loading tipset %s: %w", tsk, err)
@ -479,7 +509,7 @@ func (mca mca) StateMinerProvingSet(ctx context.Context, maddr address.Address,
return stmgr.GetMinerProvingSet(ctx, mca.sm, ts, maddr)
}
func (mca mca) WalletSign(ctx context.Context, a address.Address, v []byte) (*types.Signature, error) {
func (mca mca) WalletSign(ctx context.Context, a address.Address, v []byte) (*crypto.Signature, error) {
return mca.w.Sign(ctx, a, v)
}
@ -493,7 +523,7 @@ type eppProvider struct{}
func (epp *eppProvider) GenerateCandidates(ctx context.Context, _ sectorbuilder.SortedPublicSectorInfo, eprand []byte) ([]sectorbuilder.EPostCandidate, error) {
return []sectorbuilder.EPostCandidate{
{
SectorID: 1,
SectorNum: 1,
PartialTicket: [32]byte{},
Ticket: [32]byte{},
SectorChallengeIndex: 1,
@ -514,7 +544,7 @@ type ProofInput struct {
}
func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner address.Address, epp ElectionPoStProver, a MiningCheckAPI) (*ProofInput, error) {
r, err := a.ChainGetRandomness(ctx, ts.Key(), round-build.EcRandomnessLookback)
epostRand, err := a.ChainGetRandomness(ctx, ts.Key(), crypto.DomainSeparationTag_ElectionPoStChallengeSeed, abi.ChainEpoch(round-build.EcRandomnessLookback), miner.Bytes())
if err != nil {
return nil, xerrors.Errorf("chain get randomness: %w", err)
}
@ -524,7 +554,7 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add
return nil, xerrors.Errorf("failed to get miner worker: %w", err)
}
vrfout, err := ComputeVRF(ctx, a.WalletSign, mworker, miner, DSepElectionPost, r)
vrfout, err := ComputeVRF(ctx, a.WalletSign, mworker, epostRand)
if err != nil {
return nil, xerrors.Errorf("failed to compute VRF: %w", err)
}
@ -539,11 +569,15 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add
var sinfos []ffi.PublicSectorInfo
for _, s := range pset {
cr, err := commcid.CIDToReplicaCommitmentV1(s.Info.Info.SealedCID)
if err != nil {
return nil, xerrors.Errorf("get sealed cid: %w", err)
}
var commRa [32]byte
copy(commRa[:], s.CommR)
copy(commRa[:], cr)
sinfos = append(sinfos, ffi.PublicSectorInfo{
SectorID: s.SectorID,
CommR: commRa,
SectorNum: s.ID,
CommR: commRa,
})
}
sectors := sectorbuilder.NewSortedPublicSectorInfo(sinfos)
@ -599,7 +633,7 @@ func ComputeProof(ctx context.Context, epp ElectionPoStProver, pi *ProofInput) (
copy(part, win.PartialTicket[:])
ept.Candidates = append(ept.Candidates, types.EPostTicket{
Partial: part,
SectorID: win.SectorID,
SectorID: win.SectorNum,
ChallengeIndex: win.SectorChallengeIndex,
})
}
@ -607,42 +641,14 @@ func ComputeProof(ctx context.Context, epp ElectionPoStProver, pi *ProofInput) (
return &ept, nil
}
type SignFunc func(context.Context, address.Address, []byte) (*types.Signature, error)
type SignFunc func(context.Context, address.Address, []byte) (*crypto.Signature, error)
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 {
func VerifyVRF(ctx context.Context, worker address.Address, vrfBase, vrfproof []byte) error {
_, 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,
sig := &crypto.Signature{
Type: crypto.SigTypeBLS,
Data: vrfproof,
}
@ -653,20 +659,34 @@ func VerifyVRF(ctx context.Context, worker, miner address.Address, p uint64, inp
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
}
func ComputeVRF(ctx context.Context, sign SignFunc, worker address.Address, sigInput []byte) ([]byte, error) {
sig, err := sign(ctx, worker, sigInput)
if err != nil {
return nil, err
}
if sig.Type != types.KTBLS {
if sig.Type != crypto.SigTypeBLS {
return nil, fmt.Errorf("miner worker address was not a BLS key")
}
return sig.Data, nil
}
type genFakeVerifier struct{}
var _ sectorbuilder.Verifier = (*genFakeVerifier)(nil)
func (m genFakeVerifier) VerifyElectionPost(ctx context.Context, sectorSize abi.SectorSize, sectorInfo sectorbuilder.SortedPublicSectorInfo, challengeSeed []byte, proof []byte, candidates []sectorbuilder.EPostCandidate, proverID address.Address) (bool, error) {
panic("nyi")
}
func (m genFakeVerifier) GenerateDataCommitment(ssize abi.PaddedPieceSize, pieces []ffi.PublicPieceInfo) ([sectorbuilder.CommLen]byte, error) {
return sbmock.MockVerifier.GenerateDataCommitment(ssize, pieces)
}
func (m genFakeVerifier) VerifySeal(sectorSize abi.SectorSize, commR, commD []byte, proverID address.Address, ticket []byte, seed []byte, sectorID abi.SectorNumber, proof []byte) (bool, error) {
return true, nil
}
func (m genFakeVerifier) VerifyFallbackPost(ctx context.Context, sectorSize abi.SectorSize, sectorInfo sectorbuilder.SortedPublicSectorInfo, challengeSeed []byte, proof []byte, candidates []sectorbuilder.EPostCandidate, proverID address.Address, faults uint64) (bool, error) {
panic("nyi")
}

View File

@ -3,20 +3,25 @@ package gen
import (
"testing"
"github.com/filecoin-project/specs-actors/actors/abi"
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
"github.com/filecoin-project/lotus/build"
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
)
func init() {
build.SectorSizes = []uint64{1024}
build.SectorSizes = []abi.SectorSize{1024}
build.MinimumMinerPower = 1024
}
func testGeneration(t testing.TB, n int, msgs int) {
g, err := NewGenerator()
if err != nil {
t.Fatal(err)
t.Fatalf("%+v", err)
}
g.msgsPerBlock = msgs
@ -24,7 +29,7 @@ func testGeneration(t testing.TB, n int, msgs int) {
for i := 0; i < n; i++ {
mts, err := g.NextTipSet()
if err != nil {
t.Fatalf("error at H:%d, %s", i, err)
t.Fatalf("error at H:%d, %+v", i, err)
}
_ = mts
}

View File

@ -0,0 +1,286 @@
package genesis
import (
"context"
"encoding/json"
"github.com/filecoin-project/go-amt-ipld/v2"
"github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/account"
"github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-datastore"
bstore "github.com/ipfs/go-ipfs-blockstore"
cbor "github.com/ipfs/go-ipld-cbor"
logging "github.com/ipfs/go-log/v2"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/genesis"
)
const AccountStart = 100
const MinerStart = 1000
const MaxAccounts = MinerStart - AccountStart
var log = logging.Logger("genesis")
type GenesisBootstrap struct {
Genesis *types.BlockHeader
}
/*
From a list of parameters, create a genesis block / initial state
The process:
- Bootstrap state (MakeInitialStateTree)
- Create empty state
- Create system actor
- Make init actor
- Create accounts mappings
- Set NextID to MinerStart
- Setup Reward (1.4B fil)
- Setup Cron
- Create empty power actor
- Create empty market
- Setup burnt fund address
- Initialize account / msig balances
- Instantiate early vm with genesis syscalls
- Create miners
- Each:
- power.CreateMiner, set msg value to PowerBalance
- market.AddFunds with correct value
- market.PublishDeals for related sectors
- Set precommits
- Commit presealed sectors
Data Types:
PreSeal :{
CommR CID
CommD CID
SectorID SectorNumber
Deal market.DealProposal # Start at 0, self-deal!
}
Genesis: {
Accounts: [ # non-miner, non-singleton actors, max len = MaxAccounts
{
Type: "account" / "multisig",
Value: "attofil",
[Meta: {msig settings, account key..}]
},...
],
Miners: [
{
Owner, Worker Addr # ID
MarketBalance, PowerBalance TokenAmount
SectorSize uint64
PreSeals []PreSeal
},...
],
}
*/
func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template genesis.Template) (*state.StateTree, error) {
// Create empty state tree
cst := cbor.NewCborStore(bs)
_, err := cst.Put(context.TODO(), []struct{}{})
if err != nil {
return nil, xerrors.Errorf("putting empty object: %w", err)
}
state, err := state.NewStateTree(cst)
if err != nil {
return nil, xerrors.Errorf("making new state tree: %w", err)
}
emptyobject, err := cst.Put(context.TODO(), []struct{}{})
if err != nil {
return nil, xerrors.Errorf("failed putting empty object: %w", err)
}
// Create system actor
sysact, err := SetupSystemActor(bs)
if err != nil {
return nil, xerrors.Errorf("setup init actor: %w", err)
}
if err := state.SetActor(builtin.SystemActorAddr, sysact); err != nil {
return nil, xerrors.Errorf("set init actor: %w", err)
}
// Create init actor
initact, err := SetupInitActor(bs, template.NetworkName, template.Accounts)
if err != nil {
return nil, xerrors.Errorf("setup init actor: %w", err)
}
if err := state.SetActor(builtin.InitActorAddr, initact); err != nil {
return nil, xerrors.Errorf("set init actor: %w", err)
}
// Setup reward
err = state.SetActor(builtin.RewardActorAddr, &types.Actor{
Code: builtin.RewardActorCodeID,
Balance: big.Int{Int: build.InitialReward},
Head: emptyobject, // TODO ?
})
if err != nil {
return nil, xerrors.Errorf("set network account actor: %w", err)
}
// Setup cron
cronact, err := SetupCronActor(bs)
if err != nil {
return nil, xerrors.Errorf("setup cron actor: %w", err)
}
if err := state.SetActor(builtin.CronActorAddr, cronact); err != nil {
return nil, xerrors.Errorf("set cron actor: %w", err)
}
// Create empty power actor
spact, err := SetupStoragePowerActor(bs)
if err != nil {
return nil, xerrors.Errorf("setup storage market actor: %w", err)
}
if err := state.SetActor(builtin.StoragePowerActorAddr, spact); err != nil {
return nil, xerrors.Errorf("set storage market actor: %w", err)
}
// Create empty market actor
marketact, err := SetupStorageMarketActor(bs)
if err != nil {
return nil, xerrors.Errorf("setup storage market actor: %w", err)
}
if err := state.SetActor(builtin.StorageMarketActorAddr, marketact); err != nil {
return nil, xerrors.Errorf("set market actor: %w", err)
}
// Setup burnt-funds
err = state.SetActor(builtin.BurntFundsActorAddr, &types.Actor{
Code: builtin.AccountActorCodeID,
Balance: types.NewInt(0),
Head: emptyobject,
})
if err != nil {
return nil, xerrors.Errorf("set burnt funds account actor: %w", err)
}
// Create accounts
for id, info := range template.Accounts {
if info.Type != genesis.TAccount {
return nil, xerrors.New("unsupported account type") // TODO: msigs
}
ida, err := address.NewIDAddress(uint64(AccountStart + id))
if err != nil {
return nil, err
}
var ainfo genesis.AccountMeta
if err := json.Unmarshal(info.Meta, &ainfo); err != nil {
return nil, xerrors.Errorf("unmarshaling account meta: %w", err)
}
st, err := cst.Put(ctx, &account.State{Address: ainfo.Owner})
if err != nil {
return nil, err
}
err = state.SetActor(ida, &types.Actor{
Code: builtin.AccountActorCodeID,
Balance: info.Balance,
Head: st,
})
if err != nil {
return nil, xerrors.Errorf("setting account from actmap: %w", err)
}
}
return state, nil
}
func MakeGenesisBlock(ctx context.Context, bs bstore.Blockstore, sys runtime.Syscalls, template genesis.Template) (*GenesisBootstrap, error) {
st, err := MakeInitialStateTree(ctx, bs, template)
if err != nil {
return nil, xerrors.Errorf("make initial state tree failed: %w", err)
}
stateroot, err := st.Flush(ctx)
if err != nil {
return nil, xerrors.Errorf("flush state tree failed: %w", err)
}
// temp chainstore
cs := store.NewChainStore(bs, datastore.NewMapDatastore(), sys)
stateroot, err = SetupStorageMiners(ctx, cs, stateroot, template.Miners)
if err != nil {
return nil, xerrors.Errorf("setup storage miners failed: %w", err)
}
cst := cbor.NewCborStore(bs)
emptyroot, err := amt.FromArray(ctx, cst, nil)
if err != nil {
return nil, xerrors.Errorf("amt build failed: %w", err)
}
mm := &types.MsgMeta{
BlsMessages: emptyroot,
SecpkMessages: emptyroot,
}
mmb, err := mm.ToStorageBlock()
if err != nil {
return nil, xerrors.Errorf("serializing msgmeta failed: %w", err)
}
if err := bs.Put(mmb); err != nil {
return nil, xerrors.Errorf("putting msgmeta block to blockstore: %w", err)
}
log.Infof("Empty Genesis root: %s", emptyroot)
genesisticket := &types.Ticket{
VRFProof: []byte("vrf proof0000000vrf proof0000000"),
}
b := &types.BlockHeader{
Miner: builtin.InitActorAddr,
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),
ParentStateRoot: stateroot,
Messages: mmb.Cid(),
ParentMessageReceipts: emptyroot,
BLSAggregate: crypto.Signature{Type: crypto.SigTypeBLS, Data: []byte("signatureeee")},
BlockSig: &crypto.Signature{Type: crypto.SigTypeBLS, Data: []byte("block signatureeee")},
Timestamp: template.Timestamp,
}
sb, err := b.ToStorageBlock()
if err != nil {
return nil, xerrors.Errorf("serializing block header failed: %w", err)
}
if err := bs.Put(sb); err != nil {
return nil, xerrors.Errorf("putting header to blockstore: %w", err)
}
return &GenesisBootstrap{
Genesis: b,
}, nil
}

266
chain/gen/genesis/miners.go Normal file
View File

@ -0,0 +1,266 @@
package genesis
import (
"bytes"
"context"
"fmt"
"math/rand"
cborutil "github.com/filecoin-project/go-cbor-util"
commcid "github.com/filecoin-project/go-fil-commcid"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/genesis"
)
func MinerAddress(genesisIndex uint64) address.Address {
maddr, err := address.NewIDAddress(MinerStart + genesisIndex)
if err != nil {
panic(err)
}
return maddr
}
func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid, miners []genesis.Miner) (cid.Cid, error) {
networkPower := big.Zero()
for _, m := range miners {
networkPower = big.Add(networkPower, big.NewInt(int64(m.SectorSize)*int64(len(m.Sectors))))
}
vm, err := vm.NewVM(sroot, 0, &fakeRand{}, builtin.SystemActorAddr, cs.Blockstore(), cs.VMSys())
if err != nil {
return cid.Undef, xerrors.Errorf("failed to create NewVM: %w", err)
}
err = vm.MutateState(ctx, builtin.StoragePowerActorAddr, func(cst cbor.IpldStore, st *power.State) error {
st.TotalNetworkPower = networkPower
return nil
})
if len(miners) == 0 {
return cid.Undef, xerrors.New("no genesis miners")
}
for i, m := range miners {
// Create miner through power actor
var maddr address.Address
{
constructorParams := &power.CreateMinerParams{
Worker: m.Worker,
SectorSize: m.SectorSize,
Peer: m.PeerId,
}
params := mustEnc(constructorParams)
rval, err := doExecValue(ctx, vm, builtin.StoragePowerActorAddr, m.Owner, m.PowerBalance, builtin.MethodsPower.CreateMiner, params)
if err != nil {
return cid.Undef, xerrors.Errorf("failed to create genesis miner: %w", err)
}
var ma power.CreateMinerReturn
if err := ma.UnmarshalCBOR(bytes.NewReader(rval)); err != nil {
return cid.Undef, err
}
expma := MinerAddress(uint64(i))
if ma.IDAddress != expma {
return cid.Undef, xerrors.Errorf("miner assigned wrong address: %s != %s", ma.IDAddress, expma)
}
maddr = ma.IDAddress
}
// Add market funds
{
params := mustEnc(&maddr)
_, err := doExecValue(ctx, vm, builtin.StorageMarketActorAddr, m.Worker, m.MarketBalance, builtin.MethodsMarket.AddBalance, params)
if err != nil {
return cid.Undef, xerrors.Errorf("failed to create genesis miner: %w", err)
}
}
{
params := mustEnc(&m.Worker)
_, err := doExecValue(ctx, vm, builtin.StorageMarketActorAddr, m.Worker, big.Zero(), builtin.MethodsMarket.AddBalance, params)
if err != nil {
return cid.Undef, xerrors.Errorf("failed to create genesis miner: %w", err)
}
}
// Publish preseal deals
var dealIDs []abi.DealID
{
params := &market.PublishStorageDealsParams{}
for _, preseal := range m.Sectors {
params.Deals = append(params.Deals, market.ClientDealProposal{
Proposal: preseal.Deal,
ClientSignature: crypto.Signature{Type: crypto.SigTypeBLS}, // TODO: do we want to sign these? Or do we want to fake signatures for genesis setup?
})
fmt.Printf("calling publish storage deals on miner %s with worker %s\n", preseal.Deal.Provider, m.Worker)
}
ret, err := doExecValue(ctx, vm, builtin.StorageMarketActorAddr, m.Worker, big.Zero(), builtin.MethodsMarket.PublishStorageDeals, mustEnc(params))
if err != nil {
return cid.Undef, xerrors.Errorf("failed to create genesis miner: %w", err)
}
var ids market.PublishStorageDealsReturn
if err := ids.UnmarshalCBOR(bytes.NewReader(ret)); err != nil {
return cid.Undef, err
}
dealIDs = ids.IDs
}
// setup windowed post
{
err = vm.MutateState(ctx, maddr, func(cst cbor.IpldStore, st *miner.State) error {
// TODO: Randomize so all genesis miners don't fall on the same epoch
st.PoStState.ProvingPeriodStart = miner.ProvingPeriod
return nil
})
payload, err := cborutil.Dump(&miner.CronEventPayload{
EventType: miner.CronEventWindowedPoStExpiration,
})
if err != nil {
return cid.Undef, err
}
params := &power.EnrollCronEventParams{
EventEpoch: miner.ProvingPeriod,
Payload: payload,
}
_, err = doExecValue(ctx, vm, builtin.StoragePowerActorAddr, maddr, big.Zero(), builtin.MethodsPower.EnrollCronEvent, mustEnc(params))
if err != nil {
return cid.Undef, xerrors.Errorf("failed to verify preseal deals miner: %w", err)
}
}
// Commit sectors
for pi, preseal := range m.Sectors {
// TODO: Maybe check seal (Can just be snark inputs, doesn't go into the genesis file)
// check deals, get dealWeight
dealWeight := big.Zero()
{
params := &market.VerifyDealsOnSectorProveCommitParams{
DealIDs: []abi.DealID{dealIDs[pi]},
SectorExpiry: preseal.Deal.EndEpoch,
}
ret, err := doExecValue(ctx, vm, builtin.StorageMarketActorAddr, maddr, big.Zero(), builtin.MethodsMarket.VerifyDealsOnSectorProveCommit, mustEnc(params))
if err != nil {
return cid.Undef, xerrors.Errorf("failed to verify preseal deals miner: %w", err)
}
if err := dealWeight.UnmarshalCBOR(bytes.NewReader(ret)); err != nil {
return cid.Undef, err
}
}
// update power claims
pledge := big.Zero()
{
err = vm.MutateState(ctx, builtin.StoragePowerActorAddr, func(cst cbor.IpldStore, st *power.State) error {
weight := &power.SectorStorageWeightDesc{
SectorSize: m.SectorSize,
Duration: preseal.Deal.Duration(),
DealWeight: dealWeight,
}
spower := power.ConsensusPowerForWeight(weight)
pledge = power.PledgeForWeight(weight, big.Sub(st.TotalNetworkPower, spower))
err := st.AddToClaim(&state.AdtStore{cst}, maddr, spower, pledge)
if err != nil {
return xerrors.Errorf("add to claim: %w", err)
}
return nil
})
if err != nil {
return cid.Undef, xerrors.Errorf("register power claim in power actor: %w", err)
}
}
// Put sectors to miner sector sets
{
newSectorInfo := &miner.SectorOnChainInfo{
Info: miner.SectorPreCommitInfo{
SectorNumber: preseal.SectorID,
SealedCID: commcid.ReplicaCommitmentV1ToCID(preseal.CommR[:]),
SealRandEpoch: 0,
DealIDs: []abi.DealID{dealIDs[pi]},
Expiration: preseal.Deal.EndEpoch,
},
ActivationEpoch: 0,
DealWeight: dealWeight,
PledgeRequirement: pledge,
}
err = vm.MutateState(ctx, maddr, func(cst cbor.IpldStore, st *miner.State) error {
store := &state.AdtStore{cst}
if err = st.PutSector(store, newSectorInfo); err != nil {
return xerrors.Errorf("failed to prove commit: %v", err)
}
st.ProvingSet = st.Sectors
return nil
})
if err != nil {
return cid.Cid{}, xerrors.Errorf("put to sset: %w", err)
}
}
{
sectorBf := abi.NewBitField()
sectorBf.Set(uint64(preseal.SectorID))
payload, err := cborutil.Dump(&miner.CronEventPayload{
EventType: miner.CronEventSectorExpiry,
Sectors: &sectorBf,
})
if err != nil {
return cid.Undef, err
}
params := &power.EnrollCronEventParams{
EventEpoch: preseal.Deal.EndEpoch,
Payload: payload,
}
_, err = doExecValue(ctx, vm, builtin.StoragePowerActorAddr, maddr, big.Zero(), builtin.MethodsPower.EnrollCronEvent, mustEnc(params))
if err != nil {
return cid.Undef, xerrors.Errorf("failed to verify preseal deals miner: %w", err)
}
}
}
}
c, err := vm.Flush(ctx)
return c, err
}
// TODO: copied from actors test harness, deduplicate or remove from here
type fakeRand struct{}
func (fr *fakeRand) GetRandomness(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch int64, entropy []byte) ([]byte, error) {
out := make([]byte, 32)
rand.New(rand.NewSource(randEpoch)).Read(out)
return out, nil
}

View File

@ -0,0 +1,28 @@
package genesis
import (
"context"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/util/adt"
bstore "github.com/ipfs/go-ipfs-blockstore"
cbor "github.com/ipfs/go-ipld-cbor"
)
func SetupSystemActor(bs bstore.Blockstore) (*types.Actor, error) {
var st adt.EmptyValue
cst := cbor.NewCborStore(bs)
statecid, err := cst.Put(context.TODO(), &st)
if err != nil {
return nil, err
}
act := &types.Actor{
Code: builtin.SystemActorCodeID,
Head: statecid,
}
return act, nil
}

View File

@ -0,0 +1,69 @@
package genesis
import (
"context"
"encoding/json"
"fmt"
"github.com/filecoin-project/specs-actors/actors/builtin"
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
"github.com/ipfs/go-hamt-ipld"
bstore "github.com/ipfs/go-ipfs-blockstore"
cbor "github.com/ipfs/go-ipld-cbor"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/genesis"
)
func SetupInitActor(bs bstore.Blockstore, netname string, initialActors []genesis.Actor) (*types.Actor, error) {
if len(initialActors) > MaxAccounts {
return nil, xerrors.New("too many initial actors")
}
var ias init_.State
ias.NextID = MinerStart
ias.NetworkName = netname
cst := cbor.NewCborStore(bs)
amap := hamt.NewNode(cst, hamt.UseTreeBitWidth(5)) // TODO: use spec adt map
for i, a := range initialActors {
if a.Type != genesis.TAccount {
return nil, xerrors.Errorf("unsupported account type: %s", a.Type) // TODO: Support msig (skip here)
}
var ainfo genesis.AccountMeta
if err := json.Unmarshal(a.Meta, &ainfo); err != nil {
return nil, xerrors.Errorf("unmarshaling account meta: %w", err)
}
fmt.Printf("init set %s t0%d\n", ainfo.Owner, AccountStart+uint64(i))
if err := amap.Set(context.TODO(), string(ainfo.Owner.Bytes()), AccountStart+uint64(i)); err != nil {
return nil, err
}
}
if err := amap.Flush(context.TODO()); err != nil {
return nil, err
}
amapcid, err := cst.Put(context.TODO(), amap)
if err != nil {
return nil, err
}
ias.AddressMap = amapcid
statecid, err := cst.Put(context.TODO(), &ias)
if err != nil {
return nil, err
}
act := &types.Actor{
Code: builtin.InitActorCodeID,
Head: statecid,
}
return act, nil
}

View File

@ -0,0 +1 @@
package genesis

View File

@ -0,0 +1,33 @@
package genesis
import (
"context"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/cron"
bstore "github.com/ipfs/go-ipfs-blockstore"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/filecoin-project/lotus/chain/types"
)
func SetupCronActor(bs bstore.Blockstore) (*types.Actor, error) {
cst := cbor.NewCborStore(bs)
cas := &cron.State{Entries: []cron.Entry{{
Receiver: builtin.StoragePowerActorAddr,
MethodNum: builtin.MethodsPower.OnEpochTickEnd,
},
}}
stcid, err := cst.Put(context.TODO(), cas)
if err != nil {
return nil, err
}
return &types.Actor{
Code: builtin.CronActorCodeID,
Head: stcid,
Nonce: 0,
Balance: types.NewInt(0),
}, nil
}

View File

@ -0,0 +1,46 @@
package genesis
import (
"context"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/ipfs/go-hamt-ipld"
bstore "github.com/ipfs/go-ipfs-blockstore"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/filecoin-project/lotus/chain/types"
)
func SetupStoragePowerActor(bs bstore.Blockstore) (*types.Actor, error) {
ctx := context.TODO()
cst := cbor.NewCborStore(bs)
nd := hamt.NewNode(cst, hamt.UseTreeBitWidth(5))
emptyhamt, err := cst.Put(ctx, nd)
if err != nil {
return nil, err
}
sms := &power.State{
TotalNetworkPower: big.NewInt(1),
MinerCount: 0,
EscrowTable: emptyhamt,
CronEventQueue: emptyhamt,
PoStDetectedFaultMiners: emptyhamt,
Claims: emptyhamt,
NumMinersMeetingMinPower: 0,
}
stcid, err := cst.Put(ctx, sms)
if err != nil {
return nil, err
}
return &types.Actor{
Code: builtin.StoragePowerActorCodeID,
Head: stcid,
Nonce: 0,
Balance: types.NewInt(0),
}, nil
}

View File

@ -0,0 +1,42 @@
package genesis
import (
"context"
"github.com/ipfs/go-hamt-ipld"
"github.com/filecoin-project/go-amt-ipld/v2"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/market"
bstore "github.com/ipfs/go-ipfs-blockstore"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/filecoin-project/lotus/chain/types"
)
func SetupStorageMarketActor(bs bstore.Blockstore) (*types.Actor, error) {
cst := cbor.NewCborStore(bs)
a, err := amt.NewAMT(cst).Flush(context.TODO())
if err != nil {
return nil, err
}
h, err := cst.Put(context.TODO(), hamt.NewNode(cst, hamt.UseTreeBitWidth(5)))
if err != nil {
return nil, err
}
sms := market.ConstructState(a, h, h)
stcid, err := cst.Put(context.TODO(), sms)
if err != nil {
return nil, err
}
act := &types.Actor{
Code: builtin.StorageMarketActorCodeID,
Head: stcid,
Balance: types.NewInt(0),
}
return act, nil
}

53
chain/gen/genesis/util.go Normal file
View File

@ -0,0 +1,53 @@
package genesis
import (
"context"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
)
func mustEnc(i cbg.CBORMarshaler) []byte {
enc, err := actors.SerializeParams(i)
if err != nil {
panic(err) // ok
}
return enc
}
func doExec(ctx context.Context, vm *vm.VM, to, from address.Address, method abi.MethodNum, params []byte) ([]byte, error) {
return doExecValue(ctx, vm, to, from, types.NewInt(0), method, params)
}
func doExecValue(ctx context.Context, vm *vm.VM, to, from address.Address, value types.BigInt, method abi.MethodNum, params []byte) ([]byte, error) {
act, err := vm.StateTree().GetActor(from)
if err != nil {
return nil, xerrors.Errorf("doExec failed to get from actor: %w", err)
}
ret, err := vm.ApplyMessage(ctx, &types.Message{
To: to,
From: from,
Method: method,
Params: params,
GasLimit: types.NewInt(1000000),
GasPrice: types.NewInt(0),
Value: value,
Nonce: act.Nonce,
})
if err != nil {
return nil, xerrors.Errorf("doExec apply message failed: %w", err)
}
if ret.ExitCode != 0 {
return nil, xerrors.Errorf("failed to call method: %w", ret.ActorErr)
}
return ret.Return, nil
}

View File

@ -5,6 +5,8 @@ import (
bls "github.com/filecoin-project/filecoin-ffi"
amt "github.com/filecoin-project/go-amt-ipld/v2"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/crypto"
cid "github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
cbg "github.com/whyrusleeping/cbor-gen"
@ -18,7 +20,7 @@ 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, ticket *types.Ticket, proof *types.EPostProof, msgs []*types.SignedMessage, height, 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 abi.ChainEpoch, 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)
@ -44,9 +46,9 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wal
var secpkMessages []*types.SignedMessage
var blsMsgCids, secpkMsgCids []cid.Cid
var blsSigs []types.Signature
var blsSigs []crypto.Signature
for _, msg := range msgs {
if msg.Signature.TypeCode() == types.IKTBLS {
if msg.Signature.Type == crypto.SigTypeBLS {
blsSigs = append(blsSigs, msg.Signature)
blsMessages = append(blsMessages, &msg.Message)
@ -131,7 +133,7 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wal
return fullBlock, nil
}
func aggregateSignatures(sigs []types.Signature) (types.Signature, error) {
func aggregateSignatures(sigs []crypto.Signature) (crypto.Signature, error) {
var blsSigs []bls.Signature
for _, s := range sigs {
var bsig bls.Signature
@ -140,8 +142,8 @@ func aggregateSignatures(sigs []types.Signature) (types.Signature, error) {
}
aggSig := bls.Aggregate(blsSigs)
return types.Signature{
Type: types.KTBLS,
return crypto.Signature{
Type: crypto.SigTypeBLS,
Data: aggSig[:],
}, nil
}

View File

@ -1,676 +0,0 @@
package gen
import (
"bytes"
"context"
"fmt"
amt "github.com/filecoin-project/go-amt-ipld/v2"
"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"
cbor "github.com/ipfs/go-ipld-cbor"
peer "github.com/libp2p/go-libp2p-core/peer"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/build"
actors "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/state"
"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"
)
type GenesisBootstrap struct {
Genesis *types.BlockHeader
}
func SetupInitActor(bs bstore.Blockstore, addrs []address.Address) (*types.Actor, error) {
var ias actors.InitActorState
ias.NextID = 100
cst := cbor.NewCborStore(bs)
amap := hamt.NewNode(cst)
for i, a := range addrs {
if err := amap.Set(context.TODO(), string(a.Bytes()), 100+uint64(i)); err != nil {
return nil, err
}
}
ias.NextID += uint64(len(addrs))
if err := amap.Flush(context.TODO()); err != nil {
return nil, err
}
amapcid, err := cst.Put(context.TODO(), amap)
if err != nil {
return nil, err
}
ias.AddressMap = amapcid
statecid, err := cst.Put(context.TODO(), &ias)
if err != nil {
return nil, err
}
act := &types.Actor{
Code: actors.InitCodeCid,
Head: statecid,
}
return act, nil
}
func MakeInitialStateTree(bs bstore.Blockstore, actmap map[address.Address]types.BigInt) (*state.StateTree, error) {
cst := cbor.NewCborStore(bs)
state, err := state.NewStateTree(cst)
if err != nil {
return nil, xerrors.Errorf("making new state tree: %w", err)
}
emptyobject, err := cst.Put(context.TODO(), map[string]string{})
if err != nil {
return nil, xerrors.Errorf("failed putting empty object: %w", err)
}
var addrs []address.Address
for a := range actmap {
addrs = append(addrs, a)
}
initact, err := SetupInitActor(bs, addrs)
if err != nil {
return nil, xerrors.Errorf("setup init actor: %w", err)
}
if err := state.SetActor(actors.InitAddress, initact); err != nil {
return nil, xerrors.Errorf("set init actor: %w", err)
}
cronact, err := SetupCronActor(bs)
if err != nil {
return nil, xerrors.Errorf("setup cron actor: %w", err)
}
if err := state.SetActor(actors.CronAddress, cronact); err != nil {
return nil, xerrors.Errorf("set cron actor: %w", err)
}
spact, err := SetupStoragePowerActor(bs)
if err != nil {
return nil, xerrors.Errorf("setup storage market actor: %w", err)
}
if err := state.SetActor(actors.StoragePowerAddress, spact); 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)
}
err = state.SetActor(actors.NetworkAddress, &types.Actor{
Code: actors.AccountCodeCid,
Balance: netAmt,
Head: emptyobject,
})
if err != nil {
return nil, xerrors.Errorf("set network account actor: %w", err)
}
err = state.SetActor(actors.BurntFundsAddress, &types.Actor{
Code: actors.AccountCodeCid,
Balance: types.NewInt(0),
Head: emptyobject,
})
if err != nil {
return nil, xerrors.Errorf("set burnt funds account actor: %w", err)
}
for a, v := range actmap {
err = state.SetActor(a, &types.Actor{
Code: actors.AccountCodeCid,
Balance: v,
Head: emptyobject,
})
if err != nil {
return nil, xerrors.Errorf("setting account from actmap: %w", err)
}
}
return state, nil
}
func SetupCronActor(bs bstore.Blockstore) (*types.Actor, error) {
cst := cbor.NewCborStore(bs)
cas := &actors.CronActorState{}
stcid, err := cst.Put(context.TODO(), cas)
if err != nil {
return nil, err
}
return &types.Actor{
Code: actors.CronCodeCid,
Head: stcid,
Nonce: 0,
Balance: types.NewInt(0),
}, nil
}
func SetupStoragePowerActor(bs bstore.Blockstore) (*types.Actor, error) {
ctx := context.TODO()
cst := cbor.NewCborStore(bs)
nd := hamt.NewNode(cst)
emptyhamt, err := cst.Put(ctx, nd)
if err != nil {
return nil, err
}
blks := cbor.NewCborStore(bs)
emptyamt, err := amt.FromArray(ctx, blks, nil)
if err != nil {
return nil, xerrors.Errorf("amt build failed: %w", err)
}
sms := &actors.StoragePowerState{
Miners: emptyhamt,
ProvingBuckets: emptyamt,
TotalStorage: types.NewInt(0),
}
stcid, err := cst.Put(ctx, sms)
if err != nil {
return nil, err
}
return &types.Actor{
Code: actors.StoragePowerCodeCid,
Head: stcid,
Nonce: 0,
Balance: types.NewInt(0),
}, nil
}
func SetupStorageMarketActor(bs bstore.Blockstore, sroot cid.Cid, deals []actors.StorageDealProposal) (cid.Cid, error) {
ctx := context.TODO()
cst := cbor.NewCborStore(bs)
nd := hamt.NewNode(cst)
emptyHAMT, err := cst.Put(ctx, nd)
if err != nil {
return cid.Undef, err
}
cdeals := make([]cbg.CBORMarshaler, len(deals))
for i, deal := range deals {
cdeals[i] = &actors.OnChainDeal{
PieceRef: deal.PieceRef,
PieceSize: deal.PieceSize,
Client: deal.Client,
Provider: deal.Provider,
ProposalExpiration: deal.ProposalExpiration,
Duration: deal.Duration,
StoragePricePerEpoch: deal.StoragePricePerEpoch,
StorageCollateral: deal.StorageCollateral,
ActivationEpoch: 1,
}
}
dealAmt, err := amt.FromArray(ctx, cst, cdeals)
if err != nil {
return cid.Undef, xerrors.Errorf("amt build failed: %w", err)
}
sms := &actors.StorageMarketState{
Balances: emptyHAMT,
Deals: dealAmt,
NextDealID: uint64(len(deals)),
}
stcid, err := cst.Put(context.TODO(), sms)
if err != nil {
return cid.Undef, err
}
act := &types.Actor{
Code: actors.StorageMarketCodeCid,
Head: stcid,
Nonce: 0,
Balance: types.NewInt(0),
}
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(context.TODO())
}
type GenMinerCfg struct {
PreSeals map[string]genesis.GenesisMiner
// The addresses of the created miner, this is set by the genesis setup
MinerAddrs []address.Address
PeerIDs []peer.ID
}
func mustEnc(i cbg.CBORMarshaler) []byte {
enc, err := actors.SerializeParams(i)
if err != nil {
panic(err) // ok
}
return enc
}
func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid, gmcfg *GenMinerCfg) (cid.Cid, []actors.StorageDealProposal, error) {
vm, err := vm.NewVM(sroot, 0, nil, actors.NetworkAddress, cs.Blockstore(), cs.VMSys())
if err != nil {
return cid.Undef, nil, xerrors.Errorf("failed to create NewVM: %w", err)
}
if len(gmcfg.MinerAddrs) == 0 {
return cid.Undef, nil, xerrors.New("no genesis miners")
}
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))
}
var deals []actors.StorageDealProposal
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, ps.Worker, types.FromFil(6500), actors.SPAMethods.CreateStorageMiner, params)
if err != nil {
return cid.Undef, nil, xerrors.Errorf("failed to create genesis miner: %w", err)
}
maddrret, err := address.NewFromBytes(rval)
if err != nil {
return cid.Undef, nil, err
}
_, err = vm.Flush(ctx)
if err != nil {
return cid.Undef, nil, err
}
cst := cbor.NewCborStore(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, nil, xerrors.Errorf("failed to update total storage: %w", err)
}
// 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, nil, xerrors.Errorf("vm.Flush failed: %w", err)
}
st := vm.StateTree()
mact, err := st.GetActor(maddr)
if err != nil {
return cid.Undef, nil, xerrors.Errorf("get miner actor failed: %w", err)
}
var mstate actors.StorageMinerActorState
if err := cst.Get(ctx, mact.Head, &mstate); err != nil {
return cid.Undef, nil, xerrors.Errorf("getting miner actor state failed: %w", err)
}
mstate.Power = types.BigMul(types.NewInt(ps.SectorSize), types.NewInt(uint64(len(ps.Sectors))))
for _, s := range ps.Sectors {
nssroot, err := actors.AddToSectorSet(ctx, cst, 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)
}
nstate, err := cst.Put(ctx, &mstate)
if err != nil {
return cid.Undef, nil, err
}
mact.Head = nstate
if err := st.SetActor(maddr, mact); err != nil {
return cid.Undef, nil, err
}
}
c, err := vm.Flush(ctx)
return c, deals, err
}
func reassignMinerActorAddress(vm *vm.VM, cst cbor.IpldStore, 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 cbor.IpldStore, 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 cbor.IpldStore, 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) {
return doExecValue(ctx, vm, to, from, types.NewInt(0), method, params)
}
func doExecValue(ctx context.Context, vm *vm.VM, to, from address.Address, value types.BigInt, method uint64, params []byte) ([]byte, error) {
act, err := vm.StateTree().GetActor(from)
if err != nil {
return nil, xerrors.Errorf("doExec failed to get from actor: %w", err)
}
ret, err := vm.ApplyMessage(context.TODO(), &types.Message{
To: to,
From: from,
Method: method,
Params: params,
GasLimit: types.NewInt(1000000),
GasPrice: types.NewInt(0),
Value: value,
Nonce: act.Nonce,
})
if err != nil {
return nil, xerrors.Errorf("doExec apply message failed: %w", err)
}
if ret.ExitCode != 0 {
return nil, fmt.Errorf("failed to call method: %s", ret.ActorErr)
}
return ret.Return, nil
}
func MakeGenesisBlock(bs bstore.Blockstore, sys *types.VMSyscalls, balances map[address.Address]types.BigInt, gmcfg *GenMinerCfg, ts uint64) (*GenesisBootstrap, error) {
ctx := context.TODO()
state, err := MakeInitialStateTree(bs, balances)
if err != nil {
return nil, xerrors.Errorf("make initial state tree failed: %w", err)
}
stateroot, err := state.Flush(ctx)
if err != nil {
return nil, xerrors.Errorf("flush state tree failed: %w", err)
}
// temp chainstore
cs := store.NewChainStore(bs, datastore.NewMapDatastore(), sys)
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)
}
cst := cbor.NewCborStore(bs)
emptyroot, err := amt.FromArray(ctx, cst, nil)
if err != nil {
return nil, xerrors.Errorf("amt build failed: %w", err)
}
mm := &types.MsgMeta{
BlsMessages: emptyroot,
SecpkMessages: emptyroot,
}
mmb, err := mm.ToStorageBlock()
if err != nil {
return nil, xerrors.Errorf("serializing msgmeta failed: %w", err)
}
if err := bs.Put(mmb); err != nil {
return nil, xerrors.Errorf("putting msgmeta block to blockstore: %w", err)
}
log.Infof("Empty Genesis root: %s", emptyroot)
genesisticket := &types.Ticket{
VRFProof: []byte("vrf proof0000000vrf proof0000000"),
}
b := &types.BlockHeader{
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),
ParentStateRoot: stateroot,
Messages: mmb.Cid(),
ParentMessageReceipts: emptyroot,
BLSAggregate: types.Signature{Type: types.KTBLS, Data: []byte("signatureeee")},
BlockSig: &types.Signature{Type: types.KTBLS, Data: []byte("block signatureeee")},
Timestamp: ts,
}
sb, err := b.ToStorageBlock()
if err != nil {
return nil, xerrors.Errorf("serializing block header failed: %w", err)
}
if err := bs.Put(sb); err != nil {
return nil, xerrors.Errorf("putting header to blockstore: %w", err)
}
return &GenesisBootstrap{
Genesis: b,
}, nil
}
func AdjustInitActorStartID(ctx context.Context, bs blockstore.Blockstore, stateroot cid.Cid, val uint64) (cid.Cid, error) {
cst := cbor.NewCborStore(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(ctx)
}

View File

@ -4,6 +4,7 @@ import (
"context"
"sync"
"github.com/filecoin-project/specs-actors/actors/builtin"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
@ -40,7 +41,7 @@ func (fm *FundMgr) EnsureAvailable(ctx context.Context, addr address.Address, am
return err
}
avail = bal.Available
avail = types.BigSub(bal.Escrow, bal.Locked)
}
toAdd := types.NewInt(0)
@ -55,13 +56,20 @@ func (fm *FundMgr) EnsureAvailable(ctx context.Context, addr address.Address, am
fm.lk.Unlock()
var err error
params, err := actors.SerializeParams(&addr)
if err != nil {
return err
}
smsg, err := fm.mpool.MpoolPushMessage(ctx, &types.Message{
To: actors.StorageMarketAddress,
To: builtin.StorageMarketActorAddr,
From: addr,
Value: toAdd,
GasPrice: types.NewInt(0),
GasLimit: types.NewInt(1000000),
Method: actors.SMAMethods.AddBalance,
Method: builtin.MethodsMarket.AddBalance,
Params: params,
})
if err != nil {
return err

View File

@ -8,6 +8,7 @@ import (
"sync"
"time"
"github.com/filecoin-project/specs-actors/actors/crypto"
lru "github.com/hashicorp/golang-lru"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-datastore"
@ -342,7 +343,7 @@ func (mp *MessagePool) addSkipChecks(m *types.SignedMessage) error {
func (mp *MessagePool) addLocked(m *types.SignedMessage) error {
log.Debugf("mpooladd: %s %s", m.Message.From, m.Message.Nonce)
if m.Signature.Type == types.KTBLS {
if m.Signature.Type == crypto.SigTypeBLS {
mp.blsSigCache.Add(m.Cid(), m.Signature)
}
@ -656,7 +657,7 @@ func (mp *MessagePool) RecoverSig(msg *types.Message) *types.SignedMessage {
if !ok {
return nil
}
sig, ok := val.(types.Signature)
sig, ok := val.(crypto.Signature)
if !ok {
log.Errorf("value in signature cache was not a signature (got %T)", val)
return nil

View File

@ -11,6 +11,7 @@ import (
"github.com/filecoin-project/lotus/chain/wallet"
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
"github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-datastore"
)
@ -146,7 +147,7 @@ func TestMessagePool(t *testing.T) {
a := mock.MkBlock(nil, 1, 1)
sender, err := w.GenerateKey(types.KTBLS)
sender, err := w.GenerateKey(crypto.SigTypeBLS)
if err != nil {
t.Fatal(err)
}
@ -188,7 +189,7 @@ func TestRevertMessages(t *testing.T) {
a := mock.MkBlock(nil, 1, 1)
b := mock.MkBlock(mock.TipSet(a), 1, 1)
sender, err := w.GenerateKey(types.KTBLS)
sender, err := w.GenerateKey(crypto.SigTypeBLS)
if err != nil {
t.Fatal(err)
}

View File

@ -5,6 +5,7 @@ import (
"encoding/json"
"time"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/ipfs/go-cid"
logging "github.com/ipfs/go-log/v2"
pubsub "github.com/libp2p/go-libp2p-pubsub"
@ -68,7 +69,7 @@ type message struct {
// TipSet
Cids []cid.Cid
Blocks []*types.BlockHeader
Height uint64
Height abi.ChainEpoch
Weight types.BigInt
Time uint64
Nonce uint64

View File

@ -3,7 +3,10 @@ package state
import (
"context"
"fmt"
"github.com/filecoin-project/specs-actors/actors/builtin"
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/ipfs/go-cid"
hamt "github.com/ipfs/go-hamt-ipld"
cbor "github.com/ipfs/go-ipld-cbor"
@ -12,7 +15,6 @@ import (
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/types"
)
@ -28,14 +30,14 @@ type StateTree struct {
func NewStateTree(cst cbor.IpldStore) (*StateTree, error) {
return &StateTree{
root: hamt.NewNode(cst),
root: hamt.NewNode(cst, hamt.UseTreeBitWidth(5)),
Store: cst,
actorcache: make(map[address.Address]*types.Actor),
}, nil
}
func LoadStateTree(cst cbor.IpldStore, c cid.Cid) (*StateTree, error) {
nd, err := hamt.LoadNode(context.Background(), cst, c)
nd, err := hamt.LoadNode(context.Background(), cst, c, hamt.UseTreeBitWidth(5))
if err != nil {
log.Errorf("loading hamt node %s failed: %s", c, err)
return nil, err
@ -72,17 +74,21 @@ func (st *StateTree) LookupID(addr address.Address) (address.Address, error) {
return addr, nil
}
act, err := st.GetActor(actors.InitAddress)
act, err := st.GetActor(builtin.InitActorAddr)
if err != nil {
return address.Undef, xerrors.Errorf("getting init actor: %w", err)
}
var ias actors.InitActorState
var ias init_.State
if err := st.Store.Get(context.TODO(), act.Head, &ias); err != nil {
return address.Undef, xerrors.Errorf("loading init actor state: %w", err)
}
return ias.Lookup(st.Store, addr)
a, err := ias.ResolveAddress(&AdtStore{st.Store}, addr)
if err != nil {
return address.Undef, xerrors.Errorf("resolve address %s: %w", addr, err)
}
return a, nil
}
func (st *StateTree) GetActor(addr address.Address) (*types.Actor, error) {
@ -92,8 +98,8 @@ func (st *StateTree) GetActor(addr address.Address) (*types.Actor, error) {
iaddr, err := st.LookupID(addr)
if err != nil {
if xerrors.Is(err, hamt.ErrNotFound) {
return nil, xerrors.Errorf("resolution lookup failed (%s): %w", addr, types.ErrActorNotFound)
if xerrors.Is(err, init_.ErrAddressNotFound) {
return nil, xerrors.Errorf("resolution lookup failed (%s): %w", addr, err)
}
return nil, xerrors.Errorf("address resolution: %w", err)
}
@ -151,13 +157,13 @@ func (st *StateTree) Snapshot(ctx context.Context) error {
func (st *StateTree) RegisterNewAddress(addr address.Address, act *types.Actor) (address.Address, error) {
var out address.Address
err := st.MutateActor(actors.InitAddress, func(initact *types.Actor) error {
var ias actors.InitActorState
err := st.MutateActor(builtin.InitActorAddr, func(initact *types.Actor) error {
var ias init_.State
if err := st.Store.Get(context.TODO(), initact.Head, &ias); err != nil {
return err
}
oaddr, err := ias.AddActor(st.Store, addr)
oaddr, err := ias.MapAddressToNewID(&AdtStore{st.Store}, addr)
if err != nil {
return err
}
@ -182,8 +188,16 @@ func (st *StateTree) RegisterNewAddress(addr address.Address, act *types.Actor)
return out, nil
}
type AdtStore struct{ cbor.IpldStore }
func (a *AdtStore) Context() context.Context {
return context.TODO()
}
var _ adt.Store = (*AdtStore)(nil)
func (st *StateTree) Revert() error {
nd, err := hamt.LoadNode(context.Background(), st.Store, st.snapshot)
nd, err := hamt.LoadNode(context.Background(), st.Store, st.snapshot, hamt.UseTreeBitWidth(5))
if err != nil {
return err
}

View File

@ -2,10 +2,10 @@ package state
import (
"context"
"github.com/filecoin-project/specs-actors/actors/builtin"
"testing"
address "github.com/filecoin-project/go-address"
actors "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/types"
cbor "github.com/ipfs/go-ipld-cbor"
)
@ -27,8 +27,8 @@ func BenchmarkStateTreeSet(b *testing.B) {
}
err = st.SetActor(a, &types.Actor{
Balance: types.NewInt(1258812523),
Code: actors.StorageMinerCodeCid,
Head: actors.AccountCodeCid,
Code: builtin.StorageMinerActorCodeID,
Head: builtin.AccountActorCodeID,
Nonce: uint64(i),
})
if err != nil {
@ -54,8 +54,8 @@ func BenchmarkStateTreeSetFlush(b *testing.B) {
}
err = st.SetActor(a, &types.Actor{
Balance: types.NewInt(1258812523),
Code: actors.StorageMinerCodeCid,
Head: actors.AccountCodeCid,
Code: builtin.StorageMinerActorCodeID,
Head: builtin.AccountActorCodeID,
Nonce: uint64(i),
})
if err != nil {
@ -80,8 +80,8 @@ func BenchmarkStateTree10kGetActor(b *testing.B) {
}
err = st.SetActor(a, &types.Actor{
Balance: types.NewInt(1258812523 + uint64(i)),
Code: actors.StorageMinerCodeCid,
Head: actors.AccountCodeCid,
Code: builtin.StorageMinerActorCodeID,
Head: builtin.AccountActorCodeID,
Nonce: uint64(i),
})
if err != nil {
@ -123,8 +123,8 @@ func TestSetCache(t *testing.T) {
act := &types.Actor{
Balance: types.NewInt(0),
Code: actors.StorageMinerCodeCid,
Head: actors.AccountCodeCid,
Code: builtin.StorageMinerActorCodeID,
Head: builtin.AccountActorCodeID,
Nonce: 0,
}

View File

@ -3,23 +3,24 @@ package stmgr
import (
"context"
"fmt"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/ipfs/go-cid"
"go.opencensus.io/trace"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
)
func (sm *StateManager) CallRaw(ctx context.Context, msg *types.Message, bstate cid.Cid, r vm.Rand, bheight uint64) (*api.MethodCall, error) {
func (sm *StateManager) CallRaw(ctx context.Context, msg *types.Message, bstate cid.Cid, r vm.Rand, bheight abi.ChainEpoch) (*api.MethodCall, error) {
ctx, span := trace.StartSpan(ctx, "statemanager.CallRaw")
defer span.End()
vmi, err := vm.NewVM(bstate, bheight, r, actors.NetworkAddress, sm.cs.Blockstore(), sm.cs.VMSys())
vmi, err := vm.NewVM(bstate, bheight, r, builtin.SystemActorAddr, sm.cs.Blockstore(), sm.cs.VMSys())
if err != nil {
return nil, xerrors.Errorf("failed to set up vm: %w", err)
}

View File

@ -3,12 +3,13 @@ package stmgr
import (
"context"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/ipfs/go-cid"
)
var ForksAtHeight = map[uint64]func(context.Context, *StateManager, cid.Cid) (cid.Cid, error){}
var ForksAtHeight = map[abi.ChainEpoch]func(context.Context, *StateManager, cid.Cid) (cid.Cid, error){}
func (sm *StateManager) handleStateForks(ctx context.Context, pstate cid.Cid, height, parentH uint64) (_ cid.Cid, err error) {
func (sm *StateManager) handleStateForks(ctx context.Context, pstate cid.Cid, height, parentH abi.ChainEpoch) (_ cid.Cid, err error) {
for i := parentH; i < height; i++ {
f, ok := ForksAtHeight[i]
if ok {

View File

@ -7,6 +7,12 @@ import (
"testing"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin"
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
@ -28,7 +34,7 @@ import (
)
func init() {
build.SectorSizes = []uint64{1024}
build.SectorSizes = []abi.SectorSize{1024}
build.MinimumMinerPower = 1024
}
@ -69,10 +75,14 @@ func (ta *testActor) Constructor(act *types.Actor, vmctx types.VMContext, params
if err != nil {
return nil, err
}
empty, err := vmctx.Storage().Put(&adt.EmptyValue{})
if err != nil {
return nil, err
}
fmt.Println("NEW ACTOR ADDRESS IS: ", vmctx.Message().To.String())
return nil, vmctx.Storage().Commit(actors.EmptyCBOR, c)
return nil, vmctx.Storage().Commit(empty, c)
}
func (ta *testActor) TestMethod(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, aerrors.ActorError) {
@ -114,8 +124,6 @@ func TestForkHeightTriggers(t *testing.T) {
t.Fatal(err)
}
actors.BuiltInActors[actcid] = true
// predicting the address here... may break if other assumptions change
taddr, err := address.NewIDAddress(1000)
if err != nil {
@ -156,7 +164,7 @@ func TestForkHeightTriggers(t *testing.T) {
}
inv.Register(actcid, &testActor{}, &testActorState{})
sm.SetVMConstructor(func(c cid.Cid, h uint64, r vm.Rand, a address.Address, b blockstore.Blockstore, s *types.VMSyscalls) (*vm.VM, error) {
sm.SetVMConstructor(func(c cid.Cid, h abi.ChainEpoch, r vm.Rand, a address.Address, b blockstore.Blockstore, s runtime.Syscalls) (*vm.VM, error) {
nvm, err := vm.NewVM(c, h, r, a, b, s)
if err != nil {
return nil, err
@ -169,15 +177,15 @@ func TestForkHeightTriggers(t *testing.T) {
var msgs []*types.SignedMessage
enc, err := actors.SerializeParams(&actors.ExecParams{Code: actcid})
enc, err := actors.SerializeParams(&init_.ExecParams{CodeCID: actcid})
if err != nil {
t.Fatal(err)
}
m := &types.Message{
From: cg.Banker(),
To: actors.InitAddress,
Method: actors.IAMethods.Exec,
To: builtin.InitActorAddr,
Method: builtin.MethodsInit.Exec,
Params: enc,
GasLimit: types.NewInt(10000),
GasPrice: types.NewInt(0),

View File

@ -7,11 +7,17 @@ import (
"github.com/filecoin-project/go-address"
amt "github.com/filecoin-project/go-amt-ipld/v2"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/state"
"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/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/specs-actors/actors/util/adt"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
@ -32,7 +38,7 @@ type StateManager struct {
stCache map[string][]cid.Cid
compWait map[string]chan struct{}
stlk sync.Mutex
newVM func(cid.Cid, uint64, vm.Rand, address.Address, blockstore.Blockstore, *types.VMSyscalls) (*vm.VM, error)
newVM func(cid.Cid, abi.ChainEpoch, vm.Rand, address.Address, blockstore.Blockstore, runtime.Syscalls) (*vm.VM, error)
}
func NewStateManager(cs *store.ChainStore) *StateManager {
@ -148,13 +154,13 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
return cid.Undef, cid.Undef, xerrors.Errorf("instantiating VM failed: %w", err)
}
netact, err := vmi.StateTree().GetActor(actors.NetworkAddress)
rewardActor, err := vmi.StateTree().GetActor(builtin.RewardActorAddr)
if err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("failed to get network actor: %w", err)
}
reward := vm.MiningReward(netact.Balance)
for tsi, b := range blks {
netact, err = vmi.StateTree().GetActor(actors.NetworkAddress)
reward := vm.MiningReward(rewardActor.Balance)
for _, b := range blks {
rewardActor, err = vmi.StateTree().GetActor(builtin.RewardActorAddr)
if err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("failed to get network actor: %w", err)
}
@ -170,27 +176,9 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
return cid.Undef, cid.Undef, xerrors.Errorf("failed to get miner owner actor")
}
if err := vm.Transfer(netact, act, reward); err != nil {
if err := vm.Transfer(rewardActor, act, reward); err != nil {
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 for block %s (miner %s) invocation failed: %w", b.Cid(), b.Miner, err)
}
if ret.ExitCode != 0 {
return cid.Undef, cid.Undef, xerrors.Errorf("submit election post invocation returned nonzero exit code: %d (err = %s, block = %s, miner = %s, tsi = %d)", ret.ExitCode, ret.ActorErr, b.Cid(), b.Miner, tsi)
}
}
// TODO: can't use method from chainstore because it doesnt let us know who the block miners were
@ -259,19 +247,19 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
}
// TODO: this nonce-getting is a tiny bit ugly
ca, err := vmi.StateTree().GetActor(actors.CronAddress)
ca, err := vmi.StateTree().GetActor(builtin.SystemActorAddr)
if err != nil {
return cid.Undef, cid.Undef, err
}
ret, err := vmi.ApplyMessage(ctx, &types.Message{
To: actors.CronAddress,
From: actors.CronAddress,
To: builtin.CronActorAddr,
From: builtin.SystemActorAddr,
Nonce: ca.Nonce,
Value: types.NewInt(0),
GasPrice: types.NewInt(0),
GasLimit: types.NewInt(1 << 30), // Make super sure this is never too little
Method: actors.CAMethods.EpochTick,
Method: builtin.MethodsCron.EpochTick,
Params: nil,
})
if err != nil {
@ -295,15 +283,27 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
return st, rectroot, nil
}
func (sm *StateManager) GetActor(addr address.Address, ts *types.TipSet) (*types.Actor, error) {
func (sm *StateManager) parentState(ts *types.TipSet) cid.Cid {
if ts == nil {
ts = sm.cs.GetHeaviestTipSet()
}
stcid := ts.ParentState()
return ts.ParentState()
}
func (sm *StateManager) GetActor(addr address.Address, ts *types.TipSet) (*types.Actor, error) {
cst := cbor.NewCborStore(sm.cs.Blockstore())
state, err := state.LoadStateTree(cst, stcid)
state, err := state.LoadStateTree(cst, sm.parentState(ts))
if err != nil {
return nil, xerrors.Errorf("load state tree: %w", err)
}
return state.GetActor(addr)
}
func (sm *StateManager) getActorRaw(addr address.Address, st cid.Cid) (*types.Actor, error) {
cst := cbor.NewCborStore(sm.cs.Blockstore())
state, err := state.LoadStateTree(cst, st)
if err != nil {
return nil, xerrors.Errorf("load state tree: %w", err)
}
@ -335,11 +335,30 @@ func (sm *StateManager) LoadActorState(ctx context.Context, a address.Address, o
cst := cbor.NewCborStore(sm.cs.Blockstore())
if err := cst.Get(ctx, act.Head, out); err != nil {
var r cbg.Deferred
cst.Get(ctx, act.Head, &r)
fmt.Printf("badhead %x\n", r.Raw)
return nil, err
}
return act, nil
}
func (sm *StateManager) LoadActorStateRaw(ctx context.Context, a address.Address, out interface{}, st cid.Cid) (*types.Actor, error) {
act, err := sm.getActorRaw(a, st)
if err != nil {
return nil, err
}
cst := cbor.NewCborStore(sm.cs.Blockstore())
if err := cst.Get(ctx, act.Head, out); err != nil {
return nil, err
}
return act, nil
}
func (sm *StateManager) ResolveToKeyAddress(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
switch addr.Protocol() {
case address.BLS, address.SECP256K1:
@ -381,6 +400,15 @@ func (sm *StateManager) GetBlsPublicKey(ctx context.Context, addr address.Addres
return pubk, nil
}
func (sm *StateManager) LookupID(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
cst := cbor.NewCborStore(sm.cs.Blockstore())
state, err := state.LoadStateTree(cst, sm.parentState(ts))
if err != nil {
return address.Undef, xerrors.Errorf("load state tree: %w", err)
}
return state.LookupID(addr)
}
func (sm *StateManager) GetReceipt(ctx context.Context, msg cid.Cid, ts *types.TipSet) (*types.MessageReceipt, error) {
m, err := sm.cs.GetCMessage(msg)
if err != nil {
@ -577,7 +605,7 @@ func (sm *StateManager) ListAllActors(ctx context.Context, ts *types.TipSet) ([]
}
cst := cbor.NewCborStore(sm.cs.Blockstore())
r, err := hamt.LoadNode(ctx, cst, st)
r, err := hamt.LoadNode(ctx, cst, st, hamt.UseTreeBitWidth(5))
if err != nil {
return nil, err
}
@ -598,18 +626,49 @@ func (sm *StateManager) ListAllActors(ctx context.Context, ts *types.TipSet) ([]
return out, nil
}
func (sm *StateManager) MarketBalance(ctx context.Context, addr address.Address, ts *types.TipSet) (actors.StorageParticipantBalance, error) {
var state actors.StorageMarketState
if _, err := sm.LoadActorState(ctx, actors.StorageMarketAddress, &state, ts); err != nil {
return actors.StorageParticipantBalance{}, err
}
cst := cbor.NewCborStore(sm.cs.Blockstore())
b, _, err := actors.GetMarketBalances(ctx, cst, state.Balances, addr)
func (sm *StateManager) MarketBalance(ctx context.Context, addr address.Address, ts *types.TipSet) (api.MarketBalance, error) {
var state market.State
_, err := sm.LoadActorState(ctx, builtin.StorageMarketActorAddr, &state, ts)
if err != nil {
return actors.StorageParticipantBalance{}, err
return api.MarketBalance{}, err
}
return b[0], nil
addr, err = sm.LookupID(ctx, addr, ts)
if err != nil {
return api.MarketBalance{}, err
}
var out api.MarketBalance
et := adt.AsBalanceTable(sm.cs.Store(ctx), state.EscrowTable)
ehas, err := et.Has(addr)
if err != nil {
return api.MarketBalance{}, err
}
if ehas {
out.Escrow, err = et.Get(addr)
if err != nil {
return api.MarketBalance{}, xerrors.Errorf("getting escrow balance: %w", err)
}
} else {
out.Escrow = big.Zero()
}
lt := adt.AsBalanceTable(sm.cs.Store(ctx), state.LockedTable)
lhas, err := lt.Has(addr)
if err != nil {
return api.MarketBalance{}, err
}
if lhas {
out.Locked, err = lt.Get(addr)
if err != nil {
return api.MarketBalance{}, xerrors.Errorf("getting locked balance: %w", err)
}
} else {
out.Locked = big.Zero()
}
return out, nil
}
func (sm *StateManager) ValidateChain(ctx context.Context, ts *types.TipSet) error {
@ -641,6 +700,6 @@ func (sm *StateManager) ValidateChain(ctx context.Context, ts *types.TipSet) err
return nil
}
func (sm *StateManager) SetVMConstructor(nvm func(cid.Cid, uint64, vm.Rand, address.Address, blockstore.Blockstore, *types.VMSyscalls) (*vm.VM, error)) {
func (sm *StateManager) SetVMConstructor(nvm func(cid.Cid, abi.ChainEpoch, vm.Rand, address.Address, blockstore.Blockstore, runtime.Syscalls) (*vm.VM, error)) {
sm.newVM = nvm
}

View File

@ -2,17 +2,27 @@ package stmgr
import (
"context"
"github.com/filecoin-project/lotus/chain/state"
amt "github.com/filecoin-project/go-amt-ipld/v2"
commcid "github.com/filecoin-project/go-fil-commcid"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
ffi "github.com/filecoin-project/filecoin-ffi"
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
ffi "github.com/filecoin-project/filecoin-ffi"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
@ -26,146 +36,83 @@ import (
)
func GetMinerWorkerRaw(ctx context.Context, sm *StateManager, st cid.Cid, maddr address.Address) (address.Address, error) {
recp, err := sm.CallRaw(ctx, &types.Message{
To: maddr,
From: maddr,
Method: actors.MAMethods.GetWorkerAddr,
}, st, nil, 0)
var mas miner.State
_, err := sm.LoadActorStateRaw(ctx, maddr, &mas, st)
if err != nil {
return address.Undef, xerrors.Errorf("callRaw failed: %w", err)
return address.Undef, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
}
if recp.ExitCode != 0 {
return address.Undef, xerrors.Errorf("getting miner worker addr failed (exit code %d)", recp.ExitCode)
}
worker, err := address.NewFromBytes(recp.Return)
cst := cbor.NewCborStore(sm.cs.Blockstore())
state, err := state.LoadStateTree(cst, st)
if err != nil {
return address.Undef, err
return address.Undef, xerrors.Errorf("load state tree: %w", err)
}
if worker.Protocol() == address.ID {
return address.Undef, xerrors.Errorf("need to resolve worker address to a pubkeyaddr")
}
return worker, nil
return vm.ResolveToKeyAddr(state, cst, mas.Info.Worker)
}
func GetMinerOwner(ctx context.Context, sm *StateManager, st cid.Cid, maddr address.Address) (address.Address, error) {
recp, err := sm.CallRaw(ctx, &types.Message{
To: maddr,
From: maddr,
Method: actors.MAMethods.GetOwner,
}, st, nil, 0)
var mas miner.State
_, err := sm.LoadActorStateRaw(ctx, maddr, &mas, st)
if err != nil {
return address.Undef, xerrors.Errorf("callRaw failed: %w", err)
return address.Undef, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
}
if recp.ExitCode != 0 {
return address.Undef, xerrors.Errorf("getting miner owner addr failed (exit code %d)", recp.ExitCode)
}
owner, err := address.NewFromBytes(recp.Return)
cst := cbor.NewCborStore(sm.cs.Blockstore())
state, err := state.LoadStateTree(cst, st)
if err != nil {
return address.Undef, err
return address.Undef, xerrors.Errorf("load state tree: %w", err)
}
if owner.Protocol() == address.ID {
return address.Undef, xerrors.Errorf("need to resolve owner address to a pubkeyaddr")
}
return owner, nil
return vm.ResolveToKeyAddr(state, cst, mas.Info.Owner)
}
func GetPower(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (types.BigInt, types.BigInt, error) {
var err error
var mpow types.BigInt
if maddr != address.Undef {
enc, aerr := actors.SerializeParams(&actors.PowerLookupParams{maddr})
if aerr != nil {
return types.EmptyInt, types.EmptyInt, aerr
}
ret, err := sm.Call(ctx, &types.Message{
From: maddr,
To: actors.StoragePowerAddress,
Method: actors.SPAMethods.PowerLookup,
Params: enc,
}, ts)
if err != nil {
return types.EmptyInt, types.EmptyInt, xerrors.Errorf("failed to get miner power from chain: %w", err)
}
if ret.ExitCode != 0 {
return types.EmptyInt, types.EmptyInt, xerrors.Errorf("failed to get miner power from chain (exit code %d)", ret.ExitCode)
}
mpow = types.BigFromBytes(ret.Return)
}
ret, err := sm.Call(ctx, &types.Message{
From: actors.StoragePowerAddress,
To: actors.StoragePowerAddress,
Method: actors.SPAMethods.GetTotalStorage,
}, ts)
var ps power.State
_, err := sm.LoadActorState(ctx, builtin.StoragePowerActorAddr, &ps, ts)
if err != nil {
return types.EmptyInt, types.EmptyInt, xerrors.Errorf("failed to get total power from chain: %w", err)
}
if ret.ExitCode != 0 {
return types.EmptyInt, types.EmptyInt, xerrors.Errorf("failed to get total power from chain (exit code %d)", ret.ExitCode)
return big.Zero(), big.Zero(), xerrors.Errorf("(get sset) failed to load power actor state: %w", err)
}
tpow := types.BigFromBytes(ret.Return)
var mpow big.Int
if maddr != address.Undef {
var claim power.Claim
if _, err := adt.AsMap(sm.cs.Store(ctx), ps.Claims).Get(adt.AddrKey(maddr), &claim); err != nil {
return big.Zero(), big.Zero(), err
}
return mpow, tpow, nil
mpow = claim.Power
}
return mpow, ps.TotalNetworkPower, nil
}
func GetMinerPeerID(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (peer.ID, error) {
recp, err := sm.Call(ctx, &types.Message{
To: maddr,
From: maddr,
Method: actors.MAMethods.GetPeerID,
}, ts)
var mas miner.State
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil {
return "", xerrors.Errorf("call failed: %w", err)
return "", xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
}
if recp.ExitCode != 0 {
return "", xerrors.Errorf("getting miner peer ID failed (exit code %d)", recp.ExitCode)
}
return peer.IDFromBytes(recp.Return)
return mas.Info.PeerId, nil
}
func GetMinerWorker(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (address.Address, error) {
recp, err := sm.Call(ctx, &types.Message{
To: maddr,
From: maddr,
Method: actors.MAMethods.GetWorkerAddr,
}, ts)
if err != nil {
return address.Undef, xerrors.Errorf("call failed: %w", err)
}
if recp.ExitCode != 0 {
return address.Undef, xerrors.Errorf("getting miner peer ID failed (exit code %d)", recp.ExitCode)
}
return address.NewFromBytes(recp.Return)
return GetMinerWorkerRaw(ctx, sm, sm.parentState(ts), maddr)
}
func GetMinerElectionPeriodStart(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (uint64, error) {
var mas actors.StorageMinerActorState
func GetMinerPostState(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (*miner.PoStState, error) {
var mas miner.State
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil {
return 0, xerrors.Errorf("(get eps) failed to load miner actor state: %w", err)
return nil, xerrors.Errorf("(get eps) failed to load miner actor state: %w", err)
}
return mas.ElectionPeriodStart, nil
return &mas.PoStState, nil
}
func SectorSetSizes(ctx context.Context, sm *StateManager, maddr address.Address, ts *types.TipSet) (api.MinerSectors, error) {
var mas actors.StorageMinerActorState
var mas miner.State
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil {
return api.MinerSectors{}, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
@ -189,7 +136,7 @@ func SectorSetSizes(ctx context.Context, sm *StateManager, maddr address.Address
}
func GetMinerProvingSet(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) ([]*api.ChainSectorInfo, error) {
var mas actors.StorageMinerActorState
var mas miner.State
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil {
return nil, xerrors.Errorf("(get pset) failed to load miner actor state: %w", err)
@ -199,7 +146,7 @@ func GetMinerProvingSet(ctx context.Context, sm *StateManager, ts *types.TipSet,
}
func GetMinerSectorSet(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) ([]*api.ChainSectorInfo, error) {
var mas actors.StorageMinerActorState
var mas miner.State
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil {
return nil, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
@ -216,11 +163,15 @@ func GetSectorsForElectionPost(ctx context.Context, sm *StateManager, ts *types.
var uselessOtherArray []ffi.PublicSectorInfo
for _, s := range sectors {
cr, err := commcid.CIDToReplicaCommitmentV1(s.Info.Info.SealedCID)
if err != nil {
return nil, err
}
var uselessBuffer [32]byte
copy(uselessBuffer[:], s.CommR)
copy(uselessBuffer[:], cr)
uselessOtherArray = append(uselessOtherArray, ffi.PublicSectorInfo{
SectorID: s.SectorID,
CommR: uselessBuffer,
SectorNum: s.ID,
CommR: uselessBuffer,
})
}
@ -228,34 +179,23 @@ func GetSectorsForElectionPost(ctx context.Context, sm *StateManager, ts *types.
return &ssi, nil
}
func GetMinerSectorSize(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (uint64, error) {
var mas actors.StorageMinerActorState
func GetMinerSectorSize(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (abi.SectorSize, error) {
var mas miner.State
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil {
return 0, xerrors.Errorf("(get ssize) failed to load miner actor state: %w", err)
}
cst := cbor.NewCborStore(sm.cs.Blockstore())
var minfo actors.MinerInfo
if err := cst.Get(ctx, mas.Info, &minfo); err != nil {
return 0, xerrors.Errorf("failed to read miner info: %w", err)
}
return minfo.SectorSize, nil
return mas.Info.SectorSize, nil
}
func GetMinerSlashed(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("(get mslash) failed to load miner actor state: %w", err)
}
return mas.SlashedAt, nil
log.Warn("stub GetMinerSlashed")
return 0, nil
}
func GetMinerFaults(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) ([]uint64, error) {
var mas actors.StorageMinerActorState
func GetMinerFaults(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) ([]abi.SectorNumber, error) {
var mas miner.State
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil {
return nil, xerrors.Errorf("(get ssize) failed to load miner actor state: %w", err)
@ -266,36 +206,62 @@ func GetMinerFaults(ctx context.Context, sm *StateManager, ts *types.TipSet, mad
return nil, aerrors.HandleExternalError(lerr, "could not load proving set node")
}
return mas.FaultSet.All(2 * ss.Count)
faults, err := mas.FaultSet.All(2 * ss.Count)
if err != nil {
return nil, xerrors.Errorf("reading fault bit set: %w", err)
}
out := make([]abi.SectorNumber, len(faults))
for i, fault := range faults {
out[i] = abi.SectorNumber(fault)
}
return out, nil
}
func GetStorageDeal(ctx context.Context, sm *StateManager, dealId uint64, ts *types.TipSet) (*actors.OnChainDeal, error) {
var state actors.StorageMarketState
if _, err := sm.LoadActorState(ctx, actors.StorageMarketAddress, &state, ts); err != nil {
func GetStorageDeal(ctx context.Context, sm *StateManager, dealId abi.DealID, ts *types.TipSet) (*api.MarketDeal, error) {
var state market.State
if _, err := sm.LoadActorState(ctx, builtin.StorageMarketActorAddr, &state, ts); err != nil {
return nil, err
}
da, err := amt.LoadAMT(ctx, cbor.NewCborStore(sm.ChainStore().Blockstore()), state.Deals)
da, err := amt.LoadAMT(ctx, cbor.NewCborStore(sm.ChainStore().Blockstore()), state.Proposals)
if err != nil {
return nil, err
}
var ocd actors.OnChainDeal
if err := da.Get(ctx, dealId, &ocd); err != nil {
var dp market.DealProposal
if err := da.Get(ctx, uint64(dealId), &dp); err != nil {
return nil, err
}
return &ocd, nil
sa := market.AsDealStateArray(sm.ChainStore().Store(ctx), state.States)
st, err := sa.Get(dealId)
if err != nil {
return nil, err
}
return &api.MarketDeal{
Proposal: dp,
State: *st,
}, nil
}
func ListMinerActors(ctx context.Context, sm *StateManager, ts *types.TipSet) ([]address.Address, error) {
var state actors.StoragePowerState
if _, err := sm.LoadActorState(ctx, actors.StoragePowerAddress, &state, ts); err != nil {
var state power.State
if _, err := sm.LoadActorState(ctx, builtin.StoragePowerActorAddr, &state, ts); err != nil {
return nil, err
}
cst := cbor.NewCborStore(sm.ChainStore().Blockstore())
miners, err := actors.MinerSetList(ctx, cst, state.Miners)
var miners []address.Address
err := adt.AsMap(sm.cs.Store(ctx), state.Claims).ForEach(nil, func(k string) error {
a, err := address.NewFromBytes([]byte(k))
if err != nil {
return err
}
miners = append(miners, a)
return nil
})
if err != nil {
return nil, err
}
@ -311,14 +277,13 @@ func LoadSectorsFromSet(ctx context.Context, bs blockstore.Blockstore, ssc cid.C
var sset []*api.ChainSectorInfo
if err := a.ForEach(ctx, func(i uint64, v *cbg.Deferred) error {
var comms [][]byte
if err := cbor.DecodeInto(v.Raw, &comms); err != nil {
var oci miner.SectorOnChainInfo
if err := cbor.DecodeInto(v.Raw, &oci); err != nil {
return err
}
sset = append(sset, &api.ChainSectorInfo{
SectorID: i,
CommR: comms[0],
CommD: comms[1],
Info: oci,
ID: abi.SectorNumber(i),
})
return nil
}); err != nil {
@ -328,7 +293,7 @@ func LoadSectorsFromSet(ctx context.Context, bs blockstore.Blockstore, ssc cid.C
return sset, nil
}
func ComputeState(ctx context.Context, sm *StateManager, height uint64, msgs []*types.Message, ts *types.TipSet) (cid.Cid, error) {
func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch, msgs []*types.Message, ts *types.TipSet) (cid.Cid, error) {
if ts == nil {
ts = sm.cs.GetHeaviestTipSet()
}
@ -344,7 +309,7 @@ func ComputeState(ctx context.Context, sm *StateManager, height uint64, msgs []*
}
r := store.NewChainRand(sm.cs, ts.Cids(), height)
vmi, err := vm.NewVM(fstate, height, r, actors.NetworkAddress, sm.cs.Blockstore(), sm.cs.VMSys())
vmi, err := vm.NewVM(fstate, height, r, builtin.SystemActorAddr, sm.cs.Blockstore(), sm.cs.VMSys())
if err != nil {
return cid.Undef, err
}

View File

@ -3,20 +3,26 @@ package store
import (
"bytes"
"context"
"crypto/sha256"
"encoding/binary"
"encoding/json"
"github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/minio/blake2b-simd"
"io"
"sync"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"go.opencensus.io/trace"
"go.uber.org/multierr"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/vm"
amt "github.com/filecoin-project/go-amt-ipld/v2"
"github.com/filecoin-project/lotus/chain/types"
lru "github.com/hashicorp/golang-lru"
@ -51,7 +57,7 @@ type ChainStore struct {
pubLk sync.Mutex
tstLk sync.Mutex
tipsets map[uint64][]cid.Cid
tipsets map[abi.ChainEpoch][]cid.Cid
reorgCh chan<- reorg
headChangeNotifs []func(rev, app []*types.TipSet) error
@ -59,17 +65,17 @@ type ChainStore struct {
mmCache *lru.ARCCache
tsCache *lru.ARCCache
vmcalls *types.VMSyscalls
vmcalls runtime.Syscalls
}
func NewChainStore(bs bstore.Blockstore, ds dstore.Batching, vmcalls *types.VMSyscalls) *ChainStore {
func NewChainStore(bs bstore.Blockstore, ds dstore.Batching, vmcalls runtime.Syscalls) *ChainStore {
c, _ := lru.NewARC(2048)
tsc, _ := lru.NewARC(4096)
cs := &ChainStore{
bs: bs,
ds: ds,
bestTips: pubsub.New(64),
tipsets: make(map[uint64][]cid.Cid),
tipsets: make(map[abi.ChainEpoch][]cid.Cid),
mmCache: c,
tsCache: tsc,
vmcalls: vmcalls,
@ -829,7 +835,35 @@ func (cs *ChainStore) Blockstore() bstore.Blockstore {
return cs.bs
}
func (cs *ChainStore) VMSys() *types.VMSyscalls {
func ActorStore(ctx context.Context, bs blockstore.Blockstore) adt.Store {
return &astore{
cst: cbor.NewCborStore(bs),
ctx: ctx,
}
}
type astore struct {
cst cbor.IpldStore
ctx context.Context
}
func (a *astore) Context() context.Context {
return a.ctx
}
func (a *astore) Get(ctx context.Context, c cid.Cid, out interface{}) error {
return a.cst.Get(ctx, c, out)
}
func (a *astore) Put(ctx context.Context, v interface{}) (cid.Cid, error) {
return a.cst.Put(ctx, v)
}
func (cs *ChainStore) Store(ctx context.Context) adt.Store {
return ActorStore(ctx, cs.bs)
}
func (cs *ChainStore) VMSys() runtime.Syscalls {
return cs.vmcalls
}
@ -855,22 +889,30 @@ func (cs *ChainStore) TryFillTipSet(ts *types.TipSet) (*FullTipSet, error) {
return NewFullTipSet(out), nil
}
func drawRandomness(t *types.Ticket, round int64) []byte {
h := sha256.New()
var buf [8]byte
binary.LittleEndian.PutUint64(buf[:], uint64(round))
func drawRandomness(t *types.Ticket, pers crypto.DomainSeparationTag, round int64, entropy []byte) ([]byte, error) {
// TODO: Make this spec compliant
h := blake2b.New256()
if err := binary.Write(h, binary.BigEndian, int64(pers)); err != nil {
return nil, xerrors.Errorf("deriving randomness: %w", err)
}
h.Write(t.VRFProof)
h.Write(buf[:])
if err := binary.Write(h, binary.BigEndian, round); err != nil {
return nil, xerrors.Errorf("deriving randomness: %w", err)
}
h.Write(entropy)
return h.Sum(nil)
return h.Sum(nil), nil
}
func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, round int64) ([]byte, error) {
func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, pers crypto.DomainSeparationTag, round int64, entropy []byte) (out []byte, err error) {
_, span := trace.StartSpan(ctx, "store.GetRandomness")
defer span.End()
span.AddAttributes(trace.Int64Attribute("round", round))
defer func() {
log.Infof("getRand %v %d %d %x -> %x", blks, pers, round, entropy, out)
}()
for {
nts, err := cs.LoadTipSet(types.NewTipSetKey(blks...))
if err != nil {
@ -880,7 +922,7 @@ func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, round i
mtb := nts.MinTicketBlock()
if int64(nts.Height()) <= round {
return drawRandomness(nts.MinTicketBlock().Ticket, round), nil
return drawRandomness(nts.MinTicketBlock().Ticket, pers, round, entropy)
}
// special case for lookback behind genesis block
@ -888,10 +930,13 @@ func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, round i
if mtb.Height == 0 {
// round is negative
thash := drawRandomness(mtb.Ticket, round*-1)
thash, err := drawRandomness(mtb.Ticket, pers, round*-1, entropy)
if err != nil {
return nil, err
}
// for negative lookbacks, just use the hash of the positive tickethash value
h := sha256.Sum256(thash)
h := blake2b.Sum256(thash)
return h[:], nil
}
@ -899,7 +944,7 @@ func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, round i
}
}
func (cs *ChainStore) GetTipsetByHeight(ctx context.Context, h uint64, ts *types.TipSet) (*types.TipSet, error) {
func (cs *ChainStore) GetTipsetByHeight(ctx context.Context, h abi.ChainEpoch, ts *types.TipSet) (*types.TipSet, error) {
if ts == nil {
ts = cs.GetHeaviestTipSet()
}
@ -1007,10 +1052,10 @@ func (cs *ChainStore) Import(r io.Reader) (*types.TipSet, error) {
type chainRand struct {
cs *ChainStore
blks []cid.Cid
bh uint64
bh abi.ChainEpoch
}
func NewChainRand(cs *ChainStore, blks []cid.Cid, bheight uint64) vm.Rand {
func NewChainRand(cs *ChainStore, blks []cid.Cid, bheight abi.ChainEpoch) vm.Rand {
return &chainRand{
cs: cs,
blks: blks,
@ -1018,8 +1063,8 @@ func NewChainRand(cs *ChainStore, blks []cid.Cid, bheight uint64) vm.Rand {
}
}
func (cr *chainRand) GetRandomness(ctx context.Context, round int64) ([]byte, error) {
return cr.cs.GetRandomness(ctx, cr.blks, round)
func (cr *chainRand) GetRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round int64, entropy []byte) ([]byte, error) {
return cr.cs.GetRandomness(ctx, cr.blks, pers, round, entropy)
}
func (cs *ChainStore) GetTipSetFromKey(tsk types.TipSetKey) (*types.TipSet, error) {

View File

@ -9,11 +9,12 @@ import (
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/repo"
"github.com/filecoin-project/specs-actors/actors/abi"
blockstore "github.com/ipfs/go-ipfs-blockstore"
)
func init() {
build.SectorSizes = []uint64{1024}
build.SectorSizes = []abi.SectorSize{1024}
build.MinimumMinerPower = 1024
}

View File

@ -5,9 +5,13 @@ import (
"math/big"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
big2 "github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
cbor "github.com/ipfs/go-ipld-cbor"
"golang.org/x/xerrors"
)
@ -23,19 +27,27 @@ func (cs *ChainStore) Weight(ctx context.Context, ts *types.TipSet) (types.BigIn
// >>> wFunction(totalPowerAtTipset(ts)) * 2^8 <<< + (wFunction(totalPowerAtTipset(ts)) * len(ts.blocks) * wRatio_num * 2^8) / (e * wRatio_den)
ret, err := cs.call(ctx, &types.Message{
From: actors.StoragePowerAddress,
To: actors.StoragePowerAddress,
Method: actors.SPAMethods.GetTotalStorage,
}, ts)
if err != nil {
return types.EmptyInt, xerrors.Errorf("failed to get total power from chain: %w", err)
}
if ret.ExitCode != 0 {
return types.EmptyInt, xerrors.Errorf("failed to get total power from chain (exit code %d)", ret.ExitCode)
tpow := big2.Zero()
{
cst := cbor.NewCborStore(cs.Blockstore())
state, err := state.LoadStateTree(cst, ts.ParentState())
if err != nil {
return types.NewInt(0), xerrors.Errorf("load state tree: %w", err)
}
act, err := state.GetActor(builtin.StoragePowerActorAddr)
if err != nil {
return types.NewInt(0), xerrors.Errorf("get power actor: %w", err)
}
var st power.State
if err := cst.Get(ctx, act.Head, &st); err != nil {
return types.NewInt(0), xerrors.Errorf("get power actor head: %w", err)
}
tpow = st.TotalNetworkPower
}
log2P := int64(0)
tpow := types.BigFromBytes(ret.Return)
if tpow.GreaterThan(zero) {
log2P = int64(tpow.BitLen() - 1)
} else {
@ -60,7 +72,7 @@ func (cs *ChainStore) call(ctx context.Context, msg *types.Message, ts *types.Ti
r := NewChainRand(cs, ts.Cids(), ts.Height())
vmi, err := vm.NewVM(bstate, ts.Height(), r, actors.NetworkAddress, cs.bs, cs.vmcalls)
vmi, err := vm.NewVM(bstate, ts.Height(), r, builtin.SystemActorAddr, cs.bs, cs.vmcalls)
if err != nil {
return nil, xerrors.Errorf("failed to set up vm: %w", err)
}

View File

@ -1,18 +1,20 @@
package chain
import (
"bytes"
"context"
"crypto/sha256"
"errors"
"fmt"
"github.com/filecoin-project/specs-actors/actors/builtin"
"sync"
"time"
"github.com/Gurpartap/async"
bls "github.com/filecoin-project/filecoin-ffi"
amt "github.com/filecoin-project/go-amt-ipld/v2"
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/hashicorp/go-multierror"
"github.com/ipfs/go-cid"
dstore "github.com/ipfs/go-datastore"
@ -26,11 +28,12 @@ import (
"go.opencensus.io/trace"
"golang.org/x/xerrors"
bls "github.com/filecoin-project/filecoin-ffi"
"github.com/filecoin-project/go-address"
"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/blocksync"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/state"
@ -464,30 +467,21 @@ func (syncer *Syncer) ValidateTipSet(ctx context.Context, fts *store.FullTipSet)
}
func (syncer *Syncer) minerIsValid(ctx context.Context, maddr address.Address, baseTs *types.TipSet) error {
var err error
enc, err := actors.SerializeParams(&actors.IsValidMinerParam{Addr: maddr})
var spast power.State
_, err := syncer.sm.LoadActorState(ctx, builtin.StoragePowerActorAddr, &spast, baseTs)
if err != nil {
return err
}
ret, err := syncer.sm.Call(ctx, &types.Message{
To: actors.StoragePowerAddress,
From: maddr,
Method: actors.SPAMethods.IsValidMiner,
Params: enc,
}, baseTs)
var claim power.Claim
exist, err := adt.AsMap(syncer.store.Store(ctx), spast.Claims).Get(adt.AddrKey(maddr), &claim)
if err != nil {
return xerrors.Errorf("checking if block miner is valid failed: %w", err)
return err
}
if ret.ExitCode != 0 {
return xerrors.Errorf("StorageMarket.IsValidMiner check failed (exit code %d)", ret.ExitCode)
}
if !bytes.Equal(ret.Return, cbg.CborBoolTrue) {
if !exist {
return xerrors.New("miner isn't valid")
}
return nil
}
@ -520,9 +514,11 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
log.Warn("Got block from the future, but within threshold", h.Timestamp, time.Now().Unix())
}
if h.Timestamp < baseTs.MinTimestamp()+(build.BlockDelay*(h.Height-baseTs.Height())) {
if h.Timestamp < baseTs.MinTimestamp()+(build.BlockDelay*uint64(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())
diff := (baseTs.MinTimestamp() + (build.BlockDelay * uint64(h.Height-baseTs.Height()))) - h.Timestamp
return xerrors.Errorf("block was generated too soon (h.ts:%d < base.mints:%d + BLOCK_DELAY:%d * deltaH:%d; diff %d)", h.Timestamp, baseTs.MinTimestamp(), build.BlockDelay, h.Height-baseTs.Height(), diff)
}
winnerCheck := async.Err(func() error {
@ -545,7 +541,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
return xerrors.Errorf("failed to get sector size for block miner: %w", err)
}
snum := types.BigDiv(mpow, types.NewInt(ssize))
snum := types.BigDiv(mpow, types.NewInt(uint64(ssize)))
if len(h.EPostProof.Candidates) == 0 {
return xerrors.Errorf("no candidates")
@ -617,10 +613,12 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
})
tktsCheck := async.Err(func() error {
vrfBase := baseTs.MinTicket().VRFProof
err := gen.VerifyVRF(ctx, waddr, h.Miner, gen.DSepTicket, vrfBase, h.Ticket.VRFProof)
vrfBase, err := syncer.sm.ChainStore().GetRandomness(ctx, baseTs.Cids(), crypto.DomainSeparationTag_TicketProduction, int64(baseTs.Height()), h.Miner.Bytes())
if err != nil {
return xerrors.Errorf("failed to get randomness for verifying election proof: %w", err)
}
err = gen.VerifyVRF(ctx, waddr, vrfBase, h.Ticket.VRFProof)
if err != nil {
return xerrors.Errorf("validating block tickets failed: %w", err)
}
@ -654,12 +652,12 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
}
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))
rand, err := syncer.sm.ChainStore().GetRandomness(ctx, baseTs.Cids(), crypto.DomainSeparationTag_ElectionPoStChallengeSeed, int64(h.Height-build.EcRandomnessLookback), h.Miner.Bytes())
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 {
if err := VerifyElectionPoStVRF(ctx, h.EPostProof.PostRand, rand, waddr); err != nil {
return xerrors.Errorf("checking eproof failed: %w", err)
}
@ -674,7 +672,7 @@ func (syncer *Syncer) VerifyElectionPoStProof(ctx context.Context, h *types.Bloc
copy(partial[:], t.Partial)
winners = append(winners, sectorbuilder.EPostCandidate{
PartialTicket: partial,
SectorID: t.SectorID,
SectorNum: t.SectorID,
SectorChallengeIndex: t.ChallengeIndex,
})
}
@ -825,7 +823,7 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock
return nil
}
func (syncer *Syncer) verifyBlsAggregate(ctx context.Context, sig types.Signature, msgs []cid.Cid, pubks []bls.PublicKey) error {
func (syncer *Syncer) verifyBlsAggregate(ctx context.Context, sig crypto.Signature, msgs []cid.Cid, pubks []bls.PublicKey) error {
_, span := trace.StartSpan(ctx, "syncer.verifyBlsAggregate")
defer span.End()
span.AddAttributes(
@ -1119,8 +1117,8 @@ func persistMessages(bs bstore.Blockstore, bst *blocksync.BSTipSet) error {
}
}
for _, m := range bst.SecpkMessages {
if m.Signature.Type != types.KTSecp256k1 {
return xerrors.Errorf("unknown signature type on message %s: %q", m.Cid(), m.Signature.TypeCode)
if m.Signature.Type != crypto.SigTypeSecp256k1 {
return xerrors.Errorf("unknown signature type on message %s: %q", m.Cid(), m.Signature.Type)
}
//log.Infof("putting secp256k1 message: %s", m.Cid())
if _, err := store.PutMessage(bs, m); err != nil {
@ -1178,8 +1176,8 @@ func (syncer *Syncer) collectChain(ctx context.Context, ts *types.TipSet) error
return nil
}
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 {
func VerifyElectionPoStVRF(ctx context.Context, evrf []byte, rand []byte, worker address.Address) error {
if err := gen.VerifyVRF(ctx, worker, rand, evrf); err != nil {
return xerrors.Errorf("failed to verify post_randomness vrf: %w", err)
}

View File

@ -7,6 +7,7 @@ import (
"testing"
"time"
"github.com/filecoin-project/specs-actors/actors/abi"
logging "github.com/ipfs/go-log/v2"
"github.com/libp2p/go-libp2p-core/peer"
mocknet "github.com/libp2p/go-libp2p/p2p/net/mock"
@ -27,7 +28,7 @@ import (
func init() {
build.InsecurePoStValidation = true
os.Setenv("TRUST_PARAMS", "1")
build.SectorSizes = []uint64{1024}
build.SectorSizes = []abi.SectorSize{1024}
build.MinimumMinerPower = 1024
}
@ -158,7 +159,6 @@ func (tu *syncTestUtil) pushTsExpectErr(to int, fts *store.FullTipSet, experr bo
require.NoError(tu.t, err)
}
}
}
func (tu *syncTestUtil) mineOnBlock(blk *store.FullTipSet, src int, miners []int, wait, fail bool) *store.FullTipSet {
@ -398,7 +398,7 @@ func TestSyncBadTimestamp(t *testing.T) {
tu.waitUntilSync(0, client)
base := tu.g.CurTipset
tu.g.Timestamper = func(pts *types.TipSet, tl uint64) uint64 {
tu.g.Timestamper = func(pts *types.TipSet, tl abi.ChainEpoch) uint64 {
return pts.MinTimestamp() + (build.BlockDelay / 2)
}

View File

@ -5,6 +5,8 @@ import (
"sync"
"time"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/types"
)
@ -31,7 +33,7 @@ type SyncerState struct {
Target *types.TipSet
Base *types.TipSet
Stage api.SyncStateStage
Height uint64
Height abi.ChainEpoch
Message string
Start time.Time
End time.Time
@ -66,7 +68,7 @@ func (ss *SyncerState) Init(base, target *types.TipSet) {
ss.End = time.Time{}
}
func (ss *SyncerState) SetHeight(h uint64) {
func (ss *SyncerState) SetHeight(h abi.ChainEpoch) {
if ss == nil {
return
}

View File

@ -1,12 +1,12 @@
package types
import (
"fmt"
"github.com/ipfs/go-cid"
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
)
var ErrActorNotFound = fmt.Errorf("actor not found")
var ErrActorNotFound = init_.ErrAddressNotFound
type Actor struct {
Code cid.Cid

View File

@ -1,27 +0,0 @@
package types
import (
"github.com/filecoin-project/go-address"
cbor "github.com/ipfs/go-ipld-cbor"
)
func init() {
cbor.RegisterCborType(SignedStorageAsk{})
cbor.RegisterCborType(StorageAsk{})
}
type SignedStorageAsk struct {
Ask *StorageAsk
Signature *Signature
}
type StorageAsk struct {
// Price per GiB / Epoch
Price BigInt
MinPieceSize uint64
Miner address.Address
Timestamp uint64
Expiry uint64
SeqNo uint64
}

View File

@ -1,41 +1,21 @@
package types
import (
"encoding/json"
"fmt"
"io"
"math/big"
"github.com/filecoin-project/lotus/build"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/polydawn/refmt/obj/atlas"
big2 "github.com/filecoin-project/specs-actors/actors/abi/big"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/build"
)
const BigIntMaxSerializedLen = 128 // is this big enough? or too big?
var TotalFilecoinInt = FromFil(build.TotalFilecoin)
func init() {
cbor.RegisterCborType(atlas.BuildEntry(BigInt{}).Transform().
TransformMarshal(atlas.MakeMarshalTransformFunc(
func(i BigInt) ([]byte, error) {
return i.cborBytes(), nil
})).
TransformUnmarshal(atlas.MakeUnmarshalTransformFunc(
func(x []byte) (BigInt, error) {
return fromCborBytes(x)
})).
Complete())
}
var EmptyInt = BigInt{}
type BigInt struct {
*big.Int
}
type BigInt = big2.Int
func NewInt(i uint64) BigInt {
return BigInt{big.NewInt(0).SetUint64(i)}
@ -83,50 +63,9 @@ func BigCmp(a, b BigInt) int {
return a.Int.Cmp(b.Int)
}
func (bi BigInt) Nil() bool {
return bi.Int == nil
}
// LessThan returns true if bi < o
func (bi BigInt) LessThan(o BigInt) bool {
return BigCmp(bi, o) < 0
}
// GreaterThan returns true if bi > o
func (bi BigInt) GreaterThan(o BigInt) bool {
return BigCmp(bi, o) > 0
}
// Equals returns true if bi == o
func (bi BigInt) Equals(o BigInt) bool {
return BigCmp(bi, o) == 0
}
func (bi *BigInt) MarshalJSON() ([]byte, error) {
return json.Marshal(bi.String())
}
func (bi *BigInt) UnmarshalJSON(b []byte) error {
var s string
if err := json.Unmarshal(b, &s); err != nil {
return err
}
i, ok := big.NewInt(0).SetString(s, 10)
if !ok {
if string(s) == "<nil>" {
return nil
}
return xerrors.Errorf("failed to parse bigint string: '%s'", string(b))
}
bi.Int = i
return nil
}
var sizeUnits = []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB"}
func (bi BigInt) SizeStr() string {
func SizeStr(bi BigInt) string {
r := new(big.Rat).SetInt(bi.Int)
den := big.NewRat(1, 1024)
@ -139,121 +78,3 @@ func (bi BigInt) SizeStr() string {
f, _ := r.Float64()
return fmt.Sprintf("%.3g %s", f, sizeUnits[i])
}
func (bi *BigInt) Scan(value interface{}) error {
switch value := value.(type) {
case string:
i, ok := big.NewInt(0).SetString(value, 10)
if !ok {
if value == "<nil>" {
return nil
}
return xerrors.Errorf("failed to parse bigint string: '%s'", value)
}
bi.Int = i
return nil
case int64:
bi.Int = big.NewInt(value)
return nil
default:
return xerrors.Errorf("non-string types unsupported: %T", value)
}
}
func (bi *BigInt) cborBytes() []byte {
if bi.Int == nil {
return []byte{}
}
switch {
case bi.Sign() > 0:
return append([]byte{0}, bi.Bytes()...)
case bi.Sign() < 0:
return append([]byte{1}, bi.Bytes()...)
default: // bi.Sign() == 0:
return []byte{}
}
}
func fromCborBytes(buf []byte) (BigInt, error) {
if len(buf) == 0 {
return NewInt(0), nil
}
var negative bool
switch buf[0] {
case 0:
negative = false
case 1:
negative = true
default:
return EmptyInt, fmt.Errorf("big int prefix should be either 0 or 1, got %d", buf[0])
}
i := big.NewInt(0).SetBytes(buf[1:])
if negative {
i.Neg(i)
}
return BigInt{i}, nil
}
func (bi *BigInt) MarshalCBOR(w io.Writer) error {
if bi.Int == nil {
zero := NewInt(0)
return zero.MarshalCBOR(w)
}
enc := bi.cborBytes()
header := cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(enc)))
if _, err := w.Write(header); err != nil {
return err
}
if _, err := w.Write(enc); err != nil {
return err
}
return nil
}
func (bi *BigInt) UnmarshalCBOR(br io.Reader) error {
maj, extra, err := cbg.CborReadHeader(br)
if err != nil {
return err
}
if maj != cbg.MajByteString {
return fmt.Errorf("cbor input for fil big int was not a byte string (%x)", maj)
}
if extra == 0 {
bi.Int = big.NewInt(0)
return nil
}
if extra > BigIntMaxSerializedLen {
return fmt.Errorf("big integer byte array too long")
}
buf := make([]byte, extra)
if _, err := io.ReadFull(br, buf); err != nil {
return err
}
i, err := fromCborBytes(buf)
if err != nil {
return err
}
*bi = i
return nil
}
func (bi *BigInt) IsZero() bool {
return bi.Int.Sign() == 0
}

View File

@ -67,7 +67,7 @@ func TestSizeStr(t *testing.T) {
}
for _, c := range cases {
assert.Equal(t, c.out, NewInt(c.in).SizeStr(), "input %+v, produced wrong result", c)
assert.Equal(t, c.out, SizeStr(NewInt(c.in)), "input %+v, produced wrong result", c)
}
}
@ -75,6 +75,6 @@ func TestSizeStrBig(t *testing.T) {
ZiB := big.NewInt(50000)
ZiB = ZiB.Lsh(ZiB, 70)
assert.Equal(t, "5e+04 ZiB", BigInt{Int: ZiB}.SizeStr(), "inout %+v, produced wrong result", ZiB)
assert.Equal(t, "5e+04 ZiB", SizeStr(BigInt{Int: ZiB}), "inout %+v, produced wrong result", ZiB)
}

View File

@ -1,226 +0,0 @@
package types
import (
"errors"
"fmt"
"io"
rlepluslazy "github.com/filecoin-project/lotus/lib/rlepluslazy"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
)
var ErrBitFieldTooMany = errors.New("to many items in RLE")
type BitField struct {
rle rlepluslazy.RLE
bits map[uint64]struct{}
}
func NewBitField() BitField {
bf, err := NewBitFieldFromBytes([]byte{})
if err != nil {
panic(fmt.Sprintf("creating empty rle: %+v", err))
}
return bf
}
func NewBitFieldFromBytes(rle []byte) (BitField, error) {
bf := BitField{}
rlep, err := rlepluslazy.FromBuf(rle)
if err != nil {
return BitField{}, xerrors.Errorf("could not decode rle+: %w", err)
}
bf.rle = rlep
bf.bits = make(map[uint64]struct{})
return bf, nil
}
func BitFieldFromSet(setBits []uint64) BitField {
res := BitField{bits: make(map[uint64]struct{})}
for _, b := range setBits {
res.bits[b] = struct{}{}
}
return res
}
func MergeBitFields(a, b BitField) (BitField, error) {
ra, err := a.rle.RunIterator()
if err != nil {
return BitField{}, err
}
rb, err := b.rle.RunIterator()
if err != nil {
return BitField{}, err
}
merge, err := rlepluslazy.Sum(ra, rb)
if err != nil {
return BitField{}, err
}
mergebytes, err := rlepluslazy.EncodeRuns(merge, nil)
if err != nil {
return BitField{}, err
}
rle, err := rlepluslazy.FromBuf(mergebytes)
if err != nil {
return BitField{}, err
}
return BitField{
rle: rle,
bits: make(map[uint64]struct{}),
}, nil
}
func (bf BitField) sum() (rlepluslazy.RunIterator, error) {
if len(bf.bits) == 0 {
return bf.rle.RunIterator()
}
a, err := bf.rle.RunIterator()
if err != nil {
return nil, err
}
slc := make([]uint64, 0, len(bf.bits))
for b := range bf.bits {
slc = append(slc, b)
}
b, err := rlepluslazy.RunsFromSlice(slc)
if err != nil {
return nil, err
}
res, err := rlepluslazy.Sum(a, b)
if err != nil {
return nil, err
}
return res, nil
}
// Set ...s bit in the BitField
func (bf BitField) Set(bit uint64) {
bf.bits[bit] = struct{}{}
}
func (bf BitField) Count() (uint64, error) {
s, err := bf.sum()
if err != nil {
return 0, err
}
return rlepluslazy.Count(s)
}
// All returns all set bits
func (bf BitField) All(max uint64) ([]uint64, error) {
c, err := bf.Count()
if err != nil {
return nil, xerrors.Errorf("count errror: %w", err)
}
if c > max {
return nil, xerrors.Errorf("expected %d, got %d: %w", max, c, ErrBitFieldTooMany)
}
runs, err := bf.sum()
if err != nil {
return nil, err
}
res, err := rlepluslazy.SliceFromRuns(runs)
if err != nil {
return nil, err
}
return res, nil
}
func (bf BitField) AllMap(max uint64) (map[uint64]bool, error) {
c, err := bf.Count()
if err != nil {
return nil, xerrors.Errorf("count errror: %w", err)
}
if c > max {
return nil, xerrors.Errorf("expected %d, got %d: %w", max, c, ErrBitFieldTooMany)
}
runs, err := bf.sum()
if err != nil {
return nil, err
}
res, err := rlepluslazy.SliceFromRuns(runs)
if err != nil {
return nil, err
}
out := make(map[uint64]bool)
for _, i := range res {
out[i] = true
}
return out, nil
}
func (bf BitField) MarshalCBOR(w io.Writer) error {
ints := make([]uint64, 0, len(bf.bits))
for i := range bf.bits {
ints = append(ints, i)
}
s, err := bf.sum()
if err != nil {
return err
}
rle, err := rlepluslazy.EncodeRuns(s, []byte{})
if err != nil {
return err
}
if len(rle) > 8192 {
return xerrors.Errorf("encoded bitfield was too large (%d)", len(rle))
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(rle)))); err != nil {
return err
}
if _, err = w.Write(rle); err != nil {
return xerrors.Errorf("writing rle: %w", err)
}
return nil
}
func (bf *BitField) UnmarshalCBOR(r io.Reader) error {
br := cbg.GetPeeker(r)
maj, extra, err := cbg.CborReadHeader(br)
if err != nil {
return err
}
if extra > 8192 {
return fmt.Errorf("array too large")
}
if maj != cbg.MajByteString {
return fmt.Errorf("expected byte array")
}
buf := make([]byte, extra)
if _, err := io.ReadFull(br, buf); err != nil {
return err
}
rle, err := rlepluslazy.FromBuf(buf)
if err != nil {
return xerrors.Errorf("could not decode rle+: %w", err)
}
bf.rle = rle
bf.bits = make(map[uint64]struct{})
return nil
}

View File

@ -4,6 +4,9 @@ import (
"bytes"
"math/big"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/crypto"
block "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
"github.com/minio/sha256-simd"
@ -21,7 +24,7 @@ type Ticket struct {
type EPostTicket struct {
Partial []byte
SectorID uint64
SectorID abi.SectorNumber
ChallengeIndex uint64
}
@ -42,7 +45,7 @@ type BlockHeader struct {
ParentWeight BigInt // 4
Height uint64 // 5
Height abi.ChainEpoch // 5
ParentStateRoot cid.Cid // 6
@ -50,11 +53,11 @@ type BlockHeader struct {
Messages cid.Cid // 8
BLSAggregate Signature // 9
BLSAggregate crypto.Signature // 9
Timestamp uint64 // 10
BlockSig *Signature // 11
BlockSig *crypto.Signature // 11
ForkSignaling uint64 // 12
}
@ -163,8 +166,8 @@ var blocksPerEpoch = NewInt(build.BlocksPerEpoch)
const sha256bits = 256
func IsTicketWinner(partialTicket []byte, ssizeI uint64, snum uint64, totpow BigInt) bool {
ssize := NewInt(ssizeI)
func IsTicketWinner(partialTicket []byte, ssizeI abi.SectorSize, snum uint64, totpow BigInt) bool {
ssize := NewInt(uint64(ssizeI))
ssampled := ElectionPostChallengeCount(snum, 0) // TODO: faults in epost?
/*
Need to check that

View File

@ -7,6 +7,7 @@ import (
"testing"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/crypto"
cid "github.com/ipfs/go-cid"
)
@ -34,12 +35,12 @@ func testBlockHeader(t testing.TB) *BlockHeader {
},
Parents: []cid.Cid{c, c},
ParentMessageReceipts: c,
BLSAggregate: Signature{Type: KTBLS, Data: []byte("boo! im a signature")},
BLSAggregate: crypto.Signature{Type: crypto.SigTypeBLS, Data: []byte("boo! im a signature")},
ParentWeight: NewInt(123125126212),
Messages: c,
Height: 85919298723,
ParentStateRoot: c,
BlockSig: &Signature{Type: KTBLS, Data: []byte("boo! im a signature")},
BlockSig: &crypto.Signature{Type: crypto.SigTypeBLS, Data: []byte("boo! im a signature")},
}
}

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,7 @@ import (
"bytes"
"fmt"
"github.com/filecoin-project/specs-actors/actors/abi"
block "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
"github.com/multiformats/go-multihash"
@ -22,10 +23,26 @@ type Message struct {
GasPrice BigInt
GasLimit BigInt
Method uint64 // TODO: decide
Method abi.MethodNum
Params []byte
}
func (t *Message) BlockMiner() address.Address {
panic("implement me")
}
func (t *Message) Caller() address.Address {
return t.From
}
func (t *Message) Receiver() address.Address {
return t.To
}
func (t *Message) ValueReceived() abi.TokenAmount {
return t.Value
}
func DecodeMessage(b []byte) (*Message, error) {
var msg Message
if err := msg.UnmarshalCBOR(bytes.NewReader(b)); err != nil {

View File

@ -5,9 +5,12 @@ import (
"fmt"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/wallet"
"github.com/ipfs/go-cid"
)
func Address(i uint64) address.Address {
@ -47,7 +50,7 @@ func MkBlock(parents *types.TipSet, weightInc uint64, ticketNonce uint64) *types
}
var pcids []cid.Cid
var height uint64
var height abi.ChainEpoch
weight := types.NewInt(weightInc)
if parents != nil {
pcids = parents.Cids()
@ -65,12 +68,12 @@ func MkBlock(parents *types.TipSet, weightInc uint64, ticketNonce uint64) *types
},
Parents: pcids,
ParentMessageReceipts: c,
BLSAggregate: types.Signature{Type: types.KTBLS, Data: []byte("boo! im a signature")},
BLSAggregate: crypto.Signature{Type: crypto.SigTypeBLS, Data: []byte("boo! im a signature")},
ParentWeight: weight,
Messages: c,
Height: height,
ParentStateRoot: c,
BlockSig: &types.Signature{Type: types.KTBLS, Data: []byte("boo! im a signature")},
BlockSig: &crypto.Signature{Type: crypto.SigTypeBLS, Data: []byte("boo! im a signature")},
}
}

View File

@ -1,123 +0,0 @@
package types
import (
"bytes"
"encoding/binary"
"fmt"
"io"
cbg "github.com/whyrusleeping/cbor-gen"
)
const SignatureMaxLength = 200
const (
KTSecp256k1 = "secp256k1"
KTBLS = "bls"
)
const (
IKTUnknown = -1
IKTSecp256k1 = iota
IKTBLS
)
type Signature struct {
Type string
Data []byte
}
func SignatureFromBytes(x []byte) (Signature, error) {
val, nr := binary.Uvarint(x)
if nr != 1 {
return Signature{}, fmt.Errorf("signatures with type field longer than one byte are invalid")
}
var ts string
switch val {
case IKTSecp256k1:
ts = KTSecp256k1
case IKTBLS:
ts = KTBLS
default:
return Signature{}, fmt.Errorf("unsupported signature type: %d", val)
}
return Signature{
Type: ts,
Data: x[1:],
}, nil
}
func (s *Signature) TypeCode() int {
switch s.Type {
case KTSecp256k1:
return IKTSecp256k1
case KTBLS:
return IKTBLS
default:
return IKTUnknown
}
}
func (s *Signature) MarshalCBOR(w io.Writer) error {
if s == nil {
_, err := w.Write(cbg.CborNull)
return err
}
header := cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(s.Data)+1))
if _, err := w.Write(header); err != nil {
return err
}
if _, err := w.Write([]byte{byte(s.TypeCode())}); err != nil {
return err
}
if _, err := w.Write(s.Data); err != nil {
return err
}
return nil
}
func (s *Signature) UnmarshalCBOR(br io.Reader) error {
maj, l, err := cbg.CborReadHeader(br)
if err != nil {
return err
}
if maj != cbg.MajByteString {
return fmt.Errorf("cbor input for signature was not a byte string")
}
if l > SignatureMaxLength {
return fmt.Errorf("cbor byte array for signature was too long")
}
buf := make([]byte, l)
if _, err := io.ReadFull(br, buf); err != nil {
return err
}
switch buf[0] {
default:
return fmt.Errorf("invalid signature type in cbor input: %d", buf[0])
case IKTSecp256k1:
s.Type = KTSecp256k1
case IKTBLS:
s.Type = KTBLS
}
s.Data = buf[1:]
return nil
}
func (s *Signature) Equals(o *Signature) bool {
if s == nil || o == nil {
return s == o
}
return s.Type == o.Type && bytes.Equal(s.Data, o.Data)
}

View File

@ -3,12 +3,14 @@ package types
import (
"bytes"
"testing"
"github.com/filecoin-project/specs-actors/actors/crypto"
)
func TestSignatureSerializeRoundTrip(t *testing.T) {
s := &Signature{
s := &crypto.Signature{
Data: []byte("foo bar cat dog"),
Type: KTBLS,
Type: crypto.SigTypeBLS,
}
buf := new(bytes.Buffer)
@ -16,7 +18,7 @@ func TestSignatureSerializeRoundTrip(t *testing.T) {
t.Fatal(err)
}
var outs Signature
var outs crypto.Signature
if err := outs.UnmarshalCBOR(buf); err != nil {
t.Fatal(err)
}

View File

@ -3,13 +3,14 @@ package types
import (
"bytes"
"github.com/filecoin-project/specs-actors/actors/crypto"
block "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
"github.com/multiformats/go-multihash"
)
func (m *SignedMessage) ToStorageBlock() (block.Block, error) {
if m.Signature.Type == KTBLS {
if m.Signature.Type == crypto.SigTypeBLS {
return m.Message.ToStorageBlock()
}
@ -28,7 +29,7 @@ func (m *SignedMessage) ToStorageBlock() (block.Block, error) {
}
func (m *SignedMessage) Cid() cid.Cid {
if m.Signature.Type == KTBLS {
if m.Signature.Type == crypto.SigTypeBLS {
return m.Message.Cid()
}
@ -42,7 +43,7 @@ func (m *SignedMessage) Cid() cid.Cid {
type SignedMessage struct {
Message Message
Signature Signature
Signature crypto.Signature
}
func DecodeSignedMessage(data []byte) (*SignedMessage, error) {

View File

@ -7,6 +7,7 @@ import (
"io"
"sort"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/ipfs/go-cid"
logging "github.com/ipfs/go-log/v2"
cbg "github.com/whyrusleeping/cbor-gen"
@ -18,7 +19,7 @@ var log = logging.Logger("types")
type TipSet struct {
cids []cid.Cid
blks []*BlockHeader
height uint64
height abi.ChainEpoch
}
// why didnt i just export the fields? Because the struct has methods with the
@ -26,7 +27,7 @@ type TipSet struct {
type ExpTipSet struct {
Cids []cid.Cid
Blocks []*BlockHeader
Height uint64
Height abi.ChainEpoch
}
func (ts *TipSet) MarshalJSON() ([]byte, error) {
@ -135,7 +136,7 @@ func (ts *TipSet) Key() TipSetKey {
return NewTipSetKey(ts.cids...)
}
func (ts *TipSet) Height() uint64 {
func (ts *TipSet) Height() abi.ChainEpoch {
return ts.height
}

View File

@ -3,6 +3,10 @@ package types
import (
"context"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
@ -31,46 +35,22 @@ type VMContext interface {
Message() *Message
Origin() address.Address
Ipld() cbor.IpldStore
Send(to address.Address, method uint64, value BigInt, params []byte) ([]byte, aerrors.ActorError)
BlockHeight() uint64
Send(to address.Address, method abi.MethodNum, value BigInt, params []byte) ([]byte, aerrors.ActorError)
BlockHeight() abi.ChainEpoch
GasUsed() BigInt
Storage() Storage
StateTree() (StateTree, aerrors.ActorError)
VerifySignature(sig *Signature, from address.Address, data []byte) aerrors.ActorError
ActorCodeCID(address.Address) (cid.Cid, error)
LookupID(address.Address) (address.Address, error)
VerifySignature(sig *crypto.Signature, from address.Address, data []byte) aerrors.ActorError
ChargeGas(uint64) aerrors.ActorError
GetRandomness(height uint64) ([]byte, aerrors.ActorError)
GetRandomness(personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) ([]byte, aerrors.ActorError)
GetBalance(address.Address) (BigInt, aerrors.ActorError)
Sys() *VMSyscalls
Sys() runtime.Syscalls
Context() context.Context
}
const CommitmentBytesLen = 32
type PublicSectorInfo struct {
SectorID uint64
CommR [CommitmentBytesLen]byte
}
type Candidate struct {
SectorID uint64
PartialTicket [32]byte
Ticket [32]byte
SectorChallengeIndex uint64
}
type VMSyscalls struct {
ValidatePoRep func(context.Context, address.Address, uint64, []byte, []byte, []byte, []byte, []byte, uint64) (bool, aerrors.ActorError)
VerifyFallbackPost func(ctx context.Context,
sectorSize uint64,
sectorInfo []PublicSectorInfo,
challengeSeed []byte,
proof []byte,
candidates []Candidate,
proverID address.Address,
faults uint64) (bool, error)
}
type storageWrapper struct {
s Storage
}

View File

@ -1,88 +1,22 @@
package types
import (
"bytes"
import(
"encoding/base64"
"github.com/filecoin-project/go-address"
cborrpc "github.com/filecoin-project/go-cbor-util"
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
cbor "github.com/ipfs/go-ipld-cbor"
)
type SignedVoucher struct {
TimeLock uint64
SecretPreimage []byte
Extra *ModVerifyParams
Lane uint64
Nonce uint64
Amount BigInt
MinCloseHeight uint64
Merges []Merge
Signature *Signature
}
func (sv *SignedVoucher) SigningBytes() ([]byte, error) {
osv := *sv
osv.Signature = nil
buf := new(bytes.Buffer)
if err := osv.MarshalCBOR(buf); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
func (sv *SignedVoucher) EncodedString() (string, error) {
buf := new(bytes.Buffer)
if err := sv.MarshalCBOR(buf); err != nil {
return "", err
}
return base64.RawURLEncoding.EncodeToString(buf.Bytes()), nil
}
func (sv *SignedVoucher) Equals(other *SignedVoucher) bool {
// TODO: make this less bad
selfB, err := cborrpc.Dump(sv)
if err != nil {
log.Errorf("SignedVoucher.Equals: dump self: %s", err)
return false
}
otherB, err := cborrpc.Dump(other)
if err != nil {
log.Errorf("SignedVoucher.Equals: dump other: %s", err)
return false
}
return bytes.Equal(selfB, otherB)
}
func DecodeSignedVoucher(s string) (*SignedVoucher, error) {
func DecodeSignedVoucher(s string) (*paych.SignedVoucher, error) {
data, err := base64.RawURLEncoding.DecodeString(s)
if err != nil {
return nil, err
}
var sv SignedVoucher
var sv paych.SignedVoucher
if err := cbor.DecodeInto(data, &sv); err != nil {
return nil, err
}
return &sv, nil
}
type Merge struct {
Lane uint64
Nonce uint64
}
type ModVerifyParams struct {
Actor address.Address
Method uint64
Data []byte
}

View File

@ -2,6 +2,9 @@ package validation
import (
"context"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/go-sectorbuilder"
vchain "github.com/filecoin-project/chain-validation/pkg/chain"
@ -33,7 +36,7 @@ func (a *Applier) ApplyMessage(eCtx *vchain.ExecutionContext, state vstate.Wrapp
if err != nil {
return vchain.MessageReceipt{}, err
}
lotusVM, err := vm.NewVM(base, eCtx.Epoch, randSrc, minerAddr, st.bs, vm.Syscalls(sectorbuilder.ProofVerifier))
lotusVM, err := vm.NewVM(base, abi.ChainEpoch(eCtx.Epoch), randSrc, minerAddr, st.bs, vm.Syscalls(sectorbuilder.ProofVerifier))
if err != nil {
return vchain.MessageReceipt{}, err
}

View File

@ -2,6 +2,7 @@ package validation
import (
"context"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
@ -10,15 +11,16 @@ import (
vaddress "github.com/filecoin-project/chain-validation/pkg/state/address"
vtypes "github.com/filecoin-project/chain-validation/pkg/state/types"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/types"
)
type Signer interface {
Sign(ctx context.Context, addr vaddress.Address, msg []byte) (*types.Signature, error)
Sign(ctx context.Context, addr vaddress.Address, msg []byte) (*crypto.Signature, error)
}
type MessageFactory struct {
@ -53,7 +55,7 @@ func (mf *MessageFactory) MakeMessage(from, to vaddress.Address, method vchain.M
valueDec,
types.BigInt{gasPrice.Int},
types.NewInt(uint64(gasLimit)),
methodId,
abi.MethodNum(methodId),
params,
}
@ -72,18 +74,17 @@ func (mf *MessageFactory) FromActorCodeCid(code vactors.ActorCodeID) cid.Cid {
// This will change to a mapping to method ids when method dispatch is updated to use integers.
var methods = []uint64{
vchain.NoMethod: 0,
vchain.InitExec: actors.IAMethods.Exec,
vchain.InitExec: uint64(builtin.MethodsInit.Exec),
vchain.StoragePowerConstructor: actors.SPAMethods.Constructor,
vchain.StoragePowerCreateStorageMiner: actors.SPAMethods.CreateStorageMiner,
vchain.StoragePowerUpdatePower: actors.SPAMethods.UpdateStorage,
vchain.StoragePowerConstructor: uint64(builtin.MethodsPower.Constructor),
vchain.StoragePowerCreateStorageMiner: uint64(builtin.MethodsPower.CreateMiner),
vchain.StorageMinerUpdatePeerID: actors.MAMethods.UpdatePeerID,
vchain.StorageMinerGetOwner: actors.MAMethods.GetOwner,
vchain.StorageMinerGetPower: actors.MAMethods.GetPower,
vchain.StorageMinerGetWorkerAddr: actors.MAMethods.GetWorkerAddr,
vchain.StorageMinerGetPeerID: actors.MAMethods.GetPeerID,
vchain.StorageMinerGetSectorSize: actors.MAMethods.GetSectorSize,
vchain.StorageMinerUpdatePeerID: 0, //actors.MAMethods.UpdatePeerID,
vchain.StorageMinerGetOwner: 0, //actors.MAMethods.GetOwner,
vchain.StorageMinerGetPower: 0, //actors.MAMethods.GetPower,
vchain.StorageMinerGetWorkerAddr: 0, //actors.MAMethods.GetWorkerAddr,
vchain.StorageMinerGetPeerID: 0, //actors.MAMethods.GetPeerID,
vchain.StorageMinerGetSectorSize: 0, //actors.MAMethods.GetSectorSize,
vchain.MultiSigConstructor: uint64(builtin.MethodsMultisig.Constructor),
vchain.MultiSigPropose: uint64(builtin.MethodsMultisig.Propose),

View File

@ -20,8 +20,9 @@ import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-crypto"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/gen/genesis"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
@ -132,7 +133,7 @@ func (s *StateWrapper) SetSingletonActor(addr vactors.SingletonActorID, balance
switch lotusAddr {
case actors.InitAddress:
initact, err := gen.SetupInitActor(s.bs, nil)
initact, err := genesis.SetupInitActor(s.bs, "testing", nil)
if err != nil {
return nil, nil, err
}
@ -142,7 +143,7 @@ func (s *StateWrapper) SetSingletonActor(addr vactors.SingletonActorID, balance
return &actorWrapper{*initact}, s.storage, s.flush(tree)
case actors.StorageMarketAddress:
nsroot, err := gen.SetupStorageMarketActor(s.bs, s.stateRoot, nil)
nsroot, err := genesis.SetupStorageMarketActor(s.bs)
if err != nil {
return nil, nil, err
}
@ -158,7 +159,7 @@ func (s *StateWrapper) SetSingletonActor(addr vactors.SingletonActorID, balance
}
return &actorWrapper{*smact}, s.storage, s.flush(tree)
case actors.StoragePowerAddress:
spact, err := gen.SetupStoragePowerActor(s.bs)
spact, err := genesis.SetupStoragePowerActor(s.bs)
if err != nil {
return nil, nil, err
}

View File

@ -11,11 +11,21 @@ import (
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/cron"
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
"github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/multisig"
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/builtin/system"
vmr "github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/specs-actors/actors/builtin/multisig"
vmr "github.com/filecoin-project/specs-actors/actors/runtime"
)
type invoker struct {
@ -33,20 +43,21 @@ func NewInvoker() *invoker {
}
// add builtInCode using: register(cid, singleton)
inv.Register(actors.InitCodeCid, actors.InitActor{}, actors.InitActorState{})
inv.Register(actors.CronCodeCid, actors.CronActor{}, actors.CronActorState{})
inv.Register(actors.StoragePowerCodeCid, actors.StoragePowerActor{}, actors.StoragePowerState{})
inv.Register(actors.StorageMarketCodeCid, actors.StorageMarketActor{}, actors.StorageMarketState{})
inv.Register(actors.StorageMinerCodeCid, actors.StorageMinerActor{}, actors.StorageMinerActorState{})
inv.Register(actors.MultisigCodeCid, multisig.MultiSigActor{}, multisig.MultiSigActorState{})
inv.Register(actors.PaymentChannelCodeCid, actors.PaymentChannelActor{}, actors.PaymentChannelActorState{})
inv.Register(builtin.SystemActorCodeID, system.Actor{}, adt.EmptyValue{})
inv.Register(builtin.InitActorCodeID, init_.Actor{}, init_.State{})
inv.Register(builtin.CronActorCodeID, cron.Actor{}, cron.State{})
inv.Register(builtin.StoragePowerActorCodeID, power.Actor{}, power.State{})
inv.Register(builtin.StorageMarketActorCodeID, market.Actor{}, market.State{})
inv.Register(builtin.StorageMinerActorCodeID, miner.Actor{}, miner.State{})
inv.Register(builtin.MultisigActorCodeID, multisig.Actor{}, multisig.State{})
inv.Register(builtin.PaymentChannelActorCodeID, paych.Actor{}, paych.State{})
return inv
}
func (inv *invoker) Invoke(act *types.Actor, vmctx types.VMContext, method uint64, params []byte) ([]byte, aerrors.ActorError) {
func (inv *invoker) Invoke(act *types.Actor, vmctx types.VMContext, method abi.MethodNum, params []byte) ([]byte, aerrors.ActorError) {
if act.Code == actors.AccountCodeCid {
if act.Code == builtin.AccountActorCodeID {
return nil, aerrors.Newf(254, "cannot invoke methods on account actors")
}
@ -55,7 +66,7 @@ func (inv *invoker) Invoke(act *types.Actor, vmctx types.VMContext, method uint6
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 {
if method >= abi.MethodNum(len(code)) || code[method] == nil {
return nil, aerrors.Newf(255, "no method %d on actor", method)
}
return code[method](act, vmctx, params)
@ -252,7 +263,7 @@ func DecodeParams(b []byte, out interface{}) error {
}
func DumpActorState(code cid.Cid, b []byte) (interface{}, error) {
if code == actors.AccountCodeCid { // Account code special case
if code == builtin.AccountActorCodeID { // Account code special case
return nil, nil
}

View File

@ -2,12 +2,13 @@ package vm
import (
"context"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/account"
"github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/types"
@ -15,7 +16,7 @@ import (
func init() {
cst := cbor.NewMemCborStore()
emptyobject, err := cst.Put(context.TODO(), map[string]string{})
emptyobject, err := cst.Put(context.TODO(), []struct{}{})
if err != nil {
panic(err)
}
@ -54,7 +55,7 @@ func makeActor(st *state.StateTree, addr address.Address) (*types.Actor, aerrors
}
func NewBLSAccountActor(st *state.StateTree, addr address.Address) (*types.Actor, aerrors.ActorError) {
var acstate actors.AccountActorState
var acstate account.State
acstate.Address = addr
c, err := st.Store.Put(context.TODO(), &acstate)
@ -63,7 +64,7 @@ func NewBLSAccountActor(st *state.StateTree, addr address.Address) (*types.Actor
}
nact := &types.Actor{
Code: actors.AccountCodeCid,
Code: builtin.AccountActorCodeID,
Balance: types.NewInt(0),
Head: c,
}
@ -73,7 +74,7 @@ func NewBLSAccountActor(st *state.StateTree, addr address.Address) (*types.Actor
func NewSecp256k1AccountActor(st *state.StateTree, addr address.Address) (*types.Actor, aerrors.ActorError) {
nact := &types.Actor{
Code: actors.AccountCodeCid,
Code: builtin.AccountActorCodeID,
Balance: types.NewInt(0),
Head: EmptyObjectCid,
}

View File

@ -3,36 +3,62 @@ package vm
import (
"bytes"
"context"
"fmt"
"encoding/binary"
"runtime/debug"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/specs-actors/actors/crypto"
vmr "github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/specs-actors/actors/runtime/exitcode"
"github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/types"
)
type runtimeShim struct {
vmctx types.VMContext
vmr.Runtime
}
var _ runtime.Runtime = (*runtimeShim)(nil)
func (rs *runtimeShim) ResolveAddress(address address.Address) (ret address.Address, ok bool) {
r, err := rs.vmctx.LookupID(address)
if err != nil { // TODO: check notfound
rs.Abortf(exitcode.ErrPlaceholder, "resolve address: %v", err)
}
return r, true
}
func (rs *runtimeShim) Get(c cid.Cid, o vmr.CBORUnmarshaler) bool {
err := rs.vmctx.Storage().Get(c, o)
if err != nil { // todo: not found
rs.Abortf(exitcode.ErrPlaceholder, "storage get: %v", err)
}
return true
}
func (rs *runtimeShim) Put(x vmr.CBORMarshaler) cid.Cid {
c, err := rs.vmctx.Storage().Put(x)
if err != nil {
rs.Abortf(exitcode.ErrPlaceholder, "storage put: %v", err) // todo: spec code?
}
return c
}
var _ vmr.Runtime = (*runtimeShim)(nil)
func (rs *runtimeShim) shimCall(f func() interface{}) (rval []byte, aerr aerrors.ActorError) {
defer func() {
if r := recover(); r != nil {
if ar, ok := r.(aerrors.ActorError); ok {
log.Warn("VM.Call failure: ", ar)
debug.PrintStack()
aerr = ar
return
}
fmt.Println("caught one of those actor errors: ", r)
log.Warn("caught one of those actor errors: ", r)
debug.PrintStack()
log.Errorf("ERROR")
aerr = aerrors.Newf(1, "generic spec actors failure")
@ -56,14 +82,132 @@ func (rs *runtimeShim) shimCall(f func() interface{}) (rval []byte, aerr aerrors
}
}
func (rs *runtimeShim) Message() vmr.Message {
var err error
rawm := *rs.vmctx.Message() // TODO: normalize addresses earlier
rawm.From, err = rs.vmctx.LookupID(rawm.From)
if err != nil {
rs.Abortf(exitcode.ErrPlaceholder, "resolve from address: %v", err)
}
rawm.To, err = rs.vmctx.LookupID(rawm.To)
if err != nil {
rs.Abortf(exitcode.ErrPlaceholder, "resolve to address: %v", err)
}
return &rawm
}
func (rs *runtimeShim) ValidateImmediateCallerAcceptAny() {
return
}
func (rs *runtimeShim) CurrentBalance() abi.TokenAmount {
b, err := rs.vmctx.GetBalance(rs.vmctx.Message().To)
if err != nil {
rs.Abortf(exitcode.ExitCode(err.RetCode()), "get current balance: %v", err)
}
return b
}
func (rs *runtimeShim) GetActorCodeCID(addr address.Address) (ret cid.Cid, ok bool) {
ret, err := rs.vmctx.ActorCodeCID(addr)
if err != nil {
// todo: notfound
rs.Abortf(exitcode.ErrPlaceholder, "%v", err)
}
return ret, true
}
func (rs *runtimeShim) GetRandomness(personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) abi.Randomness {
r, err := rs.vmctx.GetRandomness(personalization, randEpoch, entropy)
if err != nil {
rs.Abortf(exitcode.SysErrInternal, "getting randomness: %v", err)
}
return r
}
func (rs *runtimeShim) Store() vmr.Store {
return rs
}
func (rs *runtimeShim) NewActorAddress() address.Address {
var b bytes.Buffer
if err := rs.ImmediateCaller().MarshalCBOR(&b); err != nil { // todo: spec says cbor; why not just bytes?
rs.Abortf(exitcode.ErrSerialization, "writing caller address into a buffer: %v", err)
}
var err error
st, err := rs.vmctx.StateTree()
if err != nil {
rs.Abortf(exitcode.SysErrInternal, "getting statetree: %v", err)
}
act, err := st.GetActor(rs.vmctx.Origin())
if err != nil {
rs.Abortf(exitcode.SysErrInternal, "getting top level actor: %v", err)
}
if err := binary.Write(&b, binary.BigEndian, act.Nonce); err != nil {
rs.Abortf(exitcode.ErrSerialization, "writing nonce address into a buffer: %v", err)
}
if err := binary.Write(&b, binary.BigEndian, uint64(0)); err != nil { // TODO: expose on vm
rs.Abortf(exitcode.ErrSerialization, "writing callSeqNum address into a buffer: %v", err)
}
addr, err := address.NewActorAddress(b.Bytes())
if err != nil {
rs.Abortf(exitcode.ErrSerialization, "create actor address: %v", err)
}
return addr
}
func (rs *runtimeShim) CreateActor(codeId cid.Cid, address address.Address) {
var err error
st, err := rs.vmctx.StateTree()
if err != nil {
rs.Abortf(exitcode.SysErrInternal, "getting statetree: %v", err)
}
err = st.SetActor(address, &types.Actor{
Code: codeId,
Head: EmptyObjectCid,
Nonce: 0,
Balance: big.Zero(),
})
if err != nil {
rs.Abortf(exitcode.SysErrInternal, "creating actor entry: %v", err)
}
return
}
func (rs *runtimeShim) DeleteActor() {
panic("implement me")
}
func (rs *runtimeShim) Syscalls() vmr.Syscalls {
return rs.vmctx.Sys()
}
func (rs *runtimeShim) StartSpan(name string) vmr.TraceSpan {
panic("implement me")
}
func (rs *runtimeShim) ValidateImmediateCallerIs(as ...address.Address) {
imm, err := rs.vmctx.LookupID(rs.vmctx.Message().From)
if err != nil {
rs.Abortf(exitcode.ErrIllegalState, "couldn't resolve immediate caller")
}
for _, a := range as {
if rs.vmctx.Message().From == a {
if imm == a {
return
}
}
fmt.Println("Caller: ", rs.vmctx.Message().From, as)
panic("we like to panic when people call the wrong methods")
rs.Abortf(exitcode.ErrForbidden, "caller %s is not one of %s", rs.vmctx.Message().From, as)
}
func (rs *runtimeShim) ImmediateCaller() address.Address {
@ -74,44 +218,20 @@ func (rs *runtimeShim) Context() context.Context {
return rs.vmctx.Context()
}
func (rs *runtimeShim) IpldGet(c cid.Cid, o vmr.CBORUnmarshaler) bool {
if err := rs.vmctx.Storage().Get(c, o); err != nil {
panic(err) // y o o o o o l l l l o o o o o
}
return true
}
func (rs *runtimeShim) IpldPut(o vmr.CBORMarshaler) cid.Cid {
c, err := rs.vmctx.Storage().Put(o)
if err != nil {
panic(err)
}
return c
}
func (rs *runtimeShim) Abort(code exitcode.ExitCode, msg string, args ...interface{}) {
panic(aerrors.Newf(uint8(code), msg, args...))
func (rs *runtimeShim) Abortf(code exitcode.ExitCode, msg string, args ...interface{}) {
panic(aerrors.NewfSkip(2, uint8(code), msg, args...))
}
func (rs *runtimeShim) AbortStateMsg(msg string) {
rs.Abort(101, msg)
panic(aerrors.NewfSkip(3, 101, msg))
}
func (rs *runtimeShim) ValidateImmediateCallerType(...cid.Cid) {
log.Info("validate caller type is dumb")
}
func (rs *runtimeShim) CurrentBalance() abi.TokenAmount {
b, err := rs.vmctx.GetBalance(rs.vmctx.Message().From)
if err != nil {
rs.Abort(1, err.Error())
}
return abi.TokenAmount(b)
}
func (rs *runtimeShim) CurrEpoch() abi.ChainEpoch {
return abi.ChainEpoch(rs.vmctx.BlockHeight())
return rs.vmctx.BlockHeight()
}
type dumbWrapperType struct {
@ -122,13 +242,17 @@ func (dwt *dumbWrapperType) Into(um vmr.CBORUnmarshaler) error {
return um.UnmarshalCBOR(bytes.NewReader(dwt.val))
}
func (rs *runtimeShim) Send(to address.Address, method abi.MethodNum, m runtime.CBORMarshaler, value abi.TokenAmount) (vmr.SendReturn, exitcode.ExitCode) {
buf := new(bytes.Buffer)
if err := m.MarshalCBOR(buf); err != nil {
rs.Abort(exitcode.SysErrInvalidParameters, "failed to marshal input parameters: %s", err)
func (rs *runtimeShim) Send(to address.Address, method abi.MethodNum, m vmr.CBORMarshaler, value abi.TokenAmount) (vmr.SendReturn, exitcode.ExitCode) {
var params []byte
if m != nil {
buf := new(bytes.Buffer)
if err := m.MarshalCBOR(buf); err != nil {
rs.Abortf(exitcode.SysErrInvalidParameters, "failed to marshal input parameters: %s", err)
}
params = buf.Bytes()
}
ret, err := rs.vmctx.Send(to, uint64(method), types.BigInt(value), buf.Bytes())
ret, err := rs.vmctx.Send(to, method, types.BigInt(value), params)
if err != nil {
if err.IsFatal() {
panic(err)
@ -146,6 +270,16 @@ type shimStateHandle struct {
rs *runtimeShim
}
func (ssh *shimStateHandle) Create(obj vmr.CBORMarshaler) {
c, err := ssh.rs.vmctx.Storage().Put(obj)
if err != nil {
panic(err)
}
if err := ssh.rs.vmctx.Storage().Commit(EmptyObjectCid, c); err != nil {
panic(err)
}
}
func (ssh *shimStateHandle) Readonly(obj vmr.CBORUnmarshaler) {
if err := ssh.rs.vmctx.Storage().Get(ssh.rs.vmctx.Storage().GetHead(), obj); err != nil {
panic(err)
@ -170,15 +304,3 @@ func (ssh *shimStateHandle) Transaction(obj vmr.CBORer, f func() interface{}) in
return out
}
func (ssh *shimStateHandle) Construct(f func() vmr.CBORMarshaler) {
out := f()
c, err := ssh.rs.vmctx.Storage().Put(out)
if err != nil {
panic(err)
}
if err := ssh.rs.vmctx.Storage().Commit(actors.EmptyCBOR, c); err != nil {
panic(err)
}
}

View File

@ -1,69 +1,131 @@
package vm
import (
"context"
ffi "github.com/filecoin-project/filecoin-ffi"
"github.com/filecoin-project/go-address"
commcid "github.com/filecoin-project/go-fil-commcid"
"github.com/filecoin-project/go-sectorbuilder"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/types"
"go.opencensus.io/trace"
"github.com/filecoin-project/lotus/lib/zerocomm"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/ipfs/go-cid"
mh "github.com/multiformats/go-multihash"
"golang.org/x/xerrors"
"math/bits"
)
func init() {
mh.Codes[0xf104] = "filecoin"
}
// Actual type is defined in chain/types/vmcontext.go because the VMContext interface is there
func Syscalls(verifier sectorbuilder.Verifier) *types.VMSyscalls {
return &types.VMSyscalls{
ValidatePoRep: func(ctx context.Context, maddr address.Address, ssize uint64, commD, commR, ticket, proof, seed []byte, sectorID uint64) (bool, actors.ActorError) {
_, span := trace.StartSpan(ctx, "ValidatePoRep")
defer span.End()
ok, err := verifier.VerifySeal(ssize, commR, commD, maddr, ticket, seed, sectorID, proof)
if err != nil {
return false, aerrors.Absorb(err, 25, "verify seal failed")
}
return ok, nil
},
VerifyFallbackPost: func(ctx context.Context,
sectorSize uint64,
sectorInfo []types.PublicSectorInfo,
challengeSeed []byte,
proof []byte,
candidates []types.Candidate,
proverID address.Address,
faults uint64) (bool, error) {
sI := make([]ffi.PublicSectorInfo, len(sectorInfo))
for i, v := range sectorInfo {
sI[i] = ffi.PublicSectorInfo{
SectorID: v.SectorID,
CommR: v.CommR,
}
}
cand := make([]sectorbuilder.EPostCandidate, len(candidates))
for i, v := range candidates {
cand[i] = sectorbuilder.EPostCandidate{
SectorID: v.SectorID,
PartialTicket: v.PartialTicket,
Ticket: v.Ticket,
SectorChallengeIndex: v.SectorChallengeIndex,
}
}
return verifier.VerifyFallbackPost(
ctx,
sectorSize,
sectorbuilder.NewSortedPublicSectorInfo(sI),
challengeSeed,
proof,
cand,
proverID,
faults,
)
},
}
func Syscalls(verifier sectorbuilder.Verifier) runtime.Syscalls {
return &syscallShim{verifier}
}
type syscallShim struct {
verifier sectorbuilder.Verifier
}
func (ss *syscallShim) ComputeUnsealedSectorCID(ssize abi.SectorSize, pieces []abi.PieceInfo) (cid.Cid, error) {
// TODO: does this pull in unwanted dependencies?
var ffipieces []ffi.PublicPieceInfo
var sum abi.PaddedPieceSize
for _, p := range pieces {
ffipieces = append(ffipieces, ffi.PublicPieceInfo{
Size: p.Size.Unpadded(),
CommP: cidToCommD(p.PieceCID),
})
sum += p.Size
}
{
// pad remaining space with 0 CommPs
toFill := uint64(abi.PaddedPieceSize(ssize) - sum)
n := bits.OnesCount64(toFill)
for i := 0; i < n; i++ {
next := bits.TrailingZeros64(toFill)
psize := uint64(1) << next
toFill ^= psize
unpadded := abi.PaddedPieceSize(psize).Unpadded()
ffipieces = append(ffipieces, ffi.PublicPieceInfo{
Size: unpadded,
CommP: zerocomm.ForSize(unpadded),
})
}
}
commd, err := sectorbuilder.GenerateDataCommitment(ssize, ffipieces)
if err != nil {
log.Errorf("generate data commitment failed: %s", err)
return cid.Undef, err
}
return commcid.DataCommitmentV1ToCID(commd[:]), nil
}
func (ss *syscallShim) HashBlake2b(data []byte) [32]byte {
panic("NYI")
}
func (ss *syscallShim) VerifyConsensusFault(a, b []byte) bool {
panic("NYI")
}
func (ss *syscallShim) VerifyPoSt(ssize abi.SectorSize, proof abi.PoStVerifyInfo) (bool, error) {
panic("NYI")
}
func cidToCommD(c cid.Cid) [32]byte {
b := c.Bytes()
var out [32]byte
copy(out[:], b[len(b)-32:])
return out
}
func cidToCommR(c cid.Cid) [32]byte {
b := c.Bytes()
var out [32]byte
copy(out[:], b[len(b)-32:])
return out
}
func (ss *syscallShim) VerifySeal(ssize abi.SectorSize, info abi.SealVerifyInfo) (bool, error) {
//_, span := trace.StartSpan(ctx, "ValidatePoRep")
//defer span.End()
commD := cidToCommD(info.UnsealedCID)
commR := cidToCommR(info.OnChain.SealedCID)
miner, err := address.NewIDAddress(uint64(info.Miner))
if err != nil {
return false, xerrors.Errorf("weirdly failed to construct address: %w", err)
}
ticket := []byte(info.Randomness)
proof := []byte(info.OnChain.Proof)
seed := []byte(info.InteractiveRandomness)
log.Infof("Werif %d r:%x; d:%x; m:%s; t:%x; s:%x; N:%d; p:%x", ssize, commR, commD, miner, ticket, seed, info.SectorID.Number, proof)
//func(ctx context.Context, maddr address.Address, ssize abi.SectorSize, commD, commR, ticket, proof, seed []byte, sectorID abi.SectorNumber)
ok, err := ss.verifier.VerifySeal(ssize, commR[:], commD[:], miner, ticket, seed, info.SectorID.Number, proof)
if err != nil {
return false, xerrors.Errorf("failed to validate PoRep: %w", err)
}
return ok, nil
}
func (ss *syscallShim) VerifySignature(sig crypto.Signature, addr address.Address, input []byte) bool {
return true
/* // TODO: in genesis setup, we are currently faking signatures
if err := ss.rt.vmctx.VerifySignature(&sig, addr, input); err != nil {
return false
}
return true
*/
}

View File

@ -4,7 +4,9 @@ import (
"bytes"
"context"
"fmt"
"github.com/filecoin-project/specs-actors/actors/builtin"
"math/big"
"reflect"
block "github.com/ipfs/go-block-format"
cid "github.com/ipfs/go-cid"
@ -12,13 +14,20 @@ import (
blockstore "github.com/ipfs/go-ipfs-blockstore"
cbor "github.com/ipfs/go-ipld-cbor"
logging "github.com/ipfs/go-log/v2"
mh "github.com/multiformats/go-multihash"
cbg "github.com/whyrusleeping/cbor-gen"
"go.opencensus.io/trace"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
commcid "github.com/filecoin-project/go-fil-commcid"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin/account"
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
"github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/types"
@ -50,13 +59,13 @@ type VMContext struct {
vm *VM
state *state.StateTree
msg *types.Message
height uint64
height abi.ChainEpoch
cst cbor.IpldStore
gasAvailable types.BigInt
gasUsed types.BigInt
sys *types.VMSyscalls
sys runtime.Syscalls
// root cid of the state of the actor this invocation will be on
sroot cid.Cid
@ -70,16 +79,15 @@ func (vmc *VMContext) Message() *types.Message {
return vmc.msg
}
func (vmc *VMContext) GetRandomness(height uint64) ([]byte, aerrors.ActorError) {
res, err := vmc.vm.rand.GetRandomness(vmc.ctx, int64(height))
func (vmc *VMContext) GetRandomness(personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) ([]byte, aerrors.ActorError) {
res, err := vmc.vm.rand.GetRandomness(vmc.ctx, personalization, int64(randEpoch), entropy)
if err != nil {
return nil, aerrors.Escalate(err, "could not get randomness")
}
return res, nil
}
func (vmc *VMContext) Sys() *types.VMSyscalls {
func (vmc *VMContext) Sys() runtime.Syscalls {
return vmc.sys
}
@ -133,7 +141,7 @@ func (vmc *VMContext) Origin() address.Address {
}
// Send allows the current execution context to invoke methods on other actors in the system
func (vmc *VMContext) Send(to address.Address, method uint64, value types.BigInt, params []byte) ([]byte, aerrors.ActorError) {
func (vmc *VMContext) Send(to address.Address, method abi.MethodNum, value types.BigInt, params []byte) ([]byte, aerrors.ActorError) {
ctx, span := trace.StartSpan(vmc.ctx, "vmc.Send")
defer span.End()
if span.IsRecordingEvents() {
@ -158,7 +166,7 @@ func (vmc *VMContext) Send(to address.Address, method uint64, value types.BigInt
}
// BlockHeight returns the height of the block this message was added to the chain in
func (vmc *VMContext) BlockHeight() uint64 {
func (vmc *VMContext) BlockHeight() abi.ChainEpoch {
return vmc.height
}
@ -176,16 +184,28 @@ func (vmc *VMContext) ChargeGas(amount uint64) aerrors.ActorError {
}
func (vmc *VMContext) StateTree() (types.StateTree, aerrors.ActorError) {
if vmc.msg.To != actors.InitAddress {
if vmc.msg.To != builtin.InitActorAddr {
return nil, aerrors.Escalate(fmt.Errorf("only init actor can access state tree directly"), "invalid use of StateTree")
}
return vmc.state, nil
}
func (vmc *VMContext) ActorCodeCID(addr address.Address) (ret cid.Cid, err error) {
act, err := vmc.state.GetActor(addr)
if err != nil {
return cid.Undef, err
}
return act.Code, nil
}
func (vmc *VMContext) LookupID(a address.Address) (address.Address, error) {
return vmc.state.LookupID(a)
}
const GasVerifySignature = 50
func (vmctx *VMContext) VerifySignature(sig *types.Signature, act address.Address, data []byte) aerrors.ActorError {
func (vmctx *VMContext) VerifySignature(sig *crypto.Signature, act address.Address, data []byte) aerrors.ActorError {
if err := vmctx.ChargeGas(GasVerifySignature); err != nil {
return err
}
@ -215,11 +235,11 @@ func ResolveToKeyAddr(state types.StateTree, cst cbor.IpldStore, addr address.Ad
return address.Undef, aerrors.Newf(1, "failed to find actor: %s", addr)
}
if act.Code != actors.AccountCodeCid {
if act.Code != builtin.AccountActorCodeID {
return address.Undef, aerrors.New(1, "address was not for an account actor")
}
var aast actors.AccountActorState
var aast account.State
if err := cst.Get(context.TODO(), act.Head, &aast); err != nil {
return address.Undef, aerrors.Escalate(err, fmt.Sprintf("failed to get account actor state for %s", addr))
}
@ -301,15 +321,15 @@ type VM struct {
base cid.Cid
cst *cbor.BasicIpldStore
buf *bufbstore.BufferedBS
blockHeight uint64
blockHeight abi.ChainEpoch
blockMiner address.Address
inv *invoker
rand Rand
Syscalls *types.VMSyscalls
Syscalls runtime.Syscalls
}
func NewVM(base cid.Cid, height uint64, r Rand, maddr address.Address, cbs blockstore.Blockstore, syscalls *types.VMSyscalls) (*VM, error) {
func NewVM(base cid.Cid, height abi.ChainEpoch, r Rand, maddr address.Address, cbs blockstore.Blockstore, syscalls runtime.Syscalls) (*VM, error) {
buf := bufbstore.NewBufferedBstore(cbs)
cst := cbor.NewCborStore(buf)
state, err := state.LoadStateTree(cst, base)
@ -331,7 +351,7 @@ func NewVM(base cid.Cid, height uint64, r Rand, maddr address.Address, cbs block
}
type Rand interface {
GetRandomness(ctx context.Context, h int64) ([]byte, error)
GetRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round int64, entropy []byte) ([]byte, error)
}
type ApplyRet struct {
@ -350,7 +370,7 @@ func (vm *VM) send(ctx context.Context, msg *types.Message, parent *VMContext,
toActor, err := st.GetActor(msg.To)
if err != nil {
if xerrors.Is(err, types.ErrActorNotFound) {
if xerrors.Is(err, init_.ErrAddressNotFound) {
a, err := TryCreateAccountActor(st, msg.To)
if err != nil {
return nil, aerrors.Absorb(err, 1, "could not create account"), nil
@ -543,6 +563,37 @@ func (vm *VM) Flush(ctx context.Context) (cid.Cid, error) {
return root, nil
}
// vm.MutateState(idAddr, func(cst cbor.IpldStore, st *ActorStateType) error {...})
func (vm *VM) MutateState(ctx context.Context, addr address.Address, fn interface{}) error {
act, err := vm.cstate.GetActor(addr)
if err != nil {
return xerrors.Errorf("actor not found: %w", err)
}
st := reflect.New(reflect.TypeOf(fn).In(1).Elem())
if err := vm.cst.Get(ctx, act.Head, st.Interface()); err != nil {
return xerrors.Errorf("read actor head: %w", err)
}
out := reflect.ValueOf(fn).Call([]reflect.Value{reflect.ValueOf(vm.cst), st})
if !out[0].IsNil() && out[0].Interface().(error) != nil {
return out[0].Interface().(error)
}
head, err := vm.cst.Put(ctx, st.Interface())
if err != nil {
return xerrors.Errorf("put new actor head: %w", err)
}
act.Head = head
if err := vm.cstate.SetActor(addr, act); err != nil {
return xerrors.Errorf("set actor: %w", err)
}
return nil
}
func linksForObj(blk block.Block) ([]cid.Cid, error) {
switch blk.Cid().Prefix().Codec {
case cid.DagCBOR:
@ -595,7 +646,7 @@ func copyRec(from, to blockstore.Blockstore, root cid.Cid, cp func(block.Block)
}
for _, link := range links {
if link.Prefix().MhType == 0 {
if link.Prefix().MhType == mh.IDENTITY || link.Prefix().MhType == uint64(commcid.FC_SEALED_V1) || link.Prefix().MhType == uint64(commcid.FC_UNSEALED_V1) {
continue
}
@ -622,11 +673,11 @@ func (vm *VM) StateTree() types.StateTree {
return vm.cstate
}
func (vm *VM) SetBlockHeight(h uint64) {
func (vm *VM) SetBlockHeight(h abi.ChainEpoch) {
vm.blockHeight = h
}
func (vm *VM) Invoke(act *types.Actor, vmctx *VMContext, method uint64, params []byte) ([]byte, aerrors.ActorError) {
func (vm *VM) Invoke(act *types.Actor, vmctx *VMContext, method abi.MethodNum, params []byte) ([]byte, aerrors.ActorError) {
ctx, span := trace.StartSpan(vmctx.ctx, "vm.Invoke")
defer span.End()
if span.IsRecordingEvents() {

View File

@ -6,6 +6,7 @@ import (
"strings"
"sync"
"github.com/filecoin-project/specs-actors/actors/crypto"
logging "github.com/ipfs/go-log/v2"
"golang.org/x/xerrors"
@ -23,6 +24,8 @@ var log = logging.Logger("wallet")
const (
KNamePrefix = "wallet-"
KDefault = "default"
KTBLS = "bls"
KTSecp256k1 = "secp256k1"
)
type Wallet struct {
@ -52,7 +55,7 @@ func KeyWallet(keys ...*Key) *Wallet {
}
}
func (w *Wallet) Sign(ctx context.Context, addr address.Address, msg []byte) (*types.Signature, error) {
func (w *Wallet) Sign(ctx context.Context, addr address.Address, msg []byte) (*crypto.Signature, error) {
ki, err := w.findKey(addr)
if err != nil {
return nil, err
@ -61,7 +64,7 @@ func (w *Wallet) Sign(ctx context.Context, addr address.Address, msg []byte) (*t
return nil, xerrors.Errorf("signing using key '%s': %w", addr.String(), types.ErrKeyInfoNotFound)
}
return sigs.Sign(ki.Type, ki.PrivateKey, msg)
return sigs.Sign(ActSigType(ki.Type), ki.PrivateKey, msg)
}
func (w *Wallet) findKey(addr address.Address) (*Key, error) {
@ -179,19 +182,19 @@ func (w *Wallet) SetDefault(a address.Address) error {
return nil
}
func GenerateKey(typ string) (*Key, error) {
func GenerateKey(typ crypto.SigType) (*Key, error) {
pk, err := sigs.Generate(typ)
if err != nil {
return nil, err
}
ki := types.KeyInfo{
Type: typ,
Type: kstoreSigType(typ),
PrivateKey: pk,
}
return NewKey(ki)
}
func (w *Wallet) GenerateKey(typ string) (address.Address, error) {
func (w *Wallet) GenerateKey(typ crypto.SigType) (address.Address, error) {
w.lk.Lock()
defer w.lk.Unlock()
@ -240,18 +243,18 @@ func NewKey(keyinfo types.KeyInfo) (*Key, error) {
}
var err error
k.PublicKey, err = sigs.ToPublic(k.Type, k.PrivateKey)
k.PublicKey, err = sigs.ToPublic(ActSigType(k.Type), k.PrivateKey)
if err != nil {
return nil, err
}
switch k.Type {
case types.KTSecp256k1:
case KTSecp256k1:
k.Address, err = address.NewSecp256k1Address(k.PublicKey)
if err != nil {
return nil, xerrors.Errorf("converting Secp256k1 to address: %w", err)
}
case types.KTBLS:
case KTBLS:
k.Address, err = address.NewBLSAddress(k.PublicKey)
if err != nil {
return nil, xerrors.Errorf("converting BLS to address: %w", err)
@ -262,3 +265,25 @@ func NewKey(keyinfo types.KeyInfo) (*Key, error) {
return k, nil
}
func kstoreSigType(typ crypto.SigType) string {
switch typ {
case crypto.SigTypeBLS:
return KTBLS
case crypto.SigTypeSecp256k1:
return KTSecp256k1
default:
return ""
}
}
func ActSigType(typ string) crypto.SigType {
switch typ {
case KTBLS:
return crypto.SigTypeBLS
case KTSecp256k1:
return crypto.SigTypeSecp256k1
default:
return 0
}
}

View File

@ -11,6 +11,11 @@ import (
"strings"
"time"
"github.com/filecoin-project/go-address"
cborutil "github.com/filecoin-project/go-cbor-util"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
cid "github.com/ipfs/go-cid"
"golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2"
@ -250,7 +255,7 @@ var chainSetHeadCmd = &cli.Command{
ts, err = api.ChainGetGenesis(ctx)
}
if ts == nil && cctx.IsSet("epoch") {
ts, err = api.ChainGetTipSetByHeight(ctx, cctx.Uint64("epoch"), types.EmptyTSK)
ts, err = api.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(cctx.Uint64("epoch")), types.EmptyTSK)
}
if ts == nil {
ts, err = parseTipSet(api, ctx, cctx.Args().Slice())
@ -313,7 +318,7 @@ var chainListCmd = &cli.Command{
var head *types.TipSet
if cctx.IsSet("height") {
head, err = api.ChainGetTipSetByHeight(ctx, cctx.Uint64("height"), types.EmptyTSK)
head, err = api.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(cctx.Uint64("height")), types.EmptyTSK)
} else {
head, err = api.ChainHead(ctx)
}
@ -446,7 +451,7 @@ var chainBisectCmd = &cli.Command{
subPath := cctx.Args().Get(2)
highest, err := api.ChainGetTipSetByHeight(ctx, end, types.EmptyTSK)
highest, err := api.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(end), types.EmptyTSK)
if err != nil {
return err
}
@ -460,7 +465,7 @@ var chainBisectCmd = &cli.Command{
start = end
}
midTs, err := api.ChainGetTipSetByHeight(ctx, mid, highest.Key())
midTs, err := api.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(mid), highest.Key())
if err != nil {
return err
}
@ -506,7 +511,7 @@ var chainBisectCmd = &cli.Command{
return nil
}
prev = mid
prev = abi.ChainEpoch(mid)
}
},
}
@ -594,18 +599,31 @@ var slashConsensusFault = &cli.Command{
return err
}
params, err := actors.SerializeParams(&actors.ArbitrateConsensusFaultParams{
Block1: b1,
Block2: b2,
bh1, err := cborutil.Dump(b1)
if err != nil {
return err
}
bh2, err := cborutil.Dump(b2)
if err != nil {
return err
}
params, err := actors.SerializeParams(&power.ReportConsensusFaultParams{
BlockHeader1: bh1,
BlockHeader2: bh2,
Target: address.Address{},
FaultEpoch: 0,
FaultType: 0,
})
msg := &types.Message{
To: actors.StoragePowerAddress,
To: builtin.StoragePowerActorAddr,
From: def,
Value: types.NewInt(0),
GasPrice: types.NewInt(1),
GasLimit: types.NewInt(10000000),
Method: actors.SPAMethods.ArbitrateConsensusFault,
Method: builtin.MethodsPower.ReportConsensusFault,
Params: params,
}

View File

@ -14,7 +14,7 @@ import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-fil-markets/storagemarket"
actors "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/types"
)
@ -291,27 +291,15 @@ var clientQueryAskCmd = &cli.Command{
}
pid = p
} else {
ret, err := api.StateCall(ctx, &types.Message{
To: maddr,
From: maddr,
Method: actors.MAMethods.GetPeerID,
}, types.EmptyTSK)
p, err := api.StateMinerPeerID(ctx, maddr, types.EmptyTSK)
if err != nil {
return xerrors.Errorf("failed to get peerID for miner: %w", err)
}
if ret.ExitCode != 0 {
return fmt.Errorf("call to GetPeerID was unsuccesful (exit code %d)", ret.ExitCode)
}
if peer.ID(ret.Return) == peer.ID("SETME") {
if p == peer.ID("SETME") {
return fmt.Errorf("the miner hasn't initialized yet")
}
p, err := peer.IDFromBytes(ret.Return)
if err != nil {
return err
}
pid = p
}

View File

@ -14,6 +14,7 @@ import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin"
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
samsig "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
cid "github.com/ipfs/go-cid"
"github.com/ipfs/go-hamt-ipld"
@ -104,9 +105,9 @@ var msigCreateCmd = &cli.Command{
}
// new actors are created by invoking 'exec' on the init actor with the constructor params
execParams := &actors.ExecParams{
Code: actors.MultisigCodeCid,
Params: enc,
execParams := &init_.ExecParams{
CodeCID: builtin.MultisigActorCodeID,
ConstructorParams: enc,
}
enc, err = actors.SerializeParams(execParams)
@ -116,9 +117,9 @@ var msigCreateCmd = &cli.Command{
// now we create the message to send this with
msg := types.Message{
To: actors.InitAddress,
To: builtin.InitActorAddr,
From: sendAddr,
Method: actors.IAMethods.Exec,
Method: builtin.MethodsInit.Exec,
Params: enc,
GasPrice: types.NewInt(1),
GasLimit: types.NewInt(1000000),
@ -186,7 +187,7 @@ var msigInspectCmd = &cli.Command{
return err
}
var mstate samsig.MultiSigActorState
var mstate samsig.State
if err := mstate.UnmarshalCBOR(bytes.NewReader(obj)); err != nil {
return err
}
@ -226,19 +227,19 @@ var msigInspectCmd = &cli.Command{
},
}
func GetMultisigPending(ctx context.Context, lapi api.FullNode, hroot cid.Cid) (map[int64]*samsig.MultiSigTransaction, error) {
func GetMultisigPending(ctx context.Context, lapi api.FullNode, hroot cid.Cid) (map[int64]*samsig.Transaction, error) {
bs := apibstore.NewAPIBlockstore(lapi)
cst := cbor.NewCborStore(bs)
nd, err := hamt.LoadNode(ctx, cst, hroot)
nd, err := hamt.LoadNode(ctx, cst, hroot, hamt.UseTreeBitWidth(5))
if err != nil {
return nil, err
}
txs := make(map[int64]*samsig.MultiSigTransaction)
txs := make(map[int64]*samsig.Transaction)
err = nd.ForEach(ctx, func(k string, val interface{}) error {
d := val.(*cbg.Deferred)
var tx samsig.MultiSigTransaction
var tx samsig.Transaction
if err := tx.UnmarshalCBOR(bytes.NewReader(d.Raw)); err != nil {
return err
}
@ -255,7 +256,7 @@ func GetMultisigPending(ctx context.Context, lapi api.FullNode, hroot cid.Cid) (
return txs, nil
}
func state(tx *samsig.MultiSigTransaction) string {
func state(tx *samsig.Transaction) string {
/* // TODO(why): I strongly disagree with not having these... but i need to move forward
if tx.Complete {
return "done"
@ -347,7 +348,7 @@ var msigProposeCmd = &cli.Command{
To: msig,
From: from,
Value: types.NewInt(0),
Method: uint64(builtin.MethodsMultisig.Propose),
Method: builtin.MethodsMultisig.Propose,
Params: enc,
GasLimit: types.NewInt(100000),
GasPrice: types.NewInt(1),
@ -432,7 +433,7 @@ var msigApproveCmd = &cli.Command{
To: msig,
From: from,
Value: types.NewInt(0),
Method: uint64(builtin.MethodsMultisig.Approve),
Method: builtin.MethodsMultisig.Approve,
Params: enc,
GasLimit: types.NewInt(100000),
GasPrice: types.NewInt(1),

View File

@ -1,11 +1,15 @@
package cli
import (
"bytes"
"encoding/base64"
"fmt"
"github.com/filecoin-project/go-address"
types "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
"gopkg.in/urfave/cli.v2"
types "github.com/filecoin-project/lotus/chain/types"
)
var paychCmd = &cli.Command{
@ -136,7 +140,7 @@ var paychVoucherCreateCmd = &cli.Command{
return err
}
enc, err := sv.EncodedString()
enc, err := EncodedString(sv)
if err != nil {
return err
}
@ -250,7 +254,7 @@ var paychVoucherListCmd = &cli.Command{
for _, v := range vouchers {
if cctx.Bool("export") {
enc, err := v.EncodedString()
enc, err := EncodedString(v)
if err != nil {
return err
}
@ -291,7 +295,7 @@ var paychVoucherBestSpendableCmd = &cli.Command{
return err
}
var best *types.SignedVoucher
var best *paych.SignedVoucher
for _, v := range vouchers {
spendable, err := api.PaychVoucherCheckSpendable(ctx, ch, v, nil, nil)
if err != nil {
@ -308,7 +312,7 @@ var paychVoucherBestSpendableCmd = &cli.Command{
return fmt.Errorf("No spendable vouchers for that channel")
}
enc, err := best.EncodedString()
enc, err := EncodedString(best)
if err != nil {
return err
}
@ -364,3 +368,12 @@ var paychVoucherSubmitCmd = &cli.Command{
return nil
},
}
func EncodedString(sv *paych.SignedVoucher) (string, error) {
buf := new(bytes.Buffer)
if err := sv.MarshalCBOR(buf); err != nil {
return "", err
}
return base64.RawURLEncoding.EncodeToString(buf.Bytes()), nil
}

View File

@ -5,19 +5,25 @@ import (
"context"
"encoding/json"
"fmt"
"github.com/filecoin-project/specs-actors/actors/builtin"
"reflect"
"strconv"
"strings"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/api"
actors "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/miner"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin/market"
miner2 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
samsig "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/libp2p/go-libp2p-core/peer"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/miner"
"github.com/docker/go-units"
"github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
@ -90,24 +96,16 @@ var stateMinerInfo = &cli.Command{
return err
}
var mst actors.StorageMinerActorState
var mst miner2.State
if err := mst.UnmarshalCBOR(bytes.NewReader(aso)); err != nil {
return err
}
mio, err := api.ChainReadObj(ctx, mst.Info)
if err != nil {
return err
}
var mi actors.MinerInfo
if err := mi.UnmarshalCBOR(bytes.NewReader(mio)); err != nil {
return err
}
mi := mst.Info
fmt.Printf("Owner:\t%s\n", mi.Owner)
fmt.Printf("Worker:\t%s\n", mi.Worker)
fmt.Printf("PeerID:\t%s\n", mi.PeerID)
fmt.Printf("PeerID:\t%s\n", mi.PeerId)
fmt.Printf("SectorSize:\t%s (%d)\n", units.BytesSize(float64(mi.SectorSize)), mi.SectorSize)
return nil
@ -187,9 +185,9 @@ var statePowerCmd = &cli.Command{
if cctx.Args().Present() {
mp := power.MinerPower
percI := types.BigDiv(types.BigMul(mp, types.NewInt(1000000)), tp)
fmt.Printf("%s(%s) / %s(%s) ~= %0.4f%%\n", mp.String(), mp.SizeStr(), tp.String(), tp.SizeStr(), float64(percI.Int64())/10000)
fmt.Printf("%s(%s) / %s(%s) ~= %0.4f%%\n", mp.String(), types.SizeStr(mp), tp.String(), types.SizeStr(tp), float64(percI.Int64())/10000)
} else {
fmt.Printf("%s(%s)\n", tp.String(), tp.SizeStr())
fmt.Printf("%s(%s)\n", tp.String(), types.SizeStr(tp))
}
return nil
@ -228,7 +226,7 @@ var stateSectorsCmd = &cli.Command{
}
for _, s := range sectors {
fmt.Printf("%d: %x %x\n", s.SectorID, s.CommR, s.CommD)
fmt.Printf("%d: %x\n", s.Info.Info.SectorNumber, s.Info.Info.SealedCID)
}
return nil
@ -267,7 +265,7 @@ var stateProvingSetCmd = &cli.Command{
}
for _, s := range sectors {
fmt.Printf("%d: %x %x\n", s.SectorID, s.CommR, s.CommD)
fmt.Printf("%d: %x\n", s.Info.Info.SectorNumber, s.Info.Info.SealedCID)
}
return nil
@ -278,8 +276,8 @@ var stateReplaySetCmd = &cli.Command{
Name: "replay",
Usage: "Replay a particular message within a tipset",
Action: func(cctx *cli.Context) error {
if cctx.Args().Len() < 2 {
fmt.Println("usage: <tipset> <message cid>")
if cctx.Args().Len() < 1 {
fmt.Println("usage: [tipset] <message cid>")
fmt.Println("The last cid passed will be used as the message CID")
fmt.Println("All preceding ones will be used as the tipset")
return nil
@ -291,15 +289,6 @@ var stateReplaySetCmd = &cli.Command{
return fmt.Errorf("message cid was invalid: %s", err)
}
var tscids []cid.Cid
for _, s := range args[:len(args)-1] {
c, err := cid.Decode(s)
if err != nil {
return fmt.Errorf("tipset cid was invalid: %s", err)
}
tscids = append(tscids, c)
}
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
@ -308,19 +297,41 @@ var stateReplaySetCmd = &cli.Command{
ctx := ReqContext(cctx)
var headers []*types.BlockHeader
for _, c := range tscids {
h, err := api.ChainGetBlock(ctx, c)
var ts *types.TipSet
{
var tscids []cid.Cid
for _, s := range args[:len(args)-1] {
c, err := cid.Decode(s)
if err != nil {
return fmt.Errorf("tipset cid was invalid: %s", err)
}
tscids = append(tscids, c)
}
if len(tscids) > 0 {
var headers []*types.BlockHeader
for _, c := range tscids {
h, err := api.ChainGetBlock(ctx, c)
if err != nil {
return err
}
headers = append(headers, h)
}
ts, err = types.NewTipSet(headers)
} else {
r, err := api.StateWaitMsg(ctx, mcid)
if err != nil {
return xerrors.Errorf("finding message in chain: %w", err)
}
ts, err = api.ChainGetTipSet(ctx, r.TipSet.Parents())
}
if err != nil {
return err
}
headers = append(headers, h)
}
ts, err := types.NewTipSet(headers)
if err != nil {
return err
}
res, err := api.StateReplay(ctx, ts.Key(), mcid)
@ -393,7 +404,7 @@ var stateGetDealSetCmd = &cli.Command{
return err
}
deal, err := api.StateMarketStorageDeal(ctx, dealid, ts.Key())
deal, err := api.StateMarketStorageDeal(ctx, abi.DealID(dealid), ts.Key())
if err != nil {
return err
}
@ -682,7 +693,7 @@ var stateListMessagesCmd = &cli.Command{
return err
}
msgs, err := api.StateListMessages(ctx, &types.Message{To: toa, From: froma}, ts.Key(), toh)
msgs, err := api.StateListMessages(ctx, &types.Message{To: toa, From: froma}, ts.Key(), abi.ChainEpoch(toh))
if err != nil {
return err
}
@ -735,7 +746,7 @@ var stateComputeStateCmd = &cli.Command{
return err
}
h := cctx.Uint64("height")
h := abi.ChainEpoch(cctx.Uint64("height"))
if h == 0 {
if ts == nil {
head, err := api.ChainHead(ctx)
@ -821,7 +832,7 @@ var stateCallCmd = &cli.Command{
&cli.StringFlag{
Name: "from",
Usage: "",
Value: actors.NetworkAddress.String(),
Value: builtin.SystemActorAddr.String(),
},
&cli.StringFlag{
Name: "value",
@ -888,7 +899,7 @@ var stateCallCmd = &cli.Command{
Value: types.BigInt(value),
GasLimit: types.NewInt(10000000000),
GasPrice: types.NewInt(0),
Method: method,
Method: abi.MethodNum(method),
Params: params,
}, ts.Key())
if err != nil {
@ -962,16 +973,16 @@ func parseParamsForMethod(act cid.Cid, method uint64, args []string) ([]byte, er
var f interface{}
switch act {
case actors.StorageMarketCodeCid:
f = actors.StorageMarketActor{}.Exports()[method]
case actors.StorageMinerCodeCid:
f = actors.StorageMinerActor{}.Exports()[method]
case actors.StoragePowerCodeCid:
f = actors.StoragePowerActor{}.Exports()[method]
case actors.MultisigCodeCid:
f = samsig.MultiSigActor{}.Exports()[method]
case actors.PaymentChannelCodeCid:
f = actors.PaymentChannelActor{}.Exports()[method]
case builtin.StorageMarketActorCodeID:
f = market.Actor{}.Exports()[method]
case builtin.StorageMinerActorCodeID:
f = miner2.Actor{}.Exports()[method]
case builtin.StoragePowerActorCodeID:
f = power.Actor{}.Exports()[method]
case builtin.MultisigActorCodeID:
f = samsig.Actor{}.Exports()[method]
case builtin.PaymentChannelActorCodeID:
f = paych.Actor{}.Exports()[method]
default:
return nil, fmt.Errorf("the lazy devs didnt add support for that actor to this call yet")
}

View File

@ -5,6 +5,7 @@ import (
"fmt"
"time"
"github.com/filecoin-project/specs-actors/actors/abi"
cid "github.com/ipfs/go-cid"
"gopkg.in/urfave/cli.v2"
@ -45,7 +46,7 @@ var syncStatusCmd = &cli.Command{
fmt.Printf("worker %d:\n", i)
var base, target []cid.Cid
var heightDiff int64
var theight uint64
var theight abi.ChainEpoch
if ss.Base != nil {
base = ss.Base.Cids()
heightDiff = int64(ss.Base.Height())

View File

@ -10,6 +10,8 @@ import (
"github.com/filecoin-project/go-address"
types "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/wallet"
"gopkg.in/urfave/cli.v2"
)
@ -44,7 +46,7 @@ var walletNew = &cli.Command{
t = "secp256k1"
}
nk, err := api.WalletNew(ctx, t)
nk, err := api.WalletNew(ctx, wallet.ActSigType(t))
if err != nil {
return err
}

View File

@ -3,6 +3,7 @@ package main
import (
"context"
"fmt"
"github.com/filecoin-project/specs-actors/actors/crypto"
"math/rand"
"os"
"time"
@ -59,7 +60,7 @@ var runCmd = &cli.Command{
func sendSmallFundsTxs(ctx context.Context, api api.FullNode, from address.Address, rate int) error {
var sendSet []address.Address
for i := 0; i < 20; i++ {
naddr, err := api.WalletNew(ctx, "bls")
naddr, err := api.WalletNew(ctx, crypto.SigTypeSecp256k1)
if err != nil {
return err
}

View File

@ -16,6 +16,7 @@ import (
"github.com/docker/go-units"
ffi "github.com/filecoin-project/filecoin-ffi"
paramfetch "github.com/filecoin-project/go-paramfetch"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/ipfs/go-datastore"
logging "github.com/ipfs/go-log/v2"
"github.com/mitchellh/go-homedir"
@ -32,7 +33,7 @@ import (
var log = logging.Logger("lotus-bench")
type BenchResults struct {
SectorSize uint64
SectorSize abi.SectorSize
SealingResults []SealingResult
@ -139,7 +140,7 @@ func main() {
if err != nil {
return err
}
sectorSize := uint64(sectorSizeInt)
sectorSize := abi.SectorSize(sectorSizeInt)
mds := datastore.NewMapDatastore()
cfg := &sectorbuilder.Config{
@ -155,7 +156,7 @@ func main() {
}
}
if err := paramfetch.GetParams(build.ParametersJson(), sectorSize); err != nil {
if err := paramfetch.GetParams(build.ParametersJson(), uint64(sectorSize)); err != nil {
return xerrors.Errorf("getting params: %w", err)
}
sb, err := sectorbuilder.New(cfg, mds)
@ -163,18 +164,16 @@ func main() {
return err
}
dataSize := sectorbuilder.UserBytesForSectorSize(sectorSize)
var sealTimings []SealingResult
var sealedSectors []ffi.PublicSectorInfo
numSectors := uint64(1)
for i := uint64(1); i <= numSectors && robench == ""; i++ {
numSectors := abi.SectorNumber(1)
for i := abi.SectorNumber(1); i <= numSectors && robench == ""; i++ {
start := time.Now()
log.Info("Writing piece into sector...")
r := rand.New(rand.NewSource(100 + int64(i)))
pi, err := sb.AddPiece(context.TODO(), dataSize, i, r, nil)
pi, err := sb.AddPiece(context.TODO(), abi.UnpaddedPieceSize(sectorSize), i, r, nil)
if err != nil {
return err
}
@ -196,8 +195,8 @@ func main() {
precommit := time.Now()
sealedSectors = append(sealedSectors, ffi.PublicSectorInfo{
CommR: pco.CommR,
SectorID: i,
CommR: pco.CommR,
SectorNum: i,
})
seed := sectorbuilder.SealSeed{
@ -225,7 +224,7 @@ func main() {
if !c.Bool("skip-unseal") {
log.Info("Unsealing sector")
rc, err := sb.ReadPieceFromSealedSector(context.TODO(), 1, 0, dataSize, ticket.TicketBytes[:], commD[:])
rc, err := sb.ReadPieceFromSealedSector(context.TODO(), 1, 0, abi.UnpaddedPieceSize(sectorSize), ticket.TicketBytes[:], commD[:])
if err != nil {
return err
}
@ -260,7 +259,7 @@ func main() {
return err
}
var genmm map[string]genesis.GenesisMiner
var genmm map[string]genesis.Miner
if err := json.Unmarshal(fdata, &genmm); err != nil {
return err
}
@ -272,15 +271,15 @@ func main() {
for _, s := range genm.Sectors {
sealedSectors = append(sealedSectors, ffi.PublicSectorInfo{
CommR: s.CommR,
SectorID: s.SectorID,
CommR: s.CommR,
SectorNum: s.SectorID,
})
}
}
log.Info("generating election post candidates")
sinfos := sectorbuilder.NewSortedPublicSectorInfo(sealedSectors)
candidates, err := sb.GenerateEPostCandidates(sinfos, challenge, []uint64{})
candidates, err := sb.GenerateEPostCandidates(sinfos, challenge, []abi.SectorNumber{})
if err != nil {
return err
}
@ -355,7 +354,7 @@ func main() {
fmt.Printf("unseal: %s (%s)\n", bo.SealingResults[0].Unseal, bps(bo.SectorSize, bo.SealingResults[0].Unseal))
}
}
fmt.Printf("generate candidates: %s (%s)\n", bo.PostGenerateCandidates, bps(bo.SectorSize*uint64(len(bo.SealingResults)), bo.PostGenerateCandidates))
fmt.Printf("generate candidates: %s (%s)\n", bo.PostGenerateCandidates, bps(bo.SectorSize*abi.SectorSize(len(bo.SealingResults)), bo.PostGenerateCandidates))
fmt.Printf("compute epost proof (cold): %s\n", bo.PostEProofCold)
fmt.Printf("compute epost proof (hot): %s\n", bo.PostEProofHot)
fmt.Printf("verify epost proof (cold): %s\n", bo.VerifyEPostCold)
@ -371,9 +370,9 @@ func main() {
}
}
func bps(data uint64, d time.Duration) string {
bdata := new(big.Int).SetUint64(data)
func bps(data abi.SectorSize, d time.Duration) string {
bdata := new(big.Int).SetUint64(uint64(data))
bdata = bdata.Mul(bdata, big.NewInt(time.Second.Nanoseconds()))
bps := bdata.Div(bdata, big.NewInt(d.Nanoseconds()))
return (types.BigInt{bps}).SizeStr() + "/s"
return types.SizeStr(types.BigInt{bps}) + "/s"
}

View File

@ -2,7 +2,6 @@ package main
import (
"database/sql"
"encoding/hex"
"fmt"
"sync"
"time"
@ -13,7 +12,6 @@ import (
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/types"
)
@ -267,8 +265,8 @@ create table if not exists deals
pieceSize bigint not null,
client text not null,
provider text not null,
expiration decimal not null,
duration decimal not null,
start decimal not null,
end decimal not null,
epochPrice decimal not null,
collateral decimal not null,
constraint deals_pk
@ -473,11 +471,11 @@ create temp table mh (like miner_heads excluding constraints) on commit drop;
fmt.Sprint(i.psize),
i.info.Owner.String(),
i.info.Worker.String(),
i.info.PeerID.String(),
i.info.PeerId.String(),
i.info.SectorSize,
i.state.Power.String(),
i.state.Power.String(), // TODO: SPA
i.state.Active,
i.state.ElectionPeriodStart,
i.state.PoStState.ProvingPeriodStart,
i.state.SlashedAt,
); err != nil {
return err
@ -842,7 +840,7 @@ func (st *storage) storeMpoolInclusions(msgs []api.MpoolUpdate) error {
return tx.Commit()
}
func (st *storage) storeDeals(deals map[string]actors.OnChainDeal) error {
func (st *storage) storeDeals(deals map[string]api.MarketDeal) error {
tx, err := st.db.Begin()
if err != nil {
return err
@ -854,7 +852,7 @@ func (st *storage) storeDeals(deals map[string]actors.OnChainDeal) error {
return xerrors.Errorf("prep temp: %w", err)
}
stmt, err := tx.Prepare(`copy d (id, pieceref, piecesize, client, "provider", expiration, duration, epochprice, collateral) from stdin `)
stmt, err := tx.Prepare(`copy d (id, pieceref, piecesize, client, "provider", "start", "end", epochprice, collateral) from stdin `)
if err != nil {
return err
}
@ -862,20 +860,20 @@ func (st *storage) storeDeals(deals map[string]actors.OnChainDeal) error {
var bloat uint64
for id, deal := range deals {
if len(deal.PieceRef) > 40 {
bloat += uint64(len(deal.PieceRef))
if len(deal.Proposal.PieceCID.String()) > 100 {
bloat += uint64(len(deal.Proposal.PieceCID.String()))
continue
}
if _, err := stmt.Exec(
id,
hex.EncodeToString(deal.PieceRef),
deal.PieceSize,
deal.Client.String(),
deal.Provider.String(),
fmt.Sprint(deal.ProposalExpiration),
fmt.Sprint(deal.Duration),
deal.StoragePricePerEpoch.String(),
deal.StorageCollateral.String(),
deal.Proposal.PieceCID.String(),
deal.Proposal.PieceSize,
deal.Proposal.Client.String(),
deal.Proposal.Provider.String(),
fmt.Sprint(deal.Proposal.StartEpoch),
fmt.Sprint(deal.Proposal.EndEpoch),
deal.Proposal.StoragePricePerEpoch.String(),
deal.Proposal.ProviderCollateral.String(),
); err != nil {
return err
}
@ -915,12 +913,12 @@ func (st *storage) storeDeals(deals map[string]actors.OnChainDeal) error {
}
for id, deal := range deals {
if deal.ActivationEpoch == 0 {
if deal.State.SectorStartEpoch <= 0 {
continue
}
if _, err := stmt.Exec(
id,
deal.ActivationEpoch,
deal.State.SectorStartEpoch,
); err != nil {
return err
}

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