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

View File

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

View File

@ -3,15 +3,20 @@ package apistruct
import ( import (
"context" "context"
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peer"
"github.com/filecoin-project/go-address" "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/api"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
) )
@ -44,24 +49,24 @@ type FullNodeStruct struct {
CommonStruct CommonStruct
Internal struct { Internal struct {
ChainNotify func(context.Context) (<-chan []*store.HeadChange, error) `perm:"read"` ChainNotify func(context.Context) (<-chan []*store.HeadChange, error) `perm:"read"`
ChainHead func(context.Context) (*types.TipSet, error) `perm:"read"` ChainHead func(context.Context) (*types.TipSet, error) `perm:"read"`
ChainGetRandomness func(context.Context, types.TipSetKey, int64) ([]byte, 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"` ChainGetBlock func(context.Context, cid.Cid) (*types.BlockHeader, error) `perm:"read"`
ChainGetTipSet func(context.Context, types.TipSetKey) (*types.TipSet, 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"` ChainGetBlockMessages func(context.Context, cid.Cid) (*api.BlockMessages, error) `perm:"read"`
ChainGetParentReceipts func(context.Context, cid.Cid) ([]*types.MessageReceipt, 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"` ChainGetParentMessages func(context.Context, cid.Cid) ([]api.Message, error) `perm:"read"`
ChainGetTipSetByHeight func(context.Context, uint64, types.TipSetKey) (*types.TipSet, 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"` ChainReadObj func(context.Context, cid.Cid) ([]byte, error) `perm:"read"`
ChainHasObj func(context.Context, cid.Cid) (bool, error) `perm:"read"` ChainHasObj func(context.Context, cid.Cid) (bool, error) `perm:"read"`
ChainSetHead func(context.Context, types.TipSetKey) error `perm:"admin"` ChainSetHead func(context.Context, types.TipSetKey) error `perm:"admin"`
ChainGetGenesis func(context.Context) (*types.TipSet, error) `perm:"read"` ChainGetGenesis func(context.Context) (*types.TipSet, error) `perm:"read"`
ChainTipSetWeight func(context.Context, types.TipSetKey) (types.BigInt, 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"` ChainGetNode func(ctx context.Context, p string) (interface{}, error) `perm:"read"`
ChainGetMessage func(context.Context, cid.Cid) (*types.Message, 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"` ChainGetPath func(context.Context, types.TipSetKey, types.TipSetKey) ([]*store.HeadChange, error) `perm:"read"`
ChainExport func(context.Context, types.TipSetKey) (<-chan []byte, error) `perm:"read"` ChainExport func(context.Context, types.TipSetKey) (<-chan []byte, error) `perm:"read"`
SyncState func(context.Context) (*api.SyncState, error) `perm:"read"` SyncState func(context.Context) (*api.SyncState, error) `perm:"read"`
SyncSubmitBlock func(ctx context.Context, blk *types.BlockMsg) error `perm:"write"` 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"` SyncCheckBad func(ctx context.Context, bcid cid.Cid) (string, error) `perm:"read"`
MpoolPending func(context.Context, types.TipSetKey) ([]*types.SignedMessage, 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"` MpoolPush func(context.Context, *types.SignedMessage) (cid.Cid, error) `perm:"write"`
MpoolPushMessage func(context.Context, *types.Message) (*types.SignedMessage, error) `perm:"sign"` MpoolPushMessage func(context.Context, *types.Message) (*types.SignedMessage, error) `perm:"sign"`
MpoolGetNonce func(context.Context, address.Address) (uint64, error) `perm:"read"` MpoolGetNonce func(context.Context, address.Address) (uint64, error) `perm:"read"`
MpoolSub func(context.Context) (<-chan api.MpoolUpdate, 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"` WalletHas func(context.Context, address.Address) (bool, error) `perm:"write"`
WalletList func(context.Context) ([]address.Address, error) `perm:"write"` WalletList func(context.Context) ([]address.Address, error) `perm:"write"`
WalletBalance func(context.Context, address.Address) (types.BigInt, error) `perm:"read"` 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"` WalletSignMessage func(context.Context, address.Address, *types.Message) (*types.SignedMessage, error) `perm:"sign"`
WalletDefaultAddress func(context.Context) (address.Address, error) `perm:"write"` WalletDefaultAddress func(context.Context) (address.Address, error) `perm:"write"`
WalletSetDefault func(context.Context, address.Address) error `perm:"admin"` 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"` ClientGetDealInfo func(context.Context, cid.Cid) (*api.DealInfo, error) `perm:"read"`
ClientListDeals func(ctx context.Context) ([]api.DealInfo, error) `perm:"write"` ClientListDeals func(ctx context.Context) ([]api.DealInfo, error) `perm:"write"`
ClientRetrieve func(ctx context.Context, order api.RetrievalOrder, path string) error `perm:"admin"` 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"` 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"` 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"` 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"` 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"` 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"` StateMinerPostState func(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*miner.PoStState, error) `perm:"read"`
StateMinerSectorSize func(context.Context, address.Address, types.TipSetKey) (uint64, error) `perm:"read"` StateMinerSectorSize func(context.Context, address.Address, types.TipSetKey) (abi.SectorSize, error) `perm:"read"`
StateMinerFaults func(context.Context, address.Address, types.TipSetKey) ([]uint64, 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"` 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"` 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"` 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"` StateReadState func(context.Context, *types.Actor, types.TipSetKey) (*api.ActorState, error) `perm:"read"`
StatePledgeCollateral func(context.Context, types.TipSetKey) (types.BigInt, 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"` StateWaitMsg func(context.Context, cid.Cid) (*api.MsgWait, error) `perm:"read"`
StateListMiners func(context.Context, types.TipSetKey) ([]address.Address, 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"` StateListActors func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"`
StateMarketBalance func(context.Context, address.Address, types.TipSetKey) (actors.StorageParticipantBalance, error) `perm:"read"` StateMarketBalance func(context.Context, address.Address, types.TipSetKey) (api.MarketBalance, error) `perm:"read"`
StateMarketParticipants func(context.Context, types.TipSetKey) (map[string]actors.StorageParticipantBalance, error) `perm:"read"` StateMarketParticipants func(context.Context, types.TipSetKey) (map[string]api.MarketBalance, error) `perm:"read"`
StateMarketDeals func(context.Context, types.TipSetKey) (map[string]actors.OnChainDeal, error) `perm:"read"` StateMarketDeals func(context.Context, types.TipSetKey) (map[string]api.MarketDeal, error) `perm:"read"`
StateMarketStorageDeal func(context.Context, uint64, types.TipSetKey) (*actors.OnChainDeal, 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"` 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"` 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"` 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"` 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"` StateListMessages func(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) `perm:"read"`
StateCompute func(context.Context, uint64, []*types.Message, types.TipSetKey) (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"` 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"` PaychClose func(context.Context, address.Address) (cid.Cid, error) `perm:"sign"`
PaychAllocateLane func(context.Context, address.Address) (uint64, 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"` 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"` PaychVoucherCheck func(context.Context, *paych.SignedVoucher) error `perm:"read"`
PaychVoucherCheckValid func(context.Context, address.Address, *types.SignedVoucher) error `perm:"read"` PaychVoucherCheckValid func(context.Context, address.Address, *paych.SignedVoucher) error `perm:"read"`
PaychVoucherCheckSpendable func(context.Context, address.Address, *types.SignedVoucher, []byte, []byte) (bool, error) `perm:"read"` PaychVoucherCheckSpendable func(context.Context, address.Address, *paych.SignedVoucher, []byte, []byte) (bool, error) `perm:"read"`
PaychVoucherAdd func(context.Context, address.Address, *types.SignedVoucher, []byte, types.BigInt) (types.BigInt, error) `perm:"write"` PaychVoucherAdd func(context.Context, address.Address, *paych.SignedVoucher, []byte, types.BigInt) (types.BigInt, error) `perm:"write"`
PaychVoucherCreate func(context.Context, address.Address, types.BigInt, uint64) (*types.SignedVoucher, error) `perm:"sign"` PaychVoucherCreate func(context.Context, address.Address, big.Int, uint64) (*paych.SignedVoucher, error) `perm:"sign"`
PaychVoucherList func(context.Context, address.Address) ([]*types.SignedVoucher, error) `perm:"write"` PaychVoucherList func(context.Context, address.Address) ([]*paych.SignedVoucher, error) `perm:"write"`
PaychVoucherSubmit func(context.Context, address.Address, *types.SignedVoucher) (cid.Cid, error) `perm:"sign"` PaychVoucherSubmit func(context.Context, address.Address, *paych.SignedVoucher) (cid.Cid, error) `perm:"sign"`
} }
} }
@ -153,15 +158,15 @@ type StorageMinerStruct struct {
CommonStruct CommonStruct
Internal struct { Internal struct {
ActorAddress func(context.Context) (address.Address, error) `perm:"read"` ActorAddress func(context.Context) (address.Address, error) `perm:"read"`
ActorSectorSize func(context.Context, address.Address) (uint64, error) `perm:"read"` ActorSectorSize func(context.Context, address.Address) (abi.SectorSize, error) `perm:"read"`
PledgeSector func(context.Context) error `perm:"write"` PledgeSector func(context.Context) error `perm:"write"`
SectorsStatus func(context.Context, uint64) (api.SectorInfo, error) `perm:"read"` SectorsStatus func(context.Context, abi.SectorNumber) (api.SectorInfo, error) `perm:"read"`
SectorsList func(context.Context) ([]uint64, error) `perm:"read"` SectorsList func(context.Context) ([]abi.SectorNumber, error) `perm:"read"`
SectorsRefs func(context.Context) (map[string][]api.SealedRef, error) `perm:"read"` SectorsRefs func(context.Context) (map[string][]api.SealedRef, error) `perm:"read"`
SectorsUpdate func(context.Context, uint64, api.SectorState) error `perm:"write"` SectorsUpdate func(context.Context, abi.SectorNumber, api.SectorState) error `perm:"write"`
WorkerStats func(context.Context) (sectorbuilder.WorkerStats, error) `perm:"read"` 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) 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) 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) 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) 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) return c.Internal.ChainHead(ctx)
} }
func (c *FullNodeStruct) ChainGetRandomness(ctx context.Context, pts types.TipSetKey, round int64) ([]byte, error) { 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, pts, round) 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) 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) 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) 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) 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) return c.Internal.StateMinerPeerID(ctx, m, tsk)
} }
func (c *FullNodeStruct) StateMinerElectionPeriodStart(ctx context.Context, actor address.Address, tsk types.TipSetKey) (uint64, error) { func (c *FullNodeStruct) StateMinerPostState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*miner.PoStState, error) {
return c.Internal.StateMinerElectionPeriodStart(ctx, actor, tsk) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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 // 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) return c.Internal.SectorsStatus(ctx, sid)
} }
// List all staged sectors // 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) return c.Internal.SectorsList(ctx)
} }
@ -592,7 +597,7 @@ func (c *StorageMinerStruct) SectorsRefs(ctx context.Context) (map[string][]api.
return c.Internal.SectorsRefs(ctx) 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) return c.Internal.SectorsUpdate(ctx, id, state)
} }

View File

@ -6,7 +6,8 @@ import (
"fmt" "fmt"
"io" "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" cbg "github.com/whyrusleeping/cbor-gen"
xerrors "golang.org/x/xerrors" 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 { if len("Vouchers") > cbg.MaxLength {
return xerrors.Errorf("Value in field \"Vouchers\" was too long") 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": case "Vouchers":
maj, extra, err = cbg.CborReadHeader(br) maj, extra, err = cbg.CborReadHeader(br)
@ -168,11 +169,11 @@ func (t *PaymentInfo) UnmarshalCBOR(r io.Reader) error {
return fmt.Errorf("expected cbor array") return fmt.Errorf("expected cbor array")
} }
if extra > 0 { if extra > 0 {
t.Vouchers = make([]*types.SignedVoucher, extra) t.Vouchers = make([]*paych.SignedVoucher, extra)
} }
for i := 0; i < int(extra); i++ { for i := 0; i < int(extra); i++ {
var v types.SignedVoucher var v paych.SignedVoucher
if err := v.UnmarshalCBOR(br); err != nil { if err := v.UnmarshalCBOR(br); err != nil {
return err return err
} }
@ -196,7 +197,7 @@ func (t *SealedRef) MarshalCBOR(w io.Writer) error {
return err return err
} }
// t.SectorID (uint64) (uint64) // t.SectorID (abi.SectorNumber) (uint64)
if len("SectorID") > cbg.MaxLength { if len("SectorID") > cbg.MaxLength {
return xerrors.Errorf("Value in field \"SectorID\" was too long") return xerrors.Errorf("Value in field \"SectorID\" was too long")
} }
@ -228,7 +229,7 @@ func (t *SealedRef) MarshalCBOR(w io.Writer) error {
return err return err
} }
// t.Size (uint64) (uint64) // t.Size (abi.UnpaddedPieceSize) (uint64)
if len("Size") > cbg.MaxLength { if len("Size") > cbg.MaxLength {
return xerrors.Errorf("Value in field \"Size\" was too long") 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 { if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.Size))); err != nil {
return err return err
} }
return nil return nil
} }
@ -276,39 +278,51 @@ func (t *SealedRef) UnmarshalCBOR(r io.Reader) error {
} }
switch name { switch name {
// t.SectorID (uint64) (uint64) // t.SectorID (abi.SectorNumber) (uint64)
case "SectorID": 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) // t.Offset (uint64) (uint64)
case "Offset": 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 { // t.Size (abi.UnpaddedPieceSize) (uint64)
return fmt.Errorf("wrong type for uint64 field")
}
t.Offset = uint64(extra)
// t.Size (uint64) (uint64)
case "Size": 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: default:
return fmt.Errorf("unknown struct field %d: '%s'", i, name) 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 { if err != nil {
t.Fatal(err) 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 { 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 // 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" "context"
"github.com/filecoin-project/go-address" "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 { type Signable interface {
Sign(context.Context, SignFunc) error 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 { func SignWith(ctx context.Context, signer Signer, addr address.Address, signable ...Signable) error {
for _, s := range signable { 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) return signer(ctx, addr, b)
}) })
if err != nil { 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 package build
import (
"github.com/filecoin-project/specs-actors/actors/abi"
)
func init() { func init() {
InsecurePoStValidation = true InsecurePoStValidation = true
} }
var SectorSizes = []uint64{1024} var SectorSizes = []abi.SectorSize{1024}
// Seconds // Seconds
const BlockDelay = 6 const BlockDelay = 6

View File

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

View File

@ -2,7 +2,12 @@
package build 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, 32 << 30,
} }
@ -15,16 +20,13 @@ const PropagationDelay = 6
// ElectionPeriodStart before starting fallback post computation // ElectionPeriodStart before starting fallback post computation
// //
// Epochs // Epochs
const FallbackPoStDelay = 30 const FallbackPoStDelay = miner.ProvingPeriod
// SlashablePowerDelay is the number of epochs after ElectionPeriodStart, after // SlashablePowerDelay is the number of epochs after ElectionPeriodStart, after
// which the miner is slashed // which the miner is slashed
// //
// Epochs // Epochs
const SlashablePowerDelay = 200 const SlashablePowerDelay = miner.ProvingPeriod * 3 // TODO: remove
// Epochs
const InteractivePoRepDelay = 8
// Epochs // Epochs
const InteractivePoRepConfidence = 6 const InteractivePoRepConfidence = 6

View File

@ -5,7 +5,7 @@ import "fmt"
var CurrentCommit string var CurrentCommit string
// BuildVersion is the local build version, set by build system // BuildVersion is the local build version, set by build system
const BuildVersion = "0.2.8" const BuildVersion = "0.3.0"
var UserVersion = BuildVersion + CurrentCommit 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 // 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 ( const (
majorMask = 0xff0000 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" "testing"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/gen/genesis"
"github.com/filecoin-project/go-address" "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/actors"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm" "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 { 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), from: types.NewInt(1000000),
maddr: types.NewInt(0), maddr: types.NewInt(0),
} }
st, err := gen.MakeInitialStateTree(bs, actors) st, err := genesis.MakeInitialStateTree(bs, actors)
if err != nil { if err != nil {
t.Fatal(err) 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 { func Fatal(message string, args ...interface{}) ActorError {
return &actorError{ return &actorError{
fatal: true, 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" "math/rand"
"testing" "testing"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/go-sectorbuilder" "github.com/filecoin-project/go-sectorbuilder"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
@ -17,8 +19,9 @@ import (
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors" "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/state"
"github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
@ -49,7 +52,7 @@ type Harness struct {
Nonces map[address.Address]uint64 Nonces map[address.Address]uint64
GasCharges map[address.Address]types.BigInt GasCharges map[address.Address]types.BigInt
Rand vm.Rand Rand vm.Rand
BlockHeight uint64 BlockHeight abi.ChainEpoch
lastBalanceCheck map[address.Address]types.BigInt 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 { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -191,7 +194,7 @@ func NewHarness(t *testing.T, options ...HarnessOpt) *Harness {
t.Fatal(err) t.Fatal(err)
} }
stateroot, err = gen.SetupStorageMarketActor(h.bs, stateroot, nil) stateroot, err = genesis.SetupStorageMarketActor(h.bs, stateroot, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -7,10 +7,6 @@ import (
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
) )
var (
EmptyStructCBOR = []byte{0xa0}
)
func SerializeParams(i cbg.CBORMarshaler) ([]byte, aerrors.ActorError) { func SerializeParams(i cbg.CBORMarshaler) ([]byte, aerrors.ActorError) {
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
if err := i.MarshalCBOR(buf); err != nil { 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/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
incrt "github.com/filecoin-project/lotus/lib/increadtimeout" 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/node/modules/dtypes"
"github.com/filecoin-project/lotus/peermgr"
) )
type BlockSync struct { type BlockSync struct {

View File

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

View File

@ -5,6 +5,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
logging "github.com/ipfs/go-log/v2" logging "github.com/ipfs/go-log/v2"
"golang.org/x/xerrors" "golang.org/x/xerrors"
@ -19,7 +20,7 @@ import (
var log = logging.Logger("events") var log = logging.Logger("events")
// `curH`-`ts.Height` = `confidence` // `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 RevertHandler func(ctx context.Context, ts *types.TipSet) error
type heightHandler struct { type heightHandler struct {
@ -33,7 +34,7 @@ type heightHandler struct {
type eventApi interface { type eventApi interface {
ChainNotify(context.Context) (<-chan []*store.HeadChange, error) ChainNotify(context.Context) (<-chan []*store.HeadChange, error)
ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, 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) 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 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{ heightEvents: heightEvents{
tsc: tsc, tsc: tsc,
ctx: ctx, ctx: ctx,
gcConfidence: uint64(gcConfidence), gcConfidence: abi.ChainEpoch(gcConfidence),
heightTriggers: map[uint64]*heightHandler{}, heightTriggers: map[uint64]*heightHandler{},
htTriggerHeights: map[uint64][]uint64{}, htTriggerHeights: map[abi.ChainEpoch][]uint64{},
htHeights: map[uint64][]uint64{}, htHeights: map[abi.ChainEpoch][]uint64{},
}, },
calledEvents: calledEvents{ calledEvents: calledEvents{
@ -82,7 +83,7 @@ func NewEvents(ctx context.Context, api eventApi) *Events {
revertQueue: map[msgH][]triggerH{}, revertQueue: map[msgH][]triggerH{},
triggers: map[triggerId]*callHandler{}, triggers: map[triggerId]*callHandler{},
matchers: map[triggerId][]MatchFunc{}, 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" "math"
"sync" "sync"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"golang.org/x/xerrors" "golang.org/x/xerrors"
@ -12,20 +13,20 @@ import (
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
) )
const NoTimeout = math.MaxUint64 const NoTimeout = math.MaxInt64
type triggerId = uint64 type triggerId = uint64
// msgH is the block height at which a message was present / event has happened // 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 // triggerH is the block height at which the listener will be notified about the
// message (msgH+confidence) // message (msgH+confidence)
type triggerH = uint64 type triggerH = abi.ChainEpoch
// `ts` is the tipset, in which the `msg` is included. // `ts` is the tipset, in which the `msg` is included.
// `curH`-`ts.Height` = `confidence` // `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 // CheckFunc is used for atomicity guarantees. If the condition the callbacks
// wait for has already happened in tipset `ts` // wait for has already happened in tipset `ts`
@ -39,7 +40,7 @@ type MatchFunc func(msg *types.Message) (bool, error)
type callHandler struct { type callHandler struct {
confidence int confidence int
timeout uint64 timeout abi.ChainEpoch
disabled bool // TODO: GC after gcConfidence reached disabled bool // TODO: GC after gcConfidence reached
@ -50,7 +51,7 @@ type callHandler struct {
type queuedEvent struct { type queuedEvent struct {
trigger triggerId trigger triggerId
h uint64 h abi.ChainEpoch
msg *types.Message msg *types.Message
called bool called bool
@ -77,7 +78,7 @@ type calledEvents struct {
revertQueue map[msgH][]triggerH revertQueue map[msgH][]triggerH
// [timeoutH+confidence][triggerId]{calls} // [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 { func (e *calledEvents) headChangeCalled(rev, app []*types.TipSet) error {
@ -129,7 +130,7 @@ func (e *calledEvents) checkNewCalls(ts *types.TipSet) {
for _, matchFn := range matchFns { for _, matchFn := range matchFns {
ok, err := matchFn(msg) ok, err := matchFn(msg)
if err != nil { if err != nil {
log.Warnf("event matcher failed: %s") log.Warnf("event matcher failed: %s", err)
continue continue
} }
matched = ok 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 // messages are not applied in the tipset they are included in
appliedH := ts.Height() + 1 appliedH := ts.Height() + 1
triggerH := appliedH + uint64(trigger.confidence) triggerH := appliedH + abi.ChainEpoch(trigger.confidence)
byOrigH, ok := e.confQueue[triggerH] byOrigH, ok := e.confQueue[triggerH]
if !ok { if !ok {
byOrigH = map[uint64][]*queuedEvent{} byOrigH = map[abi.ChainEpoch][]*queuedEvent{}
e.confQueue[triggerH] = byOrigH e.confQueue[triggerH] = byOrigH
} }
@ -231,9 +232,9 @@ func (e *calledEvents) applyTimeouts(ts *types.TipSet) {
continue 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 { 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()) 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 // 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 // that is being dropped. Note that the message dropped may be re-applied
// in a different tipset in small amount of time. // 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() e.lk.Lock()
defer e.lk.Unlock() defer e.lk.Unlock()
@ -322,7 +323,7 @@ func (e *calledEvents) Called(check CheckFunc, hnd CalledHandler, rev RevertHand
e.triggers[id] = &callHandler{ e.triggers[id] = &callHandler{
confidence: confidence, confidence: confidence,
timeout: timeout + uint64(confidence), timeout: timeout + abi.ChainEpoch(confidence),
disabled: !more, disabled: !more,
@ -333,15 +334,15 @@ func (e *calledEvents) Called(check CheckFunc, hnd CalledHandler, rev RevertHand
e.matchers[id] = append(e.matchers[id], mf) e.matchers[id] = append(e.matchers[id], mf)
if timeout != NoTimeout { if timeout != NoTimeout {
if e.timeouts[timeout+uint64(confidence)] == nil { if e.timeouts[timeout+abi.ChainEpoch(confidence)] == nil {
e.timeouts[timeout+uint64(confidence)] = map[uint64]int{} 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 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())) return e.Called(e.CheckMsg(ctx, msg, hnd), hnd, rev, confidence, timeout, e.MatchMsg(msg.VMMessage()))
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -4,26 +4,29 @@ import (
"bytes" "bytes"
"context" "context"
"crypto/sha256" "crypto/sha256"
"encoding/binary"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"sync/atomic" "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" block "github.com/ipfs/go-block-format"
"github.com/ipfs/go-blockservice" "github.com/ipfs/go-blockservice"
"github.com/ipfs/go-car" "github.com/ipfs/go-car"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
blockstore "github.com/ipfs/go-ipfs-blockstore" blockstore "github.com/ipfs/go-ipfs-blockstore"
offline "github.com/ipfs/go-ipfs-exchange-offline" offline "github.com/ipfs/go-ipfs-exchange-offline"
format "github.com/ipfs/go-ipld-format"
logging "github.com/ipfs/go-log/v2" logging "github.com/ipfs/go-log/v2"
"github.com/ipfs/go-merkledag" "github.com/ipfs/go-merkledag"
peer "github.com/libp2p/go-libp2p-core/peer"
ffi "github.com/filecoin-project/filecoin-ffi" 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/api"
"github.com/filecoin-project/lotus/build" "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/stmgr"
"github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
@ -33,6 +36,7 @@ import (
"github.com/filecoin-project/lotus/genesis" "github.com/filecoin-project/lotus/genesis"
"github.com/filecoin-project/lotus/lib/sigs" "github.com/filecoin-project/lotus/lib/sigs"
"github.com/filecoin-project/lotus/node/repo" "github.com/filecoin-project/lotus/node/repo"
"github.com/filecoin-project/lotus/storage/sbmock"
"go.opencensus.io/trace" "go.opencensus.io/trace"
"golang.org/x/xerrors" "golang.org/x/xerrors"
@ -54,7 +58,7 @@ type ChainGen struct {
genesis *types.BlockHeader genesis *types.BlockHeader
CurTipset *store.FullTipSet CurTipset *store.FullTipSet
Timestamper func(*types.TipSet, uint64) uint64 Timestamper func(*types.TipSet, abi.ChainEpoch) uint64
GetMessages func(*ChainGen) ([]*types.SignedMessage, error) GetMessages func(*ChainGen) ([]*types.SignedMessage, error)
@ -112,74 +116,81 @@ func NewGenerator() (*ChainGen, error) {
return nil, xerrors.Errorf("creating memrepo wallet failed: %w", err) 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 { if err != nil {
return nil, xerrors.Errorf("failed to generate banker key: %w", err) return nil, xerrors.Errorf("failed to generate banker key: %w", err)
} }
receievers := make([]address.Address, msgsPerBlock) receievers := make([]address.Address, msgsPerBlock)
for r := range receievers { for r := range receievers {
receievers[r], err = w.GenerateKey(types.KTBLS) receievers[r], err = w.GenerateKey(crypto.SigTypeBLS)
if err != nil { if err != nil {
return nil, xerrors.Errorf("failed to generate receiver key: %w", err) return nil, xerrors.Errorf("failed to generate receiver key: %w", err)
} }
} }
maddr1, err := address.NewFromString("t0300") maddr1 := genesis2.MinerAddress(0)
if err != nil {
return nil, err
}
m1temp, err := ioutil.TempDir("", "preseal") m1temp, err := ioutil.TempDir("", "preseal")
if err != nil { if err != nil {
return nil, err 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 { if err != nil {
return nil, err return nil, err
} }
maddr2, err := address.NewFromString("t0301") maddr2 := genesis2.MinerAddress(1)
if err != nil {
return nil, err
}
m2temp, err := ioutil.TempDir("", "preseal") m2temp, err := ioutil.TempDir("", "preseal")
if err != nil { if err != nil {
return nil, err 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 { if err != nil {
return nil, err return nil, err
} }
mk1, err := w.Import(&genm1.Key) mk1, err := w.Import(k1)
if err != nil { if err != nil {
return nil, err return nil, err
} }
mk2, err := w.Import(&genm2.Key) mk2, err := w.Import(k2)
if err != nil { if err != nil {
return nil, err return nil, err
} }
minercfg := &GenMinerCfg{ sys := vm.Syscalls(&genFakeVerifier{})
PeerIDs: []peer.ID{"peerID1", "peerID2"},
PreSeals: map[string]genesis.GenesisMiner{ tpl := genesis.Template{
maddr1.String(): *genm1, Accounts: []genesis.Actor{
maddr2.String(): *genm2, {
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 := genesis2.MakeGenesisBlock(context.TODO(), bs, sys, tpl)
genb, err := MakeGenesisBlock(bs, sys, map[address.Address]types.BigInt{
mk1: types.FromFil(40000),
mk2: types.FromFil(40000),
banker: types.FromFil(50000),
}, minercfg, 100000)
if err != nil { if err != nil {
return nil, xerrors.Errorf("make genesis block failed: %w", err) 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) 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) mgen := make(map[address.Address]ElectionPoStProver)
for _, m := range minercfg.MinerAddrs { for i := range tpl.Miners {
mgen[m] = &eppProvider{} mgen[genesis2.MinerAddress(uint64(i))] = &eppProvider{}
} }
sm := stmgr.NewStateManager(cs) sm := stmgr.NewStateManager(cs)
miners := []address.Address{maddr1, maddr2}
gen := &ChainGen{ gen := &ChainGen{
bs: bs, bs: bs,
cs: cs, cs: cs,
@ -213,7 +222,7 @@ func NewGenerator() (*ChainGen, error) {
w: w, w: w,
GetMessages: getRandomMessages, GetMessages: getRandomMessages,
Miners: minercfg.MinerAddrs, Miners: miners,
eppProvs: mgen, eppProvs: mgen,
banker: banker, banker: banker,
receivers: receievers, receivers: receievers,
@ -246,16 +255,32 @@ func (cg *ChainGen) GenesisCar() ([]byte, error) {
out := new(bytes.Buffer) 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 nil, xerrors.Errorf("genesis car write car failed: %w", err)
} }
return out.Bytes(), nil 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() 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) 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 { if err != nil {
return nil, nil, xerrors.Errorf("compute VRF: %w", err) 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, 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 { if err != nil {
return nil, nil, xerrors.Errorf("checking round winner failed: %w", err) 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 { 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 { if err != nil {
return nil, xerrors.Errorf("making a block for next tipset failed: %w", err) 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 }, 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 var ts uint64
if cg.Timestamper != nil { if cg.Timestamper != nil {
ts = cg.Timestamper(parents, height-parents.Height()) ts = cg.Timestamper(parents, height-parents.Height())
} else { } 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) 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 { 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) StateMinerPower(context.Context, address.Address, types.TipSetKey) (api.MinerPower, error)
StateMinerWorker(context.Context, address.Address, types.TipSetKey) (address.Address, 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) 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 { type mca struct {
@ -435,8 +460,13 @@ type mca struct {
sm *stmgr.StateManager sm *stmgr.StateManager
} }
func (mca mca) ChainGetRandomness(ctx context.Context, pts types.TipSetKey, lb int64) ([]byte, error) { func (mca mca) ChainGetRandomness(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error) {
return mca.sm.ChainStore().GetRandomness(ctx, pts.Cids(), int64(lb)) 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) { 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) 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) ts, err := mca.sm.ChainStore().LoadTipSet(tsk)
if err != nil { if err != nil {
return 0, xerrors.Errorf("loading tipset %s: %w", tsk, err) 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) 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) 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) { func (epp *eppProvider) GenerateCandidates(ctx context.Context, _ sectorbuilder.SortedPublicSectorInfo, eprand []byte) ([]sectorbuilder.EPostCandidate, error) {
return []sectorbuilder.EPostCandidate{ return []sectorbuilder.EPostCandidate{
{ {
SectorID: 1, SectorNum: 1,
PartialTicket: [32]byte{}, PartialTicket: [32]byte{},
Ticket: [32]byte{}, Ticket: [32]byte{},
SectorChallengeIndex: 1, 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) { 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 { if err != nil {
return nil, xerrors.Errorf("chain get randomness: %w", err) 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) 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 { if err != nil {
return nil, xerrors.Errorf("failed to compute VRF: %w", err) 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 var sinfos []ffi.PublicSectorInfo
for _, s := range pset { 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 var commRa [32]byte
copy(commRa[:], s.CommR) copy(commRa[:], cr)
sinfos = append(sinfos, ffi.PublicSectorInfo{ sinfos = append(sinfos, ffi.PublicSectorInfo{
SectorID: s.SectorID, SectorNum: s.ID,
CommR: commRa, CommR: commRa,
}) })
} }
sectors := sectorbuilder.NewSortedPublicSectorInfo(sinfos) sectors := sectorbuilder.NewSortedPublicSectorInfo(sinfos)
@ -599,7 +633,7 @@ func ComputeProof(ctx context.Context, epp ElectionPoStProver, pi *ProofInput) (
copy(part, win.PartialTicket[:]) copy(part, win.PartialTicket[:])
ept.Candidates = append(ept.Candidates, types.EPostTicket{ ept.Candidates = append(ept.Candidates, types.EPostTicket{
Partial: part, Partial: part,
SectorID: win.SectorID, SectorID: win.SectorNum,
ChallengeIndex: win.SectorChallengeIndex, ChallengeIndex: win.SectorChallengeIndex,
}) })
} }
@ -607,42 +641,14 @@ func ComputeProof(ctx context.Context, epp ElectionPoStProver, pi *ProofInput) (
return &ept, nil 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 ( func VerifyVRF(ctx context.Context, worker address.Address, vrfBase, vrfproof []byte) error {
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 {
_, span := trace.StartSpan(ctx, "VerifyVRF") _, span := trace.StartSpan(ctx, "VerifyVRF")
defer span.End() defer span.End()
vrfBase, err := hashVRFBase(p, miner, input) sig := &crypto.Signature{
if err != nil { Type: crypto.SigTypeBLS,
return xerrors.Errorf("computing vrf base failed: %w", err)
}
sig := &types.Signature{
Type: types.KTBLS,
Data: vrfproof, Data: vrfproof,
} }
@ -653,20 +659,34 @@ func VerifyVRF(ctx context.Context, worker, miner address.Address, p uint64, inp
return nil return nil
} }
func ComputeVRF(ctx context.Context, sign SignFunc, worker, miner address.Address, p uint64, input []byte) ([]byte, error) { func ComputeVRF(ctx context.Context, sign SignFunc, worker address.Address, sigInput []byte) ([]byte, error) {
sigInput, err := hashVRFBase(p, miner, input)
if err != nil {
return nil, err
}
sig, err := sign(ctx, worker, sigInput) sig, err := sign(ctx, worker, sigInput)
if err != nil { if err != nil {
return nil, err 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 nil, fmt.Errorf("miner worker address was not a BLS key")
} }
return sig.Data, nil 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 ( import (
"testing" "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/build"
_ "github.com/filecoin-project/lotus/lib/sigs/bls" _ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/secp" _ "github.com/filecoin-project/lotus/lib/sigs/secp"
) )
func init() { func init() {
build.SectorSizes = []uint64{1024} build.SectorSizes = []abi.SectorSize{1024}
build.MinimumMinerPower = 1024 build.MinimumMinerPower = 1024
} }
func testGeneration(t testing.TB, n int, msgs int) { func testGeneration(t testing.TB, n int, msgs int) {
g, err := NewGenerator() g, err := NewGenerator()
if err != nil { if err != nil {
t.Fatal(err) t.Fatalf("%+v", err)
} }
g.msgsPerBlock = msgs g.msgsPerBlock = msgs
@ -24,7 +29,7 @@ func testGeneration(t testing.TB, n int, msgs int) {
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
mts, err := g.NextTipSet() mts, err := g.NextTipSet()
if err != nil { if err != nil {
t.Fatalf("error at H:%d, %s", i, err) t.Fatalf("error at H:%d, %+v", i, err)
} }
_ = mts _ = 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" bls "github.com/filecoin-project/filecoin-ffi"
amt "github.com/filecoin-project/go-amt-ipld/v2" 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" cid "github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
@ -18,7 +20,7 @@ import (
"github.com/filecoin-project/lotus/chain/wallet" "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) st, recpts, err := sm.TipSetState(ctx, parents)
if err != nil { if err != nil {
return nil, xerrors.Errorf("failed to load tipset state: %w", err) 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 secpkMessages []*types.SignedMessage
var blsMsgCids, secpkMsgCids []cid.Cid var blsMsgCids, secpkMsgCids []cid.Cid
var blsSigs []types.Signature var blsSigs []crypto.Signature
for _, msg := range msgs { for _, msg := range msgs {
if msg.Signature.TypeCode() == types.IKTBLS { if msg.Signature.Type == crypto.SigTypeBLS {
blsSigs = append(blsSigs, msg.Signature) blsSigs = append(blsSigs, msg.Signature)
blsMessages = append(blsMessages, &msg.Message) blsMessages = append(blsMessages, &msg.Message)
@ -131,7 +133,7 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wal
return fullBlock, nil return fullBlock, nil
} }
func aggregateSignatures(sigs []types.Signature) (types.Signature, error) { func aggregateSignatures(sigs []crypto.Signature) (crypto.Signature, error) {
var blsSigs []bls.Signature var blsSigs []bls.Signature
for _, s := range sigs { for _, s := range sigs {
var bsig bls.Signature var bsig bls.Signature
@ -140,8 +142,8 @@ func aggregateSignatures(sigs []types.Signature) (types.Signature, error) {
} }
aggSig := bls.Aggregate(blsSigs) aggSig := bls.Aggregate(blsSigs)
return types.Signature{ return crypto.Signature{
Type: types.KTBLS, Type: crypto.SigTypeBLS,
Data: aggSig[:], Data: aggSig[:],
}, nil }, 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" "context"
"sync" "sync"
"github.com/filecoin-project/specs-actors/actors/builtin"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
@ -40,7 +41,7 @@ func (fm *FundMgr) EnsureAvailable(ctx context.Context, addr address.Address, am
return err return err
} }
avail = bal.Available avail = types.BigSub(bal.Escrow, bal.Locked)
} }
toAdd := types.NewInt(0) toAdd := types.NewInt(0)
@ -55,13 +56,20 @@ func (fm *FundMgr) EnsureAvailable(ctx context.Context, addr address.Address, am
fm.lk.Unlock() fm.lk.Unlock()
var err error
params, err := actors.SerializeParams(&addr)
if err != nil {
return err
}
smsg, err := fm.mpool.MpoolPushMessage(ctx, &types.Message{ smsg, err := fm.mpool.MpoolPushMessage(ctx, &types.Message{
To: actors.StorageMarketAddress, To: builtin.StorageMarketActorAddr,
From: addr, From: addr,
Value: toAdd, Value: toAdd,
GasPrice: types.NewInt(0), GasPrice: types.NewInt(0),
GasLimit: types.NewInt(1000000), GasLimit: types.NewInt(1000000),
Method: actors.SMAMethods.AddBalance, Method: builtin.MethodsMarket.AddBalance,
Params: params,
}) })
if err != nil { if err != nil {
return err return err

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,23 +3,24 @@ package stmgr
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"go.opencensus.io/trace" "go.opencensus.io/trace"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/lotus/api" "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/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm" "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") ctx, span := trace.StartSpan(ctx, "statemanager.CallRaw")
defer span.End() 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 { if err != nil {
return nil, xerrors.Errorf("failed to set up vm: %w", err) return nil, xerrors.Errorf("failed to set up vm: %w", err)
} }

View File

@ -3,12 +3,13 @@ package stmgr
import ( import (
"context" "context"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/ipfs/go-cid" "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++ { for i := parentH; i < height; i++ {
f, ok := ForksAtHeight[i] f, ok := ForksAtHeight[i]
if ok { if ok {

View File

@ -7,6 +7,12 @@ import (
"testing" "testing"
"github.com/filecoin-project/go-address" "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/build"
"github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/aerrors" "github.com/filecoin-project/lotus/chain/actors/aerrors"
@ -28,7 +34,7 @@ import (
) )
func init() { func init() {
build.SectorSizes = []uint64{1024} build.SectorSizes = []abi.SectorSize{1024}
build.MinimumMinerPower = 1024 build.MinimumMinerPower = 1024
} }
@ -69,10 +75,14 @@ func (ta *testActor) Constructor(act *types.Actor, vmctx types.VMContext, params
if err != nil { if err != nil {
return nil, err 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()) 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) { 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) t.Fatal(err)
} }
actors.BuiltInActors[actcid] = true
// predicting the address here... may break if other assumptions change // predicting the address here... may break if other assumptions change
taddr, err := address.NewIDAddress(1000) taddr, err := address.NewIDAddress(1000)
if err != nil { if err != nil {
@ -156,7 +164,7 @@ func TestForkHeightTriggers(t *testing.T) {
} }
inv.Register(actcid, &testActor{}, &testActorState{}) 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) nvm, err := vm.NewVM(c, h, r, a, b, s)
if err != nil { if err != nil {
return nil, err return nil, err
@ -169,15 +177,15 @@ func TestForkHeightTriggers(t *testing.T) {
var msgs []*types.SignedMessage var msgs []*types.SignedMessage
enc, err := actors.SerializeParams(&actors.ExecParams{Code: actcid}) enc, err := actors.SerializeParams(&init_.ExecParams{CodeCID: actcid})
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
m := &types.Message{ m := &types.Message{
From: cg.Banker(), From: cg.Banker(),
To: actors.InitAddress, To: builtin.InitActorAddr,
Method: actors.IAMethods.Exec, Method: builtin.MethodsInit.Exec,
Params: enc, Params: enc,
GasLimit: types.NewInt(10000), GasLimit: types.NewInt(10000),
GasPrice: types.NewInt(0), GasPrice: types.NewInt(0),

View File

@ -7,11 +7,17 @@ import (
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
amt "github.com/filecoin-project/go-amt-ipld/v2" 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/state"
"github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm" "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" cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors" "golang.org/x/xerrors"
@ -32,7 +38,7 @@ type StateManager struct {
stCache map[string][]cid.Cid stCache map[string][]cid.Cid
compWait map[string]chan struct{} compWait map[string]chan struct{}
stlk sync.Mutex 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 { 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) 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 { if err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("failed to get network actor: %w", err) return cid.Undef, cid.Undef, xerrors.Errorf("failed to get network actor: %w", err)
} }
reward := vm.MiningReward(netact.Balance) reward := vm.MiningReward(rewardActor.Balance)
for tsi, b := range blks { for _, b := range blks {
netact, err = vmi.StateTree().GetActor(actors.NetworkAddress) rewardActor, err = vmi.StateTree().GetActor(builtin.RewardActorAddr)
if err != nil { if err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("failed to get network actor: %w", err) 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") 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) 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 // 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 // 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 { if err != nil {
return cid.Undef, cid.Undef, err return cid.Undef, cid.Undef, err
} }
ret, err := vmi.ApplyMessage(ctx, &types.Message{ ret, err := vmi.ApplyMessage(ctx, &types.Message{
To: actors.CronAddress, To: builtin.CronActorAddr,
From: actors.CronAddress, From: builtin.SystemActorAddr,
Nonce: ca.Nonce, Nonce: ca.Nonce,
Value: types.NewInt(0), Value: types.NewInt(0),
GasPrice: types.NewInt(0), GasPrice: types.NewInt(0),
GasLimit: types.NewInt(1 << 30), // Make super sure this is never too little GasLimit: types.NewInt(1 << 30), // Make super sure this is never too little
Method: actors.CAMethods.EpochTick, Method: builtin.MethodsCron.EpochTick,
Params: nil, Params: nil,
}) })
if err != nil { if err != nil {
@ -295,15 +283,27 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
return st, rectroot, nil 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 { if ts == nil {
ts = sm.cs.GetHeaviestTipSet() 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()) 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 { if err != nil {
return nil, xerrors.Errorf("load state tree: %w", err) 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()) cst := cbor.NewCborStore(sm.cs.Blockstore())
if err := cst.Get(ctx, act.Head, out); err != nil { 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 nil, err
} }
return act, nil 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) { func (sm *StateManager) ResolveToKeyAddress(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
switch addr.Protocol() { switch addr.Protocol() {
case address.BLS, address.SECP256K1: case address.BLS, address.SECP256K1:
@ -381,6 +400,15 @@ func (sm *StateManager) GetBlsPublicKey(ctx context.Context, addr address.Addres
return pubk, nil 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) { func (sm *StateManager) GetReceipt(ctx context.Context, msg cid.Cid, ts *types.TipSet) (*types.MessageReceipt, error) {
m, err := sm.cs.GetCMessage(msg) m, err := sm.cs.GetCMessage(msg)
if err != nil { if err != nil {
@ -577,7 +605,7 @@ func (sm *StateManager) ListAllActors(ctx context.Context, ts *types.TipSet) ([]
} }
cst := cbor.NewCborStore(sm.cs.Blockstore()) 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 { if err != nil {
return nil, err return nil, err
} }
@ -598,18 +626,49 @@ func (sm *StateManager) ListAllActors(ctx context.Context, ts *types.TipSet) ([]
return out, nil return out, nil
} }
func (sm *StateManager) MarketBalance(ctx context.Context, addr address.Address, ts *types.TipSet) (actors.StorageParticipantBalance, error) { func (sm *StateManager) MarketBalance(ctx context.Context, addr address.Address, ts *types.TipSet) (api.MarketBalance, error) {
var state actors.StorageMarketState var state market.State
if _, err := sm.LoadActorState(ctx, actors.StorageMarketAddress, &state, ts); err != nil { _, err := sm.LoadActorState(ctx, builtin.StorageMarketActorAddr, &state, ts)
return actors.StorageParticipantBalance{}, err
}
cst := cbor.NewCborStore(sm.cs.Blockstore())
b, _, err := actors.GetMarketBalances(ctx, cst, state.Balances, addr)
if err != nil { 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 { 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 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 sm.newVM = nvm
} }

View File

@ -2,17 +2,27 @@ package stmgr
import ( import (
"context" "context"
"github.com/filecoin-project/lotus/chain/state"
amt "github.com/filecoin-project/go-amt-ipld/v2" 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" "github.com/filecoin-project/lotus/chain/actors/aerrors"
ffi "github.com/filecoin-project/filecoin-ffi"
sectorbuilder "github.com/filecoin-project/go-sectorbuilder" sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
ffi "github.com/filecoin-project/filecoin-ffi"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/api" "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/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm" "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) { func GetMinerWorkerRaw(ctx context.Context, sm *StateManager, st cid.Cid, maddr address.Address) (address.Address, error) {
recp, err := sm.CallRaw(ctx, &types.Message{ var mas miner.State
To: maddr, _, err := sm.LoadActorStateRaw(ctx, maddr, &mas, st)
From: maddr,
Method: actors.MAMethods.GetWorkerAddr,
}, st, nil, 0)
if err != nil { 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 { cst := cbor.NewCborStore(sm.cs.Blockstore())
return address.Undef, xerrors.Errorf("getting miner worker addr failed (exit code %d)", recp.ExitCode) state, err := state.LoadStateTree(cst, st)
}
worker, err := address.NewFromBytes(recp.Return)
if err != nil { if err != nil {
return address.Undef, err return address.Undef, xerrors.Errorf("load state tree: %w", err)
} }
if worker.Protocol() == address.ID { return vm.ResolveToKeyAddr(state, cst, mas.Info.Worker)
return address.Undef, xerrors.Errorf("need to resolve worker address to a pubkeyaddr")
}
return worker, nil
} }
func GetMinerOwner(ctx context.Context, sm *StateManager, st cid.Cid, maddr address.Address) (address.Address, error) { func GetMinerOwner(ctx context.Context, sm *StateManager, st cid.Cid, maddr address.Address) (address.Address, error) {
recp, err := sm.CallRaw(ctx, &types.Message{ var mas miner.State
To: maddr, _, err := sm.LoadActorStateRaw(ctx, maddr, &mas, st)
From: maddr,
Method: actors.MAMethods.GetOwner,
}, st, nil, 0)
if err != nil { 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 { cst := cbor.NewCborStore(sm.cs.Blockstore())
return address.Undef, xerrors.Errorf("getting miner owner addr failed (exit code %d)", recp.ExitCode) state, err := state.LoadStateTree(cst, st)
}
owner, err := address.NewFromBytes(recp.Return)
if err != nil { if err != nil {
return address.Undef, err return address.Undef, xerrors.Errorf("load state tree: %w", err)
} }
if owner.Protocol() == address.ID { return vm.ResolveToKeyAddr(state, cst, mas.Info.Owner)
return address.Undef, xerrors.Errorf("need to resolve owner address to a pubkeyaddr")
}
return owner, nil
} }
func GetPower(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (types.BigInt, types.BigInt, error) { func GetPower(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (types.BigInt, types.BigInt, error) {
var err error var ps power.State
_, err := sm.LoadActorState(ctx, builtin.StoragePowerActorAddr, &ps, ts)
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)
if err != nil { if err != nil {
return types.EmptyInt, types.EmptyInt, xerrors.Errorf("failed to get total power from chain: %w", err) return big.Zero(), big.Zero(), xerrors.Errorf("(get sset) failed to load power actor state: %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)
} }
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) { func GetMinerPeerID(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (peer.ID, error) {
recp, err := sm.Call(ctx, &types.Message{ var mas miner.State
To: maddr, _, err := sm.LoadActorState(ctx, maddr, &mas, ts)
From: maddr,
Method: actors.MAMethods.GetPeerID,
}, ts)
if err != nil { 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 mas.Info.PeerId, nil
return "", xerrors.Errorf("getting miner peer ID failed (exit code %d)", recp.ExitCode)
}
return peer.IDFromBytes(recp.Return)
} }
func GetMinerWorker(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (address.Address, error) { func GetMinerWorker(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (address.Address, error) {
recp, err := sm.Call(ctx, &types.Message{ return GetMinerWorkerRaw(ctx, sm, sm.parentState(ts), maddr)
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)
} }
func GetMinerElectionPeriodStart(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (uint64, error) { func GetMinerPostState(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (*miner.PoStState, error) {
var mas actors.StorageMinerActorState var mas miner.State
_, err := sm.LoadActorState(ctx, maddr, &mas, ts) _, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil { 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) { 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) _, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil { if err != nil {
return api.MinerSectors{}, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err) 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) { 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) _, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil { if err != nil {
return nil, xerrors.Errorf("(get pset) failed to load miner actor state: %w", err) 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) { 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) _, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil { if err != nil {
return nil, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err) 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 var uselessOtherArray []ffi.PublicSectorInfo
for _, s := range sectors { for _, s := range sectors {
cr, err := commcid.CIDToReplicaCommitmentV1(s.Info.Info.SealedCID)
if err != nil {
return nil, err
}
var uselessBuffer [32]byte var uselessBuffer [32]byte
copy(uselessBuffer[:], s.CommR) copy(uselessBuffer[:], cr)
uselessOtherArray = append(uselessOtherArray, ffi.PublicSectorInfo{ uselessOtherArray = append(uselessOtherArray, ffi.PublicSectorInfo{
SectorID: s.SectorID, SectorNum: s.ID,
CommR: uselessBuffer, CommR: uselessBuffer,
}) })
} }
@ -228,34 +179,23 @@ func GetSectorsForElectionPost(ctx context.Context, sm *StateManager, ts *types.
return &ssi, nil return &ssi, nil
} }
func GetMinerSectorSize(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (uint64, error) { func GetMinerSectorSize(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (abi.SectorSize, error) {
var mas actors.StorageMinerActorState var mas miner.State
_, err := sm.LoadActorState(ctx, maddr, &mas, ts) _, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil { if err != nil {
return 0, xerrors.Errorf("(get ssize) failed to load miner actor state: %w", err) return 0, xerrors.Errorf("(get ssize) failed to load miner actor state: %w", err)
} }
cst := cbor.NewCborStore(sm.cs.Blockstore()) return mas.Info.SectorSize, nil
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
} }
func GetMinerSlashed(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (uint64, error) { func GetMinerSlashed(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (uint64, error) {
var mas actors.StorageMinerActorState log.Warn("stub GetMinerSlashed")
_, err := sm.LoadActorState(ctx, maddr, &mas, ts) return 0, nil
if err != nil {
return 0, xerrors.Errorf("(get mslash) failed to load miner actor state: %w", err)
}
return mas.SlashedAt, nil
} }
func GetMinerFaults(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) ([]uint64, error) { func GetMinerFaults(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) ([]abi.SectorNumber, error) {
var mas actors.StorageMinerActorState var mas miner.State
_, err := sm.LoadActorState(ctx, maddr, &mas, ts) _, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil { if err != nil {
return nil, xerrors.Errorf("(get ssize) failed to load miner actor state: %w", err) 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 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) { func GetStorageDeal(ctx context.Context, sm *StateManager, dealId abi.DealID, ts *types.TipSet) (*api.MarketDeal, error) {
var state actors.StorageMarketState var state market.State
if _, err := sm.LoadActorState(ctx, actors.StorageMarketAddress, &state, ts); err != nil { if _, err := sm.LoadActorState(ctx, builtin.StorageMarketActorAddr, &state, ts); err != nil {
return nil, err 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 { if err != nil {
return nil, err return nil, err
} }
var ocd actors.OnChainDeal var dp market.DealProposal
if err := da.Get(ctx, dealId, &ocd); err != nil { if err := da.Get(ctx, uint64(dealId), &dp); err != nil {
return nil, err 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) { func ListMinerActors(ctx context.Context, sm *StateManager, ts *types.TipSet) ([]address.Address, error) {
var state actors.StoragePowerState var state power.State
if _, err := sm.LoadActorState(ctx, actors.StoragePowerAddress, &state, ts); err != nil { if _, err := sm.LoadActorState(ctx, builtin.StoragePowerActorAddr, &state, ts); err != nil {
return nil, err return nil, err
} }
cst := cbor.NewCborStore(sm.ChainStore().Blockstore()) var miners []address.Address
miners, err := actors.MinerSetList(ctx, cst, state.Miners) 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 { if err != nil {
return nil, err return nil, err
} }
@ -311,14 +277,13 @@ func LoadSectorsFromSet(ctx context.Context, bs blockstore.Blockstore, ssc cid.C
var sset []*api.ChainSectorInfo var sset []*api.ChainSectorInfo
if err := a.ForEach(ctx, func(i uint64, v *cbg.Deferred) error { if err := a.ForEach(ctx, func(i uint64, v *cbg.Deferred) error {
var comms [][]byte var oci miner.SectorOnChainInfo
if err := cbor.DecodeInto(v.Raw, &comms); err != nil { if err := cbor.DecodeInto(v.Raw, &oci); err != nil {
return err return err
} }
sset = append(sset, &api.ChainSectorInfo{ sset = append(sset, &api.ChainSectorInfo{
SectorID: i, Info: oci,
CommR: comms[0], ID: abi.SectorNumber(i),
CommD: comms[1],
}) })
return nil return nil
}); err != nil { }); err != nil {
@ -328,7 +293,7 @@ func LoadSectorsFromSet(ctx context.Context, bs blockstore.Blockstore, ssc cid.C
return sset, nil 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 { if ts == nil {
ts = sm.cs.GetHeaviestTipSet() 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) 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 { if err != nil {
return cid.Undef, err return cid.Undef, err
} }

View File

@ -3,20 +3,26 @@ package store
import ( import (
"bytes" "bytes"
"context" "context"
"crypto/sha256"
"encoding/binary" "encoding/binary"
"encoding/json" "encoding/json"
"github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/minio/blake2b-simd"
"io" "io"
"sync" "sync"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/specs-actors/actors/util/adt"
"go.opencensus.io/trace" "go.opencensus.io/trace"
"go.uber.org/multierr" "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" amt "github.com/filecoin-project/go-amt-ipld/v2"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
lru "github.com/hashicorp/golang-lru" lru "github.com/hashicorp/golang-lru"
@ -51,7 +57,7 @@ type ChainStore struct {
pubLk sync.Mutex pubLk sync.Mutex
tstLk sync.Mutex tstLk sync.Mutex
tipsets map[uint64][]cid.Cid tipsets map[abi.ChainEpoch][]cid.Cid
reorgCh chan<- reorg reorgCh chan<- reorg
headChangeNotifs []func(rev, app []*types.TipSet) error headChangeNotifs []func(rev, app []*types.TipSet) error
@ -59,17 +65,17 @@ type ChainStore struct {
mmCache *lru.ARCCache mmCache *lru.ARCCache
tsCache *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) c, _ := lru.NewARC(2048)
tsc, _ := lru.NewARC(4096) tsc, _ := lru.NewARC(4096)
cs := &ChainStore{ cs := &ChainStore{
bs: bs, bs: bs,
ds: ds, ds: ds,
bestTips: pubsub.New(64), bestTips: pubsub.New(64),
tipsets: make(map[uint64][]cid.Cid), tipsets: make(map[abi.ChainEpoch][]cid.Cid),
mmCache: c, mmCache: c,
tsCache: tsc, tsCache: tsc,
vmcalls: vmcalls, vmcalls: vmcalls,
@ -829,7 +835,35 @@ func (cs *ChainStore) Blockstore() bstore.Blockstore {
return cs.bs 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 return cs.vmcalls
} }
@ -855,22 +889,30 @@ func (cs *ChainStore) TryFillTipSet(ts *types.TipSet) (*FullTipSet, error) {
return NewFullTipSet(out), nil return NewFullTipSet(out), nil
} }
func drawRandomness(t *types.Ticket, round int64) []byte { func drawRandomness(t *types.Ticket, pers crypto.DomainSeparationTag, round int64, entropy []byte) ([]byte, error) {
h := sha256.New() // TODO: Make this spec compliant
var buf [8]byte h := blake2b.New256()
binary.LittleEndian.PutUint64(buf[:], uint64(round)) 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(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") _, span := trace.StartSpan(ctx, "store.GetRandomness")
defer span.End() defer span.End()
span.AddAttributes(trace.Int64Attribute("round", round)) span.AddAttributes(trace.Int64Attribute("round", round))
defer func() {
log.Infof("getRand %v %d %d %x -> %x", blks, pers, round, entropy, out)
}()
for { for {
nts, err := cs.LoadTipSet(types.NewTipSetKey(blks...)) nts, err := cs.LoadTipSet(types.NewTipSetKey(blks...))
if err != nil { if err != nil {
@ -880,7 +922,7 @@ func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, round i
mtb := nts.MinTicketBlock() mtb := nts.MinTicketBlock()
if int64(nts.Height()) <= round { 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 // 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 { if mtb.Height == 0 {
// round is negative // 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 // for negative lookbacks, just use the hash of the positive tickethash value
h := sha256.Sum256(thash) h := blake2b.Sum256(thash)
return h[:], nil 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 { if ts == nil {
ts = cs.GetHeaviestTipSet() ts = cs.GetHeaviestTipSet()
} }
@ -1007,10 +1052,10 @@ func (cs *ChainStore) Import(r io.Reader) (*types.TipSet, error) {
type chainRand struct { type chainRand struct {
cs *ChainStore cs *ChainStore
blks []cid.Cid 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{ return &chainRand{
cs: cs, cs: cs,
blks: blks, 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) { func (cr *chainRand) GetRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round int64, entropy []byte) ([]byte, error) {
return cr.cs.GetRandomness(ctx, cr.blks, round) return cr.cs.GetRandomness(ctx, cr.blks, pers, round, entropy)
} }
func (cs *ChainStore) GetTipSetFromKey(tsk types.TipSetKey) (*types.TipSet, error) { 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/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/repo" "github.com/filecoin-project/lotus/node/repo"
"github.com/filecoin-project/specs-actors/actors/abi"
blockstore "github.com/ipfs/go-ipfs-blockstore" blockstore "github.com/ipfs/go-ipfs-blockstore"
) )
func init() { func init() {
build.SectorSizes = []uint64{1024} build.SectorSizes = []abi.SectorSize{1024}
build.MinimumMinerPower = 1024 build.MinimumMinerPower = 1024
} }

View File

@ -5,9 +5,13 @@ import (
"math/big" "math/big"
"github.com/filecoin-project/lotus/build" "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/types"
"github.com/filecoin-project/lotus/chain/vm" "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" "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) // >>> 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{ tpow := big2.Zero()
From: actors.StoragePowerAddress, {
To: actors.StoragePowerAddress, cst := cbor.NewCborStore(cs.Blockstore())
Method: actors.SPAMethods.GetTotalStorage, state, err := state.LoadStateTree(cst, ts.ParentState())
}, ts) if err != nil {
if err != nil { return types.NewInt(0), xerrors.Errorf("load state tree: %w", err)
return types.EmptyInt, xerrors.Errorf("failed to get total power from chain: %w", err) }
}
if ret.ExitCode != 0 { act, err := state.GetActor(builtin.StoragePowerActorAddr)
return types.EmptyInt, xerrors.Errorf("failed to get total power from chain (exit code %d)", ret.ExitCode) 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) log2P := int64(0)
tpow := types.BigFromBytes(ret.Return)
if tpow.GreaterThan(zero) { if tpow.GreaterThan(zero) {
log2P = int64(tpow.BitLen() - 1) log2P = int64(tpow.BitLen() - 1)
} else { } 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()) 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 { if err != nil {
return nil, xerrors.Errorf("failed to set up vm: %w", err) return nil, xerrors.Errorf("failed to set up vm: %w", err)
} }

View File

@ -1,18 +1,20 @@
package chain package chain
import ( import (
"bytes"
"context" "context"
"crypto/sha256" "crypto/sha256"
"errors" "errors"
"fmt" "fmt"
"github.com/filecoin-project/specs-actors/actors/builtin"
"sync" "sync"
"time" "time"
"github.com/Gurpartap/async" "github.com/Gurpartap/async"
bls "github.com/filecoin-project/filecoin-ffi"
amt "github.com/filecoin-project/go-amt-ipld/v2" amt "github.com/filecoin-project/go-amt-ipld/v2"
sectorbuilder "github.com/filecoin-project/go-sectorbuilder" 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/hashicorp/go-multierror"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
dstore "github.com/ipfs/go-datastore" dstore "github.com/ipfs/go-datastore"
@ -26,11 +28,12 @@ import (
"go.opencensus.io/trace" "go.opencensus.io/trace"
"golang.org/x/xerrors" "golang.org/x/xerrors"
bls "github.com/filecoin-project/filecoin-ffi"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build" "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/blocksync"
"github.com/filecoin-project/lotus/chain/gen" "github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/state" "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 { func (syncer *Syncer) minerIsValid(ctx context.Context, maddr address.Address, baseTs *types.TipSet) error {
var err error var spast power.State
enc, err := actors.SerializeParams(&actors.IsValidMinerParam{Addr: maddr})
_, err := syncer.sm.LoadActorState(ctx, builtin.StoragePowerActorAddr, &spast, baseTs)
if err != nil { if err != nil {
return err return err
} }
ret, err := syncer.sm.Call(ctx, &types.Message{ var claim power.Claim
To: actors.StoragePowerAddress, exist, err := adt.AsMap(syncer.store.Store(ctx), spast.Claims).Get(adt.AddrKey(maddr), &claim)
From: maddr,
Method: actors.SPAMethods.IsValidMiner,
Params: enc,
}, baseTs)
if err != nil { if err != nil {
return xerrors.Errorf("checking if block miner is valid failed: %w", err) return err
} }
if !exist {
if ret.ExitCode != 0 {
return xerrors.Errorf("StorageMarket.IsValidMiner check failed (exit code %d)", ret.ExitCode)
}
if !bytes.Equal(ret.Return, cbg.CborBoolTrue) {
return xerrors.New("miner isn't valid") return xerrors.New("miner isn't valid")
} }
return nil 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()) 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()) 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 { 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) 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 { if len(h.EPostProof.Candidates) == 0 {
return xerrors.Errorf("no candidates") 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 { tktsCheck := async.Err(func() error {
vrfBase := baseTs.MinTicket().VRFProof vrfBase, err := syncer.sm.ChainStore().GetRandomness(ctx, baseTs.Cids(), crypto.DomainSeparationTag_TicketProduction, int64(baseTs.Height()), h.Miner.Bytes())
if err != nil {
err := gen.VerifyVRF(ctx, waddr, h.Miner, gen.DSepTicket, vrfBase, h.Ticket.VRFProof) 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 { if err != nil {
return xerrors.Errorf("validating block tickets failed: %w", err) 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 { 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 { if err != nil {
return xerrors.Errorf("failed to get randomness for verifying election proof: %w", err) 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) 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) copy(partial[:], t.Partial)
winners = append(winners, sectorbuilder.EPostCandidate{ winners = append(winners, sectorbuilder.EPostCandidate{
PartialTicket: partial, PartialTicket: partial,
SectorID: t.SectorID, SectorNum: t.SectorID,
SectorChallengeIndex: t.ChallengeIndex, SectorChallengeIndex: t.ChallengeIndex,
}) })
} }
@ -825,7 +823,7 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock
return nil 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") _, span := trace.StartSpan(ctx, "syncer.verifyBlsAggregate")
defer span.End() defer span.End()
span.AddAttributes( span.AddAttributes(
@ -1119,8 +1117,8 @@ func persistMessages(bs bstore.Blockstore, bst *blocksync.BSTipSet) error {
} }
} }
for _, m := range bst.SecpkMessages { for _, m := range bst.SecpkMessages {
if m.Signature.Type != types.KTSecp256k1 { if m.Signature.Type != crypto.SigTypeSecp256k1 {
return xerrors.Errorf("unknown signature type on message %s: %q", m.Cid(), m.Signature.TypeCode) return xerrors.Errorf("unknown signature type on message %s: %q", m.Cid(), m.Signature.Type)
} }
//log.Infof("putting secp256k1 message: %s", m.Cid()) //log.Infof("putting secp256k1 message: %s", m.Cid())
if _, err := store.PutMessage(bs, m); err != nil { 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 return nil
} }
func VerifyElectionPoStVRF(ctx context.Context, evrf []byte, rand []byte, worker, miner address.Address) error { func VerifyElectionPoStVRF(ctx context.Context, evrf []byte, rand []byte, worker address.Address) error {
if err := gen.VerifyVRF(ctx, worker, miner, gen.DSepElectionPost, rand, evrf); err != nil { if err := gen.VerifyVRF(ctx, worker, rand, evrf); err != nil {
return xerrors.Errorf("failed to verify post_randomness vrf: %w", err) return xerrors.Errorf("failed to verify post_randomness vrf: %w", err)
} }

View File

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

View File

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

View File

@ -1,12 +1,12 @@
package types package types
import ( import (
"fmt"
"github.com/ipfs/go-cid" "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 { type Actor struct {
Code cid.Cid 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 package types
import ( import (
"encoding/json"
"fmt" "fmt"
"io"
"math/big" "math/big"
"github.com/filecoin-project/lotus/build" big2 "github.com/filecoin-project/specs-actors/actors/abi/big"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/polydawn/refmt/obj/atlas"
cbg "github.com/whyrusleeping/cbor-gen" "github.com/filecoin-project/lotus/build"
"golang.org/x/xerrors"
) )
const BigIntMaxSerializedLen = 128 // is this big enough? or too big? const BigIntMaxSerializedLen = 128 // is this big enough? or too big?
var TotalFilecoinInt = FromFil(build.TotalFilecoin) 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{} var EmptyInt = BigInt{}
type BigInt struct { type BigInt = big2.Int
*big.Int
}
func NewInt(i uint64) BigInt { func NewInt(i uint64) BigInt {
return BigInt{big.NewInt(0).SetUint64(i)} return BigInt{big.NewInt(0).SetUint64(i)}
@ -83,50 +63,9 @@ func BigCmp(a, b BigInt) int {
return a.Int.Cmp(b.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"} 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) r := new(big.Rat).SetInt(bi.Int)
den := big.NewRat(1, 1024) den := big.NewRat(1, 1024)
@ -139,121 +78,3 @@ func (bi BigInt) SizeStr() string {
f, _ := r.Float64() f, _ := r.Float64()
return fmt.Sprintf("%.3g %s", f, sizeUnits[i]) 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 { 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 := big.NewInt(50000)
ZiB = ZiB.Lsh(ZiB, 70) 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" "bytes"
"math/big" "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" block "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/minio/sha256-simd" "github.com/minio/sha256-simd"
@ -21,7 +24,7 @@ type Ticket struct {
type EPostTicket struct { type EPostTicket struct {
Partial []byte Partial []byte
SectorID uint64 SectorID abi.SectorNumber
ChallengeIndex uint64 ChallengeIndex uint64
} }
@ -42,7 +45,7 @@ type BlockHeader struct {
ParentWeight BigInt // 4 ParentWeight BigInt // 4
Height uint64 // 5 Height abi.ChainEpoch // 5
ParentStateRoot cid.Cid // 6 ParentStateRoot cid.Cid // 6
@ -50,11 +53,11 @@ type BlockHeader struct {
Messages cid.Cid // 8 Messages cid.Cid // 8
BLSAggregate Signature // 9 BLSAggregate crypto.Signature // 9
Timestamp uint64 // 10 Timestamp uint64 // 10
BlockSig *Signature // 11 BlockSig *crypto.Signature // 11
ForkSignaling uint64 // 12 ForkSignaling uint64 // 12
} }
@ -163,8 +166,8 @@ var blocksPerEpoch = NewInt(build.BlocksPerEpoch)
const sha256bits = 256 const sha256bits = 256
func IsTicketWinner(partialTicket []byte, ssizeI uint64, snum uint64, totpow BigInt) bool { func IsTicketWinner(partialTicket []byte, ssizeI abi.SectorSize, snum uint64, totpow BigInt) bool {
ssize := NewInt(ssizeI) ssize := NewInt(uint64(ssizeI))
ssampled := ElectionPostChallengeCount(snum, 0) // TODO: faults in epost? ssampled := ElectionPostChallengeCount(snum, 0) // TODO: faults in epost?
/* /*
Need to check that Need to check that

View File

@ -7,6 +7,7 @@ import (
"testing" "testing"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/crypto"
cid "github.com/ipfs/go-cid" cid "github.com/ipfs/go-cid"
) )
@ -34,12 +35,12 @@ func testBlockHeader(t testing.TB) *BlockHeader {
}, },
Parents: []cid.Cid{c, c}, Parents: []cid.Cid{c, c},
ParentMessageReceipts: 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), ParentWeight: NewInt(123125126212),
Messages: c, Messages: c,
Height: 85919298723, Height: 85919298723,
ParentStateRoot: c, 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" "bytes"
"fmt" "fmt"
"github.com/filecoin-project/specs-actors/actors/abi"
block "github.com/ipfs/go-block-format" block "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/multiformats/go-multihash" "github.com/multiformats/go-multihash"
@ -22,10 +23,26 @@ type Message struct {
GasPrice BigInt GasPrice BigInt
GasLimit BigInt GasLimit BigInt
Method uint64 // TODO: decide Method abi.MethodNum
Params []byte 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) { func DecodeMessage(b []byte) (*Message, error) {
var msg Message var msg Message
if err := msg.UnmarshalCBOR(bytes.NewReader(b)); err != nil { if err := msg.UnmarshalCBOR(bytes.NewReader(b)); err != nil {

View File

@ -5,9 +5,12 @@ import (
"fmt" "fmt"
"github.com/filecoin-project/go-address" "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/types"
"github.com/filecoin-project/lotus/chain/wallet" "github.com/filecoin-project/lotus/chain/wallet"
"github.com/ipfs/go-cid"
) )
func Address(i uint64) address.Address { 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 pcids []cid.Cid
var height uint64 var height abi.ChainEpoch
weight := types.NewInt(weightInc) weight := types.NewInt(weightInc)
if parents != nil { if parents != nil {
pcids = parents.Cids() pcids = parents.Cids()
@ -65,12 +68,12 @@ func MkBlock(parents *types.TipSet, weightInc uint64, ticketNonce uint64) *types
}, },
Parents: pcids, Parents: pcids,
ParentMessageReceipts: c, 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, ParentWeight: weight,
Messages: c, Messages: c,
Height: height, Height: height,
ParentStateRoot: c, 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 ( import (
"bytes" "bytes"
"testing" "testing"
"github.com/filecoin-project/specs-actors/actors/crypto"
) )
func TestSignatureSerializeRoundTrip(t *testing.T) { func TestSignatureSerializeRoundTrip(t *testing.T) {
s := &Signature{ s := &crypto.Signature{
Data: []byte("foo bar cat dog"), Data: []byte("foo bar cat dog"),
Type: KTBLS, Type: crypto.SigTypeBLS,
} }
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
@ -16,7 +18,7 @@ func TestSignatureSerializeRoundTrip(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
var outs Signature var outs crypto.Signature
if err := outs.UnmarshalCBOR(buf); err != nil { if err := outs.UnmarshalCBOR(buf); err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

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

View File

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

View File

@ -3,6 +3,10 @@ package types
import ( import (
"context" "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/go-address"
"github.com/filecoin-project/lotus/chain/actors/aerrors" "github.com/filecoin-project/lotus/chain/actors/aerrors"
@ -31,46 +35,22 @@ type VMContext interface {
Message() *Message Message() *Message
Origin() address.Address Origin() address.Address
Ipld() cbor.IpldStore Ipld() cbor.IpldStore
Send(to address.Address, method uint64, value BigInt, params []byte) ([]byte, aerrors.ActorError) Send(to address.Address, method abi.MethodNum, value BigInt, params []byte) ([]byte, aerrors.ActorError)
BlockHeight() uint64 BlockHeight() abi.ChainEpoch
GasUsed() BigInt GasUsed() BigInt
Storage() Storage Storage() Storage
StateTree() (StateTree, aerrors.ActorError) 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 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) GetBalance(address.Address) (BigInt, aerrors.ActorError)
Sys() *VMSyscalls Sys() runtime.Syscalls
Context() context.Context 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 { type storageWrapper struct {
s Storage s Storage
} }

View File

@ -1,88 +1,22 @@
package types package types
import ( import(
"bytes"
"encoding/base64" "encoding/base64"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/specs-actors/actors/builtin/paych"
cborrpc "github.com/filecoin-project/go-cbor-util"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
) )
type SignedVoucher struct { func DecodeSignedVoucher(s string) (*paych.SignedVoucher, error) {
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) {
data, err := base64.RawURLEncoding.DecodeString(s) data, err := base64.RawURLEncoding.DecodeString(s)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var sv SignedVoucher var sv paych.SignedVoucher
if err := cbor.DecodeInto(data, &sv); err != nil { if err := cbor.DecodeInto(data, &sv); err != nil {
return nil, err return nil, err
} }
return &sv, nil 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 ( import (
"context" "context"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/go-sectorbuilder" "github.com/filecoin-project/go-sectorbuilder"
vchain "github.com/filecoin-project/chain-validation/pkg/chain" 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 { if err != nil {
return vchain.MessageReceipt{}, err 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 { if err != nil {
return vchain.MessageReceipt{}, err return vchain.MessageReceipt{}, err
} }

View File

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

View File

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

View File

@ -11,11 +11,21 @@ import (
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors" "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/actors/aerrors"
"github.com/filecoin-project/lotus/chain/types" "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 { type invoker struct {
@ -33,20 +43,21 @@ func NewInvoker() *invoker {
} }
// add builtInCode using: register(cid, singleton) // add builtInCode using: register(cid, singleton)
inv.Register(actors.InitCodeCid, actors.InitActor{}, actors.InitActorState{}) inv.Register(builtin.SystemActorCodeID, system.Actor{}, adt.EmptyValue{})
inv.Register(actors.CronCodeCid, actors.CronActor{}, actors.CronActorState{}) inv.Register(builtin.InitActorCodeID, init_.Actor{}, init_.State{})
inv.Register(actors.StoragePowerCodeCid, actors.StoragePowerActor{}, actors.StoragePowerState{}) inv.Register(builtin.CronActorCodeID, cron.Actor{}, cron.State{})
inv.Register(actors.StorageMarketCodeCid, actors.StorageMarketActor{}, actors.StorageMarketState{}) inv.Register(builtin.StoragePowerActorCodeID, power.Actor{}, power.State{})
inv.Register(actors.StorageMinerCodeCid, actors.StorageMinerActor{}, actors.StorageMinerActorState{}) inv.Register(builtin.StorageMarketActorCodeID, market.Actor{}, market.State{})
inv.Register(actors.MultisigCodeCid, multisig.MultiSigActor{}, multisig.MultiSigActorState{}) inv.Register(builtin.StorageMinerActorCodeID, miner.Actor{}, miner.State{})
inv.Register(actors.PaymentChannelCodeCid, actors.PaymentChannelActor{}, actors.PaymentChannelActorState{}) inv.Register(builtin.MultisigActorCodeID, multisig.Actor{}, multisig.State{})
inv.Register(builtin.PaymentChannelActorCodeID, paych.Actor{}, paych.State{})
return inv 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") 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) 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)) 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 nil, aerrors.Newf(255, "no method %d on actor", method)
} }
return code[method](act, vmctx, params) 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) { 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 return nil, nil
} }

View File

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

View File

@ -3,36 +3,62 @@ package vm
import ( import (
"bytes" "bytes"
"context" "context"
"fmt" "encoding/binary"
"runtime/debug" "runtime/debug"
"github.com/filecoin-project/go-address" "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/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" vmr "github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/specs-actors/actors/runtime/exitcode" "github.com/filecoin-project/specs-actors/actors/runtime/exitcode"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/types"
) )
type runtimeShim struct { type runtimeShim struct {
vmctx types.VMContext 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) { func (rs *runtimeShim) shimCall(f func() interface{}) (rval []byte, aerr aerrors.ActorError) {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
if ar, ok := r.(aerrors.ActorError); ok { if ar, ok := r.(aerrors.ActorError); ok {
log.Warn("VM.Call failure: ", ar)
debug.PrintStack()
aerr = ar aerr = ar
return return
} }
fmt.Println("caught one of those actor errors: ", r) log.Warn("caught one of those actor errors: ", r)
debug.PrintStack() debug.PrintStack()
log.Errorf("ERROR") log.Errorf("ERROR")
aerr = aerrors.Newf(1, "generic spec actors failure") 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) { 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 { for _, a := range as {
if rs.vmctx.Message().From == a { if imm == a {
return return
} }
} }
fmt.Println("Caller: ", rs.vmctx.Message().From, as) rs.Abortf(exitcode.ErrForbidden, "caller %s is not one of %s", rs.vmctx.Message().From, as)
panic("we like to panic when people call the wrong methods")
} }
func (rs *runtimeShim) ImmediateCaller() address.Address { func (rs *runtimeShim) ImmediateCaller() address.Address {
@ -74,44 +218,20 @@ func (rs *runtimeShim) Context() context.Context {
return rs.vmctx.Context() return rs.vmctx.Context()
} }
func (rs *runtimeShim) IpldGet(c cid.Cid, o vmr.CBORUnmarshaler) bool { func (rs *runtimeShim) Abortf(code exitcode.ExitCode, msg string, args ...interface{}) {
if err := rs.vmctx.Storage().Get(c, o); err != nil { panic(aerrors.NewfSkip(2, uint8(code), msg, args...))
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) AbortStateMsg(msg string) { func (rs *runtimeShim) AbortStateMsg(msg string) {
rs.Abort(101, msg) panic(aerrors.NewfSkip(3, 101, msg))
} }
func (rs *runtimeShim) ValidateImmediateCallerType(...cid.Cid) { func (rs *runtimeShim) ValidateImmediateCallerType(...cid.Cid) {
log.Info("validate caller type is dumb") 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 { func (rs *runtimeShim) CurrEpoch() abi.ChainEpoch {
return abi.ChainEpoch(rs.vmctx.BlockHeight()) return rs.vmctx.BlockHeight()
} }
type dumbWrapperType struct { type dumbWrapperType struct {
@ -122,13 +242,17 @@ func (dwt *dumbWrapperType) Into(um vmr.CBORUnmarshaler) error {
return um.UnmarshalCBOR(bytes.NewReader(dwt.val)) 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) { func (rs *runtimeShim) Send(to address.Address, method abi.MethodNum, m vmr.CBORMarshaler, value abi.TokenAmount) (vmr.SendReturn, exitcode.ExitCode) {
buf := new(bytes.Buffer) var params []byte
if err := m.MarshalCBOR(buf); err != nil { if m != nil {
rs.Abort(exitcode.SysErrInvalidParameters, "failed to marshal input parameters: %s", err) 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 != nil {
if err.IsFatal() { if err.IsFatal() {
panic(err) panic(err)
@ -146,6 +270,16 @@ type shimStateHandle struct {
rs *runtimeShim 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) { func (ssh *shimStateHandle) Readonly(obj vmr.CBORUnmarshaler) {
if err := ssh.rs.vmctx.Storage().Get(ssh.rs.vmctx.Storage().GetHead(), obj); err != nil { if err := ssh.rs.vmctx.Storage().Get(ssh.rs.vmctx.Storage().GetHead(), obj); err != nil {
panic(err) panic(err)
@ -170,15 +304,3 @@ func (ssh *shimStateHandle) Transaction(obj vmr.CBORer, f func() interface{}) in
return out 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 package vm
import ( import (
"context"
ffi "github.com/filecoin-project/filecoin-ffi" ffi "github.com/filecoin-project/filecoin-ffi"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
commcid "github.com/filecoin-project/go-fil-commcid"
"github.com/filecoin-project/go-sectorbuilder" "github.com/filecoin-project/go-sectorbuilder"
"github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/lib/zerocomm"
"github.com/filecoin-project/lotus/chain/actors/aerrors" "github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/specs-actors/actors/crypto"
"go.opencensus.io/trace" "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 // Actual type is defined in chain/types/vmcontext.go because the VMContext interface is there
func Syscalls(verifier sectorbuilder.Verifier) *types.VMSyscalls { func Syscalls(verifier sectorbuilder.Verifier) runtime.Syscalls {
return &types.VMSyscalls{ return &syscallShim{verifier}
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() type syscallShim struct {
ok, err := verifier.VerifySeal(ssize, commR, commD, maddr, ticket, seed, sectorID, proof) verifier sectorbuilder.Verifier
if err != nil { }
return false, aerrors.Absorb(err, 25, "verify seal failed")
} func (ss *syscallShim) ComputeUnsealedSectorCID(ssize abi.SectorSize, pieces []abi.PieceInfo) (cid.Cid, error) {
// TODO: does this pull in unwanted dependencies?
return ok, nil var ffipieces []ffi.PublicPieceInfo
}, var sum abi.PaddedPieceSize
VerifyFallbackPost: func(ctx context.Context, for _, p := range pieces {
sectorSize uint64, ffipieces = append(ffipieces, ffi.PublicPieceInfo{
sectorInfo []types.PublicSectorInfo, Size: p.Size.Unpadded(),
challengeSeed []byte, CommP: cidToCommD(p.PieceCID),
proof []byte, })
candidates []types.Candidate, sum += p.Size
proverID address.Address, }
faults uint64) (bool, error) {
{
sI := make([]ffi.PublicSectorInfo, len(sectorInfo)) // pad remaining space with 0 CommPs
for i, v := range sectorInfo { toFill := uint64(abi.PaddedPieceSize(ssize) - sum)
sI[i] = ffi.PublicSectorInfo{ n := bits.OnesCount64(toFill)
SectorID: v.SectorID, for i := 0; i < n; i++ {
CommR: v.CommR, next := bits.TrailingZeros64(toFill)
} psize := uint64(1) << next
} toFill ^= psize
cand := make([]sectorbuilder.EPostCandidate, len(candidates)) unpadded := abi.PaddedPieceSize(psize).Unpadded()
for i, v := range candidates { ffipieces = append(ffipieces, ffi.PublicPieceInfo{
cand[i] = sectorbuilder.EPostCandidate{ Size: unpadded,
SectorID: v.SectorID, CommP: zerocomm.ForSize(unpadded),
PartialTicket: v.PartialTicket, })
Ticket: v.Ticket, }
SectorChallengeIndex: v.SectorChallengeIndex, }
}
} commd, err := sectorbuilder.GenerateDataCommitment(ssize, ffipieces)
if err != nil {
return verifier.VerifyFallbackPost( log.Errorf("generate data commitment failed: %s", err)
ctx, return cid.Undef, err
sectorSize, }
sectorbuilder.NewSortedPublicSectorInfo(sI),
challengeSeed, return commcid.DataCommitmentV1ToCID(commd[:]), nil
proof, }
cand,
proverID, func (ss *syscallShim) HashBlake2b(data []byte) [32]byte {
faults, 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" "bytes"
"context" "context"
"fmt" "fmt"
"github.com/filecoin-project/specs-actors/actors/builtin"
"math/big" "math/big"
"reflect"
block "github.com/ipfs/go-block-format" block "github.com/ipfs/go-block-format"
cid "github.com/ipfs/go-cid" cid "github.com/ipfs/go-cid"
@ -12,13 +14,20 @@ import (
blockstore "github.com/ipfs/go-ipfs-blockstore" blockstore "github.com/ipfs/go-ipfs-blockstore"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
logging "github.com/ipfs/go-log/v2" logging "github.com/ipfs/go-log/v2"
mh "github.com/multiformats/go-multihash"
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
"go.opencensus.io/trace" "go.opencensus.io/trace"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/go-address" "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/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/aerrors" "github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
@ -50,13 +59,13 @@ type VMContext struct {
vm *VM vm *VM
state *state.StateTree state *state.StateTree
msg *types.Message msg *types.Message
height uint64 height abi.ChainEpoch
cst cbor.IpldStore cst cbor.IpldStore
gasAvailable types.BigInt gasAvailable types.BigInt
gasUsed types.BigInt gasUsed types.BigInt
sys *types.VMSyscalls sys runtime.Syscalls
// root cid of the state of the actor this invocation will be on // root cid of the state of the actor this invocation will be on
sroot cid.Cid sroot cid.Cid
@ -70,16 +79,15 @@ func (vmc *VMContext) Message() *types.Message {
return vmc.msg return vmc.msg
} }
func (vmc *VMContext) GetRandomness(height uint64) ([]byte, aerrors.ActorError) { 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)
res, err := vmc.vm.rand.GetRandomness(vmc.ctx, int64(height))
if err != nil { if err != nil {
return nil, aerrors.Escalate(err, "could not get randomness") return nil, aerrors.Escalate(err, "could not get randomness")
} }
return res, nil return res, nil
} }
func (vmc *VMContext) Sys() *types.VMSyscalls { func (vmc *VMContext) Sys() runtime.Syscalls {
return vmc.sys 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 // 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") ctx, span := trace.StartSpan(vmc.ctx, "vmc.Send")
defer span.End() defer span.End()
if span.IsRecordingEvents() { 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 // 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 return vmc.height
} }
@ -176,16 +184,28 @@ func (vmc *VMContext) ChargeGas(amount uint64) aerrors.ActorError {
} }
func (vmc *VMContext) StateTree() (types.StateTree, 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 nil, aerrors.Escalate(fmt.Errorf("only init actor can access state tree directly"), "invalid use of StateTree")
} }
return vmc.state, nil 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 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 { if err := vmctx.ChargeGas(GasVerifySignature); err != nil {
return err 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) 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") 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 { 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)) 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 base cid.Cid
cst *cbor.BasicIpldStore cst *cbor.BasicIpldStore
buf *bufbstore.BufferedBS buf *bufbstore.BufferedBS
blockHeight uint64 blockHeight abi.ChainEpoch
blockMiner address.Address blockMiner address.Address
inv *invoker inv *invoker
rand Rand 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) buf := bufbstore.NewBufferedBstore(cbs)
cst := cbor.NewCborStore(buf) cst := cbor.NewCborStore(buf)
state, err := state.LoadStateTree(cst, base) 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 { 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 { 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) toActor, err := st.GetActor(msg.To)
if err != nil { if err != nil {
if xerrors.Is(err, types.ErrActorNotFound) { if xerrors.Is(err, init_.ErrAddressNotFound) {
a, err := TryCreateAccountActor(st, msg.To) a, err := TryCreateAccountActor(st, msg.To)
if err != nil { if err != nil {
return nil, aerrors.Absorb(err, 1, "could not create account"), 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 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) { func linksForObj(blk block.Block) ([]cid.Cid, error) {
switch blk.Cid().Prefix().Codec { switch blk.Cid().Prefix().Codec {
case cid.DagCBOR: case cid.DagCBOR:
@ -595,7 +646,7 @@ func copyRec(from, to blockstore.Blockstore, root cid.Cid, cp func(block.Block)
} }
for _, link := range links { 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 continue
} }
@ -622,11 +673,11 @@ func (vm *VM) StateTree() types.StateTree {
return vm.cstate return vm.cstate
} }
func (vm *VM) SetBlockHeight(h uint64) { func (vm *VM) SetBlockHeight(h abi.ChainEpoch) {
vm.blockHeight = h 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") ctx, span := trace.StartSpan(vmctx.ctx, "vm.Invoke")
defer span.End() defer span.End()
if span.IsRecordingEvents() { if span.IsRecordingEvents() {

View File

@ -6,6 +6,7 @@ import (
"strings" "strings"
"sync" "sync"
"github.com/filecoin-project/specs-actors/actors/crypto"
logging "github.com/ipfs/go-log/v2" logging "github.com/ipfs/go-log/v2"
"golang.org/x/xerrors" "golang.org/x/xerrors"
@ -23,6 +24,8 @@ var log = logging.Logger("wallet")
const ( const (
KNamePrefix = "wallet-" KNamePrefix = "wallet-"
KDefault = "default" KDefault = "default"
KTBLS = "bls"
KTSecp256k1 = "secp256k1"
) )
type Wallet struct { 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) ki, err := w.findKey(addr)
if err != nil { if err != nil {
return nil, err 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 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) { func (w *Wallet) findKey(addr address.Address) (*Key, error) {
@ -179,19 +182,19 @@ func (w *Wallet) SetDefault(a address.Address) error {
return nil return nil
} }
func GenerateKey(typ string) (*Key, error) { func GenerateKey(typ crypto.SigType) (*Key, error) {
pk, err := sigs.Generate(typ) pk, err := sigs.Generate(typ)
if err != nil { if err != nil {
return nil, err return nil, err
} }
ki := types.KeyInfo{ ki := types.KeyInfo{
Type: typ, Type: kstoreSigType(typ),
PrivateKey: pk, PrivateKey: pk,
} }
return NewKey(ki) 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() w.lk.Lock()
defer w.lk.Unlock() defer w.lk.Unlock()
@ -240,18 +243,18 @@ func NewKey(keyinfo types.KeyInfo) (*Key, error) {
} }
var err 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 { if err != nil {
return nil, err return nil, err
} }
switch k.Type { switch k.Type {
case types.KTSecp256k1: case KTSecp256k1:
k.Address, err = address.NewSecp256k1Address(k.PublicKey) k.Address, err = address.NewSecp256k1Address(k.PublicKey)
if err != nil { if err != nil {
return nil, xerrors.Errorf("converting Secp256k1 to address: %w", err) return nil, xerrors.Errorf("converting Secp256k1 to address: %w", err)
} }
case types.KTBLS: case KTBLS:
k.Address, err = address.NewBLSAddress(k.PublicKey) k.Address, err = address.NewBLSAddress(k.PublicKey)
if err != nil { if err != nil {
return nil, xerrors.Errorf("converting BLS to address: %w", err) return nil, xerrors.Errorf("converting BLS to address: %w", err)
@ -262,3 +265,25 @@ func NewKey(keyinfo types.KeyInfo) (*Key, error) {
return k, nil 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" "strings"
"time" "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" cid "github.com/ipfs/go-cid"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2" "gopkg.in/urfave/cli.v2"
@ -250,7 +255,7 @@ var chainSetHeadCmd = &cli.Command{
ts, err = api.ChainGetGenesis(ctx) ts, err = api.ChainGetGenesis(ctx)
} }
if ts == nil && cctx.IsSet("epoch") { 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 { if ts == nil {
ts, err = parseTipSet(api, ctx, cctx.Args().Slice()) ts, err = parseTipSet(api, ctx, cctx.Args().Slice())
@ -313,7 +318,7 @@ var chainListCmd = &cli.Command{
var head *types.TipSet var head *types.TipSet
if cctx.IsSet("height") { 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 { } else {
head, err = api.ChainHead(ctx) head, err = api.ChainHead(ctx)
} }
@ -446,7 +451,7 @@ var chainBisectCmd = &cli.Command{
subPath := cctx.Args().Get(2) 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 { if err != nil {
return err return err
} }
@ -460,7 +465,7 @@ var chainBisectCmd = &cli.Command{
start = end start = end
} }
midTs, err := api.ChainGetTipSetByHeight(ctx, mid, highest.Key()) midTs, err := api.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(mid), highest.Key())
if err != nil { if err != nil {
return err return err
} }
@ -506,7 +511,7 @@ var chainBisectCmd = &cli.Command{
return nil return nil
} }
prev = mid prev = abi.ChainEpoch(mid)
} }
}, },
} }
@ -594,18 +599,31 @@ var slashConsensusFault = &cli.Command{
return err return err
} }
params, err := actors.SerializeParams(&actors.ArbitrateConsensusFaultParams{ bh1, err := cborutil.Dump(b1)
Block1: b1, if err != nil {
Block2: b2, 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{ msg := &types.Message{
To: actors.StoragePowerAddress, To: builtin.StoragePowerActorAddr,
From: def, From: def,
Value: types.NewInt(0), Value: types.NewInt(0),
GasPrice: types.NewInt(1), GasPrice: types.NewInt(1),
GasLimit: types.NewInt(10000000), GasLimit: types.NewInt(10000000),
Method: actors.SPAMethods.ArbitrateConsensusFault, Method: builtin.MethodsPower.ReportConsensusFault,
Params: params, Params: params,
} }

View File

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

View File

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

View File

@ -1,11 +1,15 @@
package cli package cli
import ( import (
"bytes"
"encoding/base64"
"fmt" "fmt"
"github.com/filecoin-project/go-address" "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" "gopkg.in/urfave/cli.v2"
types "github.com/filecoin-project/lotus/chain/types"
) )
var paychCmd = &cli.Command{ var paychCmd = &cli.Command{
@ -136,7 +140,7 @@ var paychVoucherCreateCmd = &cli.Command{
return err return err
} }
enc, err := sv.EncodedString() enc, err := EncodedString(sv)
if err != nil { if err != nil {
return err return err
} }
@ -250,7 +254,7 @@ var paychVoucherListCmd = &cli.Command{
for _, v := range vouchers { for _, v := range vouchers {
if cctx.Bool("export") { if cctx.Bool("export") {
enc, err := v.EncodedString() enc, err := EncodedString(v)
if err != nil { if err != nil {
return err return err
} }
@ -291,7 +295,7 @@ var paychVoucherBestSpendableCmd = &cli.Command{
return err return err
} }
var best *types.SignedVoucher var best *paych.SignedVoucher
for _, v := range vouchers { for _, v := range vouchers {
spendable, err := api.PaychVoucherCheckSpendable(ctx, ch, v, nil, nil) spendable, err := api.PaychVoucherCheckSpendable(ctx, ch, v, nil, nil)
if err != nil { if err != nil {
@ -308,7 +312,7 @@ var paychVoucherBestSpendableCmd = &cli.Command{
return fmt.Errorf("No spendable vouchers for that channel") return fmt.Errorf("No spendable vouchers for that channel")
} }
enc, err := best.EncodedString() enc, err := EncodedString(best)
if err != nil { if err != nil {
return err return err
} }
@ -364,3 +368,12 @@ var paychVoucherSubmitCmd = &cli.Command{
return nil 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" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/filecoin-project/specs-actors/actors/builtin"
"reflect" "reflect"
"strconv" "strconv"
"strings" "strings"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/specs-actors/actors/abi"
actors "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/lotus/chain/types" miner2 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/lotus/miner"
samsig "github.com/filecoin-project/specs-actors/actors/builtin/multisig" 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" "github.com/libp2p/go-libp2p-core/peer"
"golang.org/x/xerrors" "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/docker/go-units"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
@ -90,24 +96,16 @@ var stateMinerInfo = &cli.Command{
return err return err
} }
var mst actors.StorageMinerActorState var mst miner2.State
if err := mst.UnmarshalCBOR(bytes.NewReader(aso)); err != nil { if err := mst.UnmarshalCBOR(bytes.NewReader(aso)); err != nil {
return err return err
} }
mio, err := api.ChainReadObj(ctx, mst.Info) mi := mst.Info
if err != nil {
return err
}
var mi actors.MinerInfo
if err := mi.UnmarshalCBOR(bytes.NewReader(mio)); err != nil {
return err
}
fmt.Printf("Owner:\t%s\n", mi.Owner) fmt.Printf("Owner:\t%s\n", mi.Owner)
fmt.Printf("Worker:\t%s\n", mi.Worker) 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) fmt.Printf("SectorSize:\t%s (%d)\n", units.BytesSize(float64(mi.SectorSize)), mi.SectorSize)
return nil return nil
@ -187,9 +185,9 @@ var statePowerCmd = &cli.Command{
if cctx.Args().Present() { if cctx.Args().Present() {
mp := power.MinerPower mp := power.MinerPower
percI := types.BigDiv(types.BigMul(mp, types.NewInt(1000000)), tp) 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 { } else {
fmt.Printf("%s(%s)\n", tp.String(), tp.SizeStr()) fmt.Printf("%s(%s)\n", tp.String(), types.SizeStr(tp))
} }
return nil return nil
@ -228,7 +226,7 @@ var stateSectorsCmd = &cli.Command{
} }
for _, s := range sectors { 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 return nil
@ -267,7 +265,7 @@ var stateProvingSetCmd = &cli.Command{
} }
for _, s := range sectors { 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 return nil
@ -278,8 +276,8 @@ var stateReplaySetCmd = &cli.Command{
Name: "replay", Name: "replay",
Usage: "Replay a particular message within a tipset", Usage: "Replay a particular message within a tipset",
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
if cctx.Args().Len() < 2 { if cctx.Args().Len() < 1 {
fmt.Println("usage: <tipset> <message cid>") fmt.Println("usage: [tipset] <message cid>")
fmt.Println("The last cid passed will be used as the 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") fmt.Println("All preceding ones will be used as the tipset")
return nil return nil
@ -291,15 +289,6 @@ var stateReplaySetCmd = &cli.Command{
return fmt.Errorf("message cid was invalid: %s", err) 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) api, closer, err := GetFullNodeAPI(cctx)
if err != nil { if err != nil {
return err return err
@ -308,19 +297,41 @@ var stateReplaySetCmd = &cli.Command{
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
var headers []*types.BlockHeader var ts *types.TipSet
for _, c := range tscids { {
h, err := api.ChainGetBlock(ctx, c) 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 { if err != nil {
return err return err
} }
headers = append(headers, h)
}
ts, err := types.NewTipSet(headers)
if err != nil {
return err
} }
res, err := api.StateReplay(ctx, ts.Key(), mcid) res, err := api.StateReplay(ctx, ts.Key(), mcid)
@ -393,7 +404,7 @@ var stateGetDealSetCmd = &cli.Command{
return err return err
} }
deal, err := api.StateMarketStorageDeal(ctx, dealid, ts.Key()) deal, err := api.StateMarketStorageDeal(ctx, abi.DealID(dealid), ts.Key())
if err != nil { if err != nil {
return err return err
} }
@ -682,7 +693,7 @@ var stateListMessagesCmd = &cli.Command{
return err 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 { if err != nil {
return err return err
} }
@ -735,7 +746,7 @@ var stateComputeStateCmd = &cli.Command{
return err return err
} }
h := cctx.Uint64("height") h := abi.ChainEpoch(cctx.Uint64("height"))
if h == 0 { if h == 0 {
if ts == nil { if ts == nil {
head, err := api.ChainHead(ctx) head, err := api.ChainHead(ctx)
@ -821,7 +832,7 @@ var stateCallCmd = &cli.Command{
&cli.StringFlag{ &cli.StringFlag{
Name: "from", Name: "from",
Usage: "", Usage: "",
Value: actors.NetworkAddress.String(), Value: builtin.SystemActorAddr.String(),
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "value", Name: "value",
@ -888,7 +899,7 @@ var stateCallCmd = &cli.Command{
Value: types.BigInt(value), Value: types.BigInt(value),
GasLimit: types.NewInt(10000000000), GasLimit: types.NewInt(10000000000),
GasPrice: types.NewInt(0), GasPrice: types.NewInt(0),
Method: method, Method: abi.MethodNum(method),
Params: params, Params: params,
}, ts.Key()) }, ts.Key())
if err != nil { if err != nil {
@ -962,16 +973,16 @@ func parseParamsForMethod(act cid.Cid, method uint64, args []string) ([]byte, er
var f interface{} var f interface{}
switch act { switch act {
case actors.StorageMarketCodeCid: case builtin.StorageMarketActorCodeID:
f = actors.StorageMarketActor{}.Exports()[method] f = market.Actor{}.Exports()[method]
case actors.StorageMinerCodeCid: case builtin.StorageMinerActorCodeID:
f = actors.StorageMinerActor{}.Exports()[method] f = miner2.Actor{}.Exports()[method]
case actors.StoragePowerCodeCid: case builtin.StoragePowerActorCodeID:
f = actors.StoragePowerActor{}.Exports()[method] f = power.Actor{}.Exports()[method]
case actors.MultisigCodeCid: case builtin.MultisigActorCodeID:
f = samsig.MultiSigActor{}.Exports()[method] f = samsig.Actor{}.Exports()[method]
case actors.PaymentChannelCodeCid: case builtin.PaymentChannelActorCodeID:
f = actors.PaymentChannelActor{}.Exports()[method] f = paych.Actor{}.Exports()[method]
default: default:
return nil, fmt.Errorf("the lazy devs didnt add support for that actor to this call yet") 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" "fmt"
"time" "time"
"github.com/filecoin-project/specs-actors/actors/abi"
cid "github.com/ipfs/go-cid" cid "github.com/ipfs/go-cid"
"gopkg.in/urfave/cli.v2" "gopkg.in/urfave/cli.v2"
@ -45,7 +46,7 @@ var syncStatusCmd = &cli.Command{
fmt.Printf("worker %d:\n", i) fmt.Printf("worker %d:\n", i)
var base, target []cid.Cid var base, target []cid.Cid
var heightDiff int64 var heightDiff int64
var theight uint64 var theight abi.ChainEpoch
if ss.Base != nil { if ss.Base != nil {
base = ss.Base.Cids() base = ss.Base.Cids()
heightDiff = int64(ss.Base.Height()) heightDiff = int64(ss.Base.Height())

View File

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

View File

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

View File

@ -16,6 +16,7 @@ import (
"github.com/docker/go-units" "github.com/docker/go-units"
ffi "github.com/filecoin-project/filecoin-ffi" ffi "github.com/filecoin-project/filecoin-ffi"
paramfetch "github.com/filecoin-project/go-paramfetch" paramfetch "github.com/filecoin-project/go-paramfetch"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore"
logging "github.com/ipfs/go-log/v2" logging "github.com/ipfs/go-log/v2"
"github.com/mitchellh/go-homedir" "github.com/mitchellh/go-homedir"
@ -32,7 +33,7 @@ import (
var log = logging.Logger("lotus-bench") var log = logging.Logger("lotus-bench")
type BenchResults struct { type BenchResults struct {
SectorSize uint64 SectorSize abi.SectorSize
SealingResults []SealingResult SealingResults []SealingResult
@ -139,7 +140,7 @@ func main() {
if err != nil { if err != nil {
return err return err
} }
sectorSize := uint64(sectorSizeInt) sectorSize := abi.SectorSize(sectorSizeInt)
mds := datastore.NewMapDatastore() mds := datastore.NewMapDatastore()
cfg := &sectorbuilder.Config{ 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) return xerrors.Errorf("getting params: %w", err)
} }
sb, err := sectorbuilder.New(cfg, mds) sb, err := sectorbuilder.New(cfg, mds)
@ -163,18 +164,16 @@ func main() {
return err return err
} }
dataSize := sectorbuilder.UserBytesForSectorSize(sectorSize)
var sealTimings []SealingResult var sealTimings []SealingResult
var sealedSectors []ffi.PublicSectorInfo var sealedSectors []ffi.PublicSectorInfo
numSectors := uint64(1) numSectors := abi.SectorNumber(1)
for i := uint64(1); i <= numSectors && robench == ""; i++ { for i := abi.SectorNumber(1); i <= numSectors && robench == ""; i++ {
start := time.Now() start := time.Now()
log.Info("Writing piece into sector...") log.Info("Writing piece into sector...")
r := rand.New(rand.NewSource(100 + int64(i))) 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 { if err != nil {
return err return err
} }
@ -196,8 +195,8 @@ func main() {
precommit := time.Now() precommit := time.Now()
sealedSectors = append(sealedSectors, ffi.PublicSectorInfo{ sealedSectors = append(sealedSectors, ffi.PublicSectorInfo{
CommR: pco.CommR, CommR: pco.CommR,
SectorID: i, SectorNum: i,
}) })
seed := sectorbuilder.SealSeed{ seed := sectorbuilder.SealSeed{
@ -225,7 +224,7 @@ func main() {
if !c.Bool("skip-unseal") { if !c.Bool("skip-unseal") {
log.Info("Unsealing sector") 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 { if err != nil {
return err return err
} }
@ -260,7 +259,7 @@ func main() {
return err return err
} }
var genmm map[string]genesis.GenesisMiner var genmm map[string]genesis.Miner
if err := json.Unmarshal(fdata, &genmm); err != nil { if err := json.Unmarshal(fdata, &genmm); err != nil {
return err return err
} }
@ -272,15 +271,15 @@ func main() {
for _, s := range genm.Sectors { for _, s := range genm.Sectors {
sealedSectors = append(sealedSectors, ffi.PublicSectorInfo{ sealedSectors = append(sealedSectors, ffi.PublicSectorInfo{
CommR: s.CommR, CommR: s.CommR,
SectorID: s.SectorID, SectorNum: s.SectorID,
}) })
} }
} }
log.Info("generating election post candidates") log.Info("generating election post candidates")
sinfos := sectorbuilder.NewSortedPublicSectorInfo(sealedSectors) sinfos := sectorbuilder.NewSortedPublicSectorInfo(sealedSectors)
candidates, err := sb.GenerateEPostCandidates(sinfos, challenge, []uint64{}) candidates, err := sb.GenerateEPostCandidates(sinfos, challenge, []abi.SectorNumber{})
if err != nil { if err != nil {
return err 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("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 (cold): %s\n", bo.PostEProofCold)
fmt.Printf("compute epost proof (hot): %s\n", bo.PostEProofHot) fmt.Printf("compute epost proof (hot): %s\n", bo.PostEProofHot)
fmt.Printf("verify epost proof (cold): %s\n", bo.VerifyEPostCold) fmt.Printf("verify epost proof (cold): %s\n", bo.VerifyEPostCold)
@ -371,9 +370,9 @@ func main() {
} }
} }
func bps(data uint64, d time.Duration) string { func bps(data abi.SectorSize, d time.Duration) string {
bdata := new(big.Int).SetUint64(data) bdata := new(big.Int).SetUint64(uint64(data))
bdata = bdata.Mul(bdata, big.NewInt(time.Second.Nanoseconds())) bdata = bdata.Mul(bdata, big.NewInt(time.Second.Nanoseconds()))
bps := bdata.Div(bdata, big.NewInt(d.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 ( import (
"database/sql" "database/sql"
"encoding/hex"
"fmt" "fmt"
"sync" "sync"
"time" "time"
@ -13,7 +12,6 @@ import (
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
) )
@ -267,8 +265,8 @@ create table if not exists deals
pieceSize bigint not null, pieceSize bigint not null,
client text not null, client text not null,
provider text not null, provider text not null,
expiration decimal not null, start decimal not null,
duration decimal not null, end decimal not null,
epochPrice decimal not null, epochPrice decimal not null,
collateral decimal not null, collateral decimal not null,
constraint deals_pk constraint deals_pk
@ -473,11 +471,11 @@ create temp table mh (like miner_heads excluding constraints) on commit drop;
fmt.Sprint(i.psize), fmt.Sprint(i.psize),
i.info.Owner.String(), i.info.Owner.String(),
i.info.Worker.String(), i.info.Worker.String(),
i.info.PeerID.String(), i.info.PeerId.String(),
i.info.SectorSize, i.info.SectorSize,
i.state.Power.String(), i.state.Power.String(), // TODO: SPA
i.state.Active, i.state.Active,
i.state.ElectionPeriodStart, i.state.PoStState.ProvingPeriodStart,
i.state.SlashedAt, i.state.SlashedAt,
); err != nil { ); err != nil {
return err return err
@ -842,7 +840,7 @@ func (st *storage) storeMpoolInclusions(msgs []api.MpoolUpdate) error {
return tx.Commit() 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() tx, err := st.db.Begin()
if err != nil { if err != nil {
return err return err
@ -854,7 +852,7 @@ func (st *storage) storeDeals(deals map[string]actors.OnChainDeal) error {
return xerrors.Errorf("prep temp: %w", err) 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 { if err != nil {
return err return err
} }
@ -862,20 +860,20 @@ func (st *storage) storeDeals(deals map[string]actors.OnChainDeal) error {
var bloat uint64 var bloat uint64
for id, deal := range deals { for id, deal := range deals {
if len(deal.PieceRef) > 40 { if len(deal.Proposal.PieceCID.String()) > 100 {
bloat += uint64(len(deal.PieceRef)) bloat += uint64(len(deal.Proposal.PieceCID.String()))
continue continue
} }
if _, err := stmt.Exec( if _, err := stmt.Exec(
id, id,
hex.EncodeToString(deal.PieceRef), deal.Proposal.PieceCID.String(),
deal.PieceSize, deal.Proposal.PieceSize,
deal.Client.String(), deal.Proposal.Client.String(),
deal.Provider.String(), deal.Proposal.Provider.String(),
fmt.Sprint(deal.ProposalExpiration), fmt.Sprint(deal.Proposal.StartEpoch),
fmt.Sprint(deal.Duration), fmt.Sprint(deal.Proposal.EndEpoch),
deal.StoragePricePerEpoch.String(), deal.Proposal.StoragePricePerEpoch.String(),
deal.StorageCollateral.String(), deal.Proposal.ProviderCollateral.String(),
); err != nil { ); err != nil {
return err return err
} }
@ -915,12 +913,12 @@ func (st *storage) storeDeals(deals map[string]actors.OnChainDeal) error {
} }
for id, deal := range deals { for id, deal := range deals {
if deal.ActivationEpoch == 0 { if deal.State.SectorStartEpoch <= 0 {
continue continue
} }
if _, err := stmt.Exec( if _, err := stmt.Exec(
id, id,
deal.ActivationEpoch, deal.State.SectorStartEpoch,
); err != nil { ); err != nil {
return err return err
} }

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