Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1401efb115 | ||
|
|
f417d39a08 | ||
|
|
11e35cf911 | ||
|
|
10d464a1eb | ||
|
|
d84f5dabab | ||
|
|
a6d9b302fa | ||
|
|
114a1aaffd | ||
|
|
83ba7ec8cc | ||
|
|
83dfc460d4 | ||
|
|
283fd054e8 | ||
|
|
09bff14d85 | ||
|
|
3cb1abba4f | ||
|
|
d4c92942e7 | ||
|
|
f773ab4b28 | ||
|
|
c0182f8301 | ||
|
|
c06f394b81 | ||
|
|
748d2e82a7 | ||
|
|
a5c78371fd | ||
|
|
d80e7eda93 | ||
|
|
9f9d5cb2a5 | ||
|
|
fdaa9c14ad | ||
|
|
9d8932d395 | ||
|
|
105aa40007 | ||
|
|
110f033c83 | ||
|
|
f87d325b6f | ||
|
|
ab8286fa38 | ||
|
|
feb4b3c8b4 | ||
|
|
7f7c9e978f | ||
|
|
200a95f824 | ||
|
|
d69e4c7cf2 | ||
|
|
b2834baa4b | ||
|
|
e9e27cbbb0 | ||
|
|
ef73b964fb | ||
|
|
7b1bec91ed | ||
|
|
b32d25c562 | ||
|
|
767611247c | ||
|
|
be09a8a00a | ||
|
|
2719adc1b1 | ||
|
|
f1b1d8cec6 | ||
|
|
8fa4c0a970 | ||
|
|
00a14de094 | ||
|
|
eec13ff8dc | ||
|
|
1ffdd7d5b3 | ||
|
|
e19cd9ed01 | ||
|
|
bacac245c7 | ||
|
|
e1792ffe4d | ||
|
|
9c35762966 | ||
|
|
356137439f | ||
|
|
6cc7559b04 | ||
|
|
3cd53ad9d9 | ||
|
|
6c54d2445d | ||
|
|
6a10af626c | ||
|
|
597d065e05 | ||
|
|
791aa5c6c8 | ||
|
|
82b15d2637 | ||
|
|
7d2f06cfbd | ||
|
|
6e8efb9d2c | ||
|
|
f3dc730b05 | ||
|
|
114776f2c5 | ||
|
|
4835109470 | ||
|
|
8783c7434e | ||
|
|
2d3b61675b | ||
|
|
a23ab123d7 | ||
|
|
26ed6af040 | ||
|
|
82bd7bd2ec | ||
|
|
cd0a43b7f4 | ||
|
|
b14632b750 | ||
|
|
ebcf77e830 | ||
|
|
344d30e960 | ||
|
|
efb13a0d9b | ||
|
|
0223582d41 | ||
|
|
973f61bc10 | ||
|
|
60768f4863 | ||
|
|
c60d13ee56 | ||
|
|
0f8fc119f3 | ||
|
|
e4d2e6e01d | ||
|
|
d55f10bed6 | ||
|
|
21de538d09 | ||
|
|
fe5b32026a | ||
|
|
91c10c2df5 | ||
|
|
c3420c0ceb | ||
|
|
7933cf094f | ||
|
|
4cd73f1560 | ||
|
|
8a175a7465 | ||
|
|
f7f229ae54 | ||
|
|
1323e07a2c | ||
|
|
2ad671649c | ||
|
|
d26ece10b8 | ||
|
|
4c8084dcb0 | ||
|
|
98d702fb5a | ||
|
|
17f61ac212 | ||
|
|
df67576b89 | ||
|
|
cdc2f86f5a | ||
|
|
67b3a55e30 | ||
|
|
3201e0eb8f | ||
|
|
8d2d74438b | ||
|
|
1f9446f91f | ||
|
|
4937ca1a96 | ||
|
|
264fe4edb9 | ||
|
|
cb7d99fcc7 | ||
|
|
7332a39f00 | ||
|
|
cd9af278b4 | ||
|
|
8f4911ac0d | ||
|
|
12cd478e11 | ||
|
|
e55b00f358 | ||
|
|
6f4a762664 | ||
|
|
c02daca9e9 | ||
|
|
5bd6a3cdad | ||
|
|
780f6dba34 | ||
|
|
f90cfda2e6 |
@@ -12,6 +12,7 @@
|
||||
/lotus-bench
|
||||
/lotus-gateway
|
||||
/lotus-pcr
|
||||
/lotus-wallet
|
||||
/bench.json
|
||||
/lotuspond/front/node_modules
|
||||
/lotuspond/front/build
|
||||
|
||||
@@ -1,5 +1,25 @@
|
||||
# Lotus changelog
|
||||
|
||||
# 0.9.1 / 2020-10-10
|
||||
|
||||
This release fixes an issue which may cause the actors v2 migration to compute the state incorrectly when more than one migration is running in parallel.
|
||||
|
||||
## Changes
|
||||
|
||||
- Make concurrent actor migrations safe (https://github.com/filecoin-project/lotus/pull/4293)
|
||||
- Remote wallet backends (https://github.com/filecoin-project/lotus/pull/3583)
|
||||
- Track funds in FundMgr correctly in case of AddFunds failing (https://github.com/filecoin-project/lotus/pull/4273)
|
||||
- Partial lite-node mode (https://github.com/filecoin-project/lotus/pull/4095)
|
||||
- Fix potential infinite loop in GetBestMiningCandidate (https://github.com/filecoin-project/lotus/pull/3444)
|
||||
- sync wait: Handle processed message offset (https://github.com/filecoin-project/lotus/pull/4253)
|
||||
- Add some new endpoints for querying Msig info (https://github.com/filecoin-project/lotus/pull/4250)
|
||||
- Update markets v0.7.1 (https://github.com/filecoin-project/lotus/pull/4254)
|
||||
- Optimize SearchForMessage and GetReceipt (https://github.com/filecoin-project/lotus/pull/4246)
|
||||
- Use FIL instead of attoFIL in CLI more consistently (https://github.com/filecoin-project/lotus/pull/4249)
|
||||
- fix: clash between daemon --api flag and cli tests (https://github.com/filecoin-project/lotus/pull/4241)
|
||||
- add more info to chain sync lookback failure (https://github.com/filecoin-project/lotus/pull/4245)
|
||||
- Add message counts to inspect chain output (https://github.com/filecoin-project/lotus/pull/4230)
|
||||
|
||||
# 0.9.0 / 2020-10-07
|
||||
|
||||
This consensus-breaking release of Lotus upgrades the actors version to v2.0.0. This requires migrating actor state from v0 to v2. The changes that break consensus are:
|
||||
|
||||
@@ -186,6 +186,12 @@ lotus-health:
|
||||
.PHONY: lotus-health
|
||||
BINS+=lotus-health
|
||||
|
||||
lotus-wallet:
|
||||
rm -f lotus-wallet
|
||||
go build -o lotus-wallet ./cmd/lotus-wallet
|
||||
.PHONY: lotus-wallet
|
||||
BINS+=lotus-wallet
|
||||
|
||||
testground:
|
||||
go build -tags testground -o /dev/null ./cmd/lotus
|
||||
.PHONY: testground
|
||||
|
||||
@@ -367,6 +367,10 @@ type FullNode interface {
|
||||
// StateWaitMsg looks back in the chain for a message. If not found, it blocks until the
|
||||
// message arrives on chain, and gets to the indicated confidence depth.
|
||||
StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64) (*MsgLookup, error)
|
||||
// StateWaitMsgLimited looks back up to limit epochs in the chain for a message.
|
||||
// If not found, it blocks until the message arrives on chain, and gets to the
|
||||
// indicated confidence depth.
|
||||
StateWaitMsgLimited(ctx context.Context, cid cid.Cid, confidence uint64, limit abi.ChainEpoch) (*MsgLookup, error)
|
||||
// StateListMiners returns the addresses of every miner that has claimed power in the Power Actor
|
||||
StateListMiners(context.Context, types.TipSetKey) ([]address.Address, error)
|
||||
// StateListActors returns the addresses of every actor in the state
|
||||
@@ -418,6 +422,8 @@ type FullNode interface {
|
||||
|
||||
// MsigGetAvailableBalance returns the portion of a multisig's balance that can be withdrawn or spent
|
||||
MsigGetAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error)
|
||||
// MsigGetVestingSchedule returns the vesting details of a given multisig.
|
||||
MsigGetVestingSchedule(context.Context, address.Address, types.TipSetKey) (MsigVesting, error)
|
||||
// MsigGetVested returns the amount of FIL that vested in a multisig in a certain period.
|
||||
// It takes the following params: <multisig address>, <start epoch>, <end epoch>
|
||||
MsigGetVested(context.Context, address.Address, types.TipSetKey, types.TipSetKey) (types.BigInt, error)
|
||||
@@ -871,3 +877,15 @@ type Fault struct {
|
||||
Miner address.Address
|
||||
Epoch abi.ChainEpoch
|
||||
}
|
||||
|
||||
var EmptyVesting = MsigVesting{
|
||||
InitialBalance: types.EmptyInt,
|
||||
StartEpoch: -1,
|
||||
UnlockDuration: -1,
|
||||
}
|
||||
|
||||
type MsigVesting struct {
|
||||
InitialBalance abi.TokenAmount
|
||||
StartEpoch abi.ChainEpoch
|
||||
UnlockDuration abi.ChainEpoch
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/ipfs/go-cid"
|
||||
)
|
||||
|
||||
type GatewayAPI interface {
|
||||
ChainHead(ctx context.Context) (*types.TipSet, error)
|
||||
ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
|
||||
ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
|
||||
GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
|
||||
MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
|
||||
MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
|
||||
MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error)
|
||||
StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
||||
StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
|
||||
StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
||||
StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*MsgLookup, error)
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
type MsgType string
|
||||
|
||||
const (
|
||||
MTUnknown = "unknown"
|
||||
|
||||
// Signing message CID. MsgMeta.Extra contains raw cbor message bytes
|
||||
MTChainMsg = "message"
|
||||
|
||||
// Signing a blockheader. signing raw cbor block bytes (MsgMeta.Extra is empty)
|
||||
MTBlock = "block"
|
||||
|
||||
// Signing a deal proposal. signing raw cbor proposal bytes (MsgMeta.Extra is empty)
|
||||
MTDealProposal = "dealproposal"
|
||||
|
||||
// TODO: Deals, Vouchers, VRF
|
||||
)
|
||||
|
||||
type MsgMeta struct {
|
||||
Type MsgType
|
||||
|
||||
// Additional data related to what is signed. Should be verifiable with the
|
||||
// signed bytes (e.g. CID(Extra).Bytes() == toSign)
|
||||
Extra []byte
|
||||
}
|
||||
|
||||
type WalletAPI interface {
|
||||
WalletNew(context.Context, crypto.SigType) (address.Address, error)
|
||||
WalletHas(context.Context, address.Address) (bool, error)
|
||||
WalletList(context.Context) ([]address.Address, error)
|
||||
|
||||
WalletSign(ctx context.Context, signer address.Address, toSign []byte, meta MsgMeta) (*crypto.Signature, error)
|
||||
|
||||
WalletExport(context.Context, address.Address) (*types.KeyInfo, error)
|
||||
WalletImport(context.Context, *types.KeyInfo) (address.Address, error)
|
||||
WalletDelete(context.Context, address.Address) error
|
||||
}
|
||||
@@ -36,3 +36,9 @@ func PermissionedWorkerAPI(a api.WorkerAPI) api.WorkerAPI {
|
||||
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.Internal)
|
||||
return &out
|
||||
}
|
||||
|
||||
func PermissionedWalletAPI(a api.WalletAPI) api.WalletAPI {
|
||||
var out WalletStruct
|
||||
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.Internal)
|
||||
return &out
|
||||
}
|
||||
|
||||
@@ -190,6 +190,7 @@ type FullNodeStruct struct {
|
||||
StateReadState func(context.Context, address.Address, types.TipSetKey) (*api.ActorState, error) `perm:"read"`
|
||||
StateMsgGasCost func(context.Context, cid.Cid, types.TipSetKey) (*api.MsgGasCost, error) `perm:"read"`
|
||||
StateWaitMsg func(ctx context.Context, cid cid.Cid, confidence uint64) (*api.MsgLookup, error) `perm:"read"`
|
||||
StateWaitMsgLimited func(context.Context, cid.Cid, uint64, abi.ChainEpoch) (*api.MsgLookup, error) `perm:"read"`
|
||||
StateSearchMsg func(context.Context, cid.Cid) (*api.MsgLookup, 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"`
|
||||
@@ -212,6 +213,7 @@ type FullNodeStruct struct {
|
||||
StateNetworkVersion func(context.Context, types.TipSetKey) (stnetwork.Version, error) `perm:"read"`
|
||||
|
||||
MsigGetAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"`
|
||||
MsigGetVestingSchedule func(context.Context, address.Address, types.TipSetKey) (api.MsigVesting, error) `perm:"read"`
|
||||
MsigGetVested func(context.Context, address.Address, types.TipSetKey, types.TipSetKey) (types.BigInt, error) `perm:"read"`
|
||||
MsigCreate func(context.Context, uint64, []address.Address, abi.ChainEpoch, types.BigInt, address.Address, types.BigInt) (cid.Cid, error) `perm:"sign"`
|
||||
MsigPropose func(context.Context, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) `perm:"sign"`
|
||||
@@ -360,6 +362,35 @@ type WorkerStruct struct {
|
||||
}
|
||||
}
|
||||
|
||||
type GatewayStruct struct {
|
||||
Internal struct {
|
||||
// TODO: does the gateway need perms?
|
||||
ChainGetTipSet func(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
|
||||
ChainGetTipSetByHeight func(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
|
||||
ChainHead func(ctx context.Context) (*types.TipSet, error)
|
||||
GasEstimateMessageGas func(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
|
||||
MpoolPush func(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
|
||||
MsigGetAvailableBalance func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
|
||||
MsigGetVested func(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error)
|
||||
StateAccountKey func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
||||
StateGetActor func(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
|
||||
StateLookupID func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
||||
StateWaitMsg func(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error)
|
||||
}
|
||||
}
|
||||
|
||||
type WalletStruct struct {
|
||||
Internal struct {
|
||||
WalletNew func(context.Context, crypto.SigType) (address.Address, error) `perm:"write"`
|
||||
WalletHas func(context.Context, address.Address) (bool, error) `perm:"write"`
|
||||
WalletList func(context.Context) ([]address.Address, error) `perm:"write"`
|
||||
WalletSign func(context.Context, address.Address, []byte, api.MsgMeta) (*crypto.Signature, error) `perm:"sign"`
|
||||
WalletExport func(context.Context, address.Address) (*types.KeyInfo, error) `perm:"admin"`
|
||||
WalletImport func(context.Context, *types.KeyInfo) (address.Address, error) `perm:"admin"`
|
||||
WalletDelete func(context.Context, address.Address) error `perm:"write"`
|
||||
}
|
||||
}
|
||||
|
||||
// CommonStruct
|
||||
|
||||
func (c *CommonStruct) AuthVerify(ctx context.Context, token string) ([]auth.Permission, error) {
|
||||
@@ -853,6 +884,10 @@ func (c *FullNodeStruct) StateWaitMsg(ctx context.Context, msgc cid.Cid, confide
|
||||
return c.Internal.StateWaitMsg(ctx, msgc, confidence)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) StateWaitMsgLimited(ctx context.Context, msgc cid.Cid, confidence uint64, limit abi.ChainEpoch) (*api.MsgLookup, error) {
|
||||
return c.Internal.StateWaitMsgLimited(ctx, msgc, confidence, limit)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) StateSearchMsg(ctx context.Context, msgc cid.Cid) (*api.MsgLookup, error) {
|
||||
return c.Internal.StateSearchMsg(ctx, msgc)
|
||||
}
|
||||
@@ -933,6 +968,10 @@ func (c *FullNodeStruct) MsigGetAvailableBalance(ctx context.Context, a address.
|
||||
return c.Internal.MsigGetAvailableBalance(ctx, a, tsk)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) MsigGetVestingSchedule(ctx context.Context, a address.Address, tsk types.TipSetKey) (api.MsigVesting, error) {
|
||||
return c.Internal.MsigGetVestingSchedule(ctx, a, tsk)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) MsigGetVested(ctx context.Context, a address.Address, sTsk types.TipSetKey, eTsk types.TipSetKey) (types.BigInt, error) {
|
||||
return c.Internal.MsigGetVested(ctx, a, sTsk, eTsk)
|
||||
}
|
||||
@@ -1367,7 +1406,81 @@ func (w *WorkerStruct) Closing(ctx context.Context) (<-chan struct{}, error) {
|
||||
return w.Internal.Closing(ctx)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) ChainHead(ctx context.Context) (*types.TipSet, error) {
|
||||
return g.Internal.ChainHead(ctx)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) {
|
||||
return g.Internal.ChainGetTipSet(ctx, tsk)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) {
|
||||
return g.Internal.ChainGetTipSetByHeight(ctx, h, tsk)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) {
|
||||
return g.Internal.GasEstimateMessageGas(ctx, msg, spec, tsk)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) {
|
||||
return g.Internal.MpoolPush(ctx, sm)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) {
|
||||
return g.Internal.MsigGetAvailableBalance(ctx, addr, tsk)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error) {
|
||||
return g.Internal.MsigGetVested(ctx, addr, start, end)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
|
||||
return g.Internal.StateAccountKey(ctx, addr, tsk)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error) {
|
||||
return g.Internal.StateGetActor(ctx, actor, ts)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
|
||||
return g.Internal.StateLookupID(ctx, addr, tsk)
|
||||
}
|
||||
|
||||
func (g GatewayStruct) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error) {
|
||||
return g.Internal.StateWaitMsg(ctx, msg, confidence)
|
||||
}
|
||||
|
||||
func (c *WalletStruct) WalletNew(ctx context.Context, typ crypto.SigType) (address.Address, error) {
|
||||
return c.Internal.WalletNew(ctx, typ)
|
||||
}
|
||||
|
||||
func (c *WalletStruct) WalletHas(ctx context.Context, addr address.Address) (bool, error) {
|
||||
return c.Internal.WalletHas(ctx, addr)
|
||||
}
|
||||
|
||||
func (c *WalletStruct) WalletList(ctx context.Context) ([]address.Address, error) {
|
||||
return c.Internal.WalletList(ctx)
|
||||
}
|
||||
|
||||
func (c *WalletStruct) WalletSign(ctx context.Context, k address.Address, msg []byte, meta api.MsgMeta) (*crypto.Signature, error) {
|
||||
return c.Internal.WalletSign(ctx, k, msg, meta)
|
||||
}
|
||||
|
||||
func (c *WalletStruct) WalletExport(ctx context.Context, a address.Address) (*types.KeyInfo, error) {
|
||||
return c.Internal.WalletExport(ctx, a)
|
||||
}
|
||||
|
||||
func (c *WalletStruct) WalletImport(ctx context.Context, ki *types.KeyInfo) (address.Address, error) {
|
||||
return c.Internal.WalletImport(ctx, ki)
|
||||
}
|
||||
|
||||
func (c *WalletStruct) WalletDelete(ctx context.Context, addr address.Address) error {
|
||||
return c.Internal.WalletDelete(ctx, addr)
|
||||
}
|
||||
|
||||
var _ api.Common = &CommonStruct{}
|
||||
var _ api.FullNode = &FullNodeStruct{}
|
||||
var _ api.StorageMiner = &StorageMinerStruct{}
|
||||
var _ api.WorkerAPI = &WorkerStruct{}
|
||||
var _ api.GatewayAPI = &GatewayStruct{}
|
||||
var _ api.WalletAPI = &WalletStruct{}
|
||||
|
||||
@@ -82,3 +82,29 @@ func NewWorkerRPC(ctx context.Context, addr string, requestHeader http.Header) (
|
||||
|
||||
return &res, closer, err
|
||||
}
|
||||
|
||||
// NewGatewayRPC creates a new http jsonrpc client for a gateway node.
|
||||
func NewGatewayRPC(ctx context.Context, addr string, requestHeader http.Header, opts ...jsonrpc.Option) (api.GatewayAPI, jsonrpc.ClientCloser, error) {
|
||||
var res apistruct.GatewayStruct
|
||||
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
|
||||
[]interface{}{
|
||||
&res.Internal,
|
||||
},
|
||||
requestHeader,
|
||||
opts...,
|
||||
)
|
||||
|
||||
return &res, closer, err
|
||||
}
|
||||
|
||||
func NewWalletRPC(ctx context.Context, addr string, requestHeader http.Header) (api.WalletAPI, jsonrpc.ClientCloser, error) {
|
||||
var res apistruct.WalletStruct
|
||||
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
|
||||
[]interface{}{
|
||||
&res.Internal,
|
||||
},
|
||||
requestHeader,
|
||||
)
|
||||
|
||||
return &res, closer, err
|
||||
}
|
||||
|
||||
@@ -12,10 +12,7 @@ import (
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/node"
|
||||
"github.com/filecoin-project/lotus/node/impl"
|
||||
)
|
||||
|
||||
@@ -37,11 +34,7 @@ func TestCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
||||
|
||||
func testCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration, upgradeHeight abi.ChainEpoch) {
|
||||
ctx := context.Background()
|
||||
n, sn := b(t, 1, OneMiner, node.Override(new(stmgr.UpgradeSchedule), stmgr.UpgradeSchedule{{
|
||||
Network: build.ActorUpgradeNetworkVersion,
|
||||
Height: upgradeHeight,
|
||||
Migration: stmgr.UpgradeActorsV2,
|
||||
}}))
|
||||
n, sn := b(t, []FullNodeOpts{FullNodeWithUpgradeAt(upgradeHeight)}, OneMiner)
|
||||
client := n[0].FullNode.(*impl.FullNodeAPI)
|
||||
miner := sn[0]
|
||||
|
||||
|
||||
+4
-4
@@ -48,7 +48,7 @@ func TestDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration, carExport
|
||||
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
||||
|
||||
ctx := context.Background()
|
||||
n, sn := b(t, 1, OneMiner)
|
||||
n, sn := b(t, OneFull, OneMiner)
|
||||
client := n[0].FullNode.(*impl.FullNodeAPI)
|
||||
miner := sn[0]
|
||||
|
||||
@@ -85,7 +85,7 @@ func TestDoubleDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
||||
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
||||
|
||||
ctx := context.Background()
|
||||
n, sn := b(t, 1, OneMiner)
|
||||
n, sn := b(t, OneFull, OneMiner)
|
||||
client := n[0].FullNode.(*impl.FullNodeAPI)
|
||||
miner := sn[0]
|
||||
|
||||
@@ -149,7 +149,7 @@ func TestFastRetrievalDealFlow(t *testing.T, b APIBuilder, blocktime time.Durati
|
||||
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
||||
|
||||
ctx := context.Background()
|
||||
n, sn := b(t, 1, OneMiner)
|
||||
n, sn := b(t, OneFull, OneMiner)
|
||||
client := n[0].FullNode.(*impl.FullNodeAPI)
|
||||
miner := sn[0]
|
||||
|
||||
@@ -204,7 +204,7 @@ func TestSenondDealRetrieval(t *testing.T, b APIBuilder, blocktime time.Duration
|
||||
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
||||
|
||||
ctx := context.Background()
|
||||
n, sn := b(t, 1, OneMiner)
|
||||
n, sn := b(t, OneFull, OneMiner)
|
||||
client := n[0].FullNode.(*impl.FullNodeAPI)
|
||||
miner := sn[0]
|
||||
|
||||
|
||||
+3
-3
@@ -25,7 +25,7 @@ var log = logging.Logger("apitest")
|
||||
|
||||
func (ts *testSuite) testMining(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
apis, sn := ts.makeNodes(t, 1, OneMiner)
|
||||
apis, sn := ts.makeNodes(t, OneFull, OneMiner)
|
||||
api := apis[0]
|
||||
|
||||
newHeads, err := api.ChainNotify(ctx)
|
||||
@@ -54,7 +54,7 @@ func (ts *testSuite) testMiningReal(t *testing.T) {
|
||||
}()
|
||||
|
||||
ctx := context.Background()
|
||||
apis, sn := ts.makeNodes(t, 1, OneMiner)
|
||||
apis, sn := ts.makeNodes(t, OneFull, OneMiner)
|
||||
api := apis[0]
|
||||
|
||||
newHeads, err := api.ChainNotify(ctx)
|
||||
@@ -93,7 +93,7 @@ func TestDealMining(t *testing.T, b APIBuilder, blocktime time.Duration, carExpo
|
||||
// test making a deal with a fresh miner, and see if it starts to mine
|
||||
|
||||
ctx := context.Background()
|
||||
n, sn := b(t, 1, []StorageMiner{
|
||||
n, sn := b(t, OneFull, []StorageMiner{
|
||||
{Full: 0, Preseal: PresealGenesis},
|
||||
{Full: 0, Preseal: 0}, // TODO: Add support for miners on non-first full node
|
||||
})
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ func TestPaymentChannels(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
||||
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
||||
|
||||
ctx := context.Background()
|
||||
n, sn := b(t, 2, OneMiner)
|
||||
n, sn := b(t, TwoFull, OneMiner)
|
||||
|
||||
paymentCreator := n[0]
|
||||
paymentReceiver := n[1]
|
||||
|
||||
+43
-4
@@ -4,11 +4,14 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||
|
||||
"github.com/multiformats/go-multiaddr"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/miner"
|
||||
@@ -35,17 +38,27 @@ var PresealGenesis = -1
|
||||
|
||||
const GenesisPreseals = 2
|
||||
|
||||
// Options for setting up a mock storage miner
|
||||
type StorageMiner struct {
|
||||
Full int
|
||||
Preseal int
|
||||
}
|
||||
|
||||
type OptionGenerator func([]TestNode) node.Option
|
||||
|
||||
// Options for setting up a mock full node
|
||||
type FullNodeOpts struct {
|
||||
Lite bool // run node in "lite" mode
|
||||
Opts OptionGenerator // generate dependency injection options
|
||||
}
|
||||
|
||||
// APIBuilder is a function which is invoked in test suite to provide
|
||||
// test nodes and networks
|
||||
//
|
||||
// fullOpts array defines options for each full node
|
||||
// storage array defines storage nodes, numbers in the array specify full node
|
||||
// index the storage node 'belongs' to
|
||||
type APIBuilder func(t *testing.T, nFull int, storage []StorageMiner, opts ...node.Option) ([]TestNode, []TestStorageNode)
|
||||
type APIBuilder func(t *testing.T, full []FullNodeOpts, storage []StorageMiner) ([]TestNode, []TestStorageNode)
|
||||
type testSuite struct {
|
||||
makeNodes APIBuilder
|
||||
}
|
||||
@@ -63,13 +76,39 @@ func TestApis(t *testing.T, b APIBuilder) {
|
||||
t.Run("testMiningReal", ts.testMiningReal)
|
||||
}
|
||||
|
||||
func DefaultFullOpts(nFull int) []FullNodeOpts {
|
||||
full := make([]FullNodeOpts, nFull)
|
||||
for i := range full {
|
||||
full[i] = FullNodeOpts{
|
||||
Opts: func(nodes []TestNode) node.Option {
|
||||
return node.Options()
|
||||
},
|
||||
}
|
||||
}
|
||||
return full
|
||||
}
|
||||
|
||||
var OneMiner = []StorageMiner{{Full: 0, Preseal: PresealGenesis}}
|
||||
var OneFull = DefaultFullOpts(1)
|
||||
var TwoFull = DefaultFullOpts(2)
|
||||
|
||||
var FullNodeWithUpgradeAt = func(upgradeHeight abi.ChainEpoch) FullNodeOpts {
|
||||
return FullNodeOpts{
|
||||
Opts: func(nodes []TestNode) node.Option {
|
||||
return node.Override(new(stmgr.UpgradeSchedule), stmgr.UpgradeSchedule{{
|
||||
Network: build.ActorUpgradeNetworkVersion,
|
||||
Height: upgradeHeight,
|
||||
Migration: stmgr.UpgradeActorsV2,
|
||||
}})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (ts *testSuite) testVersion(t *testing.T) {
|
||||
build.RunningNodeType = build.NodeFull
|
||||
|
||||
ctx := context.Background()
|
||||
apis, _ := ts.makeNodes(t, 1, OneMiner)
|
||||
apis, _ := ts.makeNodes(t, OneFull, OneMiner)
|
||||
api := apis[0]
|
||||
|
||||
v, err := api.Version(ctx)
|
||||
@@ -81,7 +120,7 @@ func (ts *testSuite) testVersion(t *testing.T) {
|
||||
|
||||
func (ts *testSuite) testID(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
apis, _ := ts.makeNodes(t, 1, OneMiner)
|
||||
apis, _ := ts.makeNodes(t, OneFull, OneMiner)
|
||||
api := apis[0]
|
||||
|
||||
id, err := api.ID(ctx)
|
||||
@@ -93,7 +132,7 @@ func (ts *testSuite) testID(t *testing.T) {
|
||||
|
||||
func (ts *testSuite) testConnectTwo(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
apis, _ := ts.makeNodes(t, 2, OneMiner)
|
||||
apis, _ := ts.makeNodes(t, TwoFull, OneMiner)
|
||||
|
||||
p, err := apis[0].NetPeers(ctx)
|
||||
if err != nil {
|
||||
|
||||
@@ -15,11 +15,9 @@ import (
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/mock"
|
||||
sealing "github.com/filecoin-project/lotus/extern/storage-sealing"
|
||||
"github.com/filecoin-project/lotus/node"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
bminer "github.com/filecoin-project/lotus/miner"
|
||||
"github.com/filecoin-project/lotus/node/impl"
|
||||
@@ -34,7 +32,7 @@ func init() {
|
||||
|
||||
func TestPledgeSector(t *testing.T, b APIBuilder, blocktime time.Duration, nSectors int) {
|
||||
ctx := context.Background()
|
||||
n, sn := b(t, 1, OneMiner)
|
||||
n, sn := b(t, OneFull, OneMiner)
|
||||
client := n[0].FullNode.(*impl.FullNodeAPI)
|
||||
miner := sn[0]
|
||||
|
||||
@@ -133,11 +131,7 @@ func testWindowPostUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration,
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
n, sn := b(t, 1, OneMiner, node.Override(new(stmgr.UpgradeSchedule), stmgr.UpgradeSchedule{{
|
||||
Network: build.ActorUpgradeNetworkVersion,
|
||||
Height: upgradeHeight,
|
||||
Migration: stmgr.UpgradeActorsV2,
|
||||
}}))
|
||||
n, sn := b(t, []FullNodeOpts{FullNodeWithUpgradeAt(upgradeHeight)}, OneMiner)
|
||||
|
||||
client := n[0].FullNode.(*impl.FullNodeAPI)
|
||||
miner := sn[0]
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ func buildType() string {
|
||||
}
|
||||
|
||||
// BuildVersion is the local build version, set by build system
|
||||
const BuildVersion = "0.9.0"
|
||||
const BuildVersion = "0.9.1"
|
||||
|
||||
func UserVersion() string {
|
||||
return BuildVersion + buildType() + CurrentCommit
|
||||
|
||||
@@ -57,7 +57,7 @@ func (s *state0) CumsumBaseline() (abi.StoragePower, error) {
|
||||
}
|
||||
|
||||
func (s *state0) CumsumRealized() (abi.StoragePower, error) {
|
||||
return s.State.CumsumBaseline, nil
|
||||
return s.State.CumsumRealized, nil
|
||||
}
|
||||
|
||||
func (s *state0) InitialPledgeForPower(sectorWeight abi.StoragePower, networkTotalPledge abi.TokenAmount, networkQAPower *builtin.FilterEstimate, circSupply abi.TokenAmount) (abi.TokenAmount, error) {
|
||||
|
||||
@@ -60,7 +60,7 @@ func (s *state2) CumsumBaseline() (abi.StoragePower, error) {
|
||||
}
|
||||
|
||||
func (s *state2) CumsumRealized() (abi.StoragePower, error) {
|
||||
return s.State.CumsumBaseline, nil
|
||||
return s.State.CumsumRealized, nil
|
||||
}
|
||||
|
||||
func (s *state2) InitialPledgeForPower(qaPower abi.StoragePower, networkTotalPledge abi.TokenAmount, networkQAPower *builtin.FilterEstimate, circSupply abi.TokenAmount) (abi.TokenAmount, error) {
|
||||
|
||||
+24
-12
@@ -39,6 +39,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/cmd/lotus-seed/seed"
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
|
||||
"github.com/filecoin-project/lotus/genesis"
|
||||
"github.com/filecoin-project/lotus/journal"
|
||||
"github.com/filecoin-project/lotus/lib/blockstore"
|
||||
"github.com/filecoin-project/lotus/lib/sigs"
|
||||
"github.com/filecoin-project/lotus/node/repo"
|
||||
@@ -71,7 +72,7 @@ type ChainGen struct {
|
||||
|
||||
GetMessages func(*ChainGen) ([]*types.SignedMessage, error)
|
||||
|
||||
w *wallet.Wallet
|
||||
w *wallet.LocalWallet
|
||||
|
||||
eppProvs map[address.Address]WinningPoStProver
|
||||
Miners []address.Address
|
||||
@@ -122,6 +123,7 @@ var DefaultRemainderAccountActor = genesis.Actor{
|
||||
}
|
||||
|
||||
func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) {
|
||||
j := journal.NilJournal()
|
||||
// TODO: we really shouldn't modify a global variable here.
|
||||
policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1)
|
||||
|
||||
@@ -153,14 +155,14 @@ func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) {
|
||||
return nil, xerrors.Errorf("creating memrepo wallet failed: %w", err)
|
||||
}
|
||||
|
||||
banker, err := w.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
banker, err := w.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to generate banker key: %w", err)
|
||||
}
|
||||
|
||||
receievers := make([]address.Address, msgsPerBlock)
|
||||
for r := range receievers {
|
||||
receievers[r], err = w.GenerateKey(crypto.SigTypeBLS)
|
||||
receievers[r], err = w.WalletNew(context.Background(), crypto.SigTypeBLS)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to generate receiver key: %w", err)
|
||||
}
|
||||
@@ -190,11 +192,11 @@ func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mk1, err := w.Import(k1)
|
||||
mk1, err := w.WalletImport(context.Background(), k1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mk2, err := w.Import(k2)
|
||||
mk2, err := w.WalletImport(context.Background(), k2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -229,12 +231,12 @@ func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) {
|
||||
Timestamp: uint64(build.Clock.Now().Add(-500 * time.Duration(build.BlockDelaySecs) * time.Second).Unix()),
|
||||
}
|
||||
|
||||
genb, err := genesis2.MakeGenesisBlock(context.TODO(), bs, sys, tpl)
|
||||
genb, err := genesis2.MakeGenesisBlock(context.TODO(), j, bs, sys, tpl)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("make genesis block failed: %w", err)
|
||||
}
|
||||
|
||||
cs := store.NewChainStore(bs, ds, sys)
|
||||
cs := store.NewChainStore(bs, ds, sys, j)
|
||||
|
||||
genfb := &types.FullBlock{Header: genb.Genesis}
|
||||
gents := store.NewFullTipSet([]*types.FullBlock{genfb})
|
||||
@@ -374,7 +376,13 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add
|
||||
return nil, nil, nil, xerrors.Errorf("get miner worker: %w", err)
|
||||
}
|
||||
|
||||
vrfout, err := ComputeVRF(ctx, cg.w.Sign, worker, ticketRand)
|
||||
sf := func(ctx context.Context, a address.Address, i []byte) (*crypto.Signature, error) {
|
||||
return cg.w.WalletSign(ctx, a, i, api.MsgMeta{
|
||||
Type: api.MTUnknown,
|
||||
})
|
||||
}
|
||||
|
||||
vrfout, err := ComputeVRF(ctx, sf, worker, ticketRand)
|
||||
if err != nil {
|
||||
return nil, nil, nil, xerrors.Errorf("compute VRF: %w", err)
|
||||
}
|
||||
@@ -506,7 +514,7 @@ func (cg *ChainGen) Banker() address.Address {
|
||||
return cg.banker
|
||||
}
|
||||
|
||||
func (cg *ChainGen) Wallet() *wallet.Wallet {
|
||||
func (cg *ChainGen) Wallet() *wallet.LocalWallet {
|
||||
return cg.w
|
||||
}
|
||||
|
||||
@@ -528,7 +536,9 @@ func getRandomMessages(cg *ChainGen) ([]*types.SignedMessage, error) {
|
||||
GasPremium: types.NewInt(0),
|
||||
}
|
||||
|
||||
sig, err := cg.w.Sign(context.TODO(), cg.banker, msg.Cid().Bytes())
|
||||
sig, err := cg.w.WalletSign(context.TODO(), cg.banker, msg.Cid().Bytes(), api.MsgMeta{
|
||||
Type: api.MTUnknown, // testing
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -559,7 +569,7 @@ type MiningCheckAPI interface {
|
||||
}
|
||||
|
||||
type mca struct {
|
||||
w *wallet.Wallet
|
||||
w *wallet.LocalWallet
|
||||
sm *stmgr.StateManager
|
||||
pv ffiwrapper.Verifier
|
||||
bcn beacon.Schedule
|
||||
@@ -588,7 +598,9 @@ func (mca mca) MinerGetBaseInfo(ctx context.Context, maddr address.Address, epoc
|
||||
}
|
||||
|
||||
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.WalletSign(ctx, a, v, api.MsgMeta{
|
||||
Type: api.MTUnknown,
|
||||
})
|
||||
}
|
||||
|
||||
type WinningPoStProver interface {
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin"
|
||||
"github.com/filecoin-project/lotus/journal"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/ipfs/go-datastore"
|
||||
@@ -466,7 +467,10 @@ func VerifyPreSealedData(ctx context.Context, cs *store.ChainStore, stateroot ci
|
||||
return st, nil
|
||||
}
|
||||
|
||||
func MakeGenesisBlock(ctx context.Context, bs bstore.Blockstore, sys vm.SyscallBuilder, template genesis.Template) (*GenesisBootstrap, error) {
|
||||
func MakeGenesisBlock(ctx context.Context, j journal.Journal, bs bstore.Blockstore, sys vm.SyscallBuilder, template genesis.Template) (*GenesisBootstrap, error) {
|
||||
if j == nil {
|
||||
j = journal.NilJournal()
|
||||
}
|
||||
st, keyIDs, err := MakeInitialStateTree(ctx, bs, template)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("make initial state tree failed: %w", err)
|
||||
@@ -478,7 +482,7 @@ func MakeGenesisBlock(ctx context.Context, bs bstore.Blockstore, sys vm.SyscallB
|
||||
}
|
||||
|
||||
// temp chainstore
|
||||
cs := store.NewChainStore(bs, datastore.NewMapDatastore(), sys)
|
||||
cs := store.NewChainStore(bs, datastore.NewMapDatastore(), sys, j)
|
||||
|
||||
// Verify PreSealed Data
|
||||
stateroot, err = VerifyPreSealedData(ctx, cs, stateroot, template, keyIDs)
|
||||
|
||||
+4
-3
@@ -15,11 +15,10 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
"github.com/filecoin-project/lotus/chain/wallet"
|
||||
"github.com/filecoin-project/lotus/lib/sigs/bls"
|
||||
)
|
||||
|
||||
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wallet, bt *api.BlockTemplate) (*types.FullBlock, error) {
|
||||
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w api.WalletAPI, bt *api.BlockTemplate) (*types.FullBlock, error) {
|
||||
|
||||
pts, err := sm.ChainStore().LoadTipSet(bt.Parents)
|
||||
if err != nil {
|
||||
@@ -131,7 +130,9 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wal
|
||||
return nil, xerrors.Errorf("failed to get signing bytes for block: %w", err)
|
||||
}
|
||||
|
||||
sig, err := w.Sign(ctx, waddr, nosigbytes)
|
||||
sig, err := w.WalletSign(ctx, waddr, nosigbytes, api.MsgMeta{
|
||||
Type: api.MTBlock,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to sign new block: %w", err)
|
||||
}
|
||||
|
||||
@@ -120,9 +120,10 @@ func (fm *FundMgr) EnsureAvailable(ctx context.Context, addr, wallet address.Add
|
||||
return cid.Undef, err
|
||||
}
|
||||
fm.lk.Lock()
|
||||
defer fm.lk.Unlock()
|
||||
|
||||
bal, err := fm.api.StateMarketBalance(ctx, addr, types.EmptyTSK)
|
||||
if err != nil {
|
||||
fm.lk.Unlock()
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
@@ -138,7 +139,6 @@ func (fm *FundMgr) EnsureAvailable(ctx context.Context, addr, wallet address.Add
|
||||
toAdd = types.NewInt(0)
|
||||
}
|
||||
fm.available[idAddr] = big.Add(avail, toAdd)
|
||||
fm.lk.Unlock()
|
||||
|
||||
log.Infof("Funds operation w/ Expected Balance: %s, In State: %s, Requested: %s, Adding: %s", avail.String(), stateAvail.String(), amt.String(), toAdd.String())
|
||||
|
||||
@@ -148,6 +148,7 @@ func (fm *FundMgr) EnsureAvailable(ctx context.Context, addr, wallet address.Add
|
||||
|
||||
params, err := actors.SerializeParams(&addr)
|
||||
if err != nil {
|
||||
fm.available[idAddr] = avail
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
@@ -159,6 +160,7 @@ func (fm *FundMgr) EnsureAvailable(ctx context.Context, addr, wallet address.Add
|
||||
Params: params,
|
||||
}, nil)
|
||||
if err != nil {
|
||||
fm.available[idAddr] = avail
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
|
||||
@@ -57,9 +57,10 @@ func addFundsMsg(toAdd abi.TokenAmount, addr address.Address, wallet address.Add
|
||||
}
|
||||
|
||||
type expectedResult struct {
|
||||
addAmt abi.TokenAmount
|
||||
shouldAdd bool
|
||||
err error
|
||||
addAmt abi.TokenAmount
|
||||
shouldAdd bool
|
||||
err error
|
||||
cachedAvailable abi.TokenAmount
|
||||
}
|
||||
|
||||
func TestAddFunds(t *testing.T) {
|
||||
@@ -88,8 +89,9 @@ func TestAddFunds(t *testing.T) {
|
||||
addAmounts: []abi.TokenAmount{abi.NewTokenAmount(100)},
|
||||
expectedResults: []expectedResult{
|
||||
{
|
||||
shouldAdd: false,
|
||||
err: nil,
|
||||
shouldAdd: false,
|
||||
err: nil,
|
||||
cachedAvailable: abi.NewTokenAmount(100),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -102,18 +104,21 @@ func TestAddFunds(t *testing.T) {
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
addAmt: abi.NewTokenAmount(100),
|
||||
shouldAdd: true,
|
||||
err: nil,
|
||||
addAmt: abi.NewTokenAmount(100),
|
||||
shouldAdd: true,
|
||||
err: nil,
|
||||
cachedAvailable: abi.NewTokenAmount(200),
|
||||
},
|
||||
{
|
||||
addAmt: abi.NewTokenAmount(50),
|
||||
shouldAdd: true,
|
||||
err: nil,
|
||||
addAmt: abi.NewTokenAmount(50),
|
||||
shouldAdd: true,
|
||||
err: nil,
|
||||
cachedAvailable: abi.NewTokenAmount(250),
|
||||
},
|
||||
{
|
||||
shouldAdd: false,
|
||||
err: nil,
|
||||
shouldAdd: false,
|
||||
err: nil,
|
||||
cachedAvailable: abi.NewTokenAmount(250),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -132,7 +137,8 @@ func TestAddFunds(t *testing.T) {
|
||||
addAmounts: []abi.TokenAmount{abi.NewTokenAmount(100)},
|
||||
expectedResults: []expectedResult{
|
||||
{
|
||||
err: errors.New("something went wrong"),
|
||||
err: errors.New("something went wrong"),
|
||||
cachedAvailable: abi.NewTokenAmount(0),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -183,6 +189,10 @@ func TestAddFunds(t *testing.T) {
|
||||
} else {
|
||||
require.EqualError(t, err, expected.err.Error())
|
||||
}
|
||||
|
||||
if !expected.cachedAvailable.Nil() {
|
||||
require.Equal(t, expected.cachedAvailable, fundMgr.available[addr])
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -159,6 +159,7 @@ type MessagePool struct {
|
||||
sigValCache *lru.TwoQueueCache
|
||||
|
||||
evtTypes [3]journal.EventType
|
||||
journal journal.Journal
|
||||
}
|
||||
|
||||
type msgSet struct {
|
||||
@@ -316,7 +317,7 @@ func (ms *msgSet) getRequiredFunds(nonce uint64) types.BigInt {
|
||||
return types.BigInt{Int: requiredFunds}
|
||||
}
|
||||
|
||||
func New(api Provider, ds dtypes.MetadataDS, netName dtypes.NetworkName) (*MessagePool, error) {
|
||||
func New(api Provider, ds dtypes.MetadataDS, netName dtypes.NetworkName, j journal.Journal) (*MessagePool, error) {
|
||||
cache, _ := lru.New2Q(build.BlsSignatureCacheSize)
|
||||
verifcache, _ := lru.New2Q(build.VerifSigCacheSize)
|
||||
|
||||
@@ -325,6 +326,10 @@ func New(api Provider, ds dtypes.MetadataDS, netName dtypes.NetworkName) (*Messa
|
||||
return nil, xerrors.Errorf("error loading mpool config: %w", err)
|
||||
}
|
||||
|
||||
if j == nil {
|
||||
j = journal.NilJournal()
|
||||
}
|
||||
|
||||
mp := &MessagePool{
|
||||
ds: ds,
|
||||
addSema: make(chan struct{}, 1),
|
||||
@@ -344,10 +349,11 @@ func New(api Provider, ds dtypes.MetadataDS, netName dtypes.NetworkName) (*Messa
|
||||
netName: netName,
|
||||
cfg: cfg,
|
||||
evtTypes: [...]journal.EventType{
|
||||
evtTypeMpoolAdd: journal.J.RegisterEventType("mpool", "add"),
|
||||
evtTypeMpoolRemove: journal.J.RegisterEventType("mpool", "remove"),
|
||||
evtTypeMpoolRepub: journal.J.RegisterEventType("mpool", "repub"),
|
||||
evtTypeMpoolAdd: j.RegisterEventType("mpool", "add"),
|
||||
evtTypeMpoolRemove: j.RegisterEventType("mpool", "remove"),
|
||||
evtTypeMpoolRepub: j.RegisterEventType("mpool", "repub"),
|
||||
},
|
||||
journal: j,
|
||||
}
|
||||
|
||||
// enable initial prunes
|
||||
@@ -744,7 +750,7 @@ func (mp *MessagePool) addLocked(m *types.SignedMessage, strict, untrusted bool)
|
||||
Message: m,
|
||||
}, localUpdates)
|
||||
|
||||
journal.J.RecordEvent(mp.evtTypes[evtTypeMpoolAdd], func() interface{} {
|
||||
mp.journal.RecordEvent(mp.evtTypes[evtTypeMpoolAdd], func() interface{} {
|
||||
return MessagePoolEvt{
|
||||
Action: "add",
|
||||
Messages: []MessagePoolEvtMessage{{Message: m.Message, CID: m.Cid()}},
|
||||
@@ -865,7 +871,7 @@ func (mp *MessagePool) remove(from address.Address, nonce uint64, applied bool)
|
||||
Message: m,
|
||||
}, localUpdates)
|
||||
|
||||
journal.J.RecordEvent(mp.evtTypes[evtTypeMpoolRemove], func() interface{} {
|
||||
mp.journal.RecordEvent(mp.evtTypes[evtTypeMpoolRemove], func() interface{} {
|
||||
return MessagePoolEvt{
|
||||
Action: "remove",
|
||||
Messages: []MessagePoolEvtMessage{{Message: m.Message, CID: m.Cid()}}}
|
||||
|
||||
@@ -225,14 +225,14 @@ func TestMessagePool(t *testing.T) {
|
||||
|
||||
ds := datastore.NewMapDatastore()
|
||||
|
||||
mp, err := New(tma, ds, "mptest")
|
||||
mp, err := New(tma, ds, "mptest", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a := tma.nextBlock()
|
||||
|
||||
sender, err := w.GenerateKey(crypto.SigTypeBLS)
|
||||
sender, err := w.WalletNew(context.Background(), crypto.SigTypeBLS)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -266,14 +266,14 @@ func TestMessagePoolMessagesInEachBlock(t *testing.T) {
|
||||
|
||||
ds := datastore.NewMapDatastore()
|
||||
|
||||
mp, err := New(tma, ds, "mptest")
|
||||
mp, err := New(tma, ds, "mptest", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a := tma.nextBlock()
|
||||
|
||||
sender, err := w.GenerateKey(crypto.SigTypeBLS)
|
||||
sender, err := w.WalletNew(context.Background(), crypto.SigTypeBLS)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -315,7 +315,7 @@ func TestRevertMessages(t *testing.T) {
|
||||
|
||||
ds := datastore.NewMapDatastore()
|
||||
|
||||
mp, err := New(tma, ds, "mptest")
|
||||
mp, err := New(tma, ds, "mptest", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -323,7 +323,7 @@ func TestRevertMessages(t *testing.T) {
|
||||
a := tma.nextBlock()
|
||||
b := tma.nextBlock()
|
||||
|
||||
sender, err := w.GenerateKey(crypto.SigTypeBLS)
|
||||
sender, err := w.WalletNew(context.Background(), crypto.SigTypeBLS)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -378,7 +378,7 @@ func TestPruningSimple(t *testing.T) {
|
||||
|
||||
ds := datastore.NewMapDatastore()
|
||||
|
||||
mp, err := New(tma, ds, "mptest")
|
||||
mp, err := New(tma, ds, "mptest", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -386,7 +386,7 @@ func TestPruningSimple(t *testing.T) {
|
||||
a := tma.nextBlock()
|
||||
tma.applyBlock(t, a)
|
||||
|
||||
sender, err := w.GenerateKey(crypto.SigTypeBLS)
|
||||
sender, err := w.WalletNew(context.Background(), crypto.SigTypeBLS)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -422,7 +422,7 @@ func TestLoadLocal(t *testing.T) {
|
||||
tma := newTestMpoolAPI()
|
||||
ds := datastore.NewMapDatastore()
|
||||
|
||||
mp, err := New(tma, ds, "mptest")
|
||||
mp, err := New(tma, ds, "mptest", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -433,7 +433,7 @@ func TestLoadLocal(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -443,7 +443,7 @@ func TestLoadLocal(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -465,7 +465,7 @@ func TestLoadLocal(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
mp, err = New(tma, ds, "mptest")
|
||||
mp, err = New(tma, ds, "mptest", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -494,7 +494,7 @@ func TestClearAll(t *testing.T) {
|
||||
tma := newTestMpoolAPI()
|
||||
ds := datastore.NewMapDatastore()
|
||||
|
||||
mp, err := New(tma, ds, "mptest")
|
||||
mp, err := New(tma, ds, "mptest", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -505,7 +505,7 @@ func TestClearAll(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -515,7 +515,7 @@ func TestClearAll(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -548,7 +548,7 @@ func TestClearNonLocal(t *testing.T) {
|
||||
tma := newTestMpoolAPI()
|
||||
ds := datastore.NewMapDatastore()
|
||||
|
||||
mp, err := New(tma, ds, "mptest")
|
||||
mp, err := New(tma, ds, "mptest", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -559,7 +559,7 @@ func TestClearNonLocal(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -569,7 +569,7 @@ func TestClearNonLocal(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -609,7 +609,7 @@ func TestUpdates(t *testing.T) {
|
||||
tma := newTestMpoolAPI()
|
||||
ds := datastore.NewMapDatastore()
|
||||
|
||||
mp, err := New(tma, ds, "mptest")
|
||||
mp, err := New(tma, ds, "mptest", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -620,7 +620,7 @@ func TestUpdates(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -630,7 +630,7 @@ func TestUpdates(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/messagepool/gasguess"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/journal"
|
||||
"github.com/ipfs/go-cid"
|
||||
)
|
||||
|
||||
@@ -148,14 +147,14 @@ loop:
|
||||
}
|
||||
|
||||
if len(msgs) > 0 {
|
||||
journal.J.RecordEvent(mp.evtTypes[evtTypeMpoolRepub], func() interface{} {
|
||||
msgs := make([]MessagePoolEvtMessage, 0, len(msgs))
|
||||
mp.journal.RecordEvent(mp.evtTypes[evtTypeMpoolRepub], func() interface{} {
|
||||
msgsEv := make([]MessagePoolEvtMessage, 0, len(msgs))
|
||||
for _, m := range msgs {
|
||||
msgs = append(msgs, MessagePoolEvtMessage{Message: m.Message, CID: m.Cid()})
|
||||
msgsEv = append(msgsEv, MessagePoolEvtMessage{Message: m.Message, CID: m.Cid()})
|
||||
}
|
||||
return MessagePoolEvt{
|
||||
Action: "repub",
|
||||
Messages: msgs,
|
||||
Messages: msgsEv,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package messagepool
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -21,7 +22,7 @@ func TestRepubMessages(t *testing.T) {
|
||||
tma := newTestMpoolAPI()
|
||||
ds := datastore.NewMapDatastore()
|
||||
|
||||
mp, err := New(tma, ds, "mptest")
|
||||
mp, err := New(tma, ds, "mptest", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -32,7 +33,7 @@ func TestRepubMessages(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -42,7 +43,7 @@ func TestRepubMessages(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -13,6 +13,10 @@ import (
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/ipfs/go-datastore"
|
||||
logging "github.com/ipfs/go-log"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
@@ -21,12 +25,10 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/types/mock"
|
||||
"github.com/filecoin-project/lotus/chain/wallet"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/ipfs/go-datastore"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
|
||||
logging "github.com/ipfs/go-log"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -34,7 +36,7 @@ func init() {
|
||||
MaxActorPendingMessages = 1000000
|
||||
}
|
||||
|
||||
func makeTestMessage(w *wallet.Wallet, from, to address.Address, nonce uint64, gasLimit int64, gasPrice uint64) *types.SignedMessage {
|
||||
func makeTestMessage(w *wallet.LocalWallet, from, to address.Address, nonce uint64, gasLimit int64, gasPrice uint64) *types.SignedMessage {
|
||||
msg := &types.Message{
|
||||
From: from,
|
||||
To: to,
|
||||
@@ -45,7 +47,7 @@ func makeTestMessage(w *wallet.Wallet, from, to address.Address, nonce uint64, g
|
||||
GasFeeCap: types.NewInt(100 + gasPrice),
|
||||
GasPremium: types.NewInt(gasPrice),
|
||||
}
|
||||
sig, err := w.Sign(context.TODO(), from, msg.Cid().Bytes())
|
||||
sig, err := w.WalletSign(context.TODO(), from, msg.Cid().Bytes(), api.MsgMeta{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -58,7 +60,7 @@ func makeTestMessage(w *wallet.Wallet, from, to address.Address, nonce uint64, g
|
||||
func makeTestMpool() (*MessagePool, *testMpoolAPI) {
|
||||
tma := newTestMpoolAPI()
|
||||
ds := datastore.NewMapDatastore()
|
||||
mp, err := New(tma, ds, "test")
|
||||
mp, err := New(tma, ds, "test", nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -75,7 +77,7 @@ func TestMessageChains(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -85,7 +87,7 @@ func TestMessageChains(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -313,7 +315,7 @@ func TestMessageChainSkipping(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -323,7 +325,7 @@ func TestMessageChainSkipping(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -389,7 +391,7 @@ func TestBasicMessageSelection(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -399,7 +401,7 @@ func TestBasicMessageSelection(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -533,7 +535,7 @@ func TestMessageSelectionTrimming(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -543,7 +545,7 @@ func TestMessageSelectionTrimming(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -596,7 +598,7 @@ func TestPriorityMessageSelection(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -606,7 +608,7 @@ func TestPriorityMessageSelection(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -675,7 +677,7 @@ func TestPriorityMessageSelection2(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -685,7 +687,7 @@ func TestPriorityMessageSelection2(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -744,7 +746,7 @@ func TestPriorityMessageSelection3(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -754,7 +756,7 @@ func TestPriorityMessageSelection3(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -841,7 +843,7 @@ func TestOptimalMessageSelection1(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -851,7 +853,7 @@ func TestOptimalMessageSelection1(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -908,7 +910,7 @@ func TestOptimalMessageSelection2(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -918,7 +920,7 @@ func TestOptimalMessageSelection2(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -984,7 +986,7 @@ func TestOptimalMessageSelection3(t *testing.T) {
|
||||
nActors := 10
|
||||
// the actors
|
||||
var actors []address.Address
|
||||
var wallets []*wallet.Wallet
|
||||
var wallets []*wallet.LocalWallet
|
||||
|
||||
for i := 0; i < nActors; i++ {
|
||||
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
|
||||
@@ -992,7 +994,7 @@ func TestOptimalMessageSelection3(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a, err := w.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a, err := w.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -1064,7 +1066,7 @@ func testCompetitiveMessageSelection(t *testing.T, rng *rand.Rand, getPremium fu
|
||||
nActors := 300
|
||||
// the actors
|
||||
var actors []address.Address
|
||||
var wallets []*wallet.Wallet
|
||||
var wallets []*wallet.LocalWallet
|
||||
|
||||
for i := 0; i < nActors; i++ {
|
||||
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
|
||||
@@ -1072,7 +1074,7 @@ func testCompetitiveMessageSelection(t *testing.T, rng *rand.Rand, getPremium fu
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a, err := w.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a, err := w.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -1330,7 +1332,7 @@ readLoop:
|
||||
}
|
||||
|
||||
actorMap := make(map[address.Address]address.Address)
|
||||
actorWallets := make(map[address.Address]*wallet.Wallet)
|
||||
actorWallets := make(map[address.Address]api.WalletAPI)
|
||||
|
||||
for _, m := range msgs {
|
||||
baseNonce := baseNonces[m.Message.From]
|
||||
@@ -1342,7 +1344,7 @@ readLoop:
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a, err := w.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
a, err := w.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -1360,7 +1362,7 @@ readLoop:
|
||||
m.Message.From = localActor
|
||||
m.Message.Nonce -= baseNonce
|
||||
|
||||
sig, err := w.Sign(context.TODO(), localActor, m.Message.Cid().Bytes())
|
||||
sig, err := w.WalletSign(context.TODO(), localActor, m.Message.Cid().Bytes(), api.MsgMeta{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -5,40 +5,37 @@ import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/lotus/chain/messagepool"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/wallet"
|
||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||
"github.com/ipfs/go-datastore"
|
||||
"github.com/ipfs/go-datastore/namespace"
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||
)
|
||||
|
||||
const dsKeyActorNonce = "ActorNextNonce"
|
||||
|
||||
var log = logging.Logger("messagesigner")
|
||||
|
||||
type mpoolAPI interface {
|
||||
type MpoolNonceAPI interface {
|
||||
GetNonce(address.Address) (uint64, error)
|
||||
}
|
||||
|
||||
// MessageSigner keeps track of nonces per address, and increments the nonce
|
||||
// when signing a message
|
||||
type MessageSigner struct {
|
||||
wallet *wallet.Wallet
|
||||
wallet api.WalletAPI
|
||||
lk sync.Mutex
|
||||
mpool mpoolAPI
|
||||
mpool MpoolNonceAPI
|
||||
ds datastore.Batching
|
||||
}
|
||||
|
||||
func NewMessageSigner(wallet *wallet.Wallet, mpool *messagepool.MessagePool, ds dtypes.MetadataDS) *MessageSigner {
|
||||
return newMessageSigner(wallet, mpool, ds)
|
||||
}
|
||||
|
||||
func newMessageSigner(wallet *wallet.Wallet, mpool mpoolAPI, ds dtypes.MetadataDS) *MessageSigner {
|
||||
func NewMessageSigner(wallet api.WalletAPI, mpool MpoolNonceAPI, ds dtypes.MetadataDS) *MessageSigner {
|
||||
ds = namespace.Wrap(ds, datastore.NewKey("/message-signer/"))
|
||||
return &MessageSigner{
|
||||
wallet: wallet,
|
||||
@@ -61,7 +58,16 @@ func (ms *MessageSigner) SignMessage(ctx context.Context, msg *types.Message, cb
|
||||
|
||||
// Sign the message with the nonce
|
||||
msg.Nonce = nonce
|
||||
sig, err := ms.wallet.Sign(ctx, msg.From, msg.Cid().Bytes())
|
||||
|
||||
mb, err := msg.ToStorageBlock()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("serializing message: %w", err)
|
||||
}
|
||||
|
||||
sig, err := ms.wallet.WalletSign(ctx, msg.From, mb.Cid().Bytes(), api.MsgMeta{
|
||||
Type: api.MTChainMsg,
|
||||
Extra: mb.RawData(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to sign message: %w", err)
|
||||
}
|
||||
|
||||
@@ -47,13 +47,13 @@ func TestMessageSignerSignMessage(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
w, _ := wallet.NewWallet(wallet.NewMemKeyStore())
|
||||
from1, err := w.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
from1, err := w.WalletNew(ctx, crypto.SigTypeSecp256k1)
|
||||
require.NoError(t, err)
|
||||
from2, err := w.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
from2, err := w.WalletNew(ctx, crypto.SigTypeSecp256k1)
|
||||
require.NoError(t, err)
|
||||
to1, err := w.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
to1, err := w.WalletNew(ctx, crypto.SigTypeSecp256k1)
|
||||
require.NoError(t, err)
|
||||
to2, err := w.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
to2, err := w.WalletNew(ctx, crypto.SigTypeSecp256k1)
|
||||
require.NoError(t, err)
|
||||
|
||||
type msgSpec struct {
|
||||
@@ -177,7 +177,7 @@ func TestMessageSignerSignMessage(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
mpool := newMockMpool()
|
||||
ds := ds_sync.MutexWrap(datastore.NewMapDatastore())
|
||||
ms := newMessageSigner(w, mpool, ds)
|
||||
ms := NewMessageSigner(w, mpool, ds)
|
||||
|
||||
for _, m := range tt.msgs {
|
||||
if len(m.mpoolNonce) == 1 {
|
||||
|
||||
@@ -24,7 +24,6 @@ import (
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/migration/nv3"
|
||||
m2 "github.com/filecoin-project/specs-actors/v2/actors/migration"
|
||||
states2 "github.com/filecoin-project/specs-actors/v2/actors/states"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||
@@ -580,19 +579,6 @@ func UpgradeActorsV2(ctx context.Context, sm *StateManager, cb ExecCallback, roo
|
||||
return cid.Undef, xerrors.Errorf("upgrading to actors v2: %w", err)
|
||||
}
|
||||
|
||||
newStateTree, err := states2.LoadTree(store, newHamtRoot)
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("failed to load new state tree: %w", err)
|
||||
}
|
||||
|
||||
// Check all state-tree invariants.
|
||||
if msgs, err := states2.CheckStateInvariants(newStateTree, types.TotalFilecoinInt); err != nil {
|
||||
return cid.Undef, xerrors.Errorf("failed to check new state tree: %w", err)
|
||||
} else if !msgs.IsEmpty() {
|
||||
// This error is going to be really nasty.
|
||||
return cid.Undef, xerrors.Errorf("network upgrade failed: %v", msgs.Messages())
|
||||
}
|
||||
|
||||
newRoot, err := store.Put(ctx, &types.StateRoot{
|
||||
Version: types.StateTreeVersion1,
|
||||
Actors: newHamtRoot,
|
||||
|
||||
@@ -6,15 +6,21 @@ import (
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
ipldcbor "github.com/ipfs/go-ipld-cbor"
|
||||
logging "github.com/ipfs/go-log"
|
||||
"github.com/stretchr/testify/require"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/cbor"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
init0 "github.com/filecoin-project/specs-actors/actors/builtin/init"
|
||||
"github.com/filecoin-project/specs-actors/actors/runtime"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/actors/aerrors"
|
||||
lotusinit "github.com/filecoin-project/lotus/chain/actors/builtin/init"
|
||||
@@ -25,11 +31,6 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
ipldcbor "github.com/ipfs/go-ipld-cbor"
|
||||
logging "github.com/ipfs/go-log"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -186,7 +187,7 @@ func TestForkHeightTriggers(t *testing.T) {
|
||||
Params: enc,
|
||||
GasLimit: types.TestGasLimit,
|
||||
}
|
||||
sig, err := cg.Wallet().Sign(ctx, cg.Banker(), m.Cid().Bytes())
|
||||
sig, err := cg.Wallet().WalletSign(ctx, cg.Banker(), m.Cid().Bytes(), api.MsgMeta{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -214,7 +215,7 @@ func TestForkHeightTriggers(t *testing.T) {
|
||||
}
|
||||
nonce++
|
||||
|
||||
sig, err := cg.Wallet().Sign(ctx, cg.Banker(), m.Cid().Bytes())
|
||||
sig, err := cg.Wallet().WalletSign(ctx, cg.Banker(), m.Cid().Bytes(), api.MsgMeta{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+60
-31
@@ -2,6 +2,7 @@ package stmgr
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
@@ -37,8 +38,16 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
)
|
||||
|
||||
const LookbackNoLimit = abi.ChainEpoch(-1)
|
||||
|
||||
var log = logging.Logger("statemgr")
|
||||
|
||||
type StateManagerAPI interface {
|
||||
LoadActorTsk(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*types.Actor, error)
|
||||
LookupID(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error)
|
||||
ResolveToKeyAddress(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error)
|
||||
}
|
||||
|
||||
type versionSpec struct {
|
||||
networkVersion network.Version
|
||||
atOrBelow abi.ChainEpoch
|
||||
@@ -507,16 +516,7 @@ func (sm *StateManager) GetReceipt(ctx context.Context, msg cid.Cid, ts *types.T
|
||||
return nil, fmt.Errorf("failed to load message: %w", err)
|
||||
}
|
||||
|
||||
r, _, err := sm.tipsetExecutedMessage(ts, msg, m.VMMessage())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if r != nil {
|
||||
return r, nil
|
||||
}
|
||||
|
||||
_, r, _, err = sm.searchBackForMsg(ctx, ts, m)
|
||||
_, r, _, err := sm.searchBackForMsg(ctx, ts, m, LookbackNoLimit)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to look back through chain for message: %w", err)
|
||||
}
|
||||
@@ -525,9 +525,9 @@ func (sm *StateManager) GetReceipt(ctx context.Context, msg cid.Cid, ts *types.T
|
||||
}
|
||||
|
||||
// WaitForMessage blocks until a message appears on chain. It looks backwards in the chain to see if this has already
|
||||
// happened. It guarantees that the message has been on chain for at least confidence epochs without being reverted
|
||||
// before returning.
|
||||
func (sm *StateManager) WaitForMessage(ctx context.Context, mcid cid.Cid, confidence uint64) (*types.TipSet, *types.MessageReceipt, cid.Cid, error) {
|
||||
// happened, with an optional limit to how many epochs it will search. It guarantees that the message has been on
|
||||
// chain for at least confidence epochs without being reverted before returning.
|
||||
func (sm *StateManager) WaitForMessage(ctx context.Context, mcid cid.Cid, confidence uint64, lookbackLimit abi.ChainEpoch) (*types.TipSet, *types.MessageReceipt, cid.Cid, error) {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
|
||||
@@ -565,7 +565,7 @@ func (sm *StateManager) WaitForMessage(ctx context.Context, mcid cid.Cid, confid
|
||||
var backFm cid.Cid
|
||||
backSearchWait := make(chan struct{})
|
||||
go func() {
|
||||
fts, r, foundMsg, err := sm.searchBackForMsg(ctx, head[0].Val, msg)
|
||||
fts, r, foundMsg, err := sm.searchBackForMsg(ctx, head[0].Val, msg, lookbackLimit)
|
||||
if err != nil {
|
||||
log.Warnf("failed to look back through chain for message: %w", err)
|
||||
return
|
||||
@@ -657,7 +657,7 @@ func (sm *StateManager) SearchForMessage(ctx context.Context, mcid cid.Cid) (*ty
|
||||
return head, r, foundMsg, nil
|
||||
}
|
||||
|
||||
fts, r, foundMsg, err := sm.searchBackForMsg(ctx, head, msg)
|
||||
fts, r, foundMsg, err := sm.searchBackForMsg(ctx, head, msg, LookbackNoLimit)
|
||||
|
||||
if err != nil {
|
||||
log.Warnf("failed to look back through chain for message %s", mcid)
|
||||
@@ -671,11 +671,33 @@ func (sm *StateManager) SearchForMessage(ctx context.Context, mcid cid.Cid) (*ty
|
||||
return fts, r, foundMsg, nil
|
||||
}
|
||||
|
||||
func (sm *StateManager) searchBackForMsg(ctx context.Context, from *types.TipSet, m types.ChainMsg) (*types.TipSet, *types.MessageReceipt, cid.Cid, error) {
|
||||
// searchBackForMsg searches up to limit tipsets backwards from the given
|
||||
// tipset for a message receipt.
|
||||
// If limit is
|
||||
// - 0 then no tipsets are searched
|
||||
// - 5 then five tipset are searched
|
||||
// - LookbackNoLimit then there is no limit
|
||||
func (sm *StateManager) searchBackForMsg(ctx context.Context, from *types.TipSet, m types.ChainMsg, limit abi.ChainEpoch) (*types.TipSet, *types.MessageReceipt, cid.Cid, error) {
|
||||
limitHeight := from.Height() - limit
|
||||
noLimit := limit == LookbackNoLimit
|
||||
|
||||
cur := from
|
||||
curActor, err := sm.LoadActor(ctx, m.VMMessage().From, cur)
|
||||
if err != nil {
|
||||
return nil, nil, cid.Undef, xerrors.Errorf("failed to load initital tipset")
|
||||
}
|
||||
|
||||
mFromId, err := sm.LookupID(ctx, m.VMMessage().From, from)
|
||||
if err != nil {
|
||||
return nil, nil, cid.Undef, xerrors.Errorf("looking up From id address: %w", err)
|
||||
}
|
||||
|
||||
mNonce := m.VMMessage().Nonce
|
||||
|
||||
for {
|
||||
if cur.Height() == 0 {
|
||||
// If we've reached the genesis block, or we've reached the limit of
|
||||
// how far back to look
|
||||
if cur.Height() == 0 || !noLimit && cur.Height() <= limitHeight {
|
||||
// it ain't here!
|
||||
return nil, nil, cid.Undef, nil
|
||||
}
|
||||
@@ -686,32 +708,37 @@ func (sm *StateManager) searchBackForMsg(ctx context.Context, from *types.TipSet
|
||||
default:
|
||||
}
|
||||
|
||||
act, err := sm.LoadActor(ctx, m.VMMessage().From, cur)
|
||||
if err != nil {
|
||||
return nil, nil, cid.Cid{}, err
|
||||
}
|
||||
|
||||
// we either have no messages from the sender, or the latest message we found has a lower nonce than the one being searched for,
|
||||
// either way, no reason to lookback, it ain't there
|
||||
if act.Nonce == 0 || act.Nonce < m.VMMessage().Nonce {
|
||||
if curActor == nil || curActor.Nonce == 0 || curActor.Nonce < mNonce {
|
||||
return nil, nil, cid.Undef, nil
|
||||
}
|
||||
|
||||
ts, err := sm.cs.LoadTipSet(cur.Parents())
|
||||
pts, err := sm.cs.LoadTipSet(cur.Parents())
|
||||
if err != nil {
|
||||
return nil, nil, cid.Undef, fmt.Errorf("failed to load tipset during msg wait searchback: %w", err)
|
||||
return nil, nil, cid.Undef, xerrors.Errorf("failed to load tipset during msg wait searchback: %w", err)
|
||||
}
|
||||
|
||||
r, foundMsg, err := sm.tipsetExecutedMessage(ts, m.Cid(), m.VMMessage())
|
||||
if err != nil {
|
||||
return nil, nil, cid.Undef, fmt.Errorf("checking for message execution during lookback: %w", err)
|
||||
act, err := sm.LoadActor(ctx, mFromId, pts)
|
||||
actorNoExist := errors.Is(err, types.ErrActorNotFound)
|
||||
if err != nil && !actorNoExist {
|
||||
return nil, nil, cid.Cid{}, xerrors.Errorf("failed to load the actor: %w", err)
|
||||
}
|
||||
|
||||
if r != nil {
|
||||
return ts, r, foundMsg, nil
|
||||
// check that between cur and parent tipset the nonce fell into range of our message
|
||||
if actorNoExist || (curActor.Nonce > mNonce && act.Nonce <= mNonce) {
|
||||
r, foundMsg, err := sm.tipsetExecutedMessage(cur, m.Cid(), m.VMMessage())
|
||||
if err != nil {
|
||||
return nil, nil, cid.Undef, xerrors.Errorf("checking for message execution during lookback: %w", err)
|
||||
}
|
||||
|
||||
if r != nil {
|
||||
return pts, r, foundMsg, nil
|
||||
}
|
||||
}
|
||||
|
||||
cur = ts
|
||||
cur = pts
|
||||
curActor = act
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1384,3 +1411,5 @@ func (sm *StateManager) GetMarketState(ctx context.Context, ts *types.TipSet) (m
|
||||
}
|
||||
return actState, nil
|
||||
}
|
||||
|
||||
var _ StateManagerAPI = (*StateManager)(nil)
|
||||
|
||||
@@ -31,7 +31,7 @@ func TestIndexSeeks(t *testing.T) {
|
||||
ctx := context.TODO()
|
||||
|
||||
nbs := blockstore.NewTemporarySync()
|
||||
cs := store.NewChainStore(nbs, syncds.MutexWrap(datastore.NewMapDatastore()), nil)
|
||||
cs := store.NewChainStore(nbs, syncds.MutexWrap(datastore.NewMapDatastore()), nil, nil)
|
||||
|
||||
_, err = cs.Import(bytes.NewReader(gencar))
|
||||
if err != nil {
|
||||
|
||||
@@ -124,11 +124,15 @@ type ChainStore struct {
|
||||
vmcalls vm.SyscallBuilder
|
||||
|
||||
evtTypes [1]journal.EventType
|
||||
journal journal.Journal
|
||||
}
|
||||
|
||||
func NewChainStore(bs bstore.Blockstore, ds dstore.Batching, vmcalls vm.SyscallBuilder) *ChainStore {
|
||||
func NewChainStore(bs bstore.Blockstore, ds dstore.Batching, vmcalls vm.SyscallBuilder, j journal.Journal) *ChainStore {
|
||||
c, _ := lru.NewARC(DefaultMsgMetaCacheSize)
|
||||
tsc, _ := lru.NewARC(DefaultTipSetCacheSize)
|
||||
if j == nil {
|
||||
j = journal.NilJournal()
|
||||
}
|
||||
cs := &ChainStore{
|
||||
bs: bs,
|
||||
ds: ds,
|
||||
@@ -137,10 +141,11 @@ func NewChainStore(bs bstore.Blockstore, ds dstore.Batching, vmcalls vm.SyscallB
|
||||
mmCache: c,
|
||||
tsCache: tsc,
|
||||
vmcalls: vmcalls,
|
||||
journal: j,
|
||||
}
|
||||
|
||||
cs.evtTypes = [1]journal.EventType{
|
||||
evtTypeHeadChange: journal.J.RegisterEventType("sync", "head_change"),
|
||||
evtTypeHeadChange: j.RegisterEventType("sync", "head_change"),
|
||||
}
|
||||
|
||||
ci := NewChainIndex(cs.LoadTipSet)
|
||||
@@ -379,7 +384,7 @@ func (cs *ChainStore) reorgWorker(ctx context.Context, initialNotifees []ReorgNo
|
||||
continue
|
||||
}
|
||||
|
||||
journal.J.RecordEvent(cs.evtTypes[evtTypeHeadChange], func() interface{} {
|
||||
cs.journal.RecordEvent(cs.evtTypes[evtTypeHeadChange], func() interface{} {
|
||||
return HeadChangeEvt{
|
||||
From: r.old.Key(),
|
||||
FromHeight: r.old.Height(),
|
||||
|
||||
@@ -62,7 +62,7 @@ func BenchmarkGetRandomness(b *testing.B) {
|
||||
|
||||
bs := blockstore.NewBlockstore(bds)
|
||||
|
||||
cs := store.NewChainStore(bs, mds, nil)
|
||||
cs := store.NewChainStore(bs, mds, nil, nil)
|
||||
|
||||
b.ResetTimer()
|
||||
|
||||
@@ -96,7 +96,7 @@ func TestChainExportImport(t *testing.T) {
|
||||
}
|
||||
|
||||
nbs := blockstore.NewTemporary()
|
||||
cs := store.NewChainStore(nbs, datastore.NewMapDatastore(), nil)
|
||||
cs := store.NewChainStore(nbs, datastore.NewMapDatastore(), nil, nil)
|
||||
|
||||
root, err := cs.Import(buf)
|
||||
if err != nil {
|
||||
|
||||
+28
-34
@@ -120,12 +120,6 @@ func FetchMessagesByCids(
|
||||
return err
|
||||
}
|
||||
|
||||
// FIXME: We already sort in `fetchCids`, we are duplicating too much work,
|
||||
// we don't need to pass the index.
|
||||
if out[i] != nil {
|
||||
return fmt.Errorf("received duplicate message")
|
||||
}
|
||||
|
||||
out[i] = msg
|
||||
return nil
|
||||
})
|
||||
@@ -149,10 +143,6 @@ func FetchSignedMessagesByCids(
|
||||
return err
|
||||
}
|
||||
|
||||
if out[i] != nil {
|
||||
return fmt.Errorf("received duplicate message")
|
||||
}
|
||||
|
||||
out[i] = smsg
|
||||
return nil
|
||||
})
|
||||
@@ -172,37 +162,41 @@ func fetchCids(
|
||||
cids []cid.Cid,
|
||||
cb func(int, blocks.Block) error,
|
||||
) error {
|
||||
fetchedBlocks := bserv.GetBlocks(ctx, cids)
|
||||
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
|
||||
cidIndex := make(map[cid.Cid]int)
|
||||
for i, c := range cids {
|
||||
cidIndex[c] = i
|
||||
}
|
||||
if len(cids) != len(cidIndex) {
|
||||
return fmt.Errorf("duplicate CIDs in fetchCids input")
|
||||
}
|
||||
|
||||
for i := 0; i < len(cids); i++ {
|
||||
select {
|
||||
case block, ok := <-fetchedBlocks:
|
||||
if !ok {
|
||||
// Closed channel, no more blocks fetched, check if we have all
|
||||
// of the CIDs requested.
|
||||
// FIXME: Review this check. We don't call the callback on the
|
||||
// last index?
|
||||
if i == len(cids)-1 {
|
||||
break
|
||||
}
|
||||
|
||||
return fmt.Errorf("failed to fetch all messages")
|
||||
}
|
||||
|
||||
ix, ok := cidIndex[block.Cid()]
|
||||
if !ok {
|
||||
return fmt.Errorf("received message we didnt ask for")
|
||||
}
|
||||
|
||||
if err := cb(ix, block); err != nil {
|
||||
return err
|
||||
}
|
||||
for block := range bserv.GetBlocks(ctx, cids) {
|
||||
ix, ok := cidIndex[block.Cid()]
|
||||
if !ok {
|
||||
// Ignore duplicate/unexpected blocks. This shouldn't
|
||||
// happen, but we can be safe.
|
||||
log.Errorw("received duplicate/unexpected block when syncing", "cid", block.Cid())
|
||||
continue
|
||||
}
|
||||
|
||||
// Record that we've received the block.
|
||||
delete(cidIndex, block.Cid())
|
||||
|
||||
if err := cb(ix, block); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(cidIndex) > 0 {
|
||||
err := ctx.Err()
|
||||
if err == nil {
|
||||
err = fmt.Errorf("failed to fetch %d messages for unknown reasons", len(cidIndex))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package sub
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
address "github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
blocks "github.com/ipfs/go-block-format"
|
||||
"github.com/ipfs/go-cid"
|
||||
)
|
||||
|
||||
type getter struct {
|
||||
msgs []*types.Message
|
||||
}
|
||||
|
||||
func (g *getter) GetBlock(ctx context.Context, c cid.Cid) (blocks.Block, error) { panic("NYI") }
|
||||
|
||||
func (g *getter) GetBlocks(ctx context.Context, ks []cid.Cid) <-chan blocks.Block {
|
||||
ch := make(chan blocks.Block, len(g.msgs))
|
||||
for _, m := range g.msgs {
|
||||
by, err := m.Serialize()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
b, err := blocks.NewBlockWithCid(by, m.Cid())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ch <- b
|
||||
}
|
||||
close(ch)
|
||||
return ch
|
||||
}
|
||||
|
||||
func TestFetchCidsWithDedup(t *testing.T) {
|
||||
msgs := []*types.Message{}
|
||||
for i := 0; i < 10; i++ {
|
||||
msgs = append(msgs, &types.Message{
|
||||
From: address.TestAddress,
|
||||
To: address.TestAddress,
|
||||
|
||||
Nonce: uint64(i),
|
||||
})
|
||||
}
|
||||
cids := []cid.Cid{}
|
||||
for _, m := range msgs {
|
||||
cids = append(cids, m.Cid())
|
||||
}
|
||||
g := &getter{msgs}
|
||||
|
||||
// the cids have a duplicate
|
||||
res, err := FetchMessagesByCids(context.TODO(), g, append(cids, cids[0]))
|
||||
|
||||
t.Logf("err: %+v", err)
|
||||
t.Logf("res: %+v", res)
|
||||
if err == nil {
|
||||
t.Errorf("there should be an error")
|
||||
}
|
||||
if err == nil && (res[0] == nil || res[len(res)-1] == nil) {
|
||||
t.Fatalf("there is a nil message: first %p, last %p", res[0], res[len(res)-1])
|
||||
}
|
||||
}
|
||||
+19
-7
@@ -217,6 +217,12 @@ func (syncer *Syncer) Stop() {
|
||||
// This should be called when connecting to new peers, and additionally
|
||||
// when receiving new blocks from the network
|
||||
func (syncer *Syncer) InformNewHead(from peer.ID, fts *store.FullTipSet) bool {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
log.Errorf("panic in InformNewHead: ", err)
|
||||
}
|
||||
}()
|
||||
|
||||
ctx := context.Background()
|
||||
if fts == nil {
|
||||
log.Errorf("got nil tipset in InformNewHead")
|
||||
@@ -731,7 +737,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock, use
|
||||
|
||||
lbst, _, err := syncer.sm.TipSetState(ctx, lbts)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to compute lookback tipset state: %w", err)
|
||||
return xerrors.Errorf("failed to compute lookback tipset state (epoch %d): %w", lbts.Height(), err)
|
||||
}
|
||||
|
||||
prevBeacon, err := syncer.store.GetLatestBeaconEntry(baseTs)
|
||||
@@ -1281,9 +1287,11 @@ func (syncer *Syncer) collectHeaders(ctx context.Context, incoming *types.TipSet
|
||||
|
||||
blockSet := []*types.TipSet{incoming}
|
||||
|
||||
// Parent of the new (possibly better) tipset that we need to fetch next.
|
||||
at := incoming.Parents()
|
||||
|
||||
// we want to sync all the blocks until the height above the block we have
|
||||
// we want to sync all the blocks until the height above our
|
||||
// best tipset so far
|
||||
untilHeight := known.Height() + 1
|
||||
|
||||
ss.SetHeight(blockSet[len(blockSet)-1].Height())
|
||||
@@ -1377,13 +1385,17 @@ loop:
|
||||
}
|
||||
|
||||
base := blockSet[len(blockSet)-1]
|
||||
if base.Parents() == known.Parents() {
|
||||
// common case: receiving a block thats potentially part of the same tipset as our best block
|
||||
if base.IsChildOf(known) {
|
||||
// common case: receiving blocks that are building on top of our best tipset
|
||||
return blockSet, nil
|
||||
}
|
||||
|
||||
if types.CidArrsEqual(base.Parents().Cids(), known.Cids()) {
|
||||
// common case: receiving blocks that are building on top of our best tipset
|
||||
knownParent, err := syncer.store.LoadTipSet(known.Parents())
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to load next local tipset: %w", err)
|
||||
}
|
||||
if base.IsChildOf(knownParent) {
|
||||
// common case: receiving a block thats potentially part of the same tipset as our best block
|
||||
return blockSet, nil
|
||||
}
|
||||
|
||||
@@ -1514,7 +1526,7 @@ func (syncer *Syncer) iterFullTipsets(ctx context.Context, headers []*types.TipS
|
||||
ss.SetStage(api.StageMessages)
|
||||
|
||||
if batchErr != nil {
|
||||
return xerrors.Errorf("failed to fetch messages: %w", err)
|
||||
return xerrors.Errorf("failed to fetch messages: %w", batchErr)
|
||||
}
|
||||
|
||||
for bsi := 0; bsi < len(bstout); bsi++ {
|
||||
|
||||
+6
-6
@@ -221,8 +221,7 @@ func (tu *syncTestUtil) addSourceNode(gen int) {
|
||||
sourceRepo, genesis, blocks := tu.repoWithChain(tu.t, gen)
|
||||
var out api.FullNode
|
||||
|
||||
// TODO: Don't ignore stop
|
||||
_, err := node.New(tu.ctx,
|
||||
stop, err := node.New(tu.ctx,
|
||||
node.FullAPI(&out),
|
||||
node.Online(),
|
||||
node.Repo(sourceRepo),
|
||||
@@ -232,6 +231,7 @@ func (tu *syncTestUtil) addSourceNode(gen int) {
|
||||
node.Override(new(modules.Genesis), modules.LoadGenesis(genesis)),
|
||||
)
|
||||
require.NoError(tu.t, err)
|
||||
tu.t.Cleanup(func() { _ = stop(context.Background()) })
|
||||
|
||||
lastTs := blocks[len(blocks)-1].Blocks
|
||||
for _, lastB := range lastTs {
|
||||
@@ -253,8 +253,7 @@ func (tu *syncTestUtil) addClientNode() int {
|
||||
|
||||
var out api.FullNode
|
||||
|
||||
// TODO: Don't ignore stop
|
||||
_, err := node.New(tu.ctx,
|
||||
stop, err := node.New(tu.ctx,
|
||||
node.FullAPI(&out),
|
||||
node.Online(),
|
||||
node.Repo(repo.NewMemory(nil)),
|
||||
@@ -264,6 +263,7 @@ func (tu *syncTestUtil) addClientNode() int {
|
||||
node.Override(new(modules.Genesis), modules.LoadGenesis(tu.genesis)),
|
||||
)
|
||||
require.NoError(tu.t, err)
|
||||
tu.t.Cleanup(func() { _ = stop(context.Background()) })
|
||||
|
||||
tu.nds = append(tu.nds, out)
|
||||
return len(tu.nds) - 1
|
||||
@@ -593,7 +593,7 @@ func TestDuplicateNonce(t *testing.T) {
|
||||
GasPremium: types.NewInt(0),
|
||||
}
|
||||
|
||||
sig, err := tu.g.Wallet().Sign(context.TODO(), tu.g.Banker(), msg.Cid().Bytes())
|
||||
sig, err := tu.g.Wallet().WalletSign(context.TODO(), tu.g.Banker(), msg.Cid().Bytes(), api.MsgMeta{})
|
||||
require.NoError(t, err)
|
||||
|
||||
return &types.SignedMessage{
|
||||
@@ -685,7 +685,7 @@ func TestBadNonce(t *testing.T) {
|
||||
GasPremium: types.NewInt(0),
|
||||
}
|
||||
|
||||
sig, err := tu.g.Wallet().Sign(context.TODO(), tu.g.Banker(), msg.Cid().Bytes())
|
||||
sig, err := tu.g.Wallet().WalletSign(context.TODO(), tu.g.Banker(), msg.Cid().Bytes(), api.MsgMeta{})
|
||||
require.NoError(t, err)
|
||||
|
||||
return &types.SignedMessage{
|
||||
|
||||
+6
-2
@@ -12,11 +12,15 @@ import (
|
||||
type FIL BigInt
|
||||
|
||||
func (f FIL) String() string {
|
||||
return f.Unitless() + " FIL"
|
||||
}
|
||||
|
||||
func (f FIL) Unitless() string {
|
||||
r := new(big.Rat).SetFrac(f.Int, big.NewInt(int64(build.FilecoinPrecision)))
|
||||
if r.Sign() == 0 {
|
||||
return "0 FIL"
|
||||
return "0"
|
||||
}
|
||||
return strings.TrimRight(strings.TrimRight(r.FloatString(18), "0"), ".") + " FIL"
|
||||
return strings.TrimRight(strings.TrimRight(r.FloatString(18), "0"), ".")
|
||||
}
|
||||
|
||||
func (f FIL) Format(s fmt.State, ch rune) {
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
"github.com/ipfs/go-cid"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/wallet"
|
||||
@@ -22,7 +23,7 @@ func Address(i uint64) address.Address {
|
||||
return a
|
||||
}
|
||||
|
||||
func MkMessage(from, to address.Address, nonce uint64, w *wallet.Wallet) *types.SignedMessage {
|
||||
func MkMessage(from, to address.Address, nonce uint64, w *wallet.LocalWallet) *types.SignedMessage {
|
||||
msg := &types.Message{
|
||||
To: to,
|
||||
From: from,
|
||||
@@ -33,7 +34,7 @@ func MkMessage(from, to address.Address, nonce uint64, w *wallet.Wallet) *types.
|
||||
GasPremium: types.NewInt(1),
|
||||
}
|
||||
|
||||
sig, err := w.Sign(context.TODO(), from, msg.Cid().Bytes())
|
||||
sig, err := w.WalletSign(context.TODO(), from, msg.Cid().Bytes(), api.MsgMeta{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -59,9 +60,11 @@ func MkBlock(parents *types.TipSet, weightInc uint64, ticketNonce uint64) *types
|
||||
var pcids []cid.Cid
|
||||
var height abi.ChainEpoch
|
||||
weight := types.NewInt(weightInc)
|
||||
var timestamp uint64
|
||||
if parents != nil {
|
||||
pcids = parents.Cids()
|
||||
height = parents.Height() + 1
|
||||
timestamp = parents.MinTimestamp() + build.BlockDelaySecs
|
||||
weight = types.BigAdd(parents.Blocks()[0].ParentWeight, weight)
|
||||
}
|
||||
|
||||
@@ -79,6 +82,7 @@ func MkBlock(parents *types.TipSet, weightInc uint64, ticketNonce uint64) *types
|
||||
ParentWeight: weight,
|
||||
Messages: c,
|
||||
Height: height,
|
||||
Timestamp: timestamp,
|
||||
ParentStateRoot: pstateRoot,
|
||||
BlockSig: &crypto.Signature{Type: crypto.SigTypeBLS, Data: []byte("boo! im a signature")},
|
||||
ParentBaseFee: types.NewInt(uint64(build.MinimumBaseFee)),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
@@ -61,11 +62,11 @@ func MakeMessageSigningVectors() []vectors.MessageSigningVector {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
blsk, err := w.GenerateKey(crypto.SigTypeBLS)
|
||||
blsk, err := w.WalletNew(context.Background(), crypto.SigTypeBLS)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
bki, err := w.Export(blsk)
|
||||
bki, err := w.WalletExport(context.Background(), blsk)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -85,11 +86,11 @@ func MakeMessageSigningVectors() []vectors.MessageSigningVector {
|
||||
Signature: &bmsg.Signature,
|
||||
}
|
||||
|
||||
secpk, err := w.GenerateKey(crypto.SigTypeBLS)
|
||||
secpk, err := w.WalletNew(context.Background(), crypto.SigTypeBLS)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ski, err := w.Export(secpk)
|
||||
ski, err := w.WalletExport(context.Background(), secpk)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
package wallet
|
||||
|
||||
import (
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/lib/sigs"
|
||||
)
|
||||
|
||||
func GenerateKey(typ crypto.SigType) (*Key, error) {
|
||||
pk, err := sigs.Generate(typ)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ki := types.KeyInfo{
|
||||
Type: kstoreSigType(typ),
|
||||
PrivateKey: pk,
|
||||
}
|
||||
return NewKey(ki)
|
||||
}
|
||||
|
||||
type Key struct {
|
||||
types.KeyInfo
|
||||
|
||||
PublicKey []byte
|
||||
Address address.Address
|
||||
}
|
||||
|
||||
func NewKey(keyinfo types.KeyInfo) (*Key, error) {
|
||||
k := &Key{
|
||||
KeyInfo: keyinfo,
|
||||
}
|
||||
|
||||
var err error
|
||||
k.PublicKey, err = sigs.ToPublic(ActSigType(k.Type), k.PrivateKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch k.Type {
|
||||
case KTSecp256k1:
|
||||
k.Address, err = address.NewSecp256k1Address(k.PublicKey)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("converting Secp256k1 to address: %w", err)
|
||||
}
|
||||
case KTBLS:
|
||||
k.Address, err = address.NewBLSAddress(k.PublicKey)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("converting BLS to address: %w", err)
|
||||
}
|
||||
default:
|
||||
return nil, xerrors.Errorf("unknown key type")
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package remotewallet
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.uber.org/fx"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/api/client"
|
||||
cliutil "github.com/filecoin-project/lotus/cli/util"
|
||||
"github.com/filecoin-project/lotus/node/modules/helpers"
|
||||
)
|
||||
|
||||
type RemoteWallet struct {
|
||||
api.WalletAPI
|
||||
}
|
||||
|
||||
func SetupRemoteWallet(info string) func(mctx helpers.MetricsCtx, lc fx.Lifecycle) (*RemoteWallet, error) {
|
||||
return func(mctx helpers.MetricsCtx, lc fx.Lifecycle) (*RemoteWallet, error) {
|
||||
ai := cliutil.ParseApiInfo(info)
|
||||
|
||||
url, err := ai.DialArgs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
wapi, closer, err := client.NewWalletRPC(mctx, url, ai.AuthHeader())
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("creating jsonrpc client: %w", err)
|
||||
}
|
||||
|
||||
lc.Append(fx.Hook{
|
||||
OnStop: func(ctx context.Context) error {
|
||||
closer()
|
||||
return nil
|
||||
},
|
||||
})
|
||||
|
||||
return &RemoteWallet{wapi}, nil
|
||||
}
|
||||
}
|
||||
+42
-87
@@ -12,6 +12,7 @@ import (
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/bls" // enable bls signatures
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/secp" // enable secp signatures
|
||||
|
||||
@@ -29,15 +30,20 @@ const (
|
||||
KTSecp256k1 = "secp256k1"
|
||||
)
|
||||
|
||||
type Wallet struct {
|
||||
type LocalWallet struct {
|
||||
keys map[address.Address]*Key
|
||||
keystore types.KeyStore
|
||||
|
||||
lk sync.Mutex
|
||||
}
|
||||
|
||||
func NewWallet(keystore types.KeyStore) (*Wallet, error) {
|
||||
w := &Wallet{
|
||||
type Default interface {
|
||||
GetDefault() (address.Address, error)
|
||||
SetDefault(a address.Address) error
|
||||
}
|
||||
|
||||
func NewWallet(keystore types.KeyStore) (*LocalWallet, error) {
|
||||
w := &LocalWallet{
|
||||
keys: make(map[address.Address]*Key),
|
||||
keystore: keystore,
|
||||
}
|
||||
@@ -45,18 +51,18 @@ func NewWallet(keystore types.KeyStore) (*Wallet, error) {
|
||||
return w, nil
|
||||
}
|
||||
|
||||
func KeyWallet(keys ...*Key) *Wallet {
|
||||
func KeyWallet(keys ...*Key) *LocalWallet {
|
||||
m := make(map[address.Address]*Key)
|
||||
for _, key := range keys {
|
||||
m[key.Address] = key
|
||||
}
|
||||
|
||||
return &Wallet{
|
||||
return &LocalWallet{
|
||||
keys: m,
|
||||
}
|
||||
}
|
||||
|
||||
func (w *Wallet) Sign(ctx context.Context, addr address.Address, msg []byte) (*crypto.Signature, error) {
|
||||
func (w *LocalWallet) WalletSign(ctx context.Context, addr address.Address, msg []byte, meta api.MsgMeta) (*crypto.Signature, error) {
|
||||
ki, err := w.findKey(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -68,7 +74,7 @@ func (w *Wallet) Sign(ctx context.Context, addr address.Address, msg []byte) (*c
|
||||
return sigs.Sign(ActSigType(ki.Type), ki.PrivateKey, msg)
|
||||
}
|
||||
|
||||
func (w *Wallet) findKey(addr address.Address) (*Key, error) {
|
||||
func (w *LocalWallet) findKey(addr address.Address) (*Key, error) {
|
||||
w.lk.Lock()
|
||||
defer w.lk.Unlock()
|
||||
|
||||
@@ -96,7 +102,7 @@ func (w *Wallet) findKey(addr address.Address) (*Key, error) {
|
||||
return k, nil
|
||||
}
|
||||
|
||||
func (w *Wallet) tryFind(addr address.Address) (types.KeyInfo, error) {
|
||||
func (w *LocalWallet) tryFind(addr address.Address) (types.KeyInfo, error) {
|
||||
|
||||
ki, err := w.keystore.Get(KNamePrefix + addr.String())
|
||||
if err == nil {
|
||||
@@ -110,14 +116,12 @@ func (w *Wallet) tryFind(addr address.Address) (types.KeyInfo, error) {
|
||||
// We got an ErrKeyInfoNotFound error
|
||||
// Try again, this time with the testnet prefix
|
||||
|
||||
aChars := []rune(addr.String())
|
||||
prefixRunes := []rune(address.TestnetPrefix)
|
||||
if len(prefixRunes) != 1 {
|
||||
return types.KeyInfo{}, xerrors.Errorf("unexpected prefix length: %d", len(prefixRunes))
|
||||
tAddress, err := swapMainnetForTestnetPrefix(addr.String())
|
||||
if err != nil {
|
||||
return types.KeyInfo{}, err
|
||||
}
|
||||
|
||||
aChars[0] = prefixRunes[0]
|
||||
ki, err = w.keystore.Get(KNamePrefix + string(aChars))
|
||||
ki, err = w.keystore.Get(KNamePrefix + tAddress)
|
||||
if err != nil {
|
||||
return types.KeyInfo{}, err
|
||||
}
|
||||
@@ -132,7 +136,7 @@ func (w *Wallet) tryFind(addr address.Address) (types.KeyInfo, error) {
|
||||
return ki, nil
|
||||
}
|
||||
|
||||
func (w *Wallet) Export(addr address.Address) (*types.KeyInfo, error) {
|
||||
func (w *LocalWallet) WalletExport(ctx context.Context, addr address.Address) (*types.KeyInfo, error) {
|
||||
k, err := w.findKey(addr)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to find key to export: %w", err)
|
||||
@@ -141,7 +145,7 @@ func (w *Wallet) Export(addr address.Address) (*types.KeyInfo, error) {
|
||||
return &k.KeyInfo, nil
|
||||
}
|
||||
|
||||
func (w *Wallet) Import(ki *types.KeyInfo) (address.Address, error) {
|
||||
func (w *LocalWallet) WalletImport(ctx context.Context, ki *types.KeyInfo) (address.Address, error) {
|
||||
w.lk.Lock()
|
||||
defer w.lk.Unlock()
|
||||
|
||||
@@ -157,7 +161,7 @@ func (w *Wallet) Import(ki *types.KeyInfo) (address.Address, error) {
|
||||
return k.Address, nil
|
||||
}
|
||||
|
||||
func (w *Wallet) ListAddrs() ([]address.Address, error) {
|
||||
func (w *LocalWallet) WalletList(ctx context.Context) ([]address.Address, error) {
|
||||
all, err := w.keystore.List()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("listing keystore: %w", err)
|
||||
@@ -190,7 +194,7 @@ func (w *Wallet) ListAddrs() ([]address.Address, error) {
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (w *Wallet) GetDefault() (address.Address, error) {
|
||||
func (w *LocalWallet) GetDefault() (address.Address, error) {
|
||||
w.lk.Lock()
|
||||
defer w.lk.Unlock()
|
||||
|
||||
@@ -207,7 +211,7 @@ func (w *Wallet) GetDefault() (address.Address, error) {
|
||||
return k.Address, nil
|
||||
}
|
||||
|
||||
func (w *Wallet) SetDefault(a address.Address) error {
|
||||
func (w *LocalWallet) SetDefault(a address.Address) error {
|
||||
w.lk.Lock()
|
||||
defer w.lk.Unlock()
|
||||
|
||||
@@ -229,19 +233,7 @@ func (w *Wallet) SetDefault(a address.Address) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func GenerateKey(typ crypto.SigType) (*Key, error) {
|
||||
pk, err := sigs.Generate(typ)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ki := types.KeyInfo{
|
||||
Type: kstoreSigType(typ),
|
||||
PrivateKey: pk,
|
||||
}
|
||||
return NewKey(ki)
|
||||
}
|
||||
|
||||
func (w *Wallet) GenerateKey(typ crypto.SigType) (address.Address, error) {
|
||||
func (w *LocalWallet) WalletNew(ctx context.Context, typ crypto.SigType) (address.Address, error) {
|
||||
w.lk.Lock()
|
||||
defer w.lk.Unlock()
|
||||
|
||||
@@ -269,7 +261,7 @@ func (w *Wallet) GenerateKey(typ crypto.SigType) (address.Address, error) {
|
||||
return k.Address, nil
|
||||
}
|
||||
|
||||
func (w *Wallet) HasKey(addr address.Address) (bool, error) {
|
||||
func (w *LocalWallet) WalletHas(ctx context.Context, addr address.Address) (bool, error) {
|
||||
k, err := w.findKey(addr)
|
||||
if err != nil {
|
||||
return false, err
|
||||
@@ -277,7 +269,7 @@ func (w *Wallet) HasKey(addr address.Address) (bool, error) {
|
||||
return k != nil, nil
|
||||
}
|
||||
|
||||
func (w *Wallet) DeleteKey(addr address.Address) error {
|
||||
func (w *LocalWallet) WalletDelete(ctx context.Context, addr address.Address) error {
|
||||
k, err := w.findKey(addr)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to delete key %s : %w", addr, err)
|
||||
@@ -291,63 +283,26 @@ func (w *Wallet) DeleteKey(addr address.Address) error {
|
||||
return xerrors.Errorf("failed to delete key %s: %w", addr, err)
|
||||
}
|
||||
|
||||
tAddr, err := swapMainnetForTestnetPrefix(addr.String())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to swap prefixes: %w", err)
|
||||
}
|
||||
|
||||
// TODO: Does this always error in the not-found case? Just ignoring an error return for now.
|
||||
_ = w.keystore.Delete(KNamePrefix + tAddr)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type Key struct {
|
||||
types.KeyInfo
|
||||
var _ api.WalletAPI = &LocalWallet{}
|
||||
|
||||
PublicKey []byte
|
||||
Address address.Address
|
||||
}
|
||||
|
||||
func NewKey(keyinfo types.KeyInfo) (*Key, error) {
|
||||
k := &Key{
|
||||
KeyInfo: keyinfo,
|
||||
}
|
||||
|
||||
var err error
|
||||
k.PublicKey, err = sigs.ToPublic(ActSigType(k.Type), k.PrivateKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch k.Type {
|
||||
case KTSecp256k1:
|
||||
k.Address, err = address.NewSecp256k1Address(k.PublicKey)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("converting Secp256k1 to address: %w", err)
|
||||
}
|
||||
case KTBLS:
|
||||
k.Address, err = address.NewBLSAddress(k.PublicKey)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("converting BLS to address: %w", err)
|
||||
}
|
||||
default:
|
||||
return nil, xerrors.Errorf("unknown key type")
|
||||
func swapMainnetForTestnetPrefix(addr string) (string, error) {
|
||||
aChars := []rune(addr)
|
||||
prefixRunes := []rune(address.TestnetPrefix)
|
||||
if len(prefixRunes) != 1 {
|
||||
return "", xerrors.Errorf("unexpected prefix length: %d", len(prefixRunes))
|
||||
}
|
||||
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
|
||||
}
|
||||
aChars[0] = prefixRunes[0]
|
||||
return string(aChars), nil
|
||||
}
|
||||
|
||||
+9
-4
@@ -449,11 +449,16 @@ var chainInspectUsage = &cli.Command{
|
||||
bySender := make(map[string]int64)
|
||||
byDest := make(map[string]int64)
|
||||
byMethod := make(map[string]int64)
|
||||
bySenderC := make(map[string]int64)
|
||||
byDestC := make(map[string]int64)
|
||||
byMethodC := make(map[string]int64)
|
||||
|
||||
var sum int64
|
||||
for _, m := range msgs {
|
||||
bySender[m.Message.From.String()] += m.Message.GasLimit
|
||||
bySenderC[m.Message.From.String()]++
|
||||
byDest[m.Message.To.String()] += m.Message.GasLimit
|
||||
byDestC[m.Message.To.String()]++
|
||||
sum += m.Message.GasLimit
|
||||
|
||||
code, err := lookupActorCode(m.Message.To)
|
||||
@@ -464,7 +469,7 @@ var chainInspectUsage = &cli.Command{
|
||||
mm := stmgr.MethodsMap[code][m.Message.Method]
|
||||
|
||||
byMethod[mm.Name] += m.Message.GasLimit
|
||||
|
||||
byMethodC[mm.Name]++
|
||||
}
|
||||
|
||||
type keyGasPair struct {
|
||||
@@ -496,19 +501,19 @@ var chainInspectUsage = &cli.Command{
|
||||
fmt.Printf("By Sender:\n")
|
||||
for i := 0; i < numRes && i < len(senderVals); i++ {
|
||||
sv := senderVals[i]
|
||||
fmt.Printf("%s\t%0.2f%%\t(%d)\n", sv.Key, (100*float64(sv.Gas))/float64(sum), sv.Gas)
|
||||
fmt.Printf("%s\t%0.2f%%\t(total: %d, count: %d)\n", sv.Key, (100*float64(sv.Gas))/float64(sum), sv.Gas, bySenderC[sv.Key])
|
||||
}
|
||||
fmt.Println()
|
||||
fmt.Printf("By Receiver:\n")
|
||||
for i := 0; i < numRes && i < len(destVals); i++ {
|
||||
sv := destVals[i]
|
||||
fmt.Printf("%s\t%0.2f%%\t(%d)\n", sv.Key, (100*float64(sv.Gas))/float64(sum), sv.Gas)
|
||||
fmt.Printf("%s\t%0.2f%%\t(total: %d, count: %d)\n", sv.Key, (100*float64(sv.Gas))/float64(sum), sv.Gas, byDestC[sv.Key])
|
||||
}
|
||||
fmt.Println()
|
||||
fmt.Printf("By Method:\n")
|
||||
for i := 0; i < numRes && i < len(methodVals); i++ {
|
||||
sv := methodVals[i]
|
||||
fmt.Printf("%s\t%0.2f%%\t(%d)\n", sv.Key, (100*float64(sv.Gas))/float64(sum), sv.Gas)
|
||||
fmt.Printf("%s\t%0.2f%%\t(total: %d, count: %d)\n", sv.Key, (100*float64(sv.Gas))/float64(sum), sv.Gas, byMethodC[sv.Key])
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
+16
-7
@@ -536,7 +536,7 @@ func interactiveDeal(cctx *cli.Context) error {
|
||||
|
||||
state = "miner"
|
||||
case "miner":
|
||||
fmt.Print("Miner Address (t0..): ")
|
||||
fmt.Print("Miner Address (f0..): ")
|
||||
var maddrStr string
|
||||
|
||||
_, err := fmt.Scan(&maddrStr)
|
||||
@@ -1039,6 +1039,10 @@ var clientListDeals = &cli.Command{
|
||||
Usage: "use color in display output",
|
||||
Value: true,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "show-failed",
|
||||
Usage: "show failed/failing deals",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "watch",
|
||||
Usage: "watch deal updates in real-time, rather than a one time list",
|
||||
@@ -1055,6 +1059,7 @@ var clientListDeals = &cli.Command{
|
||||
verbose := cctx.Bool("verbose")
|
||||
color := cctx.Bool("color")
|
||||
watch := cctx.Bool("watch")
|
||||
showFailed := cctx.Bool("show-failed")
|
||||
|
||||
localDeals, err := api.ClientListDeals(ctx)
|
||||
if err != nil {
|
||||
@@ -1071,7 +1076,7 @@ var clientListDeals = &cli.Command{
|
||||
tm.Clear()
|
||||
tm.MoveCursor(1, 1)
|
||||
|
||||
err = outputStorageDeals(ctx, tm.Screen, api, localDeals, verbose, color)
|
||||
err = outputStorageDeals(ctx, tm.Screen, api, localDeals, verbose, color, showFailed)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1097,7 +1102,7 @@ var clientListDeals = &cli.Command{
|
||||
}
|
||||
}
|
||||
|
||||
return outputStorageDeals(ctx, os.Stdout, api, localDeals, cctx.Bool("verbose"), cctx.Bool("color"))
|
||||
return outputStorageDeals(ctx, os.Stdout, api, localDeals, cctx.Bool("verbose"), cctx.Bool("color"), showFailed)
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1120,7 +1125,7 @@ func dealFromDealInfo(ctx context.Context, full api.FullNode, head *types.TipSet
|
||||
}
|
||||
}
|
||||
|
||||
func outputStorageDeals(ctx context.Context, out io.Writer, full api.FullNode, localDeals []api.DealInfo, verbose bool, color bool) error {
|
||||
func outputStorageDeals(ctx context.Context, out io.Writer, full lapi.FullNode, localDeals []lapi.DealInfo, verbose bool, color bool, showFailed bool) error {
|
||||
sort.Slice(localDeals, func(i, j int) bool {
|
||||
return localDeals[i].CreationTime.Before(localDeals[j].CreationTime)
|
||||
})
|
||||
@@ -1132,12 +1137,14 @@ func outputStorageDeals(ctx context.Context, out io.Writer, full api.FullNode, l
|
||||
|
||||
var deals []deal
|
||||
for _, localDeal := range localDeals {
|
||||
deals = append(deals, dealFromDealInfo(ctx, full, head, localDeal))
|
||||
if showFailed || localDeal.State != storagemarket.StorageDealError {
|
||||
deals = append(deals, dealFromDealInfo(ctx, full, head, localDeal))
|
||||
}
|
||||
}
|
||||
|
||||
if verbose {
|
||||
w := tabwriter.NewWriter(out, 2, 4, 2, ' ', 0)
|
||||
fmt.Fprintf(w, "Created\tDealCid\tDealId\tProvider\tState\tOn Chain?\tSlashed?\tPieceCID\tSize\tPrice\tDuration\tMessage\n")
|
||||
fmt.Fprintf(w, "Created\tDealCid\tDealId\tProvider\tState\tOn Chain?\tSlashed?\tPieceCID\tSize\tPrice\tDuration\tVerified\tMessage\n")
|
||||
for _, d := range deals {
|
||||
onChain := "N"
|
||||
if d.OnChainDealState.SectorStartEpoch != -1 {
|
||||
@@ -1150,7 +1157,7 @@ func outputStorageDeals(ctx context.Context, out io.Writer, full api.FullNode, l
|
||||
}
|
||||
|
||||
price := types.FIL(types.BigMul(d.LocalDeal.PricePerEpoch, types.NewInt(d.LocalDeal.Duration)))
|
||||
fmt.Fprintf(w, "%s\t%s\t%d\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%d\t%s\n", d.LocalDeal.CreationTime.Format(time.Stamp), d.LocalDeal.ProposalCid, d.LocalDeal.DealID, d.LocalDeal.Provider, dealStateString(color, d.LocalDeal.State), onChain, slashed, d.LocalDeal.PieceCID, types.SizeStr(types.NewInt(d.LocalDeal.Size)), price, d.LocalDeal.Duration, d.LocalDeal.Message)
|
||||
fmt.Fprintf(w, "%s\t%s\t%d\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%d\t%v\t%s\n", d.LocalDeal.CreationTime.Format(time.Stamp), d.LocalDeal.ProposalCid, d.LocalDeal.DealID, d.LocalDeal.Provider, dealStateString(color, d.LocalDeal.State), onChain, slashed, d.LocalDeal.PieceCID, types.SizeStr(types.NewInt(d.LocalDeal.Size)), price, d.LocalDeal.Duration, d.LocalDeal.Verified, d.LocalDeal.Message)
|
||||
}
|
||||
return w.Flush()
|
||||
}
|
||||
@@ -1165,6 +1172,7 @@ func outputStorageDeals(ctx context.Context, out io.Writer, full api.FullNode, l
|
||||
tablewriter.Col("Size"),
|
||||
tablewriter.Col("Price"),
|
||||
tablewriter.Col("Duration"),
|
||||
tablewriter.Col("Verified"),
|
||||
tablewriter.NewLineCol("Message"))
|
||||
|
||||
for _, d := range deals {
|
||||
@@ -1194,6 +1202,7 @@ func outputStorageDeals(ctx context.Context, out io.Writer, full api.FullNode, l
|
||||
"PieceCID": piece,
|
||||
"Size": types.SizeStr(types.NewInt(d.LocalDeal.Size)),
|
||||
"Price": price,
|
||||
"Verified": d.LocalDeal.Verified,
|
||||
"Duration": d.LocalDeal.Duration,
|
||||
"Message": d.LocalDeal.Message,
|
||||
})
|
||||
|
||||
+21
-50
@@ -11,8 +11,6 @@ import (
|
||||
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/multiformats/go-multiaddr"
|
||||
manet "github.com/multiformats/go-multiaddr/net"
|
||||
"github.com/urfave/cli/v2"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
@@ -20,6 +18,7 @@ import (
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/api/client"
|
||||
cliutil "github.com/filecoin-project/lotus/cli/util"
|
||||
"github.com/filecoin-project/lotus/node/repo"
|
||||
)
|
||||
|
||||
@@ -46,37 +45,16 @@ func NewCliError(s string) error {
|
||||
// ApiConnector returns API instance
|
||||
type ApiConnector func() api.FullNode
|
||||
|
||||
type APIInfo struct {
|
||||
Addr multiaddr.Multiaddr
|
||||
Token []byte
|
||||
}
|
||||
|
||||
func (a APIInfo) DialArgs() (string, error) {
|
||||
_, addr, err := manet.DialArgs(a.Addr)
|
||||
|
||||
return "ws://" + addr + "/rpc/v0", err
|
||||
}
|
||||
|
||||
func (a APIInfo) AuthHeader() http.Header {
|
||||
if len(a.Token) != 0 {
|
||||
headers := http.Header{}
|
||||
headers.Add("Authorization", "Bearer "+string(a.Token))
|
||||
return headers
|
||||
}
|
||||
log.Warn("API Token not set and requested, capabilities might be limited.")
|
||||
return nil
|
||||
}
|
||||
|
||||
// The flag passed on the command line with the listen address of the API
|
||||
// server (only used by the tests)
|
||||
func flagForAPI(t repo.RepoType) string {
|
||||
switch t {
|
||||
case repo.FullNode:
|
||||
return "api"
|
||||
return "api-url"
|
||||
case repo.StorageMiner:
|
||||
return "miner-api"
|
||||
return "miner-api-url"
|
||||
case repo.Worker:
|
||||
return "worker-api"
|
||||
return "worker-api-url"
|
||||
default:
|
||||
panic(fmt.Sprintf("Unknown repo type: %v", t))
|
||||
}
|
||||
@@ -122,7 +100,7 @@ func envForRepoDeprecation(t repo.RepoType) string {
|
||||
}
|
||||
}
|
||||
|
||||
func GetAPIInfo(ctx *cli.Context, t repo.RepoType) (APIInfo, error) {
|
||||
func GetAPIInfo(ctx *cli.Context, t repo.RepoType) (cliutil.APIInfo, error) {
|
||||
// Check if there was a flag passed with the listen address of the API
|
||||
// server (only used by the tests)
|
||||
apiFlag := flagForAPI(t)
|
||||
@@ -130,11 +108,7 @@ func GetAPIInfo(ctx *cli.Context, t repo.RepoType) (APIInfo, error) {
|
||||
strma := ctx.String(apiFlag)
|
||||
strma = strings.TrimSpace(strma)
|
||||
|
||||
apima, err := multiaddr.NewMultiaddr(strma)
|
||||
if err != nil {
|
||||
return APIInfo{}, err
|
||||
}
|
||||
return APIInfo{Addr: apima}, nil
|
||||
return cliutil.APIInfo{Addr: strma}, nil
|
||||
}
|
||||
|
||||
envKey := envForRepo(t)
|
||||
@@ -148,36 +122,24 @@ func GetAPIInfo(ctx *cli.Context, t repo.RepoType) (APIInfo, error) {
|
||||
}
|
||||
}
|
||||
if ok {
|
||||
sp := strings.SplitN(env, ":", 2)
|
||||
if len(sp) != 2 {
|
||||
log.Warnf("invalid env(%s) value, missing token or address", envKey)
|
||||
} else {
|
||||
ma, err := multiaddr.NewMultiaddr(sp[1])
|
||||
if err != nil {
|
||||
return APIInfo{}, xerrors.Errorf("could not parse multiaddr from env(%s): %w", envKey, err)
|
||||
}
|
||||
return APIInfo{
|
||||
Addr: ma,
|
||||
Token: []byte(sp[0]),
|
||||
}, nil
|
||||
}
|
||||
return cliutil.ParseApiInfo(env), nil
|
||||
}
|
||||
|
||||
repoFlag := flagForRepo(t)
|
||||
|
||||
p, err := homedir.Expand(ctx.String(repoFlag))
|
||||
if err != nil {
|
||||
return APIInfo{}, xerrors.Errorf("could not expand home dir (%s): %w", repoFlag, err)
|
||||
return cliutil.APIInfo{}, xerrors.Errorf("could not expand home dir (%s): %w", repoFlag, err)
|
||||
}
|
||||
|
||||
r, err := repo.NewFS(p)
|
||||
if err != nil {
|
||||
return APIInfo{}, xerrors.Errorf("could not open repo at path: %s; %w", p, err)
|
||||
return cliutil.APIInfo{}, xerrors.Errorf("could not open repo at path: %s; %w", p, err)
|
||||
}
|
||||
|
||||
ma, err := r.APIEndpoint()
|
||||
if err != nil {
|
||||
return APIInfo{}, xerrors.Errorf("could not get api endpoint: %w", err)
|
||||
return cliutil.APIInfo{}, xerrors.Errorf("could not get api endpoint: %w", err)
|
||||
}
|
||||
|
||||
token, err := r.APIToken()
|
||||
@@ -185,8 +147,8 @@ func GetAPIInfo(ctx *cli.Context, t repo.RepoType) (APIInfo, error) {
|
||||
log.Warnf("Couldn't load CLI token, capabilities may be limited: %v", err)
|
||||
}
|
||||
|
||||
return APIInfo{
|
||||
Addr: ma,
|
||||
return cliutil.APIInfo{
|
||||
Addr: ma.String(),
|
||||
Token: token,
|
||||
}, nil
|
||||
}
|
||||
@@ -266,6 +228,15 @@ func GetWorkerAPI(ctx *cli.Context) (api.WorkerAPI, jsonrpc.ClientCloser, error)
|
||||
return client.NewWorkerRPC(ctx.Context, addr, headers)
|
||||
}
|
||||
|
||||
func GetGatewayAPI(ctx *cli.Context) (api.GatewayAPI, jsonrpc.ClientCloser, error) {
|
||||
addr, headers, err := GetRawAPI(ctx, repo.FullNode)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return client.NewGatewayRPC(ctx.Context, addr, headers)
|
||||
}
|
||||
|
||||
func DaemonContext(cctx *cli.Context) context.Context {
|
||||
if mtCtx, ok := cctx.App.Metadata[metadataTraceContext]; ok {
|
||||
return mtCtx.(context.Context)
|
||||
|
||||
+8
-8
@@ -121,13 +121,13 @@ func TestPaymentChannelStatus(t *testing.T) {
|
||||
create := make(chan string)
|
||||
go func() {
|
||||
// creator: paych add-funds <creator> <receiver> <amount>
|
||||
cmd = []string{creatorAddr.String(), receiverAddr.String(), fmt.Sprintf("%d", channelAmt)}
|
||||
cmd := []string{creatorAddr.String(), receiverAddr.String(), fmt.Sprintf("%d", channelAmt)}
|
||||
create <- creatorCLI.runCmd(paychAddFundsCmd, cmd)
|
||||
}()
|
||||
|
||||
// Wait for the output to stop being "Channel does not exist"
|
||||
for regexp.MustCompile(noChannelState).MatchString(out) {
|
||||
cmd = []string{creatorAddr.String(), receiverAddr.String()}
|
||||
cmd := []string{creatorAddr.String(), receiverAddr.String()}
|
||||
out = creatorCLI.runCmd(paychStatusByFromToCmd, cmd)
|
||||
}
|
||||
fmt.Println(out)
|
||||
@@ -390,7 +390,7 @@ func checkVoucherOutput(t *testing.T, list string, vouchers []voucherSpec) {
|
||||
}
|
||||
|
||||
func startTwoNodesOneMiner(ctx context.Context, t *testing.T, blocktime time.Duration) ([]test.TestNode, []address.Address) {
|
||||
n, sn := builder.RPCMockSbBuilder(t, 2, test.OneMiner)
|
||||
n, sn := builder.RPCMockSbBuilder(t, test.TwoFull, test.OneMiner)
|
||||
|
||||
paymentCreator := n[0]
|
||||
paymentReceiver := n[1]
|
||||
@@ -439,12 +439,12 @@ type mockCLI struct {
|
||||
}
|
||||
|
||||
func newMockCLI(t *testing.T) *mockCLI {
|
||||
// Create a CLI App with an --api flag so that we can specify which node
|
||||
// Create a CLI App with an --api-url flag so that we can specify which node
|
||||
// the command should be executed against
|
||||
app := cli.NewApp()
|
||||
app.Flags = []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "api",
|
||||
Name: "api-url",
|
||||
Hidden: true,
|
||||
},
|
||||
}
|
||||
@@ -476,8 +476,8 @@ func (c *mockCLIClient) runCmd(cmd *cli.Command, input []string) string {
|
||||
}
|
||||
|
||||
func (c *mockCLIClient) runCmdRaw(cmd *cli.Command, input []string) (string, error) {
|
||||
// prepend --api=<node api listener address>
|
||||
apiFlag := "--api=" + c.addr.String()
|
||||
// prepend --api-url=<node api listener address>
|
||||
apiFlag := "--api-url=" + c.addr.String()
|
||||
input = append([]string{apiFlag}, input...)
|
||||
|
||||
fs := c.flagSet(cmd)
|
||||
@@ -493,7 +493,7 @@ func (c *mockCLIClient) runCmdRaw(cmd *cli.Command, input []string) (string, err
|
||||
}
|
||||
|
||||
func (c *mockCLIClient) flagSet(cmd *cli.Command) *flag.FlagSet {
|
||||
// Apply app level flags (so we can process --api flag)
|
||||
// Apply app level flags (so we can process --api-url flag)
|
||||
fs := &flag.FlagSet{}
|
||||
for _, f := range c.cctx.App.Flags {
|
||||
err := f.Apply(fs)
|
||||
|
||||
+1
-2
@@ -9,7 +9,6 @@ import (
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/node/repo"
|
||||
manet "github.com/multiformats/go-multiaddr/net"
|
||||
)
|
||||
|
||||
var pprofCmd = &cli.Command{
|
||||
@@ -37,7 +36,7 @@ var PprofGoroutines = &cli.Command{
|
||||
if err != nil {
|
||||
return xerrors.Errorf("could not get API info: %w", err)
|
||||
}
|
||||
_, addr, err := manet.DialArgs(ainfo.Addr)
|
||||
addr, err := ainfo.Host()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+9
-3
@@ -233,7 +233,13 @@ func SyncWait(ctx context.Context, napi api.FullNode) error {
|
||||
|
||||
samples := 8
|
||||
i := 0
|
||||
var app, lastApp uint64
|
||||
var firstApp, app, lastApp uint64
|
||||
|
||||
state, err := napi.SyncState(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
firstApp = state.VMApplied
|
||||
|
||||
for {
|
||||
state, err := napi.SyncState(ctx)
|
||||
@@ -286,10 +292,10 @@ func SyncWait(ctx context.Context, napi api.FullNode) error {
|
||||
|
||||
if i%samples == 0 {
|
||||
lastApp = app
|
||||
app = state.VMApplied
|
||||
app = state.VMApplied - firstApp
|
||||
}
|
||||
if i > 0 {
|
||||
fmt.Printf("Validated %d messages (%d per second)\n", state.VMApplied, (app-lastApp)*uint64(time.Second/tick)/uint64(samples))
|
||||
fmt.Printf("Validated %d messages (%d per second)\n", state.VMApplied-firstApp, (app-lastApp)*uint64(time.Second/tick)/uint64(samples))
|
||||
lastLines++
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
package cliutil
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
"github.com/multiformats/go-multiaddr"
|
||||
manet "github.com/multiformats/go-multiaddr/net"
|
||||
)
|
||||
|
||||
var log = logging.Logger("cliutil")
|
||||
|
||||
var (
|
||||
infoWithToken = regexp.MustCompile("^[a-zA-Z0-9\\-_]+?\\.[a-zA-Z0-9\\-_]+?\\.([a-zA-Z0-9\\-_]+)?:.+$")
|
||||
)
|
||||
|
||||
type APIInfo struct {
|
||||
Addr string
|
||||
Token []byte
|
||||
}
|
||||
|
||||
func ParseApiInfo(s string) APIInfo {
|
||||
var tok []byte
|
||||
if infoWithToken.Match([]byte(s)) {
|
||||
sp := strings.SplitN(s, ":", 2)
|
||||
tok = []byte(sp[0])
|
||||
s = sp[1]
|
||||
}
|
||||
|
||||
return APIInfo{
|
||||
Addr: s,
|
||||
Token: tok,
|
||||
}
|
||||
}
|
||||
|
||||
func (a APIInfo) DialArgs() (string, error) {
|
||||
ma, err := multiaddr.NewMultiaddr(a.Addr)
|
||||
if err == nil {
|
||||
_, addr, err := manet.DialArgs(ma)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return "ws://" + addr + "/rpc/v0", nil
|
||||
}
|
||||
|
||||
_, err = url.Parse(a.Addr)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return a.Addr + "/rpc/v0", nil
|
||||
}
|
||||
|
||||
func (a APIInfo) Host() (string, error) {
|
||||
ma, err := multiaddr.NewMultiaddr(a.Addr)
|
||||
if err == nil {
|
||||
_, addr, err := manet.DialArgs(ma)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return addr, nil
|
||||
}
|
||||
|
||||
spec, err := url.Parse(a.Addr)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return spec.Host, nil
|
||||
}
|
||||
|
||||
func (a APIInfo) AuthHeader() http.Header {
|
||||
if len(a.Token) != 0 {
|
||||
headers := http.Header{}
|
||||
headers.Add("Authorization", "Bearer "+string(a.Token))
|
||||
return headers
|
||||
}
|
||||
log.Warn("API Token not set and requested, capabilities might be limited.")
|
||||
return nil
|
||||
}
|
||||
@@ -183,7 +183,7 @@ var importBenchCmd = &cli.Command{
|
||||
return nil
|
||||
}
|
||||
|
||||
cs := store.NewChainStore(bs, ds, vm.Syscalls(verifier))
|
||||
cs := store.NewChainStore(bs, ds, vm.Syscalls(verifier), nil)
|
||||
stm := stmgr.NewStateManager(cs)
|
||||
|
||||
if cctx.Bool("global-profile") {
|
||||
|
||||
+131
-42
@@ -6,85 +6,174 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/node/impl/full"
|
||||
"github.com/ipfs/go-cid"
|
||||
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
const LookbackCap = time.Hour
|
||||
const (
|
||||
LookbackCap = time.Hour
|
||||
stateWaitLookbackLimit = abi.ChainEpoch(20)
|
||||
)
|
||||
|
||||
var (
|
||||
ErrLookbackTooLong = fmt.Errorf("lookbacks of more than %s are disallowed", LookbackCap)
|
||||
)
|
||||
|
||||
type GatewayAPI struct {
|
||||
api api.FullNode
|
||||
// gatewayDepsAPI defines the API methods that the GatewayAPI depends on
|
||||
// (to make it easy to mock for tests)
|
||||
type gatewayDepsAPI interface {
|
||||
ChainHead(ctx context.Context) (*types.TipSet, error)
|
||||
ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
|
||||
ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
|
||||
GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
|
||||
MpoolPushUntrusted(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
|
||||
MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
|
||||
MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error)
|
||||
StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
||||
StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
|
||||
StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
||||
StateWaitMsgLimited(ctx context.Context, msg cid.Cid, confidence uint64, h abi.ChainEpoch) (*api.MsgLookup, error)
|
||||
}
|
||||
|
||||
func (a *GatewayAPI) getTipsetTimestamp(ctx context.Context, tsk types.TipSetKey) (time.Time, error) {
|
||||
type GatewayAPI struct {
|
||||
api gatewayDepsAPI
|
||||
}
|
||||
|
||||
func (a *GatewayAPI) checkTipsetKey(ctx context.Context, tsk types.TipSetKey) error {
|
||||
if tsk.IsEmpty() {
|
||||
return time.Now(), nil
|
||||
return nil
|
||||
}
|
||||
|
||||
ts, err := a.api.ChainGetTipSet(ctx, tsk)
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
|
||||
return time.Unix(int64(ts.Blocks()[0].Timestamp), 0), nil
|
||||
}
|
||||
|
||||
func (a *GatewayAPI) checkTipset(ctx context.Context, ts types.TipSetKey) error {
|
||||
when, err := a.getTipsetTimestamp(ctx, ts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if time.Since(when) > time.Hour {
|
||||
return a.checkTipset(ts)
|
||||
}
|
||||
|
||||
func (a *GatewayAPI) checkTipset(ts *types.TipSet) error {
|
||||
at := time.Unix(int64(ts.Blocks()[0].Timestamp), 0)
|
||||
if err := a.checkTimestamp(at); err != nil {
|
||||
return fmt.Errorf("bad tipset: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *GatewayAPI) checkTipsetHeight(ts *types.TipSet, h abi.ChainEpoch) error {
|
||||
tsBlock := ts.Blocks()[0]
|
||||
heightDelta := time.Duration(uint64(tsBlock.Height-h)*build.BlockDelaySecs) * time.Second
|
||||
timeAtHeight := time.Unix(int64(tsBlock.Timestamp), 0).Add(-heightDelta)
|
||||
|
||||
if err := a.checkTimestamp(timeAtHeight); err != nil {
|
||||
return fmt.Errorf("bad tipset height: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *GatewayAPI) checkTimestamp(at time.Time) error {
|
||||
if time.Since(at) > LookbackCap {
|
||||
return ErrLookbackTooLong
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *GatewayAPI) StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "StateGetActor")
|
||||
defer span.End()
|
||||
|
||||
if err := a.checkTipset(ctx, ts); err != nil {
|
||||
return nil, fmt.Errorf("bad tipset: %w", err)
|
||||
}
|
||||
|
||||
return a.api.StateGetActor(ctx, actor, ts)
|
||||
}
|
||||
|
||||
func (a *GatewayAPI) ChainHead(ctx context.Context) (*types.TipSet, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "ChainHead")
|
||||
defer span.End()
|
||||
// TODO: cache and invalidate cache when timestamp is up (or have internal ChainNotify)
|
||||
|
||||
return a.api.ChainHead(ctx)
|
||||
}
|
||||
|
||||
func (a *GatewayAPI) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "ChainGetTipSet")
|
||||
defer span.End()
|
||||
|
||||
if err := a.checkTipset(ctx, tsk); err != nil {
|
||||
return nil, fmt.Errorf("bad tipset: %w", err)
|
||||
}
|
||||
|
||||
// TODO: since we're limiting lookbacks, should just cache this (could really even cache the json response bytes)
|
||||
return a.api.ChainGetTipSet(ctx, tsk)
|
||||
}
|
||||
|
||||
func (a *GatewayAPI) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) {
|
||||
ts, err := a.api.ChainGetTipSet(ctx, tsk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Check if the tipset key refers to a tipset that's too far in the past
|
||||
if err := a.checkTipset(ts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Check if the height is too far in the past
|
||||
if err := a.checkTipsetHeight(ts, h); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return a.api.ChainGetTipSetByHeight(ctx, h, tsk)
|
||||
}
|
||||
|
||||
func (a *GatewayAPI) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) {
|
||||
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return a.api.GasEstimateMessageGas(ctx, msg, spec, tsk)
|
||||
}
|
||||
|
||||
func (a *GatewayAPI) MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "MpoolPush")
|
||||
defer span.End()
|
||||
|
||||
// TODO: additional anti-spam checks
|
||||
|
||||
return a.api.MpoolPushUntrusted(ctx, sm)
|
||||
}
|
||||
|
||||
func (a *GatewayAPI) MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) {
|
||||
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
||||
return types.NewInt(0), err
|
||||
}
|
||||
|
||||
return a.api.MsigGetAvailableBalance(ctx, addr, tsk)
|
||||
}
|
||||
|
||||
func (a *GatewayAPI) MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error) {
|
||||
if err := a.checkTipsetKey(ctx, start); err != nil {
|
||||
return types.NewInt(0), err
|
||||
}
|
||||
if err := a.checkTipsetKey(ctx, end); err != nil {
|
||||
return types.NewInt(0), err
|
||||
}
|
||||
|
||||
return a.api.MsigGetVested(ctx, addr, start, end)
|
||||
}
|
||||
|
||||
func (a *GatewayAPI) StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
|
||||
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
|
||||
return a.api.StateAccountKey(ctx, addr, tsk)
|
||||
}
|
||||
|
||||
func (a *GatewayAPI) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) {
|
||||
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return a.api.StateGetActor(ctx, actor, tsk)
|
||||
}
|
||||
|
||||
func (a *GatewayAPI) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
|
||||
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
|
||||
return a.api.StateLookupID(ctx, addr, tsk)
|
||||
}
|
||||
|
||||
func (a *GatewayAPI) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error) {
|
||||
return a.api.StateWaitMsgLimited(ctx, msg, confidence, stateWaitLookbackLimit)
|
||||
}
|
||||
|
||||
var _ api.GatewayAPI = (*GatewayAPI)(nil)
|
||||
var _ full.ChainModuleAPI = (*GatewayAPI)(nil)
|
||||
var _ full.GasModuleAPI = (*GatewayAPI)(nil)
|
||||
var _ full.MpoolModuleAPI = (*GatewayAPI)(nil)
|
||||
var _ full.StateModuleAPI = (*GatewayAPI)(nil)
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types/mock"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/ipfs/go-cid"
|
||||
)
|
||||
|
||||
func TestGatewayAPIChainGetTipSetByHeight(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
lookbackTimestamp := uint64(time.Now().Unix()) - uint64(LookbackCap.Seconds())
|
||||
type args struct {
|
||||
h abi.ChainEpoch
|
||||
tskh abi.ChainEpoch
|
||||
genesisTS uint64
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
expErr bool
|
||||
}{{
|
||||
name: "basic",
|
||||
args: args{
|
||||
h: abi.ChainEpoch(1),
|
||||
tskh: abi.ChainEpoch(5),
|
||||
},
|
||||
}, {
|
||||
name: "genesis",
|
||||
args: args{
|
||||
h: abi.ChainEpoch(0),
|
||||
tskh: abi.ChainEpoch(5),
|
||||
},
|
||||
}, {
|
||||
name: "same epoch as tipset",
|
||||
args: args{
|
||||
h: abi.ChainEpoch(5),
|
||||
tskh: abi.ChainEpoch(5),
|
||||
},
|
||||
}, {
|
||||
name: "tipset too old",
|
||||
args: args{
|
||||
// Tipset height is 5, genesis is at LookbackCap - 10 epochs.
|
||||
// So resulting tipset height will be 5 epochs earlier than LookbackCap.
|
||||
h: abi.ChainEpoch(1),
|
||||
tskh: abi.ChainEpoch(5),
|
||||
genesisTS: lookbackTimestamp - build.BlockDelaySecs*10,
|
||||
},
|
||||
expErr: true,
|
||||
}, {
|
||||
name: "lookup height too old",
|
||||
args: args{
|
||||
// Tipset height is 5, lookup height is 1, genesis is at LookbackCap - 3 epochs.
|
||||
// So
|
||||
// - lookup height will be 2 epochs earlier than LookbackCap.
|
||||
// - tipset height will be 2 epochs later than LookbackCap.
|
||||
h: abi.ChainEpoch(1),
|
||||
tskh: abi.ChainEpoch(5),
|
||||
genesisTS: lookbackTimestamp - build.BlockDelaySecs*3,
|
||||
},
|
||||
expErr: true,
|
||||
}, {
|
||||
name: "tipset and lookup height within acceptable range",
|
||||
args: args{
|
||||
// Tipset height is 5, lookup height is 1, genesis is at LookbackCap.
|
||||
// So
|
||||
// - lookup height will be 1 epoch later than LookbackCap.
|
||||
// - tipset height will be 5 epochs later than LookbackCap.
|
||||
h: abi.ChainEpoch(1),
|
||||
tskh: abi.ChainEpoch(5),
|
||||
genesisTS: lookbackTimestamp,
|
||||
},
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
mock := &mockGatewayDepsAPI{}
|
||||
a := &GatewayAPI{api: mock}
|
||||
|
||||
// Create tipsets from genesis up to tskh and return the highest
|
||||
ts := mock.createTipSets(tt.args.tskh, tt.args.genesisTS)
|
||||
|
||||
got, err := a.ChainGetTipSetByHeight(ctx, tt.args.h, ts.Key())
|
||||
if tt.expErr {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tt.args.h, got.Height())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type mockGatewayDepsAPI struct {
|
||||
lk sync.RWMutex
|
||||
tipsets []*types.TipSet
|
||||
}
|
||||
|
||||
func (m *mockGatewayDepsAPI) ChainHead(ctx context.Context) (*types.TipSet, error) {
|
||||
m.lk.RLock()
|
||||
defer m.lk.RUnlock()
|
||||
|
||||
return m.tipsets[len(m.tipsets)-1], nil
|
||||
}
|
||||
|
||||
func (m *mockGatewayDepsAPI) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) {
|
||||
m.lk.RLock()
|
||||
defer m.lk.RUnlock()
|
||||
|
||||
for _, ts := range m.tipsets {
|
||||
if ts.Key() == tsk {
|
||||
return ts, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// createTipSets creates tipsets from genesis up to tskh and returns the highest
|
||||
func (m *mockGatewayDepsAPI) createTipSets(h abi.ChainEpoch, genesisTimestamp uint64) *types.TipSet {
|
||||
m.lk.Lock()
|
||||
defer m.lk.Unlock()
|
||||
|
||||
targeth := h + 1 // add one for genesis block
|
||||
if genesisTimestamp == 0 {
|
||||
genesisTimestamp = uint64(time.Now().Unix()) - build.BlockDelaySecs*uint64(targeth)
|
||||
}
|
||||
var currts *types.TipSet
|
||||
for currh := abi.ChainEpoch(0); currh < targeth; currh++ {
|
||||
blks := mock.MkBlock(currts, 1, 1)
|
||||
if currh == 0 {
|
||||
blks.Timestamp = genesisTimestamp
|
||||
}
|
||||
currts = mock.TipSet(blks)
|
||||
m.tipsets = append(m.tipsets, currts)
|
||||
}
|
||||
|
||||
return m.tipsets[len(m.tipsets)-1]
|
||||
}
|
||||
|
||||
func (m *mockGatewayDepsAPI) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) {
|
||||
m.lk.Lock()
|
||||
defer m.lk.Unlock()
|
||||
|
||||
return m.tipsets[h], nil
|
||||
}
|
||||
|
||||
func (m *mockGatewayDepsAPI) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (m *mockGatewayDepsAPI) MpoolPushUntrusted(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (m *mockGatewayDepsAPI) MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (m *mockGatewayDepsAPI) MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (m *mockGatewayDepsAPI) StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (m *mockGatewayDepsAPI) StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (m *mockGatewayDepsAPI) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (m *mockGatewayDepsAPI) StateWaitMsgLimited(ctx context.Context, msg cid.Cid, confidence uint64, h abi.ChainEpoch) (*api.MsgLookup, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
init0 "github.com/filecoin-project/specs-actors/actors/builtin/init"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/multisig"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-jsonrpc"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/api/client"
|
||||
"github.com/filecoin-project/lotus/api/test"
|
||||
"github.com/filecoin-project/lotus/chain/actors/policy"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/wallet"
|
||||
"github.com/filecoin-project/lotus/node"
|
||||
builder "github.com/filecoin-project/lotus/node/test"
|
||||
)
|
||||
|
||||
func init() {
|
||||
policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1)
|
||||
policy.SetConsensusMinerMinPower(abi.NewStoragePower(2048))
|
||||
policy.SetMinVerifiedDealSize(abi.NewStoragePower(256))
|
||||
}
|
||||
|
||||
// TestEndToEnd tests that API calls can be made on a lite node that is
|
||||
// connected through a gateway to a full API node
|
||||
func TestEndToEnd(t *testing.T) {
|
||||
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
||||
|
||||
blocktime := 5 * time.Millisecond
|
||||
ctx := context.Background()
|
||||
full, lite, closer := startNodes(ctx, t, blocktime)
|
||||
defer closer()
|
||||
|
||||
// The full node starts with a wallet
|
||||
fullWalletAddr, err := full.WalletDefaultAddress(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Check the full node's wallet balance from the lite node
|
||||
balance, err := lite.WalletBalance(ctx, fullWalletAddr)
|
||||
require.NoError(t, err)
|
||||
fmt.Println(balance)
|
||||
|
||||
// Create a wallet on the lite node
|
||||
liteWalletAddr, err := lite.WalletNew(ctx, wallet.ActSigType("secp256k1"))
|
||||
require.NoError(t, err)
|
||||
|
||||
// Send some funds from the full node to the lite node
|
||||
err = sendFunds(ctx, t, full, fullWalletAddr, liteWalletAddr, types.NewInt(1e18))
|
||||
require.NoError(t, err)
|
||||
|
||||
// Send some funds from the lite node back to the full node
|
||||
err = sendFunds(ctx, t, lite, liteWalletAddr, fullWalletAddr, types.NewInt(100))
|
||||
require.NoError(t, err)
|
||||
|
||||
// Sign some data with the lite node wallet address
|
||||
data := []byte("hello")
|
||||
sig, err := lite.WalletSign(ctx, liteWalletAddr, data)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify the signature
|
||||
ok, err := lite.WalletVerify(ctx, liteWalletAddr, data, sig)
|
||||
require.NoError(t, err)
|
||||
require.True(t, ok)
|
||||
|
||||
// Create some wallets on the lite node to use for testing multisig
|
||||
var walletAddrs []address.Address
|
||||
for i := 0; i < 4; i++ {
|
||||
addr, err := lite.WalletNew(ctx, wallet.ActSigType("secp256k1"))
|
||||
require.NoError(t, err)
|
||||
|
||||
walletAddrs = append(walletAddrs, addr)
|
||||
|
||||
err = sendFunds(ctx, t, lite, liteWalletAddr, addr, types.NewInt(1e15))
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
// Create an msig with three of the addresses and threshold of two sigs
|
||||
msigAddrs := walletAddrs[:3]
|
||||
amt := types.NewInt(1000)
|
||||
addProposal, err := lite.MsigCreate(ctx, 2, msigAddrs, abi.ChainEpoch(50), amt, liteWalletAddr, types.NewInt(0))
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err := lite.StateWaitMsg(ctx, addProposal, 1)
|
||||
require.NoError(t, err)
|
||||
require.EqualValues(t, 0, res.Receipt.ExitCode)
|
||||
|
||||
var execReturn init0.ExecReturn
|
||||
err = execReturn.UnmarshalCBOR(bytes.NewReader(res.Receipt.Return))
|
||||
require.NoError(t, err)
|
||||
|
||||
// Get available balance of msig: should be greater than zero and less
|
||||
// than initial amount
|
||||
msig := execReturn.IDAddress
|
||||
msigBalance, err := lite.MsigGetAvailableBalance(ctx, msig, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
require.Greater(t, msigBalance.Int64(), int64(0))
|
||||
require.Less(t, msigBalance.Int64(), amt.Int64())
|
||||
|
||||
// Propose to add a new address to the msig
|
||||
addProposal, err = lite.MsigAddPropose(ctx, msig, walletAddrs[0], walletAddrs[3], false)
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err = lite.StateWaitMsg(ctx, addProposal, 1)
|
||||
require.NoError(t, err)
|
||||
require.EqualValues(t, 0, res.Receipt.ExitCode)
|
||||
|
||||
var proposeReturn multisig.ProposeReturn
|
||||
err = proposeReturn.UnmarshalCBOR(bytes.NewReader(res.Receipt.Return))
|
||||
require.NoError(t, err)
|
||||
|
||||
// Approve proposal (proposer is first (implicit) signer, approver is
|
||||
// second signer
|
||||
txnID := uint64(proposeReturn.TxnID)
|
||||
approval1, err := lite.MsigAddApprove(ctx, msig, walletAddrs[1], txnID, walletAddrs[0], walletAddrs[3], false)
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err = lite.StateWaitMsg(ctx, approval1, 1)
|
||||
require.NoError(t, err)
|
||||
require.EqualValues(t, 0, res.Receipt.ExitCode)
|
||||
|
||||
var approveReturn multisig.ApproveReturn
|
||||
err = approveReturn.UnmarshalCBOR(bytes.NewReader(res.Receipt.Return))
|
||||
require.NoError(t, err)
|
||||
require.True(t, approveReturn.Applied)
|
||||
}
|
||||
|
||||
func sendFunds(ctx context.Context, t *testing.T, fromNode test.TestNode, fromAddr address.Address, toAddr address.Address, amt types.BigInt) error {
|
||||
msg := &types.Message{
|
||||
From: fromAddr,
|
||||
To: toAddr,
|
||||
Value: amt,
|
||||
}
|
||||
|
||||
sm, err := fromNode.MpoolPushMessage(ctx, msg, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res, err := fromNode.StateWaitMsg(ctx, sm.Cid(), 1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if res.Receipt.ExitCode != 0 {
|
||||
return xerrors.Errorf("send funds failed with exit code %d", res.Receipt.ExitCode)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func startNodes(ctx context.Context, t *testing.T, blocktime time.Duration) (test.TestNode, test.TestNode, jsonrpc.ClientCloser) {
|
||||
var closer jsonrpc.ClientCloser
|
||||
|
||||
// Create one miner and two full nodes.
|
||||
// - Put a gateway server in front of full node 1
|
||||
// - Start full node 2 in lite mode
|
||||
// - Connect lite node -> gateway server -> full node
|
||||
opts := append(
|
||||
// Full node
|
||||
test.OneFull,
|
||||
// Lite node
|
||||
test.FullNodeOpts{
|
||||
Lite: true,
|
||||
Opts: func(nodes []test.TestNode) node.Option {
|
||||
fullNode := nodes[0]
|
||||
|
||||
// Create a gateway server in front of the full node
|
||||
_, addr, err := builder.CreateRPCServer(&GatewayAPI{api: fullNode})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create a gateway client API that connects to the gateway server
|
||||
var gapi api.GatewayAPI
|
||||
gapi, closer, err = client.NewGatewayRPC(ctx, addr, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Provide the gateway API to dependency injection
|
||||
return node.Override(new(api.GatewayAPI), gapi)
|
||||
},
|
||||
},
|
||||
)
|
||||
n, sn := builder.RPCMockSbBuilder(t, opts, test.OneMiner)
|
||||
|
||||
full := n[0]
|
||||
lite := n[1]
|
||||
miner := sn[0]
|
||||
|
||||
// Get the listener address for the full node
|
||||
fullAddr, err := full.NetAddrsListen(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Connect the miner and the full node
|
||||
err = miner.NetConnect(ctx, fullAddr)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Start mining blocks
|
||||
bm := test.NewBlockMiner(ctx, t, miner, blocktime)
|
||||
bm.MineBlocks()
|
||||
|
||||
return full, lite, closer
|
||||
}
|
||||
@@ -40,12 +40,12 @@ func main() {
|
||||
return fmt.Errorf("unrecognized key type: %q", cctx.String("type"))
|
||||
}
|
||||
|
||||
kaddr, err := w.GenerateKey(kt)
|
||||
kaddr, err := w.WalletNew(cctx.Context, kt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ki, err := w.Export(kaddr)
|
||||
ki, err := w.WalletExport(cctx.Context, kaddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -396,13 +396,13 @@ var runCmd = &cli.Command{
|
||||
Name: "pre-fee-cap-max",
|
||||
EnvVars: []string{"LOTUS_PCR_PRE_FEE_CAP_MAX"},
|
||||
Usage: "messages with a fee cap larger than this will be skipped when processing pre commit messages",
|
||||
Value: "0.0000000001",
|
||||
Value: "0.000000001",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "prove-fee-cap-max",
|
||||
EnvVars: []string{"LOTUS_PCR_PROVE_FEE_CAP_MAX"},
|
||||
Usage: "messages with a prove cap larger than this will be skipped when processing pre commit messages",
|
||||
Value: "0.0000000001",
|
||||
Value: "0.000000001",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
|
||||
+61
-27
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/docker/go-units"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/multisig"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/power"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/reward"
|
||||
|
||||
@@ -33,16 +34,19 @@ import (
|
||||
)
|
||||
|
||||
type accountInfo struct {
|
||||
Address address.Address
|
||||
Balance types.FIL
|
||||
Type string
|
||||
Power abi.StoragePower
|
||||
Worker address.Address
|
||||
Owner address.Address
|
||||
InitialPledge types.FIL
|
||||
PreCommits types.FIL
|
||||
LockedFunds types.FIL
|
||||
Sectors uint64
|
||||
Address address.Address
|
||||
Balance types.FIL
|
||||
Type string
|
||||
Power abi.StoragePower
|
||||
Worker address.Address
|
||||
Owner address.Address
|
||||
InitialPledge types.FIL
|
||||
PreCommits types.FIL
|
||||
LockedFunds types.FIL
|
||||
Sectors uint64
|
||||
VestingStart abi.ChainEpoch
|
||||
VestingDuration abi.ChainEpoch
|
||||
VestingAmount types.FIL
|
||||
}
|
||||
|
||||
var auditsCmd = &cli.Command{
|
||||
@@ -115,10 +119,8 @@ var chainBalanceCmd = &cli.Command{
|
||||
infos = append(infos, ai)
|
||||
}
|
||||
|
||||
fmt.Printf("Address,Balance,Type,Power,Worker,Owner\n")
|
||||
for _, acc := range infos {
|
||||
fmt.Printf("%s,%s,%s,%s,%s,%s\n", acc.Address, acc.Balance, acc.Type, acc.Power, acc.Worker, acc.Owner)
|
||||
}
|
||||
printAccountInfos(infos, false)
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
@@ -171,7 +173,7 @@ var chainBalanceStateCmd = &cli.Command{
|
||||
|
||||
bs := blockstore.NewBlockstore(ds)
|
||||
|
||||
cs := store.NewChainStore(bs, mds, vm.Syscalls(ffiwrapper.ProofVerifier))
|
||||
cs := store.NewChainStore(bs, mds, vm.Syscalls(ffiwrapper.ProofVerifier), nil)
|
||||
|
||||
cst := cbor.NewCborStore(bs)
|
||||
store := adt.WrapStore(ctx, cst)
|
||||
@@ -196,6 +198,7 @@ var chainBalanceStateCmd = &cli.Command{
|
||||
LockedFunds: types.FIL(big.NewInt(0)),
|
||||
InitialPledge: types.FIL(big.NewInt(0)),
|
||||
PreCommits: types.FIL(big.NewInt(0)),
|
||||
VestingAmount: types.FIL(big.NewInt(0)),
|
||||
}
|
||||
|
||||
if minerInfo && builtin.IsStorageMinerActor(act.Code) {
|
||||
@@ -234,6 +237,32 @@ var chainBalanceStateCmd = &cli.Command{
|
||||
ai.Worker = minfo.Worker
|
||||
ai.Owner = minfo.Owner
|
||||
}
|
||||
|
||||
if builtin.IsMultisigActor(act.Code) {
|
||||
mst, err := multisig.Load(store, act)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ai.VestingStart, err = mst.StartEpoch()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ib, err := mst.InitialBalance()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ai.VestingAmount = types.FIL(ib)
|
||||
|
||||
ai.VestingDuration, err = mst.UnlockDuration()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
infos = append(infos, ai)
|
||||
return nil
|
||||
})
|
||||
@@ -241,22 +270,27 @@ var chainBalanceStateCmd = &cli.Command{
|
||||
return xerrors.Errorf("failed to loop over actors: %w", err)
|
||||
}
|
||||
|
||||
if minerInfo {
|
||||
fmt.Printf("Address,Balance,Type,Sectors,Worker,Owner,InitialPledge,Locked,PreCommits\n")
|
||||
for _, acc := range infos {
|
||||
fmt.Printf("%s,%s,%s,%d,%s,%s,%s,%s,%s\n", acc.Address, acc.Balance, acc.Type, acc.Sectors, acc.Worker, acc.Owner, acc.InitialPledge, acc.LockedFunds, acc.PreCommits)
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("Address,Balance,Type\n")
|
||||
for _, acc := range infos {
|
||||
fmt.Printf("%s,%s,%s\n", acc.Address, acc.Balance, acc.Type)
|
||||
}
|
||||
}
|
||||
printAccountInfos(infos, minerInfo)
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func printAccountInfos(infos []accountInfo, minerInfo bool) {
|
||||
if minerInfo {
|
||||
fmt.Printf("Address,Balance,Type,Sectors,Worker,Owner,InitialPledge,Locked,PreCommits,VestingStart,VestingDuration,VestingAmount\n")
|
||||
for _, acc := range infos {
|
||||
fmt.Printf("%s,%s,%s,%d,%s,%s,%s,%s,%s,%d,%d,%s\n", acc.Address, acc.Balance.Unitless(), acc.Type, acc.Sectors, acc.Worker, acc.Owner, acc.InitialPledge.Unitless(), acc.LockedFunds.Unitless(), acc.PreCommits.Unitless(), acc.VestingStart, acc.VestingDuration, acc.VestingAmount.Unitless())
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("Address,Balance,Type\n")
|
||||
for _, acc := range infos {
|
||||
fmt.Printf("%s,%s,%s\n", acc.Address, acc.Balance.Unitless(), acc.Type)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var chainPledgeCmd = &cli.Command{
|
||||
Name: "stateroot-pledge",
|
||||
Description: "Calculate sector pledge numbers",
|
||||
@@ -309,7 +343,7 @@ var chainPledgeCmd = &cli.Command{
|
||||
|
||||
bs := blockstore.NewBlockstore(ds)
|
||||
|
||||
cs := store.NewChainStore(bs, mds, vm.Syscalls(ffiwrapper.ProofVerifier))
|
||||
cs := store.NewChainStore(bs, mds, vm.Syscalls(ffiwrapper.ProofVerifier), nil)
|
||||
|
||||
cst := cbor.NewCborStore(bs)
|
||||
store := adt.WrapStore(ctx, cst)
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
lcli "github.com/filecoin-project/lotus/cli"
|
||||
cliutil "github.com/filecoin-project/lotus/cli/util"
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
"github.com/multiformats/go-multiaddr"
|
||||
"github.com/urfave/cli/v2"
|
||||
@@ -111,7 +112,7 @@ var consensusCheckCmd = &cli.Command{
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ainfo := lcli.APIInfo{Addr: apima}
|
||||
ainfo := cliutil.APIInfo{Addr: apima.String()}
|
||||
addr, err := ainfo.DialArgs()
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -83,7 +83,7 @@ var exportChainCmd = &cli.Command{
|
||||
|
||||
bs := blockstore.NewBlockstore(ds)
|
||||
|
||||
cs := store.NewChainStore(bs, mds, nil)
|
||||
cs := store.NewChainStore(bs, mds, nil, nil)
|
||||
if err := cs.Load(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ var genesisVerifyCmd = &cli.Command{
|
||||
}
|
||||
bs := blockstore.NewBlockstore(datastore.NewMapDatastore())
|
||||
|
||||
cs := store.NewChainStore(bs, datastore.NewMapDatastore(), nil)
|
||||
cs := store.NewChainStore(bs, datastore.NewMapDatastore(), nil, nil)
|
||||
|
||||
cf := cctx.Args().Get(0)
|
||||
f, err := os.Open(cf)
|
||||
|
||||
@@ -105,7 +105,7 @@ var keyinfoVerifyCmd = &cli.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := w.Import(&keyInfo); err != nil {
|
||||
if _, err := w.WalletImport(cctx.Context, &keyInfo); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -220,7 +220,7 @@ var keyinfoImportCmd = &cli.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
addr, err := w.Import(&keyInfo)
|
||||
addr, err := w.WalletImport(cctx.Context, &keyInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ var stateTreePruneCmd = &cli.Command{
|
||||
|
||||
bs := blockstore.NewBlockstore(ds)
|
||||
|
||||
cs := store.NewChainStore(bs, mds, vm.Syscalls(ffiwrapper.ProofVerifier))
|
||||
cs := store.NewChainStore(bs, mds, vm.Syscalls(ffiwrapper.ProofVerifier), nil)
|
||||
if err := cs.Load(); err != nil {
|
||||
return fmt.Errorf("loading chainstore: %w", err)
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/lotus/node"
|
||||
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/urfave/cli/v2"
|
||||
@@ -64,8 +62,8 @@ func TestMinerAllInfo(t *testing.T) {
|
||||
require.NoError(t, infoAllCmd.Action(cctx))
|
||||
}
|
||||
|
||||
bp := func(t *testing.T, nFull int, storage []test.StorageMiner, opts ...node.Option) ([]test.TestNode, []test.TestStorageNode) {
|
||||
n, sn = builder.Builder(t, nFull, storage, opts...)
|
||||
bp := func(t *testing.T, fullOpts []test.FullNodeOpts, storage []test.StorageMiner) ([]test.TestNode, []test.TestStorageNode) {
|
||||
n, sn = builder.Builder(t, fullOpts, storage)
|
||||
|
||||
t.Run("pre-info-all", run)
|
||||
|
||||
|
||||
@@ -464,13 +464,12 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api lapi.FullNode,
|
||||
return err
|
||||
}
|
||||
|
||||
if jrnl, err := journal.OpenFSJournal(lr, journal.DefaultDisabledEvents); err == nil {
|
||||
journal.J = jrnl
|
||||
} else {
|
||||
j, err := journal.OpenFSJournal(lr, journal.EnvDisabledEvents())
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open filesystem journal: %w", err)
|
||||
}
|
||||
|
||||
m := miner.NewMiner(api, epp, a, slashfilter.New(mds))
|
||||
m := miner.NewMiner(api, epp, a, slashfilter.New(mds), j)
|
||||
{
|
||||
if err := m.Start(ctx); err != nil {
|
||||
return xerrors.Errorf("failed to start up genesis miner: %w", err)
|
||||
|
||||
@@ -154,14 +154,14 @@ var setAskCmd = &cli.Command{
|
||||
Name: "set-ask",
|
||||
Usage: "Configure the miner's ask",
|
||||
Flags: []cli.Flag{
|
||||
&cli.Uint64Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "price",
|
||||
Usage: "Set the price of the ask for unverified deals (specified as attoFIL / GiB / Epoch) to `PRICE`",
|
||||
Usage: "Set the price of the ask for unverified deals (specified as FIL / GiB / Epoch) to `PRICE`.",
|
||||
Required: true,
|
||||
},
|
||||
&cli.Uint64Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "verified-price",
|
||||
Usage: "Set the price of the ask for verified deals (specified as attoFIL / GiB / Epoch) to `PRICE`",
|
||||
Usage: "Set the price of the ask for verified deals (specified as FIL / GiB / Epoch) to `PRICE`",
|
||||
Required: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
@@ -185,8 +185,15 @@ var setAskCmd = &cli.Command{
|
||||
}
|
||||
defer closer()
|
||||
|
||||
pri := types.NewInt(cctx.Uint64("price"))
|
||||
vpri := types.NewInt(cctx.Uint64("verified-price"))
|
||||
pri, err := types.ParseFIL(cctx.String("price"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
vpri, err := types.ParseFIL(cctx.String("verified-price"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dur, err := time.ParseDuration("720h0m0s")
|
||||
if err != nil {
|
||||
@@ -229,7 +236,7 @@ var setAskCmd = &cli.Command{
|
||||
return xerrors.Errorf("max piece size (w/bit-padding) %s cannot exceed miner sector size %s", types.SizeStr(types.NewInt(uint64(max))), types.SizeStr(types.NewInt(uint64(smax))))
|
||||
}
|
||||
|
||||
return api.MarketSetAsk(ctx, pri, vpri, abi.ChainEpoch(qty), abi.PaddedPieceSize(min), abi.PaddedPieceSize(max))
|
||||
return api.MarketSetAsk(ctx, types.BigInt(pri), types.BigInt(vpri), abi.ChainEpoch(qty), abi.PaddedPieceSize(min), abi.PaddedPieceSize(max))
|
||||
},
|
||||
}
|
||||
|
||||
@@ -281,7 +288,7 @@ var getAskCmd = &cli.Command{
|
||||
rem = (time.Second * time.Duration(int64(dlt)*int64(build.BlockDelaySecs))).String()
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%d\t%s\t%d\n", ask.Price, ask.VerifiedPrice, types.SizeStr(types.NewInt(uint64(ask.MinPieceSize))), types.SizeStr(types.NewInt(uint64(ask.MaxPieceSize))), ask.Expiry, rem, ask.SeqNo)
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%d\t%s\t%d\n", types.FIL(ask.Price), types.FIL(ask.VerifiedPrice), types.SizeStr(types.NewInt(uint64(ask.MinPieceSize))), types.SizeStr(types.NewInt(uint64(ask.MaxPieceSize))), ask.Expiry, rem, ask.SeqNo)
|
||||
|
||||
return w.Flush()
|
||||
},
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
type LoggedWallet struct {
|
||||
under api.WalletAPI
|
||||
}
|
||||
|
||||
func (c *LoggedWallet) WalletNew(ctx context.Context, typ crypto.SigType) (address.Address, error) {
|
||||
n, err := typ.Name()
|
||||
if err != nil {
|
||||
return address.Address{}, err
|
||||
}
|
||||
|
||||
log.Infow("WalletNew", "type", n)
|
||||
|
||||
return c.under.WalletNew(ctx, typ)
|
||||
}
|
||||
|
||||
func (c *LoggedWallet) WalletHas(ctx context.Context, addr address.Address) (bool, error) {
|
||||
log.Infow("WalletHas", "address", addr)
|
||||
|
||||
return c.under.WalletHas(ctx, addr)
|
||||
}
|
||||
|
||||
func (c *LoggedWallet) WalletList(ctx context.Context) ([]address.Address, error) {
|
||||
log.Infow("WalletList")
|
||||
|
||||
return c.under.WalletList(ctx)
|
||||
}
|
||||
|
||||
func (c *LoggedWallet) WalletSign(ctx context.Context, k address.Address, msg []byte, meta api.MsgMeta) (*crypto.Signature, error) {
|
||||
switch meta.Type {
|
||||
case api.MTChainMsg:
|
||||
var cmsg types.Message
|
||||
if err := cmsg.UnmarshalCBOR(bytes.NewReader(meta.Extra)); err != nil {
|
||||
return nil, xerrors.Errorf("unmarshalling message: %w", err)
|
||||
}
|
||||
|
||||
_, bc, err := cid.CidFromBytes(msg)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("getting cid from signing bytes: %w", err)
|
||||
}
|
||||
|
||||
if !cmsg.Cid().Equals(bc) {
|
||||
return nil, xerrors.Errorf("cid(meta.Extra).bytes() != msg")
|
||||
}
|
||||
|
||||
log.Infow("WalletSign",
|
||||
"address", k,
|
||||
"type", meta.Type,
|
||||
"from", cmsg.From,
|
||||
"to", cmsg.To,
|
||||
"value", types.FIL(cmsg.Value),
|
||||
"feecap", types.FIL(cmsg.RequiredFunds()),
|
||||
"method", cmsg.Method,
|
||||
"params", hex.EncodeToString(cmsg.Params))
|
||||
default:
|
||||
log.Infow("WalletSign", "address", k, "type", meta.Type)
|
||||
}
|
||||
|
||||
return c.under.WalletSign(ctx, k, msg, meta)
|
||||
}
|
||||
|
||||
func (c *LoggedWallet) WalletExport(ctx context.Context, a address.Address) (*types.KeyInfo, error) {
|
||||
log.Infow("WalletExport", "address", a)
|
||||
|
||||
return c.under.WalletExport(ctx, a)
|
||||
}
|
||||
|
||||
func (c *LoggedWallet) WalletImport(ctx context.Context, ki *types.KeyInfo) (address.Address, error) {
|
||||
log.Infow("WalletImport", "type", ki.Type)
|
||||
|
||||
return c.under.WalletImport(ctx, ki)
|
||||
}
|
||||
|
||||
func (c *LoggedWallet) WalletDelete(ctx context.Context, addr address.Address) error {
|
||||
log.Infow("WalletDelete", "address", addr)
|
||||
|
||||
return c.under.WalletDelete(ctx, addr)
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/filecoin-project/go-jsonrpc"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/wallet"
|
||||
lcli "github.com/filecoin-project/lotus/cli"
|
||||
"github.com/filecoin-project/lotus/lib/lotuslog"
|
||||
"github.com/filecoin-project/lotus/node/repo"
|
||||
)
|
||||
|
||||
var log = logging.Logger("main")
|
||||
|
||||
const FlagWalletRepo = "wallet-repo"
|
||||
|
||||
func main() {
|
||||
lotuslog.SetupLogLevels()
|
||||
|
||||
local := []*cli.Command{
|
||||
runCmd,
|
||||
}
|
||||
|
||||
app := &cli.App{
|
||||
Name: "lotus-wallet",
|
||||
Usage: "Basic external wallet",
|
||||
Version: build.UserVersion(),
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: FlagWalletRepo,
|
||||
EnvVars: []string{"WALLET_PATH"},
|
||||
Value: "~/.lotuswallet", // TODO: Consider XDG_DATA_HOME
|
||||
},
|
||||
},
|
||||
|
||||
Commands: local,
|
||||
}
|
||||
app.Setup()
|
||||
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Warnf("%+v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var runCmd = &cli.Command{
|
||||
Name: "run",
|
||||
Usage: "Start lotus wallet",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "listen",
|
||||
Usage: "host address and port the wallet api will listen on",
|
||||
Value: "0.0.0.0:1777",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
log.Info("Starting lotus wallet")
|
||||
|
||||
ctx := lcli.ReqContext(cctx)
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
|
||||
repoPath := cctx.String(FlagWalletRepo)
|
||||
r, err := repo.NewFS(repoPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ok, err := r.Exists()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !ok {
|
||||
if err := r.Init(repo.Worker); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
lr, err := r.Lock(repo.Wallet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ks, err := lr.KeyStore()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w, err := wallet.NewWallet(ks)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
address := cctx.String("listen")
|
||||
mux := mux.NewRouter()
|
||||
|
||||
log.Info("Setting up API endpoint at " + address)
|
||||
|
||||
rpcServer := jsonrpc.NewServer()
|
||||
rpcServer.Register("Filecoin", &LoggedWallet{under: w})
|
||||
|
||||
mux.Handle("/rpc/v0", rpcServer)
|
||||
mux.PathPrefix("/").Handler(http.DefaultServeMux) // pprof
|
||||
|
||||
/*ah := &auth.Handler{
|
||||
Verify: nodeApi.AuthVerify,
|
||||
Next: mux.ServeHTTP,
|
||||
}*/
|
||||
|
||||
srv := &http.Server{
|
||||
Handler: mux,
|
||||
BaseContext: func(listener net.Listener) context.Context {
|
||||
return ctx
|
||||
},
|
||||
}
|
||||
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
log.Warn("Shutting down...")
|
||||
if err := srv.Shutdown(context.TODO()); err != nil {
|
||||
log.Errorf("shutting down RPC server failed: %s", err)
|
||||
}
|
||||
log.Warn("Graceful shutdown successful")
|
||||
}()
|
||||
|
||||
nl, err := net.Listen("tcp", address)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return srv.Serve(nl)
|
||||
},
|
||||
}
|
||||
+33
-6
@@ -15,8 +15,6 @@ import (
|
||||
"runtime/pprof"
|
||||
"strings"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
|
||||
paramfetch "github.com/filecoin-project/go-paramfetch"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/multiformats/go-multiaddr"
|
||||
@@ -32,9 +30,11 @@ import (
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
lcli "github.com/filecoin-project/lotus/cli"
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
|
||||
"github.com/filecoin-project/lotus/journal"
|
||||
"github.com/filecoin-project/lotus/lib/blockstore"
|
||||
"github.com/filecoin-project/lotus/lib/peermgr"
|
||||
"github.com/filecoin-project/lotus/lib/ulimit"
|
||||
@@ -114,6 +114,11 @@ var DaemonCmd = &cli.Command{
|
||||
Name: "halt-after-import",
|
||||
Usage: "halt the process after importing chain from file",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "lite",
|
||||
Usage: "start lotus in lite mode",
|
||||
Hidden: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "pprof",
|
||||
Usage: "specify name of file for writing cpu profile to",
|
||||
@@ -133,6 +138,8 @@ var DaemonCmd = &cli.Command{
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
isLite := cctx.Bool("lite")
|
||||
|
||||
err := runmetrics.Enable(runmetrics.RunMetricOptions{
|
||||
EnableCPU: true,
|
||||
EnableMemory: true,
|
||||
@@ -192,8 +199,10 @@ var DaemonCmd = &cli.Command{
|
||||
return xerrors.Errorf("repo init error: %w", err)
|
||||
}
|
||||
|
||||
if err := paramfetch.GetParams(lcli.ReqContext(cctx), build.ParametersJSON(), 0); err != nil {
|
||||
return xerrors.Errorf("fetching proof parameters: %w", err)
|
||||
if !isLite {
|
||||
if err := paramfetch.GetParams(lcli.ReqContext(cctx), build.ParametersJSON(), 0); err != nil {
|
||||
return xerrors.Errorf("fetching proof parameters: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
var genBytes []byte
|
||||
@@ -240,10 +249,23 @@ var DaemonCmd = &cli.Command{
|
||||
|
||||
shutdownChan := make(chan struct{})
|
||||
|
||||
// If the daemon is started in "lite mode", provide a GatewayAPI
|
||||
// for RPC calls
|
||||
liteModeDeps := node.Options()
|
||||
if isLite {
|
||||
gapi, closer, err := lcli.GetGatewayAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer closer()
|
||||
liteModeDeps = node.Override(new(api.GatewayAPI), gapi)
|
||||
}
|
||||
|
||||
var api api.FullNode
|
||||
|
||||
stop, err := node.New(ctx,
|
||||
node.FullAPI(&api),
|
||||
node.FullAPI(&api, node.Lite(isLite)),
|
||||
|
||||
node.Override(new(dtypes.Bootstrapper), isBootstrapper),
|
||||
node.Override(new(dtypes.ShutdownChan), shutdownChan),
|
||||
@@ -251,6 +273,7 @@ var DaemonCmd = &cli.Command{
|
||||
node.Repo(r),
|
||||
|
||||
genesis,
|
||||
liteModeDeps,
|
||||
|
||||
node.ApplyIf(func(s *node.Settings) bool { return cctx.IsSet("api") },
|
||||
node.Override(node.SetApiEndpointKey, func(lr repo.LockedRepo) error {
|
||||
@@ -388,7 +411,11 @@ func ImportChain(r repo.Repo, fname string, snapshot bool) (err error) {
|
||||
|
||||
bs := blockstore.NewBlockstore(ds)
|
||||
|
||||
cst := store.NewChainStore(bs, mds, vm.Syscalls(ffiwrapper.ProofVerifier))
|
||||
j, err := journal.OpenFSJournal(lr, journal.EnvDisabledEvents())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to open journal: %w", err)
|
||||
}
|
||||
cst := store.NewChainStore(bs, mds, vm.Syscalls(ffiwrapper.ProofVerifier), j)
|
||||
|
||||
log.Infof("importing chain from %s...", fname)
|
||||
|
||||
|
||||
+9
-1
@@ -200,6 +200,8 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error {
|
||||
Message: m,
|
||||
CircSupply: circSupplyDetail.FilCirculating,
|
||||
BaseFee: basefee,
|
||||
// recorded randomness will be discarded.
|
||||
Rand: conformance.NewRecordingRand(new(conformance.LogReporter), fapi),
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute precursor message: %w", err)
|
||||
@@ -212,6 +214,9 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error {
|
||||
applyret *vm.ApplyRet
|
||||
carWriter func(w io.Writer) error
|
||||
retention = opts.retain
|
||||
|
||||
// recordingRand will record randomness so we can embed it in the test vector.
|
||||
recordingRand = conformance.NewRecordingRand(new(conformance.LogReporter), fapi)
|
||||
)
|
||||
|
||||
log.Printf("using state retention strategy: %s", retention)
|
||||
@@ -231,6 +236,7 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error {
|
||||
Message: msg,
|
||||
CircSupply: circSupplyDetail.FilCirculating,
|
||||
BaseFee: basefee,
|
||||
Rand: recordingRand,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute message: %w", err)
|
||||
@@ -262,6 +268,7 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error {
|
||||
Message: msg,
|
||||
CircSupply: circSupplyDetail.FilCirculating,
|
||||
BaseFee: basefee,
|
||||
Rand: recordingRand,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute message: %w", err)
|
||||
@@ -356,7 +363,8 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error {
|
||||
{Source: fmt.Sprintf("execution_tipset:%s", execTs.Key().String())},
|
||||
{Source: "github.com/filecoin-project/lotus", Version: version.String()}},
|
||||
},
|
||||
CAR: out.Bytes(),
|
||||
Randomness: recordingRand.Recorded(),
|
||||
CAR: out.Bytes(),
|
||||
Pre: &schema.Preconditions{
|
||||
Epoch: int64(execTs.Height()),
|
||||
CircSupply: circSupply.Int,
|
||||
|
||||
@@ -14,6 +14,9 @@ import (
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
|
||||
"github.com/filecoin-project/lotus/lib/blockstore"
|
||||
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/bls" // enable bls signatures
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/secp" // enable secp signatures
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
@@ -81,10 +84,10 @@ type ExecuteTipsetResult struct {
|
||||
// and reward withdrawal per miner.
|
||||
func (d *Driver) ExecuteTipset(bs blockstore.Blockstore, ds ds.Batching, preroot cid.Cid, parentEpoch abi.ChainEpoch, tipset *schema.Tipset) (*ExecuteTipsetResult, error) {
|
||||
var (
|
||||
syscalls = mkFakedSigSyscalls(vm.Syscalls(ffiwrapper.ProofVerifier))
|
||||
syscalls = vm.Syscalls(ffiwrapper.ProofVerifier)
|
||||
vmRand = NewFixedRand()
|
||||
|
||||
cs = store.NewChainStore(bs, ds, syscalls)
|
||||
cs = store.NewChainStore(bs, ds, syscalls, nil)
|
||||
sm = stmgr.NewStateManager(cs)
|
||||
)
|
||||
|
||||
@@ -173,7 +176,7 @@ func (d *Driver) ExecuteMessage(bs blockstore.Blockstore, params ExecuteMessageP
|
||||
StateBase: params.Preroot,
|
||||
Epoch: params.Epoch,
|
||||
Bstore: bs,
|
||||
Syscalls: mkFakedSigSyscalls(vm.Syscalls(ffiwrapper.ProofVerifier)), // TODO always succeeds; need more flexibility.
|
||||
Syscalls: vm.Syscalls(ffiwrapper.ProofVerifier),
|
||||
CircSupplyCalc: func(_ context.Context, _ abi.ChainEpoch, _ *state.StateTree) (abi.TokenAmount, error) {
|
||||
return params.CircSupply, nil
|
||||
},
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
package conformance
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
|
||||
"github.com/filecoin-project/test-vectors/schema"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
)
|
||||
|
||||
type RecordingRand struct {
|
||||
reporter Reporter
|
||||
api api.FullNode
|
||||
|
||||
// once guards the loading of the head tipset.
|
||||
// can be removed when https://github.com/filecoin-project/lotus/issues/4223
|
||||
// is fixed.
|
||||
once sync.Once
|
||||
head types.TipSetKey
|
||||
lk sync.Mutex
|
||||
recorded schema.Randomness
|
||||
}
|
||||
|
||||
var _ vm.Rand = (*RecordingRand)(nil)
|
||||
|
||||
// NewRecordingRand returns a vm.Rand implementation that proxies calls to a
|
||||
// full Lotus node via JSON-RPC, and records matching rules and responses so
|
||||
// they can later be embedded in test vectors.
|
||||
func NewRecordingRand(reporter Reporter, api api.FullNode) *RecordingRand {
|
||||
return &RecordingRand{reporter: reporter, api: api}
|
||||
}
|
||||
|
||||
func (r *RecordingRand) loadHead() {
|
||||
head, err := r.api.ChainHead(context.Background())
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("could not fetch chain head while fetching randomness: %s", err))
|
||||
}
|
||||
r.head = head.Key()
|
||||
}
|
||||
|
||||
func (r *RecordingRand) GetChainRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
|
||||
r.once.Do(r.loadHead)
|
||||
ret, err := r.api.ChainGetRandomnessFromTickets(ctx, r.head, pers, round, entropy)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
r.reporter.Logf("fetched and recorded chain randomness for: dst=%d, epoch=%d, entropy=%x, result=%x", pers, round, entropy, ret)
|
||||
|
||||
match := schema.RandomnessMatch{
|
||||
On: schema.RandomnessRule{
|
||||
Kind: schema.RandomnessChain,
|
||||
DomainSeparationTag: int64(pers),
|
||||
Epoch: int64(round),
|
||||
Entropy: entropy,
|
||||
},
|
||||
Return: []byte(ret),
|
||||
}
|
||||
r.lk.Lock()
|
||||
r.recorded = append(r.recorded, match)
|
||||
r.lk.Unlock()
|
||||
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (r *RecordingRand) GetBeaconRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
|
||||
r.once.Do(r.loadHead)
|
||||
ret, err := r.api.ChainGetRandomnessFromBeacon(ctx, r.head, pers, round, entropy)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
r.reporter.Logf("fetched and recorded beacon randomness for: dst=%d, epoch=%d, entropy=%x, result=%x", pers, round, entropy, ret)
|
||||
|
||||
match := schema.RandomnessMatch{
|
||||
On: schema.RandomnessRule{
|
||||
Kind: schema.RandomnessBeacon,
|
||||
DomainSeparationTag: int64(pers),
|
||||
Epoch: int64(round),
|
||||
Entropy: entropy,
|
||||
},
|
||||
Return: []byte(ret),
|
||||
}
|
||||
r.lk.Lock()
|
||||
r.recorded = append(r.recorded, match)
|
||||
r.lk.Unlock()
|
||||
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (r *RecordingRand) Recorded() schema.Randomness {
|
||||
r.lk.Lock()
|
||||
defer r.lk.Unlock()
|
||||
|
||||
return r.recorded
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package conformance
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
|
||||
"github.com/filecoin-project/test-vectors/schema"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
)
|
||||
|
||||
type ReplayingRand struct {
|
||||
reporter Reporter
|
||||
recorded schema.Randomness
|
||||
fallback vm.Rand
|
||||
}
|
||||
|
||||
var _ vm.Rand = (*ReplayingRand)(nil)
|
||||
|
||||
// NewReplayingRand replays recorded randomness when requested, falling back to
|
||||
// fixed randomness if the value cannot be found; hence this is a safe
|
||||
// backwards-compatible replacement for fixedRand.
|
||||
func NewReplayingRand(reporter Reporter, recorded schema.Randomness) *ReplayingRand {
|
||||
return &ReplayingRand{
|
||||
reporter: reporter,
|
||||
recorded: recorded,
|
||||
fallback: NewFixedRand(),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *ReplayingRand) match(requested schema.RandomnessRule) ([]byte, bool) {
|
||||
for _, other := range r.recorded {
|
||||
if other.On.Kind == requested.Kind &&
|
||||
other.On.Epoch == requested.Epoch &&
|
||||
other.On.DomainSeparationTag == requested.DomainSeparationTag &&
|
||||
bytes.Equal(other.On.Entropy, requested.Entropy) {
|
||||
return other.Return, true
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (r *ReplayingRand) GetChainRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
|
||||
rule := schema.RandomnessRule{
|
||||
Kind: schema.RandomnessChain,
|
||||
DomainSeparationTag: int64(pers),
|
||||
Epoch: int64(round),
|
||||
Entropy: entropy,
|
||||
}
|
||||
|
||||
if ret, ok := r.match(rule); ok {
|
||||
r.reporter.Logf("returning saved chain randomness: dst=%d, epoch=%d, entropy=%x, result=%x", pers, round, entropy, ret)
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
r.reporter.Logf("returning fallback chain randomness: dst=%d, epoch=%d, entropy=%x", pers, round, entropy)
|
||||
return r.fallback.GetChainRandomness(ctx, pers, round, entropy)
|
||||
}
|
||||
|
||||
func (r *ReplayingRand) GetBeaconRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
|
||||
rule := schema.RandomnessRule{
|
||||
Kind: schema.RandomnessBeacon,
|
||||
DomainSeparationTag: int64(pers),
|
||||
Epoch: int64(round),
|
||||
Entropy: entropy,
|
||||
}
|
||||
|
||||
if ret, ok := r.match(rule); ok {
|
||||
r.reporter.Logf("returning saved beacon randomness: dst=%d, epoch=%d, entropy=%x, result=%x", pers, round, entropy, ret)
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
r.reporter.Logf("returning fallback beacon randomness: dst=%d, epoch=%d, entropy=%x", pers, round, entropy)
|
||||
return r.fallback.GetBeaconRandomness(ctx, pers, round, entropy)
|
||||
|
||||
}
|
||||
@@ -66,6 +66,7 @@ func ExecuteMessageVector(r Reporter, vector *schema.TestVector) {
|
||||
Message: msg,
|
||||
BaseFee: BaseFeeOrDefault(vector.Pre.BaseFee),
|
||||
CircSupply: CircSupplyOrDefault(vector.Pre.CircSupply),
|
||||
Rand: NewReplayingRand(r, vector.Randomness),
|
||||
})
|
||||
if err != nil {
|
||||
r.Fatalf("fatal failure when executing message: %s", err)
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
package conformance
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/runtime/proof"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/state"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
"github.com/filecoin-project/specs-actors/actors/runtime"
|
||||
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
)
|
||||
|
||||
type testSyscalls struct {
|
||||
runtime.Syscalls
|
||||
}
|
||||
|
||||
// TODO VerifySignature this will always succeed; but we want to be able to test failures too.
|
||||
func (fss *testSyscalls) VerifySignature(_ crypto.Signature, _ address.Address, _ []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO VerifySeal this will always succeed; but we want to be able to test failures too.
|
||||
func (fss *testSyscalls) VerifySeal(_ proof.SealVerifyInfo) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO VerifyPoSt this will always succeed; but we want to be able to test failures too.
|
||||
func (fss *testSyscalls) VerifyPoSt(_ proof.WindowPoStVerifyInfo) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func mkFakedSigSyscalls(base vm.SyscallBuilder) vm.SyscallBuilder {
|
||||
return func(ctx context.Context, cstate *state.StateTree, cst cbor.IpldStore) runtime.Syscalls {
|
||||
return &testSyscalls{
|
||||
base(ctx, cstate, cst),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,6 +87,7 @@
|
||||
* [MsigCreate](#MsigCreate)
|
||||
* [MsigGetAvailableBalance](#MsigGetAvailableBalance)
|
||||
* [MsigGetVested](#MsigGetVested)
|
||||
* [MsigGetVestingSchedule](#MsigGetVestingSchedule)
|
||||
* [MsigPropose](#MsigPropose)
|
||||
* [MsigSwapApprove](#MsigSwapApprove)
|
||||
* [MsigSwapCancel](#MsigSwapCancel)
|
||||
@@ -166,6 +167,7 @@
|
||||
* [StateVerifiedRegistryRootKey](#StateVerifiedRegistryRootKey)
|
||||
* [StateVerifierStatus](#StateVerifierStatus)
|
||||
* [StateWaitMsg](#StateWaitMsg)
|
||||
* [StateWaitMsgLimited](#StateWaitMsgLimited)
|
||||
* [Sync](#Sync)
|
||||
* [SyncCheckBad](#SyncCheckBad)
|
||||
* [SyncCheckpoint](#SyncCheckpoint)
|
||||
@@ -2143,6 +2145,36 @@ Inputs:
|
||||
|
||||
Response: `"0"`
|
||||
|
||||
### MsigGetVestingSchedule
|
||||
MsigGetVestingSchedule returns the vesting details of a given multisig.
|
||||
|
||||
|
||||
Perms: read
|
||||
|
||||
Inputs:
|
||||
```json
|
||||
[
|
||||
"f01234",
|
||||
[
|
||||
{
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
{
|
||||
"/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve"
|
||||
}
|
||||
]
|
||||
]
|
||||
```
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"InitialBalance": "0",
|
||||
"StartEpoch": 10101,
|
||||
"UnlockDuration": 10101
|
||||
}
|
||||
```
|
||||
|
||||
### MsigPropose
|
||||
MsigPropose proposes a multisig message
|
||||
It takes the following params: <multisig address>, <recipient address>, <value to transfer>,
|
||||
@@ -4290,6 +4322,49 @@ Response:
|
||||
}
|
||||
```
|
||||
|
||||
### StateWaitMsgLimited
|
||||
StateWaitMsgLimited looks back up to limit epochs in the chain for a message.
|
||||
If not found, it blocks until the message arrives on chain, and gets to the
|
||||
indicated confidence depth.
|
||||
|
||||
|
||||
Perms: read
|
||||
|
||||
Inputs:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
42,
|
||||
10101
|
||||
]
|
||||
```
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"Message": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"Receipt": {
|
||||
"ExitCode": 0,
|
||||
"Return": "Ynl0ZSBhcnJheQ==",
|
||||
"GasUsed": 9
|
||||
},
|
||||
"ReturnDec": {},
|
||||
"TipSet": [
|
||||
{
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
{
|
||||
"/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve"
|
||||
}
|
||||
],
|
||||
"Height": 10101
|
||||
}
|
||||
```
|
||||
|
||||
## Sync
|
||||
The Sync method group contains methods for interacting with and
|
||||
observing the lotus sync service.
|
||||
|
||||
+1
-5
@@ -290,10 +290,6 @@ func (sb *Sealer) UnsealPiece(ctx context.Context, sector abi.SectorID, offset s
|
||||
defer opr.Close() // nolint
|
||||
|
||||
padwriter := fr32.NewPadWriter(out)
|
||||
if err != nil {
|
||||
perr = xerrors.Errorf("creating new padded writer: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
bsize := uint64(size.Padded())
|
||||
if bsize > uint64(runtime.NumCPU())*fr32.MTTresh {
|
||||
@@ -302,7 +298,7 @@ func (sb *Sealer) UnsealPiece(ctx context.Context, sector abi.SectorID, offset s
|
||||
|
||||
bw := bufio.NewWriterSize(padwriter, int(abi.PaddedPieceSize(bsize).Unpadded()))
|
||||
|
||||
_, err = io.CopyN(bw, opr, int64(size))
|
||||
_, err := io.CopyN(bw, opr, int64(size))
|
||||
if err != nil {
|
||||
perr = xerrors.Errorf("copying data: %w", err)
|
||||
return
|
||||
|
||||
Vendored
+1
-1
Submodule extern/test-vectors updated: 7471e2805f...a8f968adeb
@@ -29,8 +29,8 @@ require (
|
||||
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03
|
||||
github.com/filecoin-project/go-data-transfer v0.6.7
|
||||
github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f
|
||||
github.com/filecoin-project/go-fil-markets v0.7.0
|
||||
github.com/filecoin-project/go-jsonrpc v0.1.2-0.20200822201400-474f4fdccc52
|
||||
github.com/filecoin-project/go-fil-markets v0.7.1
|
||||
github.com/filecoin-project/go-jsonrpc v0.1.2-0.20201008195726-68c6a2704e49
|
||||
github.com/filecoin-project/go-multistore v0.0.3
|
||||
github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20
|
||||
github.com/filecoin-project/go-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261
|
||||
@@ -39,9 +39,9 @@ require (
|
||||
github.com/filecoin-project/go-statestore v0.1.0
|
||||
github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b
|
||||
github.com/filecoin-project/specs-actors v0.9.12
|
||||
github.com/filecoin-project/specs-actors/v2 v2.0.1
|
||||
github.com/filecoin-project/specs-actors/v2 v2.0.3
|
||||
github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796
|
||||
github.com/filecoin-project/test-vectors/schema v0.0.3
|
||||
github.com/filecoin-project/test-vectors/schema v0.0.4
|
||||
github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1
|
||||
github.com/go-kit/kit v0.10.0
|
||||
github.com/go-ole/go-ole v1.2.4 // indirect
|
||||
@@ -94,10 +94,10 @@ require (
|
||||
github.com/libp2p/go-libp2p-discovery v0.5.0
|
||||
github.com/libp2p/go-libp2p-kad-dht v0.8.3
|
||||
github.com/libp2p/go-libp2p-mplex v0.2.4
|
||||
github.com/libp2p/go-libp2p-noise v0.1.1
|
||||
github.com/libp2p/go-libp2p-noise v0.1.2
|
||||
github.com/libp2p/go-libp2p-peerstore v0.2.6
|
||||
github.com/libp2p/go-libp2p-pubsub v0.3.6-0.20200910093904-f7f33e10cc18
|
||||
github.com/libp2p/go-libp2p-quic-transport v0.8.0
|
||||
github.com/libp2p/go-libp2p-pubsub v0.3.6
|
||||
github.com/libp2p/go-libp2p-quic-transport v0.8.2
|
||||
github.com/libp2p/go-libp2p-record v0.1.3
|
||||
github.com/libp2p/go-libp2p-routing-helpers v0.2.3
|
||||
github.com/libp2p/go-libp2p-swarm v0.2.8
|
||||
|
||||
@@ -244,16 +244,16 @@ github.com/filecoin-project/go-ds-versioning v0.1.0 h1:y/X6UksYTsK8TLCI7rttCKEvl
|
||||
github.com/filecoin-project/go-ds-versioning v0.1.0/go.mod h1:mp16rb4i2QPmxBnmanUx8i/XANp+PFCCJWiAb+VW4/s=
|
||||
github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f h1:GxJzR3oRIMTPtpZ0b7QF8FKPK6/iPAc7trhlL5k/g+s=
|
||||
github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ=
|
||||
github.com/filecoin-project/go-fil-markets v0.7.0 h1:tcEZiUNIYQJ4PBzgVpLwfdJ4ZdC4WCv9LsgvsoCXIls=
|
||||
github.com/filecoin-project/go-fil-markets v0.7.0/go.mod h1:5Pt4DXQqUoUrp9QzlSdlYTpItXxwAtqKrxRWQ6hAOqk=
|
||||
github.com/filecoin-project/go-fil-markets v0.7.1 h1:e0NlpSnaeGyDUhCOzevjcxkSA54kt9BzlXpLRgduUFI=
|
||||
github.com/filecoin-project/go-fil-markets v0.7.1/go.mod h1:5Pt4DXQqUoUrp9QzlSdlYTpItXxwAtqKrxRWQ6hAOqk=
|
||||
github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM=
|
||||
github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM=
|
||||
github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24=
|
||||
github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24=
|
||||
github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM=
|
||||
github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0/go.mod h1:7aWZdaQ1b16BVoQUYR+eEvrDCGJoPLxFpDynFjYfBjI=
|
||||
github.com/filecoin-project/go-jsonrpc v0.1.2-0.20200822201400-474f4fdccc52 h1:FXtCp0ybqdQL9knb3OGDpkNTaBbPxgkqPeWKotUwkH0=
|
||||
github.com/filecoin-project/go-jsonrpc v0.1.2-0.20200822201400-474f4fdccc52/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4=
|
||||
github.com/filecoin-project/go-jsonrpc v0.1.2-0.20201008195726-68c6a2704e49 h1:FSY245KeXFCUgyfFEu+bhrZNk8BGGJyfpSmQl2aiPU8=
|
||||
github.com/filecoin-project/go-jsonrpc v0.1.2-0.20201008195726-68c6a2704e49/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4=
|
||||
github.com/filecoin-project/go-multistore v0.0.3 h1:vaRBY4YiA2UZFPK57RNuewypB8u0DzzQwqsL0XarpnI=
|
||||
github.com/filecoin-project/go-multistore v0.0.3/go.mod h1:kaNqCC4IhU4B1uyr7YWFHd23TL4KM32aChS0jNkyUvQ=
|
||||
github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20 h1:+/4aUeUoKr6AKfPE3mBhXA5spIV6UcKdTYDPNU2Tdmg=
|
||||
@@ -276,12 +276,12 @@ github.com/filecoin-project/specs-actors v0.9.4/go.mod h1:BStZQzx5x7TmCkLv0Bpa07
|
||||
github.com/filecoin-project/specs-actors v0.9.7/go.mod h1:wM2z+kwqYgXn5Z7scV1YHLyd1Q1cy0R8HfTIWQ0BFGU=
|
||||
github.com/filecoin-project/specs-actors v0.9.12 h1:iIvk58tuMtmloFNHhAOQHG+4Gci6Lui0n7DYQGi3cJk=
|
||||
github.com/filecoin-project/specs-actors v0.9.12/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao=
|
||||
github.com/filecoin-project/specs-actors/v2 v2.0.1 h1:bf08x6tqCDfClzrv2q/rmt/A/UbBOy1KgaoogQEcLhU=
|
||||
github.com/filecoin-project/specs-actors/v2 v2.0.1/go.mod h1:v2NZVYinNIKA9acEMBm5wWXxqv5+frFEbekBFemYghY=
|
||||
github.com/filecoin-project/specs-actors/v2 v2.0.3 h1:Niy6xncgi8bI8aBCt1McdZfATBfG4Uxytt8KW4s3bAc=
|
||||
github.com/filecoin-project/specs-actors/v2 v2.0.3/go.mod h1:v2NZVYinNIKA9acEMBm5wWXxqv5+frFEbekBFemYghY=
|
||||
github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796 h1:dJsTPWpG2pcTeojO2pyn0c6l+x/3MZYCBgo/9d11JEk=
|
||||
github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796/go.mod h1:nJRRM7Aa9XVvygr3W9k6xGF46RWzr2zxF/iGoAIfA/g=
|
||||
github.com/filecoin-project/test-vectors/schema v0.0.3 h1:1zuBo25B3016inbygYLgYFdpJ2m1BDTbAOCgABRleiU=
|
||||
github.com/filecoin-project/test-vectors/schema v0.0.3/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E=
|
||||
github.com/filecoin-project/test-vectors/schema v0.0.4 h1:QTRd0gb/NP4ZOTM7Dib5U3xE1/ToGDKnYLfxkC3t/m8=
|
||||
github.com/filecoin-project/test-vectors/schema v0.0.4/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6 h1:u/UEqS66A5ckRmS4yNpjmVH56sVtS/RfclBAYocb4as=
|
||||
github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6/go.mod h1:1i71OnUq3iUe1ma7Lr6yG6/rjvM3emb6yoL7xLFzcVQ=
|
||||
@@ -863,6 +863,8 @@ github.com/libp2p/go-libp2p-netutil v0.1.0 h1:zscYDNVEcGxyUpMd0JReUZTrpMfia8PmLK
|
||||
github.com/libp2p/go-libp2p-netutil v0.1.0/go.mod h1:3Qv/aDqtMLTUyQeundkKsA+YCThNdbQD54k3TqjpbFU=
|
||||
github.com/libp2p/go-libp2p-noise v0.1.1 h1:vqYQWvnIcHpIoWJKC7Al4D6Hgj0H012TuXRhPwSMGpQ=
|
||||
github.com/libp2p/go-libp2p-noise v0.1.1/go.mod h1:QDFLdKX7nluB7DEnlVPbz7xlLHdwHFA9HiohJRr3vwM=
|
||||
github.com/libp2p/go-libp2p-noise v0.1.2 h1:IH9GRihQJTx56obm+GnpdPX4KeVIlvpXrP6xnJ0wxWk=
|
||||
github.com/libp2p/go-libp2p-noise v0.1.2/go.mod h1:9B10b7ueo7TIxZHHcjcDCo5Hd6kfKT2m77by82SFRfE=
|
||||
github.com/libp2p/go-libp2p-peer v0.0.1/go.mod h1:nXQvOBbwVqoP+T5Y5nCjeH4sP9IX/J0AMzcDUVruVoo=
|
||||
github.com/libp2p/go-libp2p-peer v0.1.1/go.mod h1:jkF12jGB4Gk/IOo+yomm+7oLWxF278F7UnrYUQ1Q8es=
|
||||
github.com/libp2p/go-libp2p-peer v0.2.0/go.mod h1:RCffaCvUyW2CJmG2gAWVqwePwW7JMgxjsHm7+J5kjWY=
|
||||
@@ -884,12 +886,12 @@ github.com/libp2p/go-libp2p-protocol v0.0.1/go.mod h1:Af9n4PiruirSDjHycM1QuiMi/1
|
||||
github.com/libp2p/go-libp2p-protocol v0.1.0/go.mod h1:KQPHpAabB57XQxGrXCNvbL6UEXfQqUgC/1adR2Xtflk=
|
||||
github.com/libp2p/go-libp2p-pubsub v0.1.1/go.mod h1:ZwlKzRSe1eGvSIdU5bD7+8RZN/Uzw0t1Bp9R1znpR/Q=
|
||||
github.com/libp2p/go-libp2p-pubsub v0.3.2-0.20200527132641-c0712c6e92cf/go.mod h1:TxPOBuo1FPdsTjFnv+FGZbNbWYsp74Culx+4ViQpato=
|
||||
github.com/libp2p/go-libp2p-pubsub v0.3.6-0.20200910093904-f7f33e10cc18 h1:+ae7vHSv/PJ4xGXwLV6LKGj32zjyB8ttJHtyV4TXal0=
|
||||
github.com/libp2p/go-libp2p-pubsub v0.3.6-0.20200910093904-f7f33e10cc18/go.mod h1:DTMSVmZZfXodB/pvdTGrY2eHPZ9W2ev7hzTH83OKHrI=
|
||||
github.com/libp2p/go-libp2p-pubsub v0.3.6 h1:9oO8W7qIWCYQYyz5z8nUsPcb3rrFehBlkbqvbSVjBxY=
|
||||
github.com/libp2p/go-libp2p-pubsub v0.3.6/go.mod h1:DTMSVmZZfXodB/pvdTGrY2eHPZ9W2ev7hzTH83OKHrI=
|
||||
github.com/libp2p/go-libp2p-quic-transport v0.1.1/go.mod h1:wqG/jzhF3Pu2NrhJEvE+IE0NTHNXslOPn9JQzyCAxzU=
|
||||
github.com/libp2p/go-libp2p-quic-transport v0.5.0/go.mod h1:IEcuC5MLxvZ5KuHKjRu+dr3LjCT1Be3rcD/4d8JrX8M=
|
||||
github.com/libp2p/go-libp2p-quic-transport v0.8.0 h1:mHA94K2+TD0e9XtjWx/P5jGGZn0GdQ4OFYwNllagv4E=
|
||||
github.com/libp2p/go-libp2p-quic-transport v0.8.0/go.mod h1:F2FG/6Bzz0U6essUVxDzE0s9CrY4XGLbl7QEmDNvU7A=
|
||||
github.com/libp2p/go-libp2p-quic-transport v0.8.2 h1:FDaXBCBJ1e5hY6gnWEJ4NbYyLk8eezr4J6AY3q3KqwM=
|
||||
github.com/libp2p/go-libp2p-quic-transport v0.8.2/go.mod h1:L+e0q15ZNaYm3seHgbsXjWP8kXLEqz+elLWKk9l8DhM=
|
||||
github.com/libp2p/go-libp2p-record v0.0.1/go.mod h1:grzqg263Rug/sRex85QrDOLntdFAymLDLm7lxMgU79Q=
|
||||
github.com/libp2p/go-libp2p-record v0.1.0/go.mod h1:ujNc8iuE5dlKWVy6wuL6dd58t0n7xI4hAIl8pE6wu5Q=
|
||||
github.com/libp2p/go-libp2p-record v0.1.1/go.mod h1:VRgKajOyMVgP/F0L5g3kH7SVskp17vFi2xheb5uMJtg=
|
||||
@@ -1022,8 +1024,8 @@ github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-b
|
||||
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
||||
github.com/lucas-clemente/quic-go v0.11.2/go.mod h1:PpMmPfPKO9nKJ/psF49ESTAGQSdfXxlg1otPbEB2nOw=
|
||||
github.com/lucas-clemente/quic-go v0.16.0/go.mod h1:I0+fcNTdb9eS1ZcjQZbDVPGchJ86chcIxPALn9lEJqE=
|
||||
github.com/lucas-clemente/quic-go v0.18.0 h1:JhQDdqxdwdmGdKsKgXi1+coHRoGhvU6z0rNzOJqZ/4o=
|
||||
github.com/lucas-clemente/quic-go v0.18.0/go.mod h1:yXttHsSNxQi8AWijC/vLP+OJczXqzHSOcJrM5ITUlCg=
|
||||
github.com/lucas-clemente/quic-go v0.18.1 h1:DMR7guC0NtVS8zNZR3IO7NARZvZygkSC56GGtC6cyys=
|
||||
github.com/lucas-clemente/quic-go v0.18.1/go.mod h1:yXttHsSNxQi8AWijC/vLP+OJczXqzHSOcJrM5ITUlCg=
|
||||
github.com/lufia/iostat v1.1.0/go.mod h1:rEPNA0xXgjHQjuI5Cy05sLlS2oRcSlWHRLrvh/AQ+Pg=
|
||||
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package journal
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
// envJournalDisabledEvents is the environment variable through which disabled
|
||||
// journal events can be customized.
|
||||
const envDisabledEvents = "LOTUS_JOURNAL_DISABLED_EVENTS"
|
||||
|
||||
func EnvDisabledEvents() DisabledEvents {
|
||||
if env, ok := os.LookupEnv(envDisabledEvents); ok {
|
||||
if ret, err := ParseDisabledEvents(env); err == nil {
|
||||
return ret
|
||||
}
|
||||
}
|
||||
// fallback if env variable is not set, or if it failed to parse.
|
||||
return DefaultDisabledEvents
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package journal
|
||||
|
||||
var (
|
||||
// J is a globally accessible Journal. It starts being NilJournal, and early
|
||||
// during the Lotus initialization routine, it is reset to whichever Journal
|
||||
// is configured (by default, the filesystem journal). Components can safely
|
||||
// record in the journal by calling: journal.J.RecordEvent(...).
|
||||
J Journal = NilJournal() // nolint
|
||||
)
|
||||
+8
-8
@@ -28,9 +28,9 @@ type RetrievalProviderEvt struct {
|
||||
}
|
||||
|
||||
// StorageClientJournaler records journal events from the storage client.
|
||||
func StorageClientJournaler(evtType journal.EventType) func(event storagemarket.ClientEvent, deal storagemarket.ClientDeal) {
|
||||
func StorageClientJournaler(j journal.Journal, evtType journal.EventType) func(event storagemarket.ClientEvent, deal storagemarket.ClientDeal) {
|
||||
return func(event storagemarket.ClientEvent, deal storagemarket.ClientDeal) {
|
||||
journal.J.RecordEvent(evtType, func() interface{} {
|
||||
j.RecordEvent(evtType, func() interface{} {
|
||||
return StorageClientEvt{
|
||||
Event: storagemarket.ClientEvents[event],
|
||||
Deal: deal,
|
||||
@@ -40,9 +40,9 @@ func StorageClientJournaler(evtType journal.EventType) func(event storagemarket.
|
||||
}
|
||||
|
||||
// StorageProviderJournaler records journal events from the storage provider.
|
||||
func StorageProviderJournaler(evtType journal.EventType) func(event storagemarket.ProviderEvent, deal storagemarket.MinerDeal) {
|
||||
func StorageProviderJournaler(j journal.Journal, evtType journal.EventType) func(event storagemarket.ProviderEvent, deal storagemarket.MinerDeal) {
|
||||
return func(event storagemarket.ProviderEvent, deal storagemarket.MinerDeal) {
|
||||
journal.J.RecordEvent(evtType, func() interface{} {
|
||||
j.RecordEvent(evtType, func() interface{} {
|
||||
return StorageProviderEvt{
|
||||
Event: storagemarket.ProviderEvents[event],
|
||||
Deal: deal,
|
||||
@@ -52,9 +52,9 @@ func StorageProviderJournaler(evtType journal.EventType) func(event storagemarke
|
||||
}
|
||||
|
||||
// RetrievalClientJournaler records journal events from the retrieval client.
|
||||
func RetrievalClientJournaler(evtType journal.EventType) func(event retrievalmarket.ClientEvent, deal retrievalmarket.ClientDealState) {
|
||||
func RetrievalClientJournaler(j journal.Journal, evtType journal.EventType) func(event retrievalmarket.ClientEvent, deal retrievalmarket.ClientDealState) {
|
||||
return func(event retrievalmarket.ClientEvent, deal retrievalmarket.ClientDealState) {
|
||||
journal.J.RecordEvent(evtType, func() interface{} {
|
||||
j.RecordEvent(evtType, func() interface{} {
|
||||
return RetrievalClientEvt{
|
||||
Event: retrievalmarket.ClientEvents[event],
|
||||
Deal: deal,
|
||||
@@ -64,9 +64,9 @@ func RetrievalClientJournaler(evtType journal.EventType) func(event retrievalmar
|
||||
}
|
||||
|
||||
// RetrievalProviderJournaler records journal events from the retrieval provider.
|
||||
func RetrievalProviderJournaler(evtType journal.EventType) func(event retrievalmarket.ProviderEvent, deal retrievalmarket.ProviderDealState) {
|
||||
func RetrievalProviderJournaler(j journal.Journal, evtType journal.EventType) func(event retrievalmarket.ProviderEvent, deal retrievalmarket.ProviderDealState) {
|
||||
return func(event retrievalmarket.ProviderEvent, deal retrievalmarket.ProviderDealState) {
|
||||
journal.J.RecordEvent(evtType, func() interface{} {
|
||||
j.RecordEvent(evtType, func() interface{} {
|
||||
return RetrievalProviderEvt{
|
||||
Event: retrievalmarket.ProviderEvents[event],
|
||||
Deal: deal,
|
||||
|
||||
@@ -6,19 +6,22 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
miner0 "github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
market0 "github.com/filecoin-project/specs-actors/actors/builtin/market"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
cborutil "github.com/filecoin-project/go-cbor-util"
|
||||
"github.com/filecoin-project/go-fil-markets/shared"
|
||||
"github.com/filecoin-project/go-fil-markets/storagemarket"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
"github.com/filecoin-project/go-state-types/exitcode"
|
||||
miner0 "github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
market0 "github.com/filecoin-project/specs-actors/actors/builtin/market"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||
"github.com/filecoin-project/lotus/chain/events"
|
||||
@@ -30,7 +33,6 @@ import (
|
||||
"github.com/filecoin-project/lotus/lib/sigs"
|
||||
"github.com/filecoin-project/lotus/markets/utils"
|
||||
"github.com/filecoin-project/lotus/node/impl/full"
|
||||
"github.com/ipfs/go-cid"
|
||||
)
|
||||
|
||||
type ClientNodeAdapter struct {
|
||||
@@ -187,7 +189,7 @@ func (c *ClientNodeAdapter) ValidatePublishedDeal(ctx context.Context, deal stor
|
||||
}
|
||||
|
||||
// TODO: timeout
|
||||
_, ret, _, err := c.sm.WaitForMessage(ctx, *deal.PublishMessage, build.MessageConfidence)
|
||||
_, ret, _, err := c.sm.WaitForMessage(ctx, *deal.PublishMessage, build.MessageConfidence, stmgr.LookbackNoLimit)
|
||||
if err != nil {
|
||||
return 0, xerrors.Errorf("waiting for deal publish message: %w", err)
|
||||
}
|
||||
@@ -422,7 +424,9 @@ func (c *ClientNodeAdapter) SignProposal(ctx context.Context, signer address.Add
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sig, err := c.Wallet.Sign(ctx, signer, buf)
|
||||
sig, err := c.Wallet.WalletSign(ctx, signer, buf, api.MsgMeta{
|
||||
Type: api.MTDealProposal,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -434,7 +438,7 @@ func (c *ClientNodeAdapter) SignProposal(ctx context.Context, signer address.Add
|
||||
}
|
||||
|
||||
func (c *ClientNodeAdapter) GetDefaultWalletAddress(ctx context.Context) (address.Address, error) {
|
||||
addr, err := c.Wallet.GetDefault()
|
||||
addr, err := c.DefWallet.GetDefault()
|
||||
return addr, err
|
||||
}
|
||||
|
||||
@@ -475,7 +479,9 @@ func (c *ClientNodeAdapter) SignBytes(ctx context.Context, signer address.Addres
|
||||
return nil, err
|
||||
}
|
||||
|
||||
localSignature, err := c.Wallet.Sign(ctx, signer, b)
|
||||
localSignature, err := c.Wallet.WalletSign(ctx, signer, b, api.MsgMeta{
|
||||
Type: api.MTUnknown, // TODO: pass type here
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+6
-3
@@ -49,7 +49,7 @@ func randTimeOffset(width time.Duration) time.Duration {
|
||||
return val - (width / 2)
|
||||
}
|
||||
|
||||
func NewMiner(api api.FullNode, epp gen.WinningPoStProver, addr address.Address, sf *slashfilter.SlashFilter) *Miner {
|
||||
func NewMiner(api api.FullNode, epp gen.WinningPoStProver, addr address.Address, sf *slashfilter.SlashFilter, j journal.Journal) *Miner {
|
||||
arc, err := lru.NewARC(10000)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -74,8 +74,9 @@ func NewMiner(api api.FullNode, epp gen.WinningPoStProver, addr address.Address,
|
||||
sf: sf,
|
||||
minedBlockHeights: arc,
|
||||
evtTypes: [...]journal.EventType{
|
||||
evtTypeBlockMined: journal.J.RegisterEventType("miner", "block_mined"),
|
||||
evtTypeBlockMined: j.RegisterEventType("miner", "block_mined"),
|
||||
},
|
||||
journal: j,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +98,7 @@ type Miner struct {
|
||||
minedBlockHeights *lru.ARCCache
|
||||
|
||||
evtTypes [1]journal.EventType
|
||||
journal journal.Journal
|
||||
}
|
||||
|
||||
func (m *Miner) Address() address.Address {
|
||||
@@ -239,7 +241,7 @@ minerLoop:
|
||||
onDone(b != nil, h, nil)
|
||||
|
||||
if b != nil {
|
||||
journal.J.RecordEvent(m.evtTypes[evtTypeBlockMined], func() interface{} {
|
||||
m.journal.RecordEvent(m.evtTypes[evtTypeBlockMined], func() interface{} {
|
||||
return map[string]interface{}{
|
||||
"parents": base.TipSet.Cids(),
|
||||
"nulls": base.NullRounds,
|
||||
@@ -327,6 +329,7 @@ func (m *Miner) GetBestMiningCandidate(ctx context.Context) (*MiningBase, error)
|
||||
}
|
||||
ltsw, err := m.api.ChainTipSetWeight(ctx, m.lastWork.TipSet.Key())
|
||||
if err != nil {
|
||||
m.lastWork = nil
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/gen"
|
||||
"github.com/filecoin-project/lotus/chain/gen/slashfilter"
|
||||
"github.com/filecoin-project/lotus/journal"
|
||||
)
|
||||
|
||||
type MineReq struct {
|
||||
@@ -32,6 +33,7 @@ func NewTestMiner(nextCh <-chan MineReq, addr address.Address) func(api.FullNode
|
||||
minedBlockHeights: arc,
|
||||
address: addr,
|
||||
sf: slashfilter.New(ds.NewMapDatastore()),
|
||||
journal: journal.NilJournal(),
|
||||
}
|
||||
|
||||
if err := m.Start(context.TODO()); err != nil {
|
||||
|
||||
+62
-38
@@ -3,9 +3,15 @@ package node
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain"
|
||||
"github.com/filecoin-project/lotus/chain/exchange"
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
"github.com/filecoin-project/lotus/chain/wallet"
|
||||
"github.com/filecoin-project/lotus/node/hello"
|
||||
|
||||
logging "github.com/ipfs/go-log"
|
||||
ci "github.com/libp2p/go-libp2p-core/crypto"
|
||||
"github.com/libp2p/go-libp2p-core/host"
|
||||
@@ -29,9 +35,7 @@ import (
|
||||
storage2 "github.com/filecoin-project/specs-storage/storage"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain"
|
||||
"github.com/filecoin-project/lotus/chain/beacon"
|
||||
"github.com/filecoin-project/lotus/chain/exchange"
|
||||
"github.com/filecoin-project/lotus/chain/gen"
|
||||
"github.com/filecoin-project/lotus/chain/gen/slashfilter"
|
||||
"github.com/filecoin-project/lotus/chain/market"
|
||||
@@ -39,10 +43,8 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/messagesigner"
|
||||
"github.com/filecoin-project/lotus/chain/metrics"
|
||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
"github.com/filecoin-project/lotus/chain/wallet"
|
||||
"github.com/filecoin-project/lotus/chain/wallet/remotewallet"
|
||||
sectorstorage "github.com/filecoin-project/lotus/extern/sector-storage"
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/stores"
|
||||
@@ -56,9 +58,9 @@ import (
|
||||
"github.com/filecoin-project/lotus/markets/storageadapter"
|
||||
"github.com/filecoin-project/lotus/miner"
|
||||
"github.com/filecoin-project/lotus/node/config"
|
||||
"github.com/filecoin-project/lotus/node/hello"
|
||||
"github.com/filecoin-project/lotus/node/impl"
|
||||
"github.com/filecoin-project/lotus/node/impl/common"
|
||||
"github.com/filecoin-project/lotus/node/impl/full"
|
||||
"github.com/filecoin-project/lotus/node/modules"
|
||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||
"github.com/filecoin-project/lotus/node/modules/helpers"
|
||||
@@ -71,10 +73,6 @@ import (
|
||||
"github.com/filecoin-project/lotus/storage/sectorblocks"
|
||||
)
|
||||
|
||||
// EnvJournalDisabledEvents is the environment variable through which disabled
|
||||
// journal events can be customized.
|
||||
const EnvJournalDisabledEvents = "LOTUS_JOURNAL_DISABLED_EVENTS"
|
||||
|
||||
//nolint:deadcode,varcheck
|
||||
var log = logging.Logger("builder")
|
||||
|
||||
@@ -158,25 +156,14 @@ type Settings struct {
|
||||
|
||||
Online bool // Online option applied
|
||||
Config bool // Config option applied
|
||||
|
||||
Lite bool // Start node in "lite" mode
|
||||
}
|
||||
|
||||
func defaults() []Option {
|
||||
return []Option{
|
||||
// global system journal.
|
||||
Override(new(journal.DisabledEvents), func() journal.DisabledEvents {
|
||||
if env, ok := os.LookupEnv(EnvJournalDisabledEvents); ok {
|
||||
if ret, err := journal.ParseDisabledEvents(env); err == nil {
|
||||
return ret
|
||||
}
|
||||
}
|
||||
// fallback if env variable is not set, or if it failed to parse.
|
||||
return journal.DefaultDisabledEvents
|
||||
}),
|
||||
Override(new(journal.DisabledEvents), journal.EnvDisabledEvents),
|
||||
Override(new(journal.Journal), modules.OpenFilesystemJournal),
|
||||
Override(InitJournalKey, func(j journal.Journal) {
|
||||
journal.J = j // eagerly sets the global journal through fx.Invoke.
|
||||
}),
|
||||
|
||||
Override(new(helpers.MetricsCtx), context.Background),
|
||||
Override(new(record.Validator), modules.RecordValidator),
|
||||
@@ -232,6 +219,10 @@ func isType(t repo.RepoType) func(s *Settings) bool {
|
||||
|
||||
// Online sets up basic libp2p node
|
||||
func Online() Option {
|
||||
isFullOrLiteNode := func(s *Settings) bool { return s.nodeType == repo.FullNode }
|
||||
isFullNode := func(s *Settings) bool { return s.nodeType == repo.FullNode && !s.Lite }
|
||||
isLiteNode := func(s *Settings) bool { return s.nodeType == repo.FullNode && s.Lite }
|
||||
|
||||
return Options(
|
||||
// make sure that online is applied before Config.
|
||||
// This is important because Config overrides some of Online units
|
||||
@@ -245,23 +236,23 @@ func Online() Option {
|
||||
// common
|
||||
Override(new(*slashfilter.SlashFilter), modules.NewSlashFilter),
|
||||
|
||||
// Full node
|
||||
|
||||
ApplyIf(isType(repo.FullNode),
|
||||
// Full node or lite node
|
||||
ApplyIf(isFullOrLiteNode,
|
||||
// TODO: Fix offline mode
|
||||
|
||||
Override(new(dtypes.BootstrapPeers), modules.BuiltinBootstrap),
|
||||
Override(new(dtypes.DrandBootstrap), modules.DrandBootstrap),
|
||||
Override(new(dtypes.DrandSchedule), modules.BuiltinDrandConfig),
|
||||
|
||||
Override(HandleIncomingMessagesKey, modules.HandleIncomingMessages),
|
||||
|
||||
Override(new(ffiwrapper.Verifier), ffiwrapper.ProofVerifier),
|
||||
Override(new(vm.SyscallBuilder), vm.Syscalls),
|
||||
Override(new(*store.ChainStore), modules.ChainStore),
|
||||
Override(new(stmgr.UpgradeSchedule), stmgr.DefaultUpgradeSchedule()),
|
||||
Override(new(*stmgr.StateManager), stmgr.NewStateManagerWithUpgradeSchedule),
|
||||
Override(new(*wallet.Wallet), wallet.NewWallet),
|
||||
Override(new(stmgr.StateManagerAPI), From(new(*stmgr.StateManager))),
|
||||
Override(new(*wallet.LocalWallet), wallet.NewWallet),
|
||||
Override(new(api.WalletAPI), From(new(*wallet.LocalWallet))),
|
||||
Override(new(wallet.Default), From(new(*wallet.LocalWallet))),
|
||||
Override(new(*messagesigner.MessageSigner), messagesigner.NewMessageSigner),
|
||||
|
||||
Override(new(dtypes.ChainGCLocker), blockstore.NewGCLocker),
|
||||
@@ -288,12 +279,6 @@ func Online() Option {
|
||||
|
||||
Override(new(dtypes.Graphsync), modules.Graphsync),
|
||||
Override(new(*dtypes.MpoolLocker), new(dtypes.MpoolLocker)),
|
||||
|
||||
Override(RunHelloKey, modules.RunHello),
|
||||
Override(RunChainExchangeKey, modules.RunChainExchange),
|
||||
Override(RunPeerMgrKey, modules.RunPeerMgr),
|
||||
Override(HandleIncomingBlocksKey, modules.HandleIncomingBlocks),
|
||||
|
||||
Override(new(*discoveryimpl.Local), modules.NewLocalDiscovery),
|
||||
Override(new(discovery.PeerResolver), modules.RetrievalResolver),
|
||||
|
||||
@@ -312,8 +297,34 @@ func Online() Option {
|
||||
Override(SettlePaymentChannelsKey, settler.SettlePaymentChannels),
|
||||
),
|
||||
|
||||
// Lite node
|
||||
ApplyIf(isLiteNode,
|
||||
Override(new(messagesigner.MpoolNonceAPI), From(new(modules.MpoolNonceAPI))),
|
||||
Override(new(full.ChainModuleAPI), From(new(api.GatewayAPI))),
|
||||
Override(new(full.GasModuleAPI), From(new(api.GatewayAPI))),
|
||||
Override(new(full.MpoolModuleAPI), From(new(api.GatewayAPI))),
|
||||
Override(new(full.StateModuleAPI), From(new(api.GatewayAPI))),
|
||||
Override(new(stmgr.StateManagerAPI), modules.NewRPCStateManager),
|
||||
),
|
||||
|
||||
// Full node
|
||||
ApplyIf(isFullNode,
|
||||
Override(new(messagesigner.MpoolNonceAPI), From(new(*messagepool.MessagePool))),
|
||||
Override(new(full.ChainModuleAPI), From(new(full.ChainModule))),
|
||||
Override(new(full.GasModuleAPI), From(new(full.GasModule))),
|
||||
Override(new(full.MpoolModuleAPI), From(new(full.MpoolModule))),
|
||||
Override(new(full.StateModuleAPI), From(new(full.StateModule))),
|
||||
Override(new(stmgr.StateManagerAPI), From(new(*stmgr.StateManager))),
|
||||
|
||||
Override(RunHelloKey, modules.RunHello),
|
||||
Override(RunChainExchangeKey, modules.RunChainExchange),
|
||||
Override(RunPeerMgrKey, modules.RunPeerMgr),
|
||||
Override(HandleIncomingMessagesKey, modules.HandleIncomingMessages),
|
||||
Override(HandleIncomingBlocksKey, modules.HandleIncomingBlocks),
|
||||
),
|
||||
|
||||
// miner
|
||||
ApplyIf(func(s *Settings) bool { return s.nodeType == repo.StorageMiner },
|
||||
ApplyIf(isType(repo.StorageMiner),
|
||||
Override(new(api.Common), From(new(common.CommonAPI))),
|
||||
Override(new(sectorstorage.StorageAuth), modules.StorageAuth),
|
||||
|
||||
@@ -448,6 +459,9 @@ func ConfigFullNode(c interface{}) Option {
|
||||
If(cfg.Metrics.HeadNotifs,
|
||||
Override(HeadMetricsKey, metrics.SendHeadNotifs(cfg.Metrics.Nickname)),
|
||||
),
|
||||
If(cfg.Wallet.RemoteBackend != "",
|
||||
Override(new(api.WalletAPI), remotewallet.SetupRemoteWallet(cfg.Wallet.RemoteBackend)),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -507,12 +521,22 @@ func Repo(r repo.Repo) Option {
|
||||
}
|
||||
}
|
||||
|
||||
func FullAPI(out *api.FullNode) Option {
|
||||
type FullOption = Option
|
||||
|
||||
func Lite(enable bool) FullOption {
|
||||
return func(s *Settings) error {
|
||||
s.Lite = enable
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func FullAPI(out *api.FullNode, fopts ...FullOption) Option {
|
||||
return Options(
|
||||
func(s *Settings) error {
|
||||
s.nodeType = repo.FullNode
|
||||
return nil
|
||||
},
|
||||
Options(fopts...),
|
||||
func(s *Settings) error {
|
||||
resAPI := &impl.FullNodeAPI{}
|
||||
s.invokes[ExtractApiKey] = fx.Populate(resAPI)
|
||||
|
||||
@@ -22,6 +22,7 @@ type FullNode struct {
|
||||
Common
|
||||
Client Client
|
||||
Metrics Metrics
|
||||
Wallet Wallet
|
||||
}
|
||||
|
||||
// // Common
|
||||
@@ -107,6 +108,10 @@ type Client struct {
|
||||
IpfsUseForRetrieval bool
|
||||
}
|
||||
|
||||
type Wallet struct {
|
||||
RemoteBackend string
|
||||
}
|
||||
|
||||
func defCommon() Common {
|
||||
return Common{
|
||||
API: API{
|
||||
|
||||
+24
-16
@@ -462,13 +462,19 @@ type retrievalSubscribeEvent struct {
|
||||
state rm.ClientDealState
|
||||
}
|
||||
|
||||
func readSubscribeEvents(ctx context.Context, subscribeEvents chan retrievalSubscribeEvent, events chan marketevents.RetrievalEvent) error {
|
||||
func readSubscribeEvents(ctx context.Context, dealID retrievalmarket.DealID, subscribeEvents chan retrievalSubscribeEvent, events chan marketevents.RetrievalEvent) error {
|
||||
for {
|
||||
var subscribeEvent retrievalSubscribeEvent
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return xerrors.New("Retrieval Timed Out")
|
||||
case subscribeEvent = <-subscribeEvents:
|
||||
if subscribeEvent.state.ID != dealID {
|
||||
// we can't check the deal ID ahead of time because:
|
||||
// 1. We need to subscribe before retrieving.
|
||||
// 2. We won't know the deal ID until after retrieving.
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
select {
|
||||
@@ -531,19 +537,6 @@ func (a *API) clientRetrieve(ctx context.Context, order api.RetrievalOrder, ref
|
||||
return err
|
||||
}*/
|
||||
|
||||
var dealID retrievalmarket.DealID
|
||||
subscribeEvents := make(chan retrievalSubscribeEvent, 1)
|
||||
subscribeCtx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
unsubscribe := a.Retrieval.SubscribeToEvents(func(event rm.ClientEvent, state rm.ClientDealState) {
|
||||
if state.PayloadCID.Equals(order.Root) && state.ID == dealID {
|
||||
select {
|
||||
case <-subscribeCtx.Done():
|
||||
case subscribeEvents <- retrievalSubscribeEvent{event, state}:
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
ppb := types.BigDiv(order.Total, types.NewInt(order.Size))
|
||||
|
||||
params, err := rm.NewParamsV1(ppb, order.PaymentInterval, order.PaymentIntervalIncrease, shared.AllSelector(), order.Piece, order.UnsealPrice)
|
||||
@@ -562,7 +555,21 @@ func (a *API) clientRetrieve(ctx context.Context, order api.RetrievalOrder, ref
|
||||
_ = a.RetrievalStoreMgr.ReleaseStore(store)
|
||||
}()
|
||||
|
||||
dealID, err = a.Retrieval.Retrieve(
|
||||
// Subscribe to events before retrieving to avoid losing events.
|
||||
subscribeEvents := make(chan retrievalSubscribeEvent, 1)
|
||||
subscribeCtx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
unsubscribe := a.Retrieval.SubscribeToEvents(func(event rm.ClientEvent, state rm.ClientDealState) {
|
||||
// We'll check the deal IDs inside readSubscribeEvents.
|
||||
if state.PayloadCID.Equals(order.Root) {
|
||||
select {
|
||||
case <-subscribeCtx.Done():
|
||||
case subscribeEvents <- retrievalSubscribeEvent{event, state}:
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
dealID, err := a.Retrieval.Retrieve(
|
||||
ctx,
|
||||
order.Root,
|
||||
params,
|
||||
@@ -573,11 +580,12 @@ func (a *API) clientRetrieve(ctx context.Context, order api.RetrievalOrder, ref
|
||||
store.StoreID())
|
||||
|
||||
if err != nil {
|
||||
unsubscribe()
|
||||
finish(xerrors.Errorf("Retrieve failed: %w", err))
|
||||
return
|
||||
}
|
||||
|
||||
err = readSubscribeEvents(ctx, subscribeEvents, events)
|
||||
err = readSubscribeEvents(ctx, dealID, subscribeEvents, events)
|
||||
|
||||
unsubscribe()
|
||||
if err != nil {
|
||||
|
||||
+25
-7
@@ -39,10 +39,28 @@ import (
|
||||
|
||||
var log = logging.Logger("fullnode")
|
||||
|
||||
type ChainModuleAPI interface {
|
||||
ChainHead(context.Context) (*types.TipSet, error)
|
||||
ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
|
||||
ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
|
||||
}
|
||||
|
||||
// ChainModule provides a default implementation of ChainModuleAPI.
|
||||
// It can be swapped out with another implementation through Dependency
|
||||
// Injection (for example with a thin RPC client).
|
||||
type ChainModule struct {
|
||||
fx.In
|
||||
|
||||
Chain *store.ChainStore
|
||||
}
|
||||
|
||||
var _ ChainModuleAPI = (*ChainModule)(nil)
|
||||
|
||||
type ChainAPI struct {
|
||||
fx.In
|
||||
|
||||
WalletAPI
|
||||
ChainModuleAPI
|
||||
|
||||
Chain *store.ChainStore
|
||||
}
|
||||
@@ -51,8 +69,8 @@ func (a *ChainAPI) ChainNotify(ctx context.Context) (<-chan []*api.HeadChange, e
|
||||
return a.Chain.SubHeadChanges(ctx), nil
|
||||
}
|
||||
|
||||
func (a *ChainAPI) ChainHead(context.Context) (*types.TipSet, error) {
|
||||
return a.Chain.GetHeaviestTipSet(), nil
|
||||
func (m *ChainModule) ChainHead(context.Context) (*types.TipSet, error) {
|
||||
return m.Chain.GetHeaviestTipSet(), nil
|
||||
}
|
||||
|
||||
func (a *ChainAPI) ChainGetRandomnessFromTickets(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error) {
|
||||
@@ -77,8 +95,8 @@ func (a *ChainAPI) ChainGetBlock(ctx context.Context, msg cid.Cid) (*types.Block
|
||||
return a.Chain.GetBlock(msg)
|
||||
}
|
||||
|
||||
func (a *ChainAPI) ChainGetTipSet(ctx context.Context, key types.TipSetKey) (*types.TipSet, error) {
|
||||
return a.Chain.LoadTipSet(key)
|
||||
func (m *ChainModule) ChainGetTipSet(ctx context.Context, key types.TipSetKey) (*types.TipSet, error) {
|
||||
return m.Chain.LoadTipSet(key)
|
||||
}
|
||||
|
||||
func (a *ChainAPI) ChainGetBlockMessages(ctx context.Context, msg cid.Cid) (*api.BlockMessages, error) {
|
||||
@@ -180,12 +198,12 @@ func (a *ChainAPI) ChainGetParentReceipts(ctx context.Context, bcid cid.Cid) ([]
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (a *ChainAPI) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) {
|
||||
ts, err := a.Chain.GetTipSetFromKey(tsk)
|
||||
func (m *ChainModule) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) {
|
||||
ts, err := m.Chain.GetTipSetFromKey(tsk)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
||||
}
|
||||
return a.Chain.GetTipsetByHeight(ctx, h, ts, true)
|
||||
return m.Chain.GetTipsetByHeight(ctx, h, ts, true)
|
||||
}
|
||||
|
||||
func (a *ChainAPI) ChainReadObj(ctx context.Context, obj cid.Cid) ([]byte, error) {
|
||||
|
||||
+82
-21
@@ -26,8 +26,27 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
type GasModuleAPI interface {
|
||||
GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
|
||||
}
|
||||
|
||||
// GasModule provides a default implementation of GasModuleAPI.
|
||||
// It can be swapped out with another implementation through Dependency
|
||||
// Injection (for example with a thin RPC client).
|
||||
type GasModule struct {
|
||||
fx.In
|
||||
Stmgr *stmgr.StateManager
|
||||
Chain *store.ChainStore
|
||||
Mpool *messagepool.MessagePool
|
||||
}
|
||||
|
||||
var _ GasModuleAPI = (*GasModule)(nil)
|
||||
|
||||
type GasAPI struct {
|
||||
fx.In
|
||||
|
||||
GasModuleAPI
|
||||
|
||||
Stmgr *stmgr.StateManager
|
||||
Chain *store.ChainStore
|
||||
Mpool *messagepool.MessagePool
|
||||
@@ -36,9 +55,24 @@ type GasAPI struct {
|
||||
const MinGasPremium = 100e3
|
||||
const MaxSpendOnFeeDenom = 100
|
||||
|
||||
func (a *GasAPI) GasEstimateFeeCap(ctx context.Context, msg *types.Message, maxqueueblks int64,
|
||||
tsk types.TipSetKey) (types.BigInt, error) {
|
||||
ts := a.Chain.GetHeaviestTipSet()
|
||||
func (a *GasAPI) GasEstimateFeeCap(
|
||||
ctx context.Context,
|
||||
msg *types.Message,
|
||||
maxqueueblks int64,
|
||||
tsk types.TipSetKey,
|
||||
) (types.BigInt, error) {
|
||||
return gasEstimateFeeCap(a.Chain, msg, maxqueueblks)
|
||||
}
|
||||
func (m *GasModule) GasEstimateFeeCap(
|
||||
ctx context.Context,
|
||||
msg *types.Message,
|
||||
maxqueueblks int64,
|
||||
tsk types.TipSetKey,
|
||||
) (types.BigInt, error) {
|
||||
return gasEstimateFeeCap(m.Chain, msg, maxqueueblks)
|
||||
}
|
||||
func gasEstimateFeeCap(cstore *store.ChainStore, msg *types.Message, maxqueueblks int64) (types.BigInt, error) {
|
||||
ts := cstore.GetHeaviestTipSet()
|
||||
|
||||
parentBaseFee := ts.Blocks()[0].ParentBaseFee
|
||||
increaseFactor := math.Pow(1.+1./float64(build.BaseFeeMaxChangeDenom), float64(maxqueueblks))
|
||||
@@ -82,9 +116,25 @@ func medianGasPremium(prices []gasMeta, blocks int) abi.TokenAmount {
|
||||
return premium
|
||||
}
|
||||
|
||||
func (a *GasAPI) GasEstimateGasPremium(ctx context.Context, nblocksincl uint64,
|
||||
sender address.Address, gaslimit int64, _ types.TipSetKey) (types.BigInt, error) {
|
||||
|
||||
func (a *GasAPI) GasEstimateGasPremium(
|
||||
ctx context.Context,
|
||||
nblocksincl uint64,
|
||||
sender address.Address,
|
||||
gaslimit int64,
|
||||
_ types.TipSetKey,
|
||||
) (types.BigInt, error) {
|
||||
return gasEstimateGasPremium(a.Chain, nblocksincl)
|
||||
}
|
||||
func (m *GasModule) GasEstimateGasPremium(
|
||||
ctx context.Context,
|
||||
nblocksincl uint64,
|
||||
sender address.Address,
|
||||
gaslimit int64,
|
||||
_ types.TipSetKey,
|
||||
) (types.BigInt, error) {
|
||||
return gasEstimateGasPremium(m.Chain, nblocksincl)
|
||||
}
|
||||
func gasEstimateGasPremium(cstore *store.ChainStore, nblocksincl uint64) (types.BigInt, error) {
|
||||
if nblocksincl == 0 {
|
||||
nblocksincl = 1
|
||||
}
|
||||
@@ -92,20 +142,20 @@ func (a *GasAPI) GasEstimateGasPremium(ctx context.Context, nblocksincl uint64,
|
||||
var prices []gasMeta
|
||||
var blocks int
|
||||
|
||||
ts := a.Chain.GetHeaviestTipSet()
|
||||
ts := cstore.GetHeaviestTipSet()
|
||||
for i := uint64(0); i < nblocksincl*2; i++ {
|
||||
if ts.Height() == 0 {
|
||||
break // genesis
|
||||
}
|
||||
|
||||
pts, err := a.Chain.LoadTipSet(ts.Parents())
|
||||
pts, err := cstore.LoadTipSet(ts.Parents())
|
||||
if err != nil {
|
||||
return types.BigInt{}, err
|
||||
}
|
||||
|
||||
blocks += len(pts.Blocks())
|
||||
|
||||
msgs, err := a.Chain.MessagesForTipset(pts)
|
||||
msgs, err := cstore.MessagesForTipset(pts)
|
||||
if err != nil {
|
||||
return types.BigInt{}, xerrors.Errorf("loading messages: %w", err)
|
||||
}
|
||||
@@ -142,19 +192,30 @@ func (a *GasAPI) GasEstimateGasPremium(ctx context.Context, nblocksincl uint64,
|
||||
}
|
||||
|
||||
func (a *GasAPI) GasEstimateGasLimit(ctx context.Context, msgIn *types.Message, _ types.TipSetKey) (int64, error) {
|
||||
|
||||
return gasEstimateGasLimit(ctx, a.Chain, a.Stmgr, a.Mpool, msgIn)
|
||||
}
|
||||
func (m *GasModule) GasEstimateGasLimit(ctx context.Context, msgIn *types.Message, _ types.TipSetKey) (int64, error) {
|
||||
return gasEstimateGasLimit(ctx, m.Chain, m.Stmgr, m.Mpool, msgIn)
|
||||
}
|
||||
func gasEstimateGasLimit(
|
||||
ctx context.Context,
|
||||
cstore *store.ChainStore,
|
||||
smgr *stmgr.StateManager,
|
||||
mpool *messagepool.MessagePool,
|
||||
msgIn *types.Message,
|
||||
) (int64, error) {
|
||||
msg := *msgIn
|
||||
msg.GasLimit = build.BlockGasLimit
|
||||
msg.GasFeeCap = types.NewInt(uint64(build.MinimumBaseFee) + 1)
|
||||
msg.GasPremium = types.NewInt(1)
|
||||
|
||||
currTs := a.Chain.GetHeaviestTipSet()
|
||||
fromA, err := a.Stmgr.ResolveToKeyAddress(ctx, msgIn.From, currTs)
|
||||
currTs := cstore.GetHeaviestTipSet()
|
||||
fromA, err := smgr.ResolveToKeyAddress(ctx, msgIn.From, currTs)
|
||||
if err != nil {
|
||||
return -1, xerrors.Errorf("getting key address: %w", err)
|
||||
}
|
||||
|
||||
pending, ts := a.Mpool.PendingFor(fromA)
|
||||
pending, ts := mpool.PendingFor(fromA)
|
||||
priorMsgs := make([]types.ChainMsg, 0, len(pending))
|
||||
for _, m := range pending {
|
||||
priorMsgs = append(priorMsgs, m)
|
||||
@@ -163,11 +224,11 @@ func (a *GasAPI) GasEstimateGasLimit(ctx context.Context, msgIn *types.Message,
|
||||
// Try calling until we find a height with no migration.
|
||||
var res *api.InvocResult
|
||||
for {
|
||||
res, err = a.Stmgr.CallWithGas(ctx, &msg, priorMsgs, ts)
|
||||
res, err = smgr.CallWithGas(ctx, &msg, priorMsgs, ts)
|
||||
if err != stmgr.ErrExpensiveFork {
|
||||
break
|
||||
}
|
||||
ts, err = a.Chain.GetTipSetFromKey(ts.Parents())
|
||||
ts, err = cstore.GetTipSetFromKey(ts.Parents())
|
||||
if err != nil {
|
||||
return -1, xerrors.Errorf("getting parent tipset: %w", err)
|
||||
}
|
||||
@@ -180,7 +241,7 @@ func (a *GasAPI) GasEstimateGasLimit(ctx context.Context, msgIn *types.Message,
|
||||
}
|
||||
|
||||
// Special case for PaymentChannel collect, which is deleting actor
|
||||
st, err := a.Stmgr.ParentState(ts)
|
||||
st, err := smgr.ParentState(ts)
|
||||
if err != nil {
|
||||
_ = err
|
||||
// somewhat ignore it as it can happen and we just want to detect
|
||||
@@ -206,17 +267,17 @@ func (a *GasAPI) GasEstimateGasLimit(ctx context.Context, msgIn *types.Message,
|
||||
return res.MsgRct.GasUsed + 76e3, nil
|
||||
}
|
||||
|
||||
func (a *GasAPI) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, _ types.TipSetKey) (*types.Message, error) {
|
||||
func (m *GasModule) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, _ types.TipSetKey) (*types.Message, error) {
|
||||
if msg.GasLimit == 0 {
|
||||
gasLimit, err := a.GasEstimateGasLimit(ctx, msg, types.TipSetKey{})
|
||||
gasLimit, err := m.GasEstimateGasLimit(ctx, msg, types.TipSetKey{})
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("estimating gas used: %w", err)
|
||||
}
|
||||
msg.GasLimit = int64(float64(gasLimit) * a.Mpool.GetConfig().GasLimitOverestimation)
|
||||
msg.GasLimit = int64(float64(gasLimit) * m.Mpool.GetConfig().GasLimitOverestimation)
|
||||
}
|
||||
|
||||
if msg.GasPremium == types.EmptyInt || types.BigCmp(msg.GasPremium, types.NewInt(0)) == 0 {
|
||||
gasPremium, err := a.GasEstimateGasPremium(ctx, 2, msg.From, msg.GasLimit, types.TipSetKey{})
|
||||
gasPremium, err := m.GasEstimateGasPremium(ctx, 2, msg.From, msg.GasLimit, types.TipSetKey{})
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("estimating gas price: %w", err)
|
||||
}
|
||||
@@ -224,7 +285,7 @@ func (a *GasAPI) GasEstimateMessageGas(ctx context.Context, msg *types.Message,
|
||||
}
|
||||
|
||||
if msg.GasFeeCap == types.EmptyInt || types.BigCmp(msg.GasFeeCap, types.NewInt(0)) == 0 {
|
||||
feeCap, err := a.GasEstimateFeeCap(ctx, msg, 20, types.EmptyTSK)
|
||||
feeCap, err := m.GasEstimateFeeCap(ctx, msg, 20, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("estimating fee cap: %w", err)
|
||||
}
|
||||
|
||||
+21
-3
@@ -10,14 +10,32 @@ import (
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/messagepool"
|
||||
"github.com/filecoin-project/lotus/chain/messagesigner"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||
)
|
||||
|
||||
type MpoolModuleAPI interface {
|
||||
MpoolPush(ctx context.Context, smsg *types.SignedMessage) (cid.Cid, error)
|
||||
}
|
||||
|
||||
// MpoolModule provides a default implementation of MpoolModuleAPI.
|
||||
// It can be swapped out with another implementation through Dependency
|
||||
// Injection (for example with a thin RPC client).
|
||||
type MpoolModule struct {
|
||||
fx.In
|
||||
|
||||
Mpool *messagepool.MessagePool
|
||||
}
|
||||
|
||||
var _ MpoolModuleAPI = (*MpoolModule)(nil)
|
||||
|
||||
type MpoolAPI struct {
|
||||
fx.In
|
||||
|
||||
MpoolModuleAPI
|
||||
|
||||
WalletAPI
|
||||
GasAPI
|
||||
|
||||
@@ -106,8 +124,8 @@ func (a *MpoolAPI) MpoolClear(ctx context.Context, local bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *MpoolAPI) MpoolPush(ctx context.Context, smsg *types.SignedMessage) (cid.Cid, error) {
|
||||
return a.Mpool.Push(smsg)
|
||||
func (m *MpoolModule) MpoolPush(ctx context.Context, smsg *types.SignedMessage) (cid.Cid, error) {
|
||||
return m.Mpool.Push(smsg)
|
||||
}
|
||||
|
||||
func (a *MpoolAPI) MpoolPushUntrusted(ctx context.Context, smsg *types.SignedMessage) (cid.Cid, error) {
|
||||
@@ -162,7 +180,7 @@ func (a *MpoolAPI) MpoolPushMessage(ctx context.Context, msg *types.Message, spe
|
||||
|
||||
// Sign and push the message
|
||||
return a.MessageSigner.SignMessage(ctx, msg, func(smsg *types.SignedMessage) error {
|
||||
if _, err := a.Mpool.Push(smsg); err != nil {
|
||||
if _, err := a.MpoolModuleAPI.MpoolPush(ctx, smsg); err != nil {
|
||||
return xerrors.Errorf("mpool push: failed to push message: %w", err)
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -23,9 +23,8 @@ import (
|
||||
type MsigAPI struct {
|
||||
fx.In
|
||||
|
||||
WalletAPI WalletAPI
|
||||
StateAPI StateAPI
|
||||
MpoolAPI MpoolAPI
|
||||
StateAPI StateAPI
|
||||
MpoolAPI MpoolAPI
|
||||
}
|
||||
|
||||
func (a *MsigAPI) messageBuilder(ctx context.Context, from address.Address) (multisig.MessageBuilder, error) {
|
||||
|
||||
+106
-39
@@ -5,14 +5,6 @@ import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin"
|
||||
"github.com/filecoin-project/lotus/chain/actors/policy"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/verifreg"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/dline"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
|
||||
cid "github.com/ipfs/go-cid"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
"go.uber.org/fx"
|
||||
@@ -22,14 +14,19 @@ import (
|
||||
"github.com/filecoin-project/go-bitfield"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"github.com/filecoin-project/go-state-types/dline"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/multisig"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/power"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/reward"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/verifreg"
|
||||
"github.com/filecoin-project/lotus/chain/actors/policy"
|
||||
"github.com/filecoin-project/lotus/chain/beacon"
|
||||
"github.com/filecoin-project/lotus/chain/gen"
|
||||
"github.com/filecoin-project/lotus/chain/state"
|
||||
@@ -42,12 +39,36 @@ import (
|
||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||
)
|
||||
|
||||
type StateModuleAPI interface {
|
||||
StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
||||
StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error)
|
||||
StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
||||
StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error)
|
||||
MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
|
||||
MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error)
|
||||
}
|
||||
|
||||
// StateModule provides a default implementation of StateModuleAPI.
|
||||
// It can be swapped out with another implementation through Dependency
|
||||
// Injection (for example with a thin RPC client).
|
||||
type StateModule struct {
|
||||
fx.In
|
||||
|
||||
StateManager *stmgr.StateManager
|
||||
Chain *store.ChainStore
|
||||
}
|
||||
|
||||
var _ StateModuleAPI = (*StateModule)(nil)
|
||||
|
||||
type StateAPI struct {
|
||||
fx.In
|
||||
|
||||
// TODO: the wallet here is only needed because we have the MinerCreateBlock
|
||||
// API attached to the state API. It probably should live somewhere better
|
||||
Wallet *wallet.Wallet
|
||||
Wallet api.WalletAPI
|
||||
DefWallet wallet.Default
|
||||
|
||||
StateModuleAPI
|
||||
|
||||
ProofVerifier ffiwrapper.Verifier
|
||||
StateManager *stmgr.StateManager
|
||||
@@ -349,27 +370,33 @@ func (a *StateAPI) StateReplay(ctx context.Context, tsk types.TipSetKey, mc cid.
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *StateAPI) stateForTs(ctx context.Context, ts *types.TipSet) (*state.StateTree, error) {
|
||||
func stateForTs(ctx context.Context, ts *types.TipSet, cstore *store.ChainStore, smgr *stmgr.StateManager) (*state.StateTree, error) {
|
||||
if ts == nil {
|
||||
ts = a.Chain.GetHeaviestTipSet()
|
||||
ts = cstore.GetHeaviestTipSet()
|
||||
}
|
||||
|
||||
st, _, err := a.StateManager.TipSetState(ctx, ts)
|
||||
st, _, err := smgr.TipSetState(ctx, ts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
buf := bufbstore.NewBufferedBstore(a.Chain.Blockstore())
|
||||
buf := bufbstore.NewBufferedBstore(cstore.Blockstore())
|
||||
cst := cbor.NewCborStore(buf)
|
||||
return state.LoadStateTree(cst, st)
|
||||
}
|
||||
func (a *StateAPI) stateForTs(ctx context.Context, ts *types.TipSet) (*state.StateTree, error) {
|
||||
return stateForTs(ctx, ts, a.Chain, a.StateManager)
|
||||
}
|
||||
func (m *StateModule) stateForTs(ctx context.Context, ts *types.TipSet) (*state.StateTree, error) {
|
||||
return stateForTs(ctx, ts, m.Chain, m.StateManager)
|
||||
}
|
||||
|
||||
func (a *StateAPI) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) {
|
||||
ts, err := a.Chain.GetTipSetFromKey(tsk)
|
||||
func (m *StateModule) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) {
|
||||
ts, err := m.Chain.GetTipSetFromKey(tsk)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
||||
}
|
||||
state, err := a.stateForTs(ctx, ts)
|
||||
state, err := m.stateForTs(ctx, ts)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("computing tipset state failed: %w", err)
|
||||
}
|
||||
@@ -377,26 +404,22 @@ func (a *StateAPI) StateGetActor(ctx context.Context, actor address.Address, tsk
|
||||
return state.GetActor(actor)
|
||||
}
|
||||
|
||||
func (a *StateAPI) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
|
||||
ts, err := a.Chain.GetTipSetFromKey(tsk)
|
||||
func (m *StateModule) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
|
||||
ts, err := m.Chain.GetTipSetFromKey(tsk)
|
||||
if err != nil {
|
||||
return address.Undef, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
||||
}
|
||||
state, err := a.stateForTs(ctx, ts)
|
||||
if err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
|
||||
return state.LookupID(addr)
|
||||
return m.StateManager.LookupID(ctx, addr, ts)
|
||||
}
|
||||
|
||||
func (a *StateAPI) StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
|
||||
ts, err := a.Chain.GetTipSetFromKey(tsk)
|
||||
func (m *StateModule) StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
|
||||
ts, err := m.Chain.GetTipSetFromKey(tsk)
|
||||
if err != nil {
|
||||
return address.Undef, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
||||
}
|
||||
|
||||
return a.StateManager.ResolveToKeyAddress(ctx, addr, ts)
|
||||
return m.StateManager.ResolveToKeyAddress(ctx, addr, ts)
|
||||
}
|
||||
|
||||
func (a *StateAPI) StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*api.ActorState, error) {
|
||||
@@ -453,22 +476,28 @@ func (a *StateAPI) MinerCreateBlock(ctx context.Context, bt *api.BlockTemplate)
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
func (a *StateAPI) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error) {
|
||||
ts, recpt, found, err := a.StateManager.WaitForMessage(ctx, msg, confidence)
|
||||
func (m *StateModule) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error) {
|
||||
return stateWaitMsgLimited(ctx, m.StateManager, m.Chain, msg, confidence, stmgr.LookbackNoLimit)
|
||||
}
|
||||
func (a *StateAPI) StateWaitMsgLimited(ctx context.Context, msg cid.Cid, confidence uint64, lookbackLimit abi.ChainEpoch) (*api.MsgLookup, error) {
|
||||
return stateWaitMsgLimited(ctx, a.StateManager, a.Chain, msg, confidence, lookbackLimit)
|
||||
}
|
||||
func stateWaitMsgLimited(ctx context.Context, smgr *stmgr.StateManager, cstore *store.ChainStore, msg cid.Cid, confidence uint64, lookbackLimit abi.ChainEpoch) (*api.MsgLookup, error) {
|
||||
ts, recpt, found, err := smgr.WaitForMessage(ctx, msg, confidence, lookbackLimit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var returndec interface{}
|
||||
if recpt.ExitCode == 0 && len(recpt.Return) > 0 {
|
||||
cmsg, err := a.Chain.GetCMessage(msg)
|
||||
cmsg, err := cstore.GetCMessage(msg)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to load message after successful receipt search: %w", err)
|
||||
}
|
||||
|
||||
vmsg := cmsg.VMMessage()
|
||||
|
||||
t, err := stmgr.GetReturnType(ctx, a.StateManager, vmsg.To, vmsg.Method, ts)
|
||||
t, err := stmgr.GetReturnType(ctx, smgr, vmsg.To, vmsg.Method, ts)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to get return type: %w", err)
|
||||
}
|
||||
@@ -799,17 +828,17 @@ func (a *StateAPI) StateCompute(ctx context.Context, height abi.ChainEpoch, msgs
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *StateAPI) MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) {
|
||||
ts, err := a.Chain.GetTipSetFromKey(tsk)
|
||||
func (m *StateModule) MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) {
|
||||
ts, err := m.Chain.GetTipSetFromKey(tsk)
|
||||
if err != nil {
|
||||
return types.EmptyInt, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
||||
}
|
||||
|
||||
act, err := a.StateManager.LoadActor(ctx, addr, ts)
|
||||
act, err := m.StateManager.LoadActor(ctx, addr, ts)
|
||||
if err != nil {
|
||||
return types.EmptyInt, xerrors.Errorf("failed to load multisig actor: %w", err)
|
||||
}
|
||||
msas, err := multisig.Load(a.Chain.Store(ctx), act)
|
||||
msas, err := multisig.Load(m.Chain.Store(ctx), act)
|
||||
if err != nil {
|
||||
return types.EmptyInt, xerrors.Errorf("failed to load multisig actor state: %w", err)
|
||||
}
|
||||
@@ -820,13 +849,51 @@ func (a *StateAPI) MsigGetAvailableBalance(ctx context.Context, addr address.Add
|
||||
return types.BigSub(act.Balance, locked), nil
|
||||
}
|
||||
|
||||
func (a *StateAPI) MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error) {
|
||||
startTs, err := a.Chain.GetTipSetFromKey(start)
|
||||
func (a *StateAPI) MsigGetVestingSchedule(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MsigVesting, error) {
|
||||
ts, err := a.Chain.GetTipSetFromKey(tsk)
|
||||
if err != nil {
|
||||
return api.EmptyVesting, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
||||
}
|
||||
|
||||
act, err := a.StateManager.LoadActor(ctx, addr, ts)
|
||||
if err != nil {
|
||||
return api.EmptyVesting, xerrors.Errorf("failed to load multisig actor: %w", err)
|
||||
}
|
||||
|
||||
msas, err := multisig.Load(a.Chain.Store(ctx), act)
|
||||
if err != nil {
|
||||
return api.EmptyVesting, xerrors.Errorf("failed to load multisig actor state: %w", err)
|
||||
}
|
||||
|
||||
ib, err := msas.InitialBalance()
|
||||
if err != nil {
|
||||
return api.EmptyVesting, xerrors.Errorf("failed to load multisig initial balance: %w", err)
|
||||
}
|
||||
|
||||
se, err := msas.StartEpoch()
|
||||
if err != nil {
|
||||
return api.EmptyVesting, xerrors.Errorf("failed to load multisig start epoch: %w", err)
|
||||
}
|
||||
|
||||
ud, err := msas.UnlockDuration()
|
||||
if err != nil {
|
||||
return api.EmptyVesting, xerrors.Errorf("failed to load multisig unlock duration: %w", err)
|
||||
}
|
||||
|
||||
return api.MsigVesting{
|
||||
InitialBalance: ib,
|
||||
StartEpoch: se,
|
||||
UnlockDuration: ud,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *StateModule) MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error) {
|
||||
startTs, err := m.Chain.GetTipSetFromKey(start)
|
||||
if err != nil {
|
||||
return types.EmptyInt, xerrors.Errorf("loading start tipset %s: %w", start, err)
|
||||
}
|
||||
|
||||
endTs, err := a.Chain.GetTipSetFromKey(end)
|
||||
endTs, err := m.Chain.GetTipSetFromKey(end)
|
||||
if err != nil {
|
||||
return types.EmptyInt, xerrors.Errorf("loading end tipset %s: %w", end, err)
|
||||
}
|
||||
@@ -837,12 +904,12 @@ func (a *StateAPI) MsigGetVested(ctx context.Context, addr address.Address, star
|
||||
return big.Zero(), nil
|
||||
}
|
||||
|
||||
act, err := a.StateManager.LoadActor(ctx, addr, endTs)
|
||||
act, err := m.StateManager.LoadActor(ctx, addr, endTs)
|
||||
if err != nil {
|
||||
return types.EmptyInt, xerrors.Errorf("failed to load multisig actor at end epoch: %w", err)
|
||||
}
|
||||
|
||||
msas, err := multisig.Load(a.Chain.Store(ctx), act)
|
||||
msas, err := multisig.Load(m.Chain.Store(ctx), act)
|
||||
if err != nil {
|
||||
return types.EmptyInt, xerrors.Errorf("failed to load multisig actor state: %w", err)
|
||||
}
|
||||
|
||||
+25
-34
@@ -3,13 +3,14 @@ package full
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"go.uber.org/fx"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/wallet"
|
||||
@@ -19,24 +20,13 @@ import (
|
||||
type WalletAPI struct {
|
||||
fx.In
|
||||
|
||||
StateManager *stmgr.StateManager
|
||||
Wallet *wallet.Wallet
|
||||
}
|
||||
|
||||
func (a *WalletAPI) WalletNew(ctx context.Context, typ crypto.SigType) (address.Address, error) {
|
||||
return a.Wallet.GenerateKey(typ)
|
||||
}
|
||||
|
||||
func (a *WalletAPI) WalletHas(ctx context.Context, addr address.Address) (bool, error) {
|
||||
return a.Wallet.HasKey(addr)
|
||||
}
|
||||
|
||||
func (a *WalletAPI) WalletList(ctx context.Context) ([]address.Address, error) {
|
||||
return a.Wallet.ListAddrs()
|
||||
StateManagerAPI stmgr.StateManagerAPI
|
||||
Default wallet.Default
|
||||
api.WalletAPI
|
||||
}
|
||||
|
||||
func (a *WalletAPI) WalletBalance(ctx context.Context, addr address.Address) (types.BigInt, error) {
|
||||
act, err := a.StateManager.LoadActorTsk(ctx, addr, types.EmptyTSK)
|
||||
act, err := a.StateManagerAPI.LoadActorTsk(ctx, addr, types.EmptyTSK)
|
||||
if xerrors.Is(err, types.ErrActorNotFound) {
|
||||
return big.Zero(), nil
|
||||
} else if err != nil {
|
||||
@@ -46,17 +36,30 @@ func (a *WalletAPI) WalletBalance(ctx context.Context, addr address.Address) (ty
|
||||
}
|
||||
|
||||
func (a *WalletAPI) WalletSign(ctx context.Context, k address.Address, msg []byte) (*crypto.Signature, error) {
|
||||
keyAddr, err := a.StateManager.ResolveToKeyAddress(ctx, k, nil)
|
||||
keyAddr, err := a.StateManagerAPI.ResolveToKeyAddress(ctx, k, nil)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to resolve ID address: %w", keyAddr)
|
||||
}
|
||||
return a.Wallet.Sign(ctx, keyAddr, msg)
|
||||
return a.WalletAPI.WalletSign(ctx, keyAddr, msg, api.MsgMeta{
|
||||
Type: api.MTUnknown,
|
||||
})
|
||||
}
|
||||
|
||||
func (a *WalletAPI) WalletSignMessage(ctx context.Context, k address.Address, msg *types.Message) (*types.SignedMessage, error) {
|
||||
mcid := msg.Cid()
|
||||
keyAddr, err := a.StateManagerAPI.ResolveToKeyAddress(ctx, k, nil)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to resolve ID address: %w", keyAddr)
|
||||
}
|
||||
|
||||
sig, err := a.WalletSign(ctx, k, mcid.Bytes())
|
||||
mb, err := msg.ToStorageBlock()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("serializing message: %w", err)
|
||||
}
|
||||
|
||||
sig, err := a.WalletAPI.WalletSign(ctx, k, mb.Cid().Bytes(), api.MsgMeta{
|
||||
Type: api.MTChainMsg,
|
||||
Extra: mb.RawData(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to sign message: %w", err)
|
||||
}
|
||||
@@ -72,23 +75,11 @@ func (a *WalletAPI) WalletVerify(ctx context.Context, k address.Address, msg []b
|
||||
}
|
||||
|
||||
func (a *WalletAPI) WalletDefaultAddress(ctx context.Context) (address.Address, error) {
|
||||
return a.Wallet.GetDefault()
|
||||
return a.Default.GetDefault()
|
||||
}
|
||||
|
||||
func (a *WalletAPI) WalletSetDefault(ctx context.Context, addr address.Address) error {
|
||||
return a.Wallet.SetDefault(addr)
|
||||
}
|
||||
|
||||
func (a *WalletAPI) WalletExport(ctx context.Context, addr address.Address) (*types.KeyInfo, error) {
|
||||
return a.Wallet.Export(addr)
|
||||
}
|
||||
|
||||
func (a *WalletAPI) WalletImport(ctx context.Context, ki *types.KeyInfo) (address.Address, error) {
|
||||
return a.Wallet.Import(ki)
|
||||
}
|
||||
|
||||
func (a *WalletAPI) WalletDelete(ctx context.Context, addr address.Address) error {
|
||||
return a.Wallet.DeleteKey(addr)
|
||||
return a.Default.SetDefault(addr)
|
||||
}
|
||||
|
||||
func (a *WalletAPI) WalletValidateAddress(ctx context.Context, str string) (address.Address, error) {
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
|
||||
"github.com/filecoin-project/lotus/journal"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain"
|
||||
@@ -51,9 +52,9 @@ func ChainBitswap(mctx helpers.MetricsCtx, lc fx.Lifecycle, host host.Host, rt r
|
||||
return exch
|
||||
}
|
||||
|
||||
func MessagePool(lc fx.Lifecycle, sm *stmgr.StateManager, ps *pubsub.PubSub, ds dtypes.MetadataDS, nn dtypes.NetworkName) (*messagepool.MessagePool, error) {
|
||||
func MessagePool(lc fx.Lifecycle, sm *stmgr.StateManager, ps *pubsub.PubSub, ds dtypes.MetadataDS, nn dtypes.NetworkName, j journal.Journal) (*messagepool.MessagePool, error) {
|
||||
mpp := messagepool.NewProvider(sm, ps)
|
||||
mp, err := messagepool.New(mpp, ds, nn)
|
||||
mp, err := messagepool.New(mpp, ds, nn, j)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("constructing mpool: %w", err)
|
||||
}
|
||||
@@ -88,8 +89,8 @@ func ChainBlockService(bs dtypes.ChainBlockstore, rem dtypes.ChainBitswap) dtype
|
||||
return blockservice.New(bs, rem)
|
||||
}
|
||||
|
||||
func ChainStore(lc fx.Lifecycle, bs dtypes.ChainBlockstore, ds dtypes.MetadataDS, syscalls vm.SyscallBuilder) *store.ChainStore {
|
||||
chain := store.NewChainStore(bs, ds, syscalls)
|
||||
func ChainStore(lc fx.Lifecycle, bs dtypes.ChainBlockstore, ds dtypes.MetadataDS, syscalls vm.SyscallBuilder, j journal.Journal) *store.ChainStore {
|
||||
chain := store.NewChainStore(bs, ds, syscalls, j)
|
||||
|
||||
if err := chain.Load(); err != nil {
|
||||
log.Warnf("loading chain state from disk: %s", err)
|
||||
|
||||
@@ -113,7 +113,7 @@ func NewClientDealFunds(ds dtypes.MetadataDS) (ClientDealFunds, error) {
|
||||
return funds.NewDealFunds(ds, datastore.NewKey("/marketfunds/client"))
|
||||
}
|
||||
|
||||
func StorageClient(lc fx.Lifecycle, h host.Host, ibs dtypes.ClientBlockstore, mds dtypes.ClientMultiDstore, r repo.LockedRepo, dataTransfer dtypes.ClientDataTransfer, discovery *discoveryimpl.Local, deals dtypes.ClientDatastore, scn storagemarket.StorageClientNode, dealFunds ClientDealFunds) (storagemarket.StorageClient, error) {
|
||||
func StorageClient(lc fx.Lifecycle, h host.Host, ibs dtypes.ClientBlockstore, mds dtypes.ClientMultiDstore, r repo.LockedRepo, dataTransfer dtypes.ClientDataTransfer, discovery *discoveryimpl.Local, deals dtypes.ClientDatastore, scn storagemarket.StorageClientNode, dealFunds ClientDealFunds, j journal.Journal) (storagemarket.StorageClient, error) {
|
||||
net := smnet.NewFromLibp2pHost(h)
|
||||
c, err := storageimpl.NewClient(net, ibs, mds, dataTransfer, discovery, deals, scn, dealFunds, storageimpl.DealPollingInterval(time.Second))
|
||||
if err != nil {
|
||||
@@ -124,8 +124,8 @@ func StorageClient(lc fx.Lifecycle, h host.Host, ibs dtypes.ClientBlockstore, md
|
||||
OnStart: func(ctx context.Context) error {
|
||||
c.SubscribeToEvents(marketevents.StorageClientLogger)
|
||||
|
||||
evtType := journal.J.RegisterEventType("markets/storage/client", "state_change")
|
||||
c.SubscribeToEvents(markets.StorageClientJournaler(evtType))
|
||||
evtType := j.RegisterEventType("markets/storage/client", "state_change")
|
||||
c.SubscribeToEvents(markets.StorageClientJournaler(j, evtType))
|
||||
|
||||
return c.Start(ctx)
|
||||
},
|
||||
@@ -137,7 +137,7 @@ func StorageClient(lc fx.Lifecycle, h host.Host, ibs dtypes.ClientBlockstore, md
|
||||
}
|
||||
|
||||
// RetrievalClient creates a new retrieval client attached to the client blockstore
|
||||
func RetrievalClient(lc fx.Lifecycle, h host.Host, mds dtypes.ClientMultiDstore, dt dtypes.ClientDataTransfer, payAPI payapi.PaychAPI, resolver discovery.PeerResolver, ds dtypes.MetadataDS, chainAPI full.ChainAPI, stateAPI full.StateAPI) (retrievalmarket.RetrievalClient, error) {
|
||||
func RetrievalClient(lc fx.Lifecycle, h host.Host, mds dtypes.ClientMultiDstore, dt dtypes.ClientDataTransfer, payAPI payapi.PaychAPI, resolver discovery.PeerResolver, ds dtypes.MetadataDS, chainAPI full.ChainAPI, stateAPI full.StateAPI, j journal.Journal) (retrievalmarket.RetrievalClient, error) {
|
||||
adapter := retrievaladapter.NewRetrievalClientNode(payAPI, chainAPI, stateAPI)
|
||||
network := rmnet.NewFromLibp2pHost(h)
|
||||
sc := storedcounter.New(ds, datastore.NewKey("/retr"))
|
||||
@@ -150,8 +150,8 @@ func RetrievalClient(lc fx.Lifecycle, h host.Host, mds dtypes.ClientMultiDstore,
|
||||
OnStart: func(ctx context.Context) error {
|
||||
client.SubscribeToEvents(marketevents.RetrievalClientLogger)
|
||||
|
||||
evtType := journal.J.RegisterEventType("markets/retrieval/client", "state_change")
|
||||
client.SubscribeToEvents(markets.RetrievalClientJournaler(evtType))
|
||||
evtType := j.RegisterEventType("markets/retrieval/client", "state_change")
|
||||
client.SubscribeToEvents(markets.RetrievalClientJournaler(j, evtType))
|
||||
|
||||
return client.Start(ctx)
|
||||
},
|
||||
|
||||
+18
-10
@@ -187,6 +187,7 @@ func GossipSub(in GossipIn) (service *pubsub.PubSub, err error) {
|
||||
build.MessagesTopic(in.Nn): 1,
|
||||
}
|
||||
|
||||
var drandTopics []string
|
||||
for _, d := range in.Dr {
|
||||
topic, err := getDrandTopic(d.Config.ChainInfoJSON)
|
||||
if err != nil {
|
||||
@@ -194,6 +195,7 @@ func GossipSub(in GossipIn) (service *pubsub.PubSub, err error) {
|
||||
}
|
||||
topicParams[topic] = drandTopicParams
|
||||
pgTopicWeights[topic] = 5
|
||||
drandTopics = append(drandTopics, topic)
|
||||
}
|
||||
|
||||
options := []pubsub.Option{
|
||||
@@ -309,6 +311,17 @@ func GossipSub(in GossipIn) (service *pubsub.PubSub, err error) {
|
||||
|
||||
options = append(options, pubsub.WithPeerGater(pgParams))
|
||||
|
||||
allowTopics := []string{
|
||||
build.BlocksTopic(in.Nn),
|
||||
build.MessagesTopic(in.Nn),
|
||||
}
|
||||
allowTopics = append(allowTopics, drandTopics...)
|
||||
options = append(options,
|
||||
pubsub.WithSubscriptionFilter(
|
||||
pubsub.WrapLimitSubscriptionFilter(
|
||||
pubsub.NewAllowlistSubscriptionFilter(allowTopics...),
|
||||
100)))
|
||||
|
||||
// tracer
|
||||
if in.Cfg.RemoteTracer != "" {
|
||||
a, err := ma.NewMultiaddr(in.Cfg.RemoteTracer)
|
||||
@@ -359,14 +372,9 @@ type tracerWrapper struct {
|
||||
topics map[string]struct{}
|
||||
}
|
||||
|
||||
func (trw *tracerWrapper) traceMessage(topics []string) bool {
|
||||
for _, topic := range topics {
|
||||
_, ok := trw.topics[topic]
|
||||
if ok {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
func (trw *tracerWrapper) traceMessage(topic string) bool {
|
||||
_, ok := trw.topics[topic]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (trw *tracerWrapper) Trace(evt *pubsub_pb.TraceEvent) {
|
||||
@@ -379,12 +387,12 @@ func (trw *tracerWrapper) Trace(evt *pubsub_pb.TraceEvent) {
|
||||
switch evt.GetType() {
|
||||
case pubsub_pb.TraceEvent_PUBLISH_MESSAGE:
|
||||
stats.Record(context.TODO(), metrics.PubsubPublishMessage.M(1))
|
||||
if trw.tr != nil && trw.traceMessage(evt.GetPublishMessage().Topics) {
|
||||
if trw.tr != nil && trw.traceMessage(evt.GetPublishMessage().GetTopic()) {
|
||||
trw.tr.Trace(evt)
|
||||
}
|
||||
case pubsub_pb.TraceEvent_DELIVER_MESSAGE:
|
||||
stats.Record(context.TODO(), metrics.PubsubDeliverMessage.M(1))
|
||||
if trw.tr != nil && trw.traceMessage(evt.GetDeliverMessage().Topics) {
|
||||
if trw.tr != nil && trw.traceMessage(evt.GetDeliverMessage().GetTopic()) {
|
||||
trw.tr.Trace(evt)
|
||||
}
|
||||
case pubsub_pb.TraceEvent_REJECT_MESSAGE:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user