Merge pull request #5822 from filecoin-project/epic/robust-message-management

Robust message management
This commit is contained in:
Aayush Rajasekaran 2021-05-10 19:58:33 -04:00 committed by GitHub
commit 8465a97c4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
49 changed files with 2709 additions and 484 deletions

View File

@ -252,6 +252,13 @@ type FullNode interface {
// MpoolBatchPushMessage batch pushes a unsigned message to mempool.
MpoolBatchPushMessage(context.Context, []*types.Message, *MessageSendSpec) ([]*types.SignedMessage, error) //perm:sign
// MpoolCheckMessages performs logical checks on a batch of messages
MpoolCheckMessages(context.Context, []*MessagePrototype) ([][]MessageCheckStatus, error) //perm:read
// MpoolCheckPendingMessages performs logical checks for all pending messages from a given address
MpoolCheckPendingMessages(context.Context, address.Address) ([][]MessageCheckStatus, error) //perm:read
// MpoolCheckReplaceMessages performs logical checks on pending messages with replacement
MpoolCheckReplaceMessages(context.Context, []*types.Message) ([][]MessageCheckStatus, error) //perm:read
// MpoolGetNonce gets next nonce for the specified sender.
// Note that this method may not be atomic. Use MpoolPushMessage instead.
MpoolGetNonce(context.Context, address.Address) (uint64, error) //perm:read
@ -579,15 +586,16 @@ type FullNode interface {
// MsigCreate creates a multisig wallet
// It takes the following params: <required number of senders>, <approving addresses>, <unlock duration>
//<initial balance>, <sender address of the create msg>, <gas price>
MsigCreate(context.Context, uint64, []address.Address, abi.ChainEpoch, types.BigInt, address.Address, types.BigInt) (cid.Cid, error) //perm:sign
MsigCreate(context.Context, uint64, []address.Address, abi.ChainEpoch, types.BigInt, address.Address, types.BigInt) (*MessagePrototype, error) //perm:sign
// MsigPropose proposes a multisig message
// It takes the following params: <multisig address>, <recipient address>, <value to transfer>,
// <sender address of the propose msg>, <method to call in the proposed message>, <params to include in the proposed message>
MsigPropose(context.Context, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) //perm:sign
MsigPropose(context.Context, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (*MessagePrototype, error) //perm:sign
// MsigApprove approves a previously-proposed multisig message by transaction ID
// It takes the following params: <multisig address>, <proposed transaction ID> <signer address>
MsigApprove(context.Context, address.Address, uint64, address.Address) (cid.Cid, error) //perm:sign
MsigApprove(context.Context, address.Address, uint64, address.Address) (*MessagePrototype, error) //perm:sign
// MsigApproveTxnHash approves a previously-proposed multisig message, specified
// using both transaction ID and a hash of the parameters used in the
@ -595,43 +603,49 @@ type FullNode interface {
// exactly the transaction you think you are.
// It takes the following params: <multisig address>, <proposed message ID>, <proposer address>, <recipient address>, <value to transfer>,
// <sender address of the approve msg>, <method to call in the proposed message>, <params to include in the proposed message>
MsigApproveTxnHash(context.Context, address.Address, uint64, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) //perm:sign
MsigApproveTxnHash(context.Context, address.Address, uint64, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (*MessagePrototype, error) //perm:sign
// MsigCancel cancels a previously-proposed multisig message
// It takes the following params: <multisig address>, <proposed transaction ID>, <recipient address>, <value to transfer>,
// <sender address of the cancel msg>, <method to call in the proposed message>, <params to include in the proposed message>
MsigCancel(context.Context, address.Address, uint64, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) //perm:sign
MsigCancel(context.Context, address.Address, uint64, address.Address, types.BigInt, address.Address, uint64, []byte) (*MessagePrototype, error) //perm:sign
// MsigAddPropose proposes adding a signer in the multisig
// It takes the following params: <multisig address>, <sender address of the propose msg>,
// <new signer>, <whether the number of required signers should be increased>
MsigAddPropose(context.Context, address.Address, address.Address, address.Address, bool) (cid.Cid, error) //perm:sign
MsigAddPropose(context.Context, address.Address, address.Address, address.Address, bool) (*MessagePrototype, error) //perm:sign
// MsigAddApprove approves a previously proposed AddSigner message
// It takes the following params: <multisig address>, <sender address of the approve msg>, <proposed message ID>,
// <proposer address>, <new signer>, <whether the number of required signers should be increased>
MsigAddApprove(context.Context, address.Address, address.Address, uint64, address.Address, address.Address, bool) (cid.Cid, error) //perm:sign
MsigAddApprove(context.Context, address.Address, address.Address, uint64, address.Address, address.Address, bool) (*MessagePrototype, error) //perm:sign
// MsigAddCancel cancels a previously proposed AddSigner message
// It takes the following params: <multisig address>, <sender address of the cancel msg>, <proposed message ID>,
// <new signer>, <whether the number of required signers should be increased>
MsigAddCancel(context.Context, address.Address, address.Address, uint64, address.Address, bool) (cid.Cid, error) //perm:sign
MsigAddCancel(context.Context, address.Address, address.Address, uint64, address.Address, bool) (*MessagePrototype, error) //perm:sign
// MsigSwapPropose proposes swapping 2 signers in the multisig
// It takes the following params: <multisig address>, <sender address of the propose msg>,
// <old signer>, <new signer>
MsigSwapPropose(context.Context, address.Address, address.Address, address.Address, address.Address) (cid.Cid, error) //perm:sign
MsigSwapPropose(context.Context, address.Address, address.Address, address.Address, address.Address) (*MessagePrototype, error) //perm:sign
// MsigSwapApprove approves a previously proposed SwapSigner
// It takes the following params: <multisig address>, <sender address of the approve msg>, <proposed message ID>,
// <proposer address>, <old signer>, <new signer>
MsigSwapApprove(context.Context, address.Address, address.Address, uint64, address.Address, address.Address, address.Address) (cid.Cid, error) //perm:sign
MsigSwapApprove(context.Context, address.Address, address.Address, uint64, address.Address, address.Address, address.Address) (*MessagePrototype, error) //perm:sign
// MsigSwapCancel cancels a previously proposed SwapSigner message
// It takes the following params: <multisig address>, <sender address of the cancel msg>, <proposed message ID>,
// <old signer>, <new signer>
MsigSwapCancel(context.Context, address.Address, address.Address, uint64, address.Address, address.Address) (cid.Cid, error) //perm:sign
MsigSwapCancel(context.Context, address.Address, address.Address, uint64, address.Address, address.Address) (*MessagePrototype, error) //perm:sign
// MsigRemoveSigner proposes the removal of a signer from the multisig.
// It accepts the multisig to make the change on, the proposer address to
// send the message from, the address to be removed, and a boolean
// indicating whether or not the signing threshold should be lowered by one
// along with the address removal.
MsigRemoveSigner(ctx context.Context, msig address.Address, proposer address.Address, toRemove address.Address, decrease bool) (cid.Cid, error) //perm:sign
MsigRemoveSigner(ctx context.Context, msig address.Address, proposer address.Address, toRemove address.Address, decrease bool) (*MessagePrototype, error) //perm:sign
// MarketAddBalance adds funds to the market actor
MarketAddBalance(ctx context.Context, wallet, addr address.Address, amt types.BigInt) (cid.Cid, error) //perm:sign
@ -664,6 +678,11 @@ type FullNode interface {
PaychVoucherList(context.Context, address.Address) ([]*paych.SignedVoucher, error) //perm:write
PaychVoucherSubmit(context.Context, address.Address, *paych.SignedVoucher, []byte, []byte) (cid.Cid, error) //perm:sign
// MethodGroup: Node
// These methods are general node management and status commands
NodeStatus(ctx context.Context, inclChainStatus bool) (NodeStatus, error) //perm:read
// CreateBackup creates node backup onder the specified file name. The
// method requires that the lotus daemon is running with the
// LOTUS_BACKUP_BASE_PATH environment variable set to some path, and that

View File

@ -0,0 +1,35 @@
// Code generated by "stringer -type=CheckStatusCode -trimprefix=CheckStatus"; DO NOT EDIT.
package api
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[CheckStatusMessageSerialize-1]
_ = x[CheckStatusMessageSize-2]
_ = x[CheckStatusMessageValidity-3]
_ = x[CheckStatusMessageMinGas-4]
_ = x[CheckStatusMessageMinBaseFee-5]
_ = x[CheckStatusMessageBaseFee-6]
_ = x[CheckStatusMessageBaseFeeLowerBound-7]
_ = x[CheckStatusMessageBaseFeeUpperBound-8]
_ = x[CheckStatusMessageGetStateNonce-9]
_ = x[CheckStatusMessageNonce-10]
_ = x[CheckStatusMessageGetStateBalance-11]
_ = x[CheckStatusMessageBalance-12]
}
const _CheckStatusCode_name = "MessageSerializeMessageSizeMessageValidityMessageMinGasMessageMinBaseFeeMessageBaseFeeMessageBaseFeeLowerBoundMessageBaseFeeUpperBoundMessageGetStateNonceMessageNonceMessageGetStateBalanceMessageBalance"
var _CheckStatusCode_index = [...]uint8{0, 16, 27, 42, 55, 72, 86, 110, 134, 154, 166, 188, 202}
func (i CheckStatusCode) String() string {
i -= 1
if i < 0 || i >= CheckStatusCode(len(_CheckStatusCode_index)-1) {
return "CheckStatusCode(" + strconv.FormatInt(int64(i+1), 10) + ")"
}
return _CheckStatusCode_name[_CheckStatusCode_index[i]:_CheckStatusCode_index[i+1]]
}

View File

@ -261,6 +261,9 @@ func init() {
},
"methods": []interface{}{}},
)
addExample(api.CheckStatusCode(0))
addExample(map[string]interface{}{"abc": 123})
}
func GetAPIType(name, pkg string) (i interface{}, t, permStruct, commonPermStruct reflect.Type) {

View File

@ -1068,6 +1068,51 @@ func (mr *MockFullNodeMockRecorder) MpoolBatchPushUntrusted(arg0, arg1 interface
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MpoolBatchPushUntrusted", reflect.TypeOf((*MockFullNode)(nil).MpoolBatchPushUntrusted), arg0, arg1)
}
// MpoolCheckMessages mocks base method
func (m *MockFullNode) MpoolCheckMessages(arg0 context.Context, arg1 []*api.MessagePrototype) ([][]api.MessageCheckStatus, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MpoolCheckMessages", arg0, arg1)
ret0, _ := ret[0].([][]api.MessageCheckStatus)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// MpoolCheckMessages indicates an expected call of MpoolCheckMessages
func (mr *MockFullNodeMockRecorder) MpoolCheckMessages(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MpoolCheckMessages", reflect.TypeOf((*MockFullNode)(nil).MpoolCheckMessages), arg0, arg1)
}
// MpoolCheckPendingMessages mocks base method
func (m *MockFullNode) MpoolCheckPendingMessages(arg0 context.Context, arg1 address.Address) ([][]api.MessageCheckStatus, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MpoolCheckPendingMessages", arg0, arg1)
ret0, _ := ret[0].([][]api.MessageCheckStatus)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// MpoolCheckPendingMessages indicates an expected call of MpoolCheckPendingMessages
func (mr *MockFullNodeMockRecorder) MpoolCheckPendingMessages(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MpoolCheckPendingMessages", reflect.TypeOf((*MockFullNode)(nil).MpoolCheckPendingMessages), arg0, arg1)
}
// MpoolCheckReplaceMessages mocks base method
func (m *MockFullNode) MpoolCheckReplaceMessages(arg0 context.Context, arg1 []*types.Message) ([][]api.MessageCheckStatus, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MpoolCheckReplaceMessages", arg0, arg1)
ret0, _ := ret[0].([][]api.MessageCheckStatus)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// MpoolCheckReplaceMessages indicates an expected call of MpoolCheckReplaceMessages
func (mr *MockFullNodeMockRecorder) MpoolCheckReplaceMessages(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MpoolCheckReplaceMessages", reflect.TypeOf((*MockFullNode)(nil).MpoolCheckReplaceMessages), arg0, arg1)
}
// MpoolClear mocks base method
func (m *MockFullNode) MpoolClear(arg0 context.Context, arg1 bool) error {
m.ctrl.T.Helper()
@ -1217,10 +1262,10 @@ func (mr *MockFullNodeMockRecorder) MpoolSub(arg0 interface{}) *gomock.Call {
}
// MsigAddApprove mocks base method
func (m *MockFullNode) MsigAddApprove(arg0 context.Context, arg1, arg2 address.Address, arg3 uint64, arg4, arg5 address.Address, arg6 bool) (cid.Cid, error) {
func (m *MockFullNode) MsigAddApprove(arg0 context.Context, arg1, arg2 address.Address, arg3 uint64, arg4, arg5 address.Address, arg6 bool) (*api.MessagePrototype, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MsigAddApprove", arg0, arg1, arg2, arg3, arg4, arg5, arg6)
ret0, _ := ret[0].(cid.Cid)
ret0, _ := ret[0].(*api.MessagePrototype)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@ -1232,10 +1277,10 @@ func (mr *MockFullNodeMockRecorder) MsigAddApprove(arg0, arg1, arg2, arg3, arg4,
}
// MsigAddCancel mocks base method
func (m *MockFullNode) MsigAddCancel(arg0 context.Context, arg1, arg2 address.Address, arg3 uint64, arg4 address.Address, arg5 bool) (cid.Cid, error) {
func (m *MockFullNode) MsigAddCancel(arg0 context.Context, arg1, arg2 address.Address, arg3 uint64, arg4 address.Address, arg5 bool) (*api.MessagePrototype, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MsigAddCancel", arg0, arg1, arg2, arg3, arg4, arg5)
ret0, _ := ret[0].(cid.Cid)
ret0, _ := ret[0].(*api.MessagePrototype)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@ -1247,10 +1292,10 @@ func (mr *MockFullNodeMockRecorder) MsigAddCancel(arg0, arg1, arg2, arg3, arg4,
}
// MsigAddPropose mocks base method
func (m *MockFullNode) MsigAddPropose(arg0 context.Context, arg1, arg2, arg3 address.Address, arg4 bool) (cid.Cid, error) {
func (m *MockFullNode) MsigAddPropose(arg0 context.Context, arg1, arg2, arg3 address.Address, arg4 bool) (*api.MessagePrototype, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MsigAddPropose", arg0, arg1, arg2, arg3, arg4)
ret0, _ := ret[0].(cid.Cid)
ret0, _ := ret[0].(*api.MessagePrototype)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@ -1262,10 +1307,10 @@ func (mr *MockFullNodeMockRecorder) MsigAddPropose(arg0, arg1, arg2, arg3, arg4
}
// MsigApprove mocks base method
func (m *MockFullNode) MsigApprove(arg0 context.Context, arg1 address.Address, arg2 uint64, arg3 address.Address) (cid.Cid, error) {
func (m *MockFullNode) MsigApprove(arg0 context.Context, arg1 address.Address, arg2 uint64, arg3 address.Address) (*api.MessagePrototype, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MsigApprove", arg0, arg1, arg2, arg3)
ret0, _ := ret[0].(cid.Cid)
ret0, _ := ret[0].(*api.MessagePrototype)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@ -1277,10 +1322,10 @@ func (mr *MockFullNodeMockRecorder) MsigApprove(arg0, arg1, arg2, arg3 interface
}
// MsigApproveTxnHash mocks base method
func (m *MockFullNode) MsigApproveTxnHash(arg0 context.Context, arg1 address.Address, arg2 uint64, arg3, arg4 address.Address, arg5 big.Int, arg6 address.Address, arg7 uint64, arg8 []byte) (cid.Cid, error) {
func (m *MockFullNode) MsigApproveTxnHash(arg0 context.Context, arg1 address.Address, arg2 uint64, arg3, arg4 address.Address, arg5 big.Int, arg6 address.Address, arg7 uint64, arg8 []byte) (*api.MessagePrototype, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MsigApproveTxnHash", arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
ret0, _ := ret[0].(cid.Cid)
ret0, _ := ret[0].(*api.MessagePrototype)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@ -1292,10 +1337,10 @@ func (mr *MockFullNodeMockRecorder) MsigApproveTxnHash(arg0, arg1, arg2, arg3, a
}
// MsigCancel mocks base method
func (m *MockFullNode) MsigCancel(arg0 context.Context, arg1 address.Address, arg2 uint64, arg3 address.Address, arg4 big.Int, arg5 address.Address, arg6 uint64, arg7 []byte) (cid.Cid, error) {
func (m *MockFullNode) MsigCancel(arg0 context.Context, arg1 address.Address, arg2 uint64, arg3 address.Address, arg4 big.Int, arg5 address.Address, arg6 uint64, arg7 []byte) (*api.MessagePrototype, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MsigCancel", arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
ret0, _ := ret[0].(cid.Cid)
ret0, _ := ret[0].(*api.MessagePrototype)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@ -1307,10 +1352,10 @@ func (mr *MockFullNodeMockRecorder) MsigCancel(arg0, arg1, arg2, arg3, arg4, arg
}
// MsigCreate mocks base method
func (m *MockFullNode) MsigCreate(arg0 context.Context, arg1 uint64, arg2 []address.Address, arg3 abi.ChainEpoch, arg4 big.Int, arg5 address.Address, arg6 big.Int) (cid.Cid, error) {
func (m *MockFullNode) MsigCreate(arg0 context.Context, arg1 uint64, arg2 []address.Address, arg3 abi.ChainEpoch, arg4 big.Int, arg5 address.Address, arg6 big.Int) (*api.MessagePrototype, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MsigCreate", arg0, arg1, arg2, arg3, arg4, arg5, arg6)
ret0, _ := ret[0].(cid.Cid)
ret0, _ := ret[0].(*api.MessagePrototype)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@ -1382,10 +1427,10 @@ func (mr *MockFullNodeMockRecorder) MsigGetVestingSchedule(arg0, arg1, arg2 inte
}
// MsigPropose mocks base method
func (m *MockFullNode) MsigPropose(arg0 context.Context, arg1, arg2 address.Address, arg3 big.Int, arg4 address.Address, arg5 uint64, arg6 []byte) (cid.Cid, error) {
func (m *MockFullNode) MsigPropose(arg0 context.Context, arg1, arg2 address.Address, arg3 big.Int, arg4 address.Address, arg5 uint64, arg6 []byte) (*api.MessagePrototype, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MsigPropose", arg0, arg1, arg2, arg3, arg4, arg5, arg6)
ret0, _ := ret[0].(cid.Cid)
ret0, _ := ret[0].(*api.MessagePrototype)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@ -1397,10 +1442,10 @@ func (mr *MockFullNodeMockRecorder) MsigPropose(arg0, arg1, arg2, arg3, arg4, ar
}
// MsigRemoveSigner mocks base method
func (m *MockFullNode) MsigRemoveSigner(arg0 context.Context, arg1, arg2, arg3 address.Address, arg4 bool) (cid.Cid, error) {
func (m *MockFullNode) MsigRemoveSigner(arg0 context.Context, arg1, arg2, arg3 address.Address, arg4 bool) (*api.MessagePrototype, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MsigRemoveSigner", arg0, arg1, arg2, arg3, arg4)
ret0, _ := ret[0].(cid.Cid)
ret0, _ := ret[0].(*api.MessagePrototype)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@ -1412,10 +1457,10 @@ func (mr *MockFullNodeMockRecorder) MsigRemoveSigner(arg0, arg1, arg2, arg3, arg
}
// MsigSwapApprove mocks base method
func (m *MockFullNode) MsigSwapApprove(arg0 context.Context, arg1, arg2 address.Address, arg3 uint64, arg4, arg5, arg6 address.Address) (cid.Cid, error) {
func (m *MockFullNode) MsigSwapApprove(arg0 context.Context, arg1, arg2 address.Address, arg3 uint64, arg4, arg5, arg6 address.Address) (*api.MessagePrototype, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MsigSwapApprove", arg0, arg1, arg2, arg3, arg4, arg5, arg6)
ret0, _ := ret[0].(cid.Cid)
ret0, _ := ret[0].(*api.MessagePrototype)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@ -1427,10 +1472,10 @@ func (mr *MockFullNodeMockRecorder) MsigSwapApprove(arg0, arg1, arg2, arg3, arg4
}
// MsigSwapCancel mocks base method
func (m *MockFullNode) MsigSwapCancel(arg0 context.Context, arg1, arg2 address.Address, arg3 uint64, arg4, arg5 address.Address) (cid.Cid, error) {
func (m *MockFullNode) MsigSwapCancel(arg0 context.Context, arg1, arg2 address.Address, arg3 uint64, arg4, arg5 address.Address) (*api.MessagePrototype, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MsigSwapCancel", arg0, arg1, arg2, arg3, arg4, arg5)
ret0, _ := ret[0].(cid.Cid)
ret0, _ := ret[0].(*api.MessagePrototype)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@ -1442,10 +1487,10 @@ func (mr *MockFullNodeMockRecorder) MsigSwapCancel(arg0, arg1, arg2, arg3, arg4,
}
// MsigSwapPropose mocks base method
func (m *MockFullNode) MsigSwapPropose(arg0 context.Context, arg1, arg2, arg3, arg4 address.Address) (cid.Cid, error) {
func (m *MockFullNode) MsigSwapPropose(arg0 context.Context, arg1, arg2, arg3, arg4 address.Address) (*api.MessagePrototype, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MsigSwapPropose", arg0, arg1, arg2, arg3, arg4)
ret0, _ := ret[0].(cid.Cid)
ret0, _ := ret[0].(*api.MessagePrototype)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@ -1692,6 +1737,21 @@ func (mr *MockFullNodeMockRecorder) NetPubsubScores(arg0 interface{}) *gomock.Ca
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetPubsubScores", reflect.TypeOf((*MockFullNode)(nil).NetPubsubScores), arg0)
}
// NodeStatus mocks base method
func (m *MockFullNode) NodeStatus(arg0 context.Context, arg1 bool) (api.NodeStatus, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "NodeStatus", arg0, arg1)
ret0, _ := ret[0].(api.NodeStatus)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// NodeStatus indicates an expected call of NodeStatus
func (mr *MockFullNodeMockRecorder) NodeStatus(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NodeStatus", reflect.TypeOf((*MockFullNode)(nil).NodeStatus), arg0, arg1)
}
// PaychAllocateLane mocks base method
func (m *MockFullNode) PaychAllocateLane(arg0 context.Context, arg1 address.Address) (uint64, error) {
m.ctrl.T.Helper()

View File

@ -235,6 +235,12 @@ type FullNodeStruct struct {
MpoolBatchPushUntrusted func(p0 context.Context, p1 []*types.SignedMessage) ([]cid.Cid, error) `perm:"write"`
MpoolCheckMessages func(p0 context.Context, p1 []*MessagePrototype) ([][]MessageCheckStatus, error) `perm:"read"`
MpoolCheckPendingMessages func(p0 context.Context, p1 address.Address) ([][]MessageCheckStatus, error) `perm:"read"`
MpoolCheckReplaceMessages func(p0 context.Context, p1 []*types.Message) ([][]MessageCheckStatus, error) `perm:"read"`
MpoolClear func(p0 context.Context, p1 bool) error `perm:"write"`
MpoolGetConfig func(p0 context.Context) (*types.MpoolConfig, error) `perm:"read"`
@ -255,19 +261,19 @@ type FullNodeStruct struct {
MpoolSub func(p0 context.Context) (<-chan MpoolUpdate, error) `perm:"read"`
MsigAddApprove func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address, p6 bool) (cid.Cid, error) `perm:"sign"`
MsigAddApprove func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address, p6 bool) (*MessagePrototype, error) `perm:"sign"`
MsigAddCancel func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 bool) (cid.Cid, error) `perm:"sign"`
MsigAddCancel func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 bool) (*MessagePrototype, error) `perm:"sign"`
MsigAddPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (cid.Cid, error) `perm:"sign"`
MsigAddPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (*MessagePrototype, error) `perm:"sign"`
MsigApprove func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address) (cid.Cid, error) `perm:"sign"`
MsigApprove func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address) (*MessagePrototype, error) `perm:"sign"`
MsigApproveTxnHash func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 address.Address, p5 types.BigInt, p6 address.Address, p7 uint64, p8 []byte) (cid.Cid, error) `perm:"sign"`
MsigApproveTxnHash func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 address.Address, p5 types.BigInt, p6 address.Address, p7 uint64, p8 []byte) (*MessagePrototype, error) `perm:"sign"`
MsigCancel func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 types.BigInt, p5 address.Address, p6 uint64, p7 []byte) (cid.Cid, error) `perm:"sign"`
MsigCancel func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 types.BigInt, p5 address.Address, p6 uint64, p7 []byte) (*MessagePrototype, error) `perm:"sign"`
MsigCreate func(p0 context.Context, p1 uint64, p2 []address.Address, p3 abi.ChainEpoch, p4 types.BigInt, p5 address.Address, p6 types.BigInt) (cid.Cid, error) `perm:"sign"`
MsigCreate func(p0 context.Context, p1 uint64, p2 []address.Address, p3 abi.ChainEpoch, p4 types.BigInt, p5 address.Address, p6 types.BigInt) (*MessagePrototype, error) `perm:"sign"`
MsigGetAvailableBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.BigInt, error) `perm:"read"`
@ -277,15 +283,17 @@ type FullNodeStruct struct {
MsigGetVestingSchedule func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MsigVesting, error) `perm:"read"`
MsigPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 address.Address, p5 uint64, p6 []byte) (cid.Cid, error) `perm:"sign"`
MsigPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 address.Address, p5 uint64, p6 []byte) (*MessagePrototype, error) `perm:"sign"`
MsigRemoveSigner func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (cid.Cid, error) `perm:"sign"`
MsigRemoveSigner func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (*MessagePrototype, error) `perm:"sign"`
MsigSwapApprove func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address, p6 address.Address) (cid.Cid, error) `perm:"sign"`
MsigSwapApprove func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address, p6 address.Address) (*MessagePrototype, error) `perm:"sign"`
MsigSwapCancel func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address) (cid.Cid, error) `perm:"sign"`
MsigSwapCancel func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address) (*MessagePrototype, error) `perm:"sign"`
MsigSwapPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 address.Address) (cid.Cid, error) `perm:"sign"`
MsigSwapPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 address.Address) (*MessagePrototype, error) `perm:"sign"`
NodeStatus func(p0 context.Context, p1 bool) (NodeStatus, error) `perm:"read"`
PaychAllocateLane func(p0 context.Context, p1 address.Address) (uint64, error) `perm:"sign"`
@ -1507,6 +1515,30 @@ func (s *FullNodeStub) MpoolBatchPushUntrusted(p0 context.Context, p1 []*types.S
return *new([]cid.Cid), xerrors.New("method not supported")
}
func (s *FullNodeStruct) MpoolCheckMessages(p0 context.Context, p1 []*MessagePrototype) ([][]MessageCheckStatus, error) {
return s.Internal.MpoolCheckMessages(p0, p1)
}
func (s *FullNodeStub) MpoolCheckMessages(p0 context.Context, p1 []*MessagePrototype) ([][]MessageCheckStatus, error) {
return *new([][]MessageCheckStatus), xerrors.New("method not supported")
}
func (s *FullNodeStruct) MpoolCheckPendingMessages(p0 context.Context, p1 address.Address) ([][]MessageCheckStatus, error) {
return s.Internal.MpoolCheckPendingMessages(p0, p1)
}
func (s *FullNodeStub) MpoolCheckPendingMessages(p0 context.Context, p1 address.Address) ([][]MessageCheckStatus, error) {
return *new([][]MessageCheckStatus), xerrors.New("method not supported")
}
func (s *FullNodeStruct) MpoolCheckReplaceMessages(p0 context.Context, p1 []*types.Message) ([][]MessageCheckStatus, error) {
return s.Internal.MpoolCheckReplaceMessages(p0, p1)
}
func (s *FullNodeStub) MpoolCheckReplaceMessages(p0 context.Context, p1 []*types.Message) ([][]MessageCheckStatus, error) {
return *new([][]MessageCheckStatus), xerrors.New("method not supported")
}
func (s *FullNodeStruct) MpoolClear(p0 context.Context, p1 bool) error {
return s.Internal.MpoolClear(p0, p1)
}
@ -1587,60 +1619,60 @@ func (s *FullNodeStub) MpoolSub(p0 context.Context) (<-chan MpoolUpdate, error)
return nil, xerrors.New("method not supported")
}
func (s *FullNodeStruct) MsigAddApprove(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address, p6 bool) (cid.Cid, error) {
func (s *FullNodeStruct) MsigAddApprove(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address, p6 bool) (*MessagePrototype, error) {
return s.Internal.MsigAddApprove(p0, p1, p2, p3, p4, p5, p6)
}
func (s *FullNodeStub) MsigAddApprove(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address, p6 bool) (cid.Cid, error) {
return *new(cid.Cid), xerrors.New("method not supported")
func (s *FullNodeStub) MsigAddApprove(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address, p6 bool) (*MessagePrototype, error) {
return nil, xerrors.New("method not supported")
}
func (s *FullNodeStruct) MsigAddCancel(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 bool) (cid.Cid, error) {
func (s *FullNodeStruct) MsigAddCancel(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 bool) (*MessagePrototype, error) {
return s.Internal.MsigAddCancel(p0, p1, p2, p3, p4, p5)
}
func (s *FullNodeStub) MsigAddCancel(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 bool) (cid.Cid, error) {
return *new(cid.Cid), xerrors.New("method not supported")
func (s *FullNodeStub) MsigAddCancel(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 bool) (*MessagePrototype, error) {
return nil, xerrors.New("method not supported")
}
func (s *FullNodeStruct) MsigAddPropose(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (cid.Cid, error) {
func (s *FullNodeStruct) MsigAddPropose(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (*MessagePrototype, error) {
return s.Internal.MsigAddPropose(p0, p1, p2, p3, p4)
}
func (s *FullNodeStub) MsigAddPropose(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (cid.Cid, error) {
return *new(cid.Cid), xerrors.New("method not supported")
func (s *FullNodeStub) MsigAddPropose(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (*MessagePrototype, error) {
return nil, xerrors.New("method not supported")
}
func (s *FullNodeStruct) MsigApprove(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address) (cid.Cid, error) {
func (s *FullNodeStruct) MsigApprove(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address) (*MessagePrototype, error) {
return s.Internal.MsigApprove(p0, p1, p2, p3)
}
func (s *FullNodeStub) MsigApprove(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address) (cid.Cid, error) {
return *new(cid.Cid), xerrors.New("method not supported")
func (s *FullNodeStub) MsigApprove(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address) (*MessagePrototype, error) {
return nil, xerrors.New("method not supported")
}
func (s *FullNodeStruct) MsigApproveTxnHash(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 address.Address, p5 types.BigInt, p6 address.Address, p7 uint64, p8 []byte) (cid.Cid, error) {
func (s *FullNodeStruct) MsigApproveTxnHash(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 address.Address, p5 types.BigInt, p6 address.Address, p7 uint64, p8 []byte) (*MessagePrototype, error) {
return s.Internal.MsigApproveTxnHash(p0, p1, p2, p3, p4, p5, p6, p7, p8)
}
func (s *FullNodeStub) MsigApproveTxnHash(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 address.Address, p5 types.BigInt, p6 address.Address, p7 uint64, p8 []byte) (cid.Cid, error) {
return *new(cid.Cid), xerrors.New("method not supported")
func (s *FullNodeStub) MsigApproveTxnHash(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 address.Address, p5 types.BigInt, p6 address.Address, p7 uint64, p8 []byte) (*MessagePrototype, error) {
return nil, xerrors.New("method not supported")
}
func (s *FullNodeStruct) MsigCancel(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 types.BigInt, p5 address.Address, p6 uint64, p7 []byte) (cid.Cid, error) {
func (s *FullNodeStruct) MsigCancel(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 types.BigInt, p5 address.Address, p6 uint64, p7 []byte) (*MessagePrototype, error) {
return s.Internal.MsigCancel(p0, p1, p2, p3, p4, p5, p6, p7)
}
func (s *FullNodeStub) MsigCancel(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 types.BigInt, p5 address.Address, p6 uint64, p7 []byte) (cid.Cid, error) {
return *new(cid.Cid), xerrors.New("method not supported")
func (s *FullNodeStub) MsigCancel(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 types.BigInt, p5 address.Address, p6 uint64, p7 []byte) (*MessagePrototype, error) {
return nil, xerrors.New("method not supported")
}
func (s *FullNodeStruct) MsigCreate(p0 context.Context, p1 uint64, p2 []address.Address, p3 abi.ChainEpoch, p4 types.BigInt, p5 address.Address, p6 types.BigInt) (cid.Cid, error) {
func (s *FullNodeStruct) MsigCreate(p0 context.Context, p1 uint64, p2 []address.Address, p3 abi.ChainEpoch, p4 types.BigInt, p5 address.Address, p6 types.BigInt) (*MessagePrototype, error) {
return s.Internal.MsigCreate(p0, p1, p2, p3, p4, p5, p6)
}
func (s *FullNodeStub) MsigCreate(p0 context.Context, p1 uint64, p2 []address.Address, p3 abi.ChainEpoch, p4 types.BigInt, p5 address.Address, p6 types.BigInt) (cid.Cid, error) {
return *new(cid.Cid), xerrors.New("method not supported")
func (s *FullNodeStub) MsigCreate(p0 context.Context, p1 uint64, p2 []address.Address, p3 abi.ChainEpoch, p4 types.BigInt, p5 address.Address, p6 types.BigInt) (*MessagePrototype, error) {
return nil, xerrors.New("method not supported")
}
func (s *FullNodeStruct) MsigGetAvailableBalance(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.BigInt, error) {
@ -1675,44 +1707,52 @@ func (s *FullNodeStub) MsigGetVestingSchedule(p0 context.Context, p1 address.Add
return *new(MsigVesting), xerrors.New("method not supported")
}
func (s *FullNodeStruct) MsigPropose(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 address.Address, p5 uint64, p6 []byte) (cid.Cid, error) {
func (s *FullNodeStruct) MsigPropose(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 address.Address, p5 uint64, p6 []byte) (*MessagePrototype, error) {
return s.Internal.MsigPropose(p0, p1, p2, p3, p4, p5, p6)
}
func (s *FullNodeStub) MsigPropose(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 address.Address, p5 uint64, p6 []byte) (cid.Cid, error) {
return *new(cid.Cid), xerrors.New("method not supported")
func (s *FullNodeStub) MsigPropose(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 address.Address, p5 uint64, p6 []byte) (*MessagePrototype, error) {
return nil, xerrors.New("method not supported")
}
func (s *FullNodeStruct) MsigRemoveSigner(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (cid.Cid, error) {
func (s *FullNodeStruct) MsigRemoveSigner(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (*MessagePrototype, error) {
return s.Internal.MsigRemoveSigner(p0, p1, p2, p3, p4)
}
func (s *FullNodeStub) MsigRemoveSigner(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (cid.Cid, error) {
return *new(cid.Cid), xerrors.New("method not supported")
func (s *FullNodeStub) MsigRemoveSigner(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (*MessagePrototype, error) {
return nil, xerrors.New("method not supported")
}
func (s *FullNodeStruct) MsigSwapApprove(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address, p6 address.Address) (cid.Cid, error) {
func (s *FullNodeStruct) MsigSwapApprove(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address, p6 address.Address) (*MessagePrototype, error) {
return s.Internal.MsigSwapApprove(p0, p1, p2, p3, p4, p5, p6)
}
func (s *FullNodeStub) MsigSwapApprove(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address, p6 address.Address) (cid.Cid, error) {
return *new(cid.Cid), xerrors.New("method not supported")
func (s *FullNodeStub) MsigSwapApprove(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address, p6 address.Address) (*MessagePrototype, error) {
return nil, xerrors.New("method not supported")
}
func (s *FullNodeStruct) MsigSwapCancel(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address) (cid.Cid, error) {
func (s *FullNodeStruct) MsigSwapCancel(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address) (*MessagePrototype, error) {
return s.Internal.MsigSwapCancel(p0, p1, p2, p3, p4, p5)
}
func (s *FullNodeStub) MsigSwapCancel(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address) (cid.Cid, error) {
return *new(cid.Cid), xerrors.New("method not supported")
func (s *FullNodeStub) MsigSwapCancel(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address) (*MessagePrototype, error) {
return nil, xerrors.New("method not supported")
}
func (s *FullNodeStruct) MsigSwapPropose(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 address.Address) (cid.Cid, error) {
func (s *FullNodeStruct) MsigSwapPropose(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 address.Address) (*MessagePrototype, error) {
return s.Internal.MsigSwapPropose(p0, p1, p2, p3, p4)
}
func (s *FullNodeStub) MsigSwapPropose(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 address.Address) (cid.Cid, error) {
return *new(cid.Cid), xerrors.New("method not supported")
func (s *FullNodeStub) MsigSwapPropose(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 address.Address) (*MessagePrototype, error) {
return nil, xerrors.New("method not supported")
}
func (s *FullNodeStruct) NodeStatus(p0 context.Context, p1 bool) (NodeStatus, error) {
return s.Internal.NodeStatus(p0, p1)
}
func (s *FullNodeStub) NodeStatus(p0 context.Context, p1 bool) (NodeStatus, error) {
return *new(NodeStatus), xerrors.New("method not supported")
}
func (s *FullNodeStruct) PaychAllocateLane(p0 context.Context, p1 address.Address) (uint64, error) {

View File

@ -29,7 +29,7 @@ func SendFunds(ctx context.Context, t *testing.T, sender TestNode, addr address.
if err != nil {
t.Fatal(err)
}
res, err := sender.StateWaitMsg(ctx, sm.Cid(), 1, lapi.LookbackNoLimit, true)
res, err := sender.StateWaitMsg(ctx, sm.Cid(), 3, lapi.LookbackNoLimit, true)
if err != nil {
t.Fatal(err)
}

View File

@ -5,6 +5,8 @@ import (
"fmt"
"time"
"github.com/filecoin-project/lotus/chain/types"
datatransfer "github.com/filecoin-project/go-data-transfer"
"github.com/filecoin-project/go-state-types/abi"
"github.com/ipfs/go-cid"
@ -116,3 +118,61 @@ type ConnMgrInfo struct {
Tags map[string]int
Conns map[string]time.Time
}
type NodeStatus struct {
SyncStatus NodeSyncStatus
PeerStatus NodePeerStatus
ChainStatus NodeChainStatus
}
type NodeSyncStatus struct {
Epoch uint64
Behind uint64
}
type NodePeerStatus struct {
PeersToPublishMsgs int
PeersToPublishBlocks int
}
type NodeChainStatus struct {
BlocksPerTipsetLast100 float64
BlocksPerTipsetLastFinality float64
}
type CheckStatusCode int
//go:generate go run golang.org/x/tools/cmd/stringer -type=CheckStatusCode -trimprefix=CheckStatus
const (
_ CheckStatusCode = iota
// Message Checks
CheckStatusMessageSerialize
CheckStatusMessageSize
CheckStatusMessageValidity
CheckStatusMessageMinGas
CheckStatusMessageMinBaseFee
CheckStatusMessageBaseFee
CheckStatusMessageBaseFeeLowerBound
CheckStatusMessageBaseFeeUpperBound
CheckStatusMessageGetStateNonce
CheckStatusMessageNonce
CheckStatusMessageGetStateBalance
CheckStatusMessageBalance
)
type CheckStatus struct {
Code CheckStatusCode
OK bool
Err string
Hint map[string]interface{}
}
type MessageCheckStatus struct {
Cid cid.Cid
CheckStatus
}
type MessagePrototype struct {
Message types.Message
ValidNonce bool
}

View File

@ -3,7 +3,9 @@ package v0api
import (
"context"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/types"
"golang.org/x/xerrors"
"github.com/ipfs/go-cid"
@ -57,4 +59,129 @@ func (w *WrapperV1Full) Version(ctx context.Context) (api.APIVersion, error) {
return ver, nil
}
func (w *WrapperV1Full) executePrototype(ctx context.Context, p *api.MessagePrototype) (cid.Cid, error) {
sm, err := w.FullNode.MpoolPushMessage(ctx, &p.Message, nil)
if err != nil {
return cid.Undef, xerrors.Errorf("pushing message: %w", err)
}
return sm.Cid(), nil
}
func (w *WrapperV1Full) MsigCreate(ctx context.Context, req uint64, addrs []address.Address, duration abi.ChainEpoch, val types.BigInt, src address.Address, gp types.BigInt) (cid.Cid, error) {
p, err := w.FullNode.MsigCreate(ctx, req, addrs, duration, val, src, gp)
if err != nil {
return cid.Undef, xerrors.Errorf("creating prototype: %w", err)
}
return w.executePrototype(ctx, p)
}
func (w *WrapperV1Full) MsigPropose(ctx context.Context, msig address.Address, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (cid.Cid, error) {
p, err := w.FullNode.MsigPropose(ctx, msig, to, amt, src, method, params)
if err != nil {
return cid.Undef, xerrors.Errorf("creating prototype: %w", err)
}
return w.executePrototype(ctx, p)
}
func (w *WrapperV1Full) MsigApprove(ctx context.Context, msig address.Address, txID uint64, src address.Address) (cid.Cid, error) {
p, err := w.FullNode.MsigApprove(ctx, msig, txID, src)
if err != nil {
return cid.Undef, xerrors.Errorf("creating prototype: %w", err)
}
return w.executePrototype(ctx, p)
}
func (w *WrapperV1Full) MsigApproveTxnHash(ctx context.Context, msig address.Address, txID uint64, proposer address.Address, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (cid.Cid, error) {
p, err := w.FullNode.MsigApproveTxnHash(ctx, msig, txID, proposer, to, amt, src, method, params)
if err != nil {
return cid.Undef, xerrors.Errorf("creating prototype: %w", err)
}
return w.executePrototype(ctx, p)
}
func (w *WrapperV1Full) MsigCancel(ctx context.Context, msig address.Address, txID uint64, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (cid.Cid, error) {
p, err := w.FullNode.MsigCancel(ctx, msig, txID, to, amt, src, method, params)
if err != nil {
return cid.Undef, xerrors.Errorf("creating prototype: %w", err)
}
return w.executePrototype(ctx, p)
}
func (w *WrapperV1Full) MsigAddPropose(ctx context.Context, msig address.Address, src address.Address, newAdd address.Address, inc bool) (cid.Cid, error) {
p, err := w.FullNode.MsigAddPropose(ctx, msig, src, newAdd, inc)
if err != nil {
return cid.Undef, xerrors.Errorf("creating prototype: %w", err)
}
return w.executePrototype(ctx, p)
}
func (w *WrapperV1Full) MsigAddApprove(ctx context.Context, msig address.Address, src address.Address, txID uint64, proposer address.Address, newAdd address.Address, inc bool) (cid.Cid, error) {
p, err := w.FullNode.MsigAddApprove(ctx, msig, src, txID, proposer, newAdd, inc)
if err != nil {
return cid.Undef, xerrors.Errorf("creating prototype: %w", err)
}
return w.executePrototype(ctx, p)
}
func (w *WrapperV1Full) MsigAddCancel(ctx context.Context, msig address.Address, src address.Address, txID uint64, newAdd address.Address, inc bool) (cid.Cid, error) {
p, err := w.FullNode.MsigAddCancel(ctx, msig, src, txID, newAdd, inc)
if err != nil {
return cid.Undef, xerrors.Errorf("creating prototype: %w", err)
}
return w.executePrototype(ctx, p)
}
func (w *WrapperV1Full) MsigSwapPropose(ctx context.Context, msig address.Address, src address.Address, oldAdd address.Address, newAdd address.Address) (cid.Cid, error) {
p, err := w.FullNode.MsigSwapPropose(ctx, msig, src, oldAdd, newAdd)
if err != nil {
return cid.Undef, xerrors.Errorf("creating prototype: %w", err)
}
return w.executePrototype(ctx, p)
}
func (w *WrapperV1Full) MsigSwapApprove(ctx context.Context, msig address.Address, src address.Address, txID uint64, proposer address.Address, oldAdd address.Address, newAdd address.Address) (cid.Cid, error) {
p, err := w.FullNode.MsigSwapApprove(ctx, msig, src, txID, proposer, oldAdd, newAdd)
if err != nil {
return cid.Undef, xerrors.Errorf("creating prototype: %w", err)
}
return w.executePrototype(ctx, p)
}
func (w *WrapperV1Full) MsigSwapCancel(ctx context.Context, msig address.Address, src address.Address, txID uint64, oldAdd address.Address, newAdd address.Address) (cid.Cid, error) {
p, err := w.FullNode.MsigSwapCancel(ctx, msig, src, txID, oldAdd, newAdd)
if err != nil {
return cid.Undef, xerrors.Errorf("creating prototype: %w", err)
}
return w.executePrototype(ctx, p)
}
func (w *WrapperV1Full) MsigRemoveSigner(ctx context.Context, msig address.Address, proposer address.Address, toRemove address.Address, decrease bool) (cid.Cid, error) {
p, err := w.FullNode.MsigRemoveSigner(ctx, msig, proposer, toRemove, decrease)
if err != nil {
return cid.Undef, xerrors.Errorf("creating prototype: %w", err)
}
return w.executePrototype(ctx, p)
}
var _ FullNode = &WrapperV1Full{}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -6,4 +6,5 @@ import (
_ "github.com/GeertJohan/go.rice/rice"
_ "github.com/golang/mock/mockgen"
_ "github.com/whyrusleeping/bencher"
_ "golang.org/x/tools/cmd/stringer"
)

431
chain/messagepool/check.go Normal file
View File

@ -0,0 +1,431 @@
package messagepool
import (
"context"
"fmt"
stdbig "math/big"
"sort"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/big"
"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/vm"
)
var baseFeeUpperBoundFactor = types.NewInt(10)
// CheckMessages performs a set of logic checks for a list of messages, prior to submitting it to the mpool
func (mp *MessagePool) CheckMessages(protos []*api.MessagePrototype) ([][]api.MessageCheckStatus, error) {
flex := make([]bool, len(protos))
msgs := make([]*types.Message, len(protos))
for i, p := range protos {
flex[i] = !p.ValidNonce
msgs[i] = &p.Message
}
return mp.checkMessages(msgs, false, flex)
}
// CheckPendingMessages performs a set of logical sets for all messages pending from a given actor
func (mp *MessagePool) CheckPendingMessages(from address.Address) ([][]api.MessageCheckStatus, error) {
var msgs []*types.Message
mp.lk.Lock()
mset, ok := mp.pending[from]
if ok {
for _, sm := range mset.msgs {
msgs = append(msgs, &sm.Message)
}
}
mp.lk.Unlock()
if len(msgs) == 0 {
return nil, nil
}
sort.Slice(msgs, func(i, j int) bool {
return msgs[i].Nonce < msgs[j].Nonce
})
return mp.checkMessages(msgs, true, nil)
}
// CheckReplaceMessages performs a set of logical checks for related messages while performing a
// replacement.
func (mp *MessagePool) CheckReplaceMessages(replace []*types.Message) ([][]api.MessageCheckStatus, error) {
msgMap := make(map[address.Address]map[uint64]*types.Message)
count := 0
mp.lk.Lock()
for _, m := range replace {
mmap, ok := msgMap[m.From]
if !ok {
mmap = make(map[uint64]*types.Message)
msgMap[m.From] = mmap
mset, ok := mp.pending[m.From]
if ok {
count += len(mset.msgs)
for _, sm := range mset.msgs {
mmap[sm.Message.Nonce] = &sm.Message
}
} else {
count++
}
}
mmap[m.Nonce] = m
}
mp.lk.Unlock()
msgs := make([]*types.Message, 0, count)
start := 0
for _, mmap := range msgMap {
end := start + len(mmap)
for _, m := range mmap {
msgs = append(msgs, m)
}
sort.Slice(msgs[start:end], func(i, j int) bool {
return msgs[start+i].Nonce < msgs[start+j].Nonce
})
start = end
}
return mp.checkMessages(msgs, true, nil)
}
// flexibleNonces should be either nil or of len(msgs), it signifies that message at given index
// has non-determied nonce at this point
func (mp *MessagePool) checkMessages(msgs []*types.Message, interned bool, flexibleNonces []bool) (result [][]api.MessageCheckStatus, err error) {
if mp.api.IsLite() {
return nil, nil
}
mp.curTsLk.Lock()
curTs := mp.curTs
mp.curTsLk.Unlock()
epoch := curTs.Height()
var baseFee big.Int
if len(curTs.Blocks()) > 0 {
baseFee = curTs.Blocks()[0].ParentBaseFee
} else {
baseFee, err = mp.api.ChainComputeBaseFee(context.Background(), curTs)
if err != nil {
return nil, xerrors.Errorf("error computing basefee: %w", err)
}
}
baseFeeLowerBound := getBaseFeeLowerBound(baseFee, baseFeeLowerBoundFactor)
baseFeeUpperBound := types.BigMul(baseFee, baseFeeUpperBoundFactor)
type actorState struct {
nextNonce uint64
requiredFunds *stdbig.Int
}
state := make(map[address.Address]*actorState)
balances := make(map[address.Address]big.Int)
result = make([][]api.MessageCheckStatus, len(msgs))
for i, m := range msgs {
// pre-check: actor nonce
check := api.MessageCheckStatus{
Cid: m.Cid(),
CheckStatus: api.CheckStatus{
Code: api.CheckStatusMessageGetStateNonce,
},
}
st, ok := state[m.From]
if !ok {
mp.lk.Lock()
mset, ok := mp.pending[m.From]
if ok && !interned {
st = &actorState{nextNonce: mset.nextNonce, requiredFunds: mset.requiredFunds}
for _, m := range mset.msgs {
st.requiredFunds = new(stdbig.Int).Add(st.requiredFunds, m.Message.Value.Int)
}
state[m.From] = st
mp.lk.Unlock()
check.OK = true
check.Hint = map[string]interface{}{
"nonce": st.nextNonce,
}
} else {
mp.lk.Unlock()
stateNonce, err := mp.getStateNonce(m.From, curTs)
if err != nil {
check.OK = false
check.Err = fmt.Sprintf("error retrieving state nonce: %s", err.Error())
} else {
check.OK = true
check.Hint = map[string]interface{}{
"nonce": stateNonce,
}
}
st = &actorState{nextNonce: stateNonce, requiredFunds: new(stdbig.Int)}
state[m.From] = st
}
} else {
check.OK = true
}
result[i] = append(result[i], check)
if !check.OK {
continue
}
// pre-check: actor balance
check = api.MessageCheckStatus{
Cid: m.Cid(),
CheckStatus: api.CheckStatus{
Code: api.CheckStatusMessageGetStateBalance,
},
}
balance, ok := balances[m.From]
if !ok {
balance, err = mp.getStateBalance(m.From, curTs)
if err != nil {
check.OK = false
check.Err = fmt.Sprintf("error retrieving state balance: %s", err)
} else {
check.OK = true
check.Hint = map[string]interface{}{
"balance": balance,
}
}
balances[m.From] = balance
} else {
check.OK = true
check.Hint = map[string]interface{}{
"balance": balance,
}
}
result[i] = append(result[i], check)
if !check.OK {
continue
}
// 1. Serialization
check = api.MessageCheckStatus{
Cid: m.Cid(),
CheckStatus: api.CheckStatus{
Code: api.CheckStatusMessageSerialize,
},
}
bytes, err := m.Serialize()
if err != nil {
check.OK = false
check.Err = err.Error()
} else {
check.OK = true
}
result[i] = append(result[i], check)
// 2. Message size
check = api.MessageCheckStatus{
Cid: m.Cid(),
CheckStatus: api.CheckStatus{
Code: api.CheckStatusMessageSize,
},
}
if len(bytes) > 32*1024-128 { // 128 bytes to account for signature size
check.OK = false
check.Err = "message too big"
} else {
check.OK = true
}
result[i] = append(result[i], check)
// 3. Syntactic validation
check = api.MessageCheckStatus{
Cid: m.Cid(),
CheckStatus: api.CheckStatus{
Code: api.CheckStatusMessageValidity,
},
}
if err := m.ValidForBlockInclusion(0, build.NewestNetworkVersion); err != nil {
check.OK = false
check.Err = fmt.Sprintf("syntactically invalid message: %s", err.Error())
} else {
check.OK = true
}
result[i] = append(result[i], check)
if !check.OK {
// skip remaining checks if it is a syntatically invalid message
continue
}
// gas checks
// 4. Min Gas
minGas := vm.PricelistByEpoch(epoch).OnChainMessage(m.ChainLength())
check = api.MessageCheckStatus{
Cid: m.Cid(),
CheckStatus: api.CheckStatus{
Code: api.CheckStatusMessageMinGas,
Hint: map[string]interface{}{
"minGas": minGas,
},
},
}
if m.GasLimit < minGas.Total() {
check.OK = false
check.Err = "GasLimit less than epoch minimum gas"
} else {
check.OK = true
}
result[i] = append(result[i], check)
// 5. Min Base Fee
check = api.MessageCheckStatus{
Cid: m.Cid(),
CheckStatus: api.CheckStatus{
Code: api.CheckStatusMessageMinBaseFee,
},
}
if m.GasFeeCap.LessThan(minimumBaseFee) {
check.OK = false
check.Err = "GasFeeCap less than minimum base fee"
} else {
check.OK = true
}
result[i] = append(result[i], check)
if !check.OK {
goto checkState
}
// 6. Base Fee
check = api.MessageCheckStatus{
Cid: m.Cid(),
CheckStatus: api.CheckStatus{
Code: api.CheckStatusMessageBaseFee,
Hint: map[string]interface{}{
"baseFee": baseFee,
},
},
}
if m.GasFeeCap.LessThan(baseFee) {
check.OK = false
check.Err = "GasFeeCap less than current base fee"
} else {
check.OK = true
}
result[i] = append(result[i], check)
// 7. Base Fee lower bound
check = api.MessageCheckStatus{
Cid: m.Cid(),
CheckStatus: api.CheckStatus{
Code: api.CheckStatusMessageBaseFeeLowerBound,
Hint: map[string]interface{}{
"baseFeeLowerBound": baseFeeLowerBound,
"baseFee": baseFee,
},
},
}
if m.GasFeeCap.LessThan(baseFeeLowerBound) {
check.OK = false
check.Err = "GasFeeCap less than base fee lower bound for inclusion in next 20 epochs"
} else {
check.OK = true
}
result[i] = append(result[i], check)
// 8. Base Fee upper bound
check = api.MessageCheckStatus{
Cid: m.Cid(),
CheckStatus: api.CheckStatus{
Code: api.CheckStatusMessageBaseFeeUpperBound,
Hint: map[string]interface{}{
"baseFeeUpperBound": baseFeeUpperBound,
"baseFee": baseFee,
},
},
}
if m.GasFeeCap.LessThan(baseFeeUpperBound) {
check.OK = true // on purpose, the checks is more of a warning
check.Err = "GasFeeCap less than base fee upper bound for inclusion in next 20 epochs"
} else {
check.OK = true
}
result[i] = append(result[i], check)
// stateful checks
checkState:
// 9. Message Nonce
check = api.MessageCheckStatus{
Cid: m.Cid(),
CheckStatus: api.CheckStatus{
Code: api.CheckStatusMessageNonce,
Hint: map[string]interface{}{
"nextNonce": st.nextNonce,
},
},
}
if (flexibleNonces == nil || !flexibleNonces[i]) && st.nextNonce != m.Nonce {
check.OK = false
check.Err = fmt.Sprintf("message nonce doesn't match next nonce (%d)", st.nextNonce)
} else {
check.OK = true
st.nextNonce++
}
result[i] = append(result[i], check)
// check required funds -vs- balance
st.requiredFunds = new(stdbig.Int).Add(st.requiredFunds, m.RequiredFunds().Int)
st.requiredFunds.Add(st.requiredFunds, m.Value.Int)
// 10. Balance
check = api.MessageCheckStatus{
Cid: m.Cid(),
CheckStatus: api.CheckStatus{
Code: api.CheckStatusMessageBalance,
Hint: map[string]interface{}{
"requiredFunds": big.Int{Int: stdbig.NewInt(0).Set(st.requiredFunds)},
},
},
}
if balance.Int.Cmp(st.requiredFunds) < 0 {
check.OK = false
check.Err = "insufficient balance"
} else {
check.OK = true
}
result[i] = append(result[i], check)
}
return result, nil
}

View File

@ -805,6 +805,13 @@ func (mp *MessagePool) GetNonce(_ context.Context, addr address.Address, _ types
return mp.getNonceLocked(addr, mp.curTs)
}
// GetActor should not be used. It is only here to satisfy interface mess caused by lite node handling
func (mp *MessagePool) GetActor(_ context.Context, addr address.Address, _ types.TipSetKey) (*types.Actor, error) {
mp.curTsLk.Lock()
defer mp.curTsLk.Unlock()
return mp.api.GetActorAfter(addr, mp.curTs)
}
func (mp *MessagePool) getNonceLocked(addr address.Address, curTs *types.TipSet) (uint64, error) {
stateNonce, err := mp.getStateNonce(addr, curTs) // sanity check
if err != nil {
@ -825,8 +832,8 @@ func (mp *MessagePool) getNonceLocked(addr address.Address, curTs *types.TipSet)
return stateNonce, nil
}
func (mp *MessagePool) getStateNonce(addr address.Address, curTs *types.TipSet) (uint64, error) {
act, err := mp.api.GetActorAfter(addr, curTs)
func (mp *MessagePool) getStateNonce(addr address.Address, ts *types.TipSet) (uint64, error) {
act, err := mp.api.GetActorAfter(addr, ts)
if err != nil {
return 0, err
}

View File

@ -103,6 +103,9 @@ func (tma *testMpoolAPI) SubscribeHeadChanges(cb func(rev, app []*types.TipSet)
func (tma *testMpoolAPI) PutMessage(m types.ChainMsg) (cid.Cid, error) {
return cid.Undef, nil
}
func (tma *testMpoolAPI) IsLite() bool {
return false
}
func (tma *testMpoolAPI) PubSubPublish(string, []byte) error {
tma.published++

View File

@ -9,6 +9,7 @@ import (
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/messagesigner"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
@ -30,17 +31,28 @@ type Provider interface {
MessagesForTipset(*types.TipSet) ([]types.ChainMsg, error)
LoadTipSet(tsk types.TipSetKey) (*types.TipSet, error)
ChainComputeBaseFee(ctx context.Context, ts *types.TipSet) (types.BigInt, error)
IsLite() bool
}
type mpoolProvider struct {
sm *stmgr.StateManager
ps *pubsub.PubSub
lite messagesigner.MpoolNonceAPI
}
func NewProvider(sm *stmgr.StateManager, ps *pubsub.PubSub) Provider {
return &mpoolProvider{sm: sm, ps: ps}
}
func NewProviderLite(sm *stmgr.StateManager, ps *pubsub.PubSub, noncer messagesigner.MpoolNonceAPI) Provider {
return &mpoolProvider{sm: sm, ps: ps, lite: noncer}
}
func (mpp *mpoolProvider) IsLite() bool {
return mpp.lite != nil
}
func (mpp *mpoolProvider) SubscribeHeadChanges(cb func(rev, app []*types.TipSet) error) *types.TipSet {
mpp.sm.ChainStore().SubscribeHeadChanges(
store.WrapHeadChangeCoalescer(
@ -61,6 +73,19 @@ func (mpp *mpoolProvider) PubSubPublish(k string, v []byte) error {
}
func (mpp *mpoolProvider) GetActorAfter(addr address.Address, ts *types.TipSet) (*types.Actor, error) {
if mpp.IsLite() {
n, err := mpp.lite.GetNonce(context.TODO(), addr, ts.Key())
if err != nil {
return nil, xerrors.Errorf("getting nonce over lite: %w", err)
}
a, err := mpp.lite.GetActor(context.TODO(), addr, ts.Key())
if err != nil {
return nil, xerrors.Errorf("getting actor over lite: %w", err)
}
a.Nonce = n
return a, nil
}
stcid, _, err := mpp.sm.TipSetState(context.TODO(), ts)
if err != nil {
return nil, xerrors.Errorf("computing tipset state for GetActor: %w", err)

View File

@ -24,6 +24,7 @@ var log = logging.Logger("messagesigner")
type MpoolNonceAPI interface {
GetNonce(context.Context, address.Address, types.TipSetKey) (uint64, error)
GetActor(context.Context, address.Address, types.TipSetKey) (*types.Actor, error)
}
// MessageSigner keeps track of nonces per address, and increments the nonce

View File

@ -41,6 +41,9 @@ func (mp *mockMpool) GetNonce(_ context.Context, addr address.Address, _ types.T
return mp.nonces[addr], nil
}
func (mp *mockMpool) GetActor(_ context.Context, addr address.Address, _ types.TipSetKey) (*types.Actor, error) {
panic("don't use it")
}
func TestMessageSignerSignMessage(t *testing.T) {
ctx := context.Background()

View File

@ -46,6 +46,15 @@ func (f FIL) Short() string {
return strings.TrimRight(strings.TrimRight(r.FloatString(3), "0"), ".") + " " + prefix + "FIL"
}
func (f FIL) Nano() string {
r := new(big.Rat).SetFrac(f.Int, big.NewInt(int64(1e9)))
if r.Sign() == 0 {
return "0"
}
return strings.TrimRight(strings.TrimRight(r.FloatString(9), "0"), ".") + " nFIL"
}
func (f FIL) Format(s fmt.State, ch rune) {
switch ch {
case 's', 'v':

View File

@ -31,6 +31,7 @@ import (
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/api"
lapi "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/lotus/build"
@ -1116,11 +1117,13 @@ var SlashConsensusFault = &cli.Command{
},
},
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
srv, err := GetFullNodeServices(cctx)
if err != nil {
return err
}
defer closer()
defer srv.Close() //nolint:errcheck
a := srv.FullNodeAPI()
ctx := ReqContext(cctx)
c1, err := cid.Parse(cctx.Args().Get(0))
@ -1128,7 +1131,7 @@ var SlashConsensusFault = &cli.Command{
return xerrors.Errorf("parsing cid 1: %w", err)
}
b1, err := api.ChainGetBlock(ctx, c1)
b1, err := a.ChainGetBlock(ctx, c1)
if err != nil {
return xerrors.Errorf("getting block 1: %w", err)
}
@ -1138,7 +1141,7 @@ var SlashConsensusFault = &cli.Command{
return xerrors.Errorf("parsing cid 2: %w", err)
}
b2, err := api.ChainGetBlock(ctx, c2)
b2, err := a.ChainGetBlock(ctx, c2)
if err != nil {
return xerrors.Errorf("getting block 2: %w", err)
}
@ -1149,7 +1152,7 @@ var SlashConsensusFault = &cli.Command{
var fromAddr address.Address
if from := cctx.String("from"); from == "" {
defaddr, err := api.WalletDefaultAddress(ctx)
defaddr, err := a.WalletDefaultAddress(ctx)
if err != nil {
return err
}
@ -1185,7 +1188,7 @@ var SlashConsensusFault = &cli.Command{
return xerrors.Errorf("parsing cid extra: %w", err)
}
bExtra, err := api.ChainGetBlock(ctx, cExtra)
bExtra, err := a.ChainGetBlock(ctx, cExtra)
if err != nil {
return xerrors.Errorf("getting block extra: %w", err)
}
@ -1203,15 +1206,17 @@ var SlashConsensusFault = &cli.Command{
return err
}
msg := &types.Message{
To: b2.Miner,
From: fromAddr,
Value: types.NewInt(0),
Method: builtin.MethodsMiner.ReportConsensusFault,
Params: enc,
proto := &api.MessagePrototype{
Message: types.Message{
To: b2.Miner,
From: fromAddr,
Value: types.NewInt(0),
Method: builtin.MethodsMiner.ReportConsensusFault,
Params: enc,
},
}
smsg, err := api.MpoolPushMessage(ctx, msg, nil)
smsg, err := InteractiveSend(ctx, cctx, srv, proto)
if err != nil {
return err
}

View File

@ -34,7 +34,7 @@ func GetFullNodeServices(ctx *cli.Context) (ServicesAPI, error) {
return tn.(ServicesAPI), nil
}
api, c, err := GetFullNodeAPI(ctx)
api, c, err := GetFullNodeAPIV1(ctx)
if err != nil {
return nil, err
}
@ -81,6 +81,7 @@ var Commands = []*cli.Command{
WithCategory("developer", FetchParamCmd),
WithCategory("network", NetCmd),
WithCategory("network", SyncCmd),
WithCategory("status", StatusCmd),
PprofCmd,
VersionCmd,
}

9
cli/init_test.go Normal file
View File

@ -0,0 +1,9 @@
package cli
import (
logging "github.com/ipfs/go-log/v2"
)
func init() {
logging.SetLogLevel("watchdog", "ERROR")
}

View File

@ -34,6 +34,7 @@ var MpoolCmd = &cli.Command{
MpoolFindCmd,
MpoolConfig,
MpoolGasPerfCmd,
mpoolManage,
},
}

360
cli/mpool_manage.go Normal file
View File

@ -0,0 +1,360 @@
package cli
import (
"context"
"fmt"
"sort"
"github.com/Kubuxu/imtui"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/messagepool"
types "github.com/filecoin-project/lotus/chain/types"
"github.com/gdamore/tcell/v2"
cid "github.com/ipfs/go-cid"
"github.com/urfave/cli/v2"
"golang.org/x/xerrors"
)
var mpoolManage = &cli.Command{
Name: "manage",
Action: func(cctx *cli.Context) error {
srv, err := GetFullNodeServices(cctx)
if err != nil {
return err
}
defer srv.Close() //nolint:errcheck
ctx := ReqContext(cctx)
_, localAddr, err := srv.LocalAddresses(ctx)
if err != nil {
return xerrors.Errorf("getting local addresses: %w", err)
}
msgs, err := srv.MpoolPendingFilter(ctx, func(sm *types.SignedMessage) bool {
if sm.Message.From.Empty() {
return false
}
for _, a := range localAddr {
if a == sm.Message.From {
return true
}
}
return false
}, types.EmptyTSK)
if err != nil {
return err
}
t, err := imtui.NewTui()
if err != nil {
panic(err)
}
mm := &mmUI{
ctx: ctx,
srv: srv,
addrs: localAddr,
messages: msgs,
}
sort.Slice(mm.addrs, func(i, j int) bool {
return mm.addrs[i].String() < mm.addrs[j].String()
})
t.PushScene(mm.addrSelect())
err = t.Run()
if err != nil {
panic(err)
}
return nil
},
}
type mmUI struct {
ctx context.Context
srv ServicesAPI
addrs []address.Address
messages []*types.SignedMessage
}
func (mm *mmUI) addrSelect() func(*imtui.Tui) error {
rows := [][]string{{"Address", "No. Messages"}}
mCount := map[address.Address]int{}
for _, sm := range mm.messages {
mCount[sm.Message.From]++
}
for _, a := range mm.addrs {
rows = append(rows, []string{a.String(), fmt.Sprintf("%d", mCount[a])})
}
flex := []int{4, 1}
sel := 0
scroll := 0
return func(t *imtui.Tui) error {
if t.CurrentKey != nil && t.CurrentKey.Key() == tcell.KeyEnter {
if sel > 0 {
t.ReplaceScene(mm.messageLising(mm.addrs[sel-1]))
}
}
t.FlexTable(0, 0, 0, &sel, &scroll, rows, flex, true)
return nil
}
}
func errUI(err error) func(*imtui.Tui) error {
return func(t *imtui.Tui) error {
return err
}
}
type msgInfo struct {
sm *types.SignedMessage
checks []api.MessageCheckStatus
}
func (mi *msgInfo) Row() []string {
cidStr := mi.sm.Cid().String()
failedChecks := 0
for _, c := range mi.checks {
if !c.OK {
failedChecks++
}
}
shortAddr := mi.sm.Message.To.String()
if len(shortAddr) > 16 {
shortAddr = "…" + shortAddr[len(shortAddr)-16:]
}
var fCk string
if failedChecks == 0 {
fCk = "[:green:]OK"
} else {
fCk = "[:orange:]" + fmt.Sprintf("%d", failedChecks)
}
return []string{"…" + cidStr[len(cidStr)-32:], shortAddr,
fmt.Sprintf("%d", mi.sm.Message.Nonce), types.FIL(mi.sm.Message.Value).String(),
fmt.Sprintf("%d", mi.sm.Message.Method), fCk}
}
func (mm *mmUI) messageLising(a address.Address) func(*imtui.Tui) error {
genMsgInfos := func() ([]msgInfo, error) {
msgs, err := mm.srv.MpoolPendingFilter(mm.ctx, func(sm *types.SignedMessage) bool {
if sm.Message.From.Empty() {
return false
}
if a == sm.Message.From {
return true
}
return false
}, types.EmptyTSK)
if err != nil {
return nil, xerrors.Errorf("getting pending: %w", err)
}
msgIdx := map[cid.Cid]*types.SignedMessage{}
for _, sm := range msgs {
if sm.Message.From == a {
msgIdx[sm.Message.Cid()] = sm
msgIdx[sm.Cid()] = sm
}
}
checks, err := mm.srv.MpoolCheckPendingMessages(mm.ctx, a)
if err != nil {
return nil, xerrors.Errorf("checking pending: %w", err)
}
msgInfos := make([]msgInfo, 0, len(checks))
for _, msgChecks := range checks {
failingChecks := []api.MessageCheckStatus{}
for _, c := range msgChecks {
if !c.OK {
failingChecks = append(failingChecks, c)
}
}
msgInfos = append(msgInfos, msgInfo{
sm: msgIdx[msgChecks[0].Cid],
checks: failingChecks,
})
}
return msgInfos, nil
}
sel := 0
scroll := 0
var msgInfos []msgInfo
var rows [][]string
flex := []int{3, 2, 1, 1, 1, 1}
refresh := true
return func(t *imtui.Tui) error {
if refresh {
var err error
msgInfos, err = genMsgInfos()
if err != nil {
return xerrors.Errorf("getting msgInfos: %w", err)
}
rows = [][]string{{"Message Cid", "To", "Nonce", "Value", "Method", "Checks"}}
for _, mi := range msgInfos {
rows = append(rows, mi.Row())
}
refresh = false
}
if t.CurrentKey != nil && t.CurrentKey.Key() == tcell.KeyEnter {
if sel > 0 {
t.PushScene(mm.messageDetail(msgInfos[sel-1]))
refresh = true
return nil
}
}
t.Label(0, 0, fmt.Sprintf("Address: %s", a), tcell.StyleDefault)
t.FlexTable(1, 0, 0, &sel, &scroll, rows, flex, true)
return nil
}
}
func (mm *mmUI) messageDetail(mi msgInfo) func(*imtui.Tui) error {
baseFee, err := mm.srv.GetBaseFee(mm.ctx)
if err != nil {
return errUI(err)
}
_ = baseFee
m := mi.sm.Message
maxFee := big.Mul(m.GasFeeCap, big.NewInt(m.GasLimit))
issues := [][]string{}
for _, c := range mi.checks {
issues = append(issues, []string{c.Code.String(), c.Err})
}
issuesFlex := []int{1, 3}
var sel, scroll int
executeReprice := false
executeNoop := false
return func(t *imtui.Tui) error {
if executeReprice {
m.GasFeeCap = big.Div(maxFee, big.NewInt(m.GasLimit))
m.GasPremium = messagepool.ComputeMinRBF(m.GasPremium)
m.GasFeeCap = big.Max(m.GasFeeCap, m.GasPremium)
_, _, err := mm.srv.PublishMessage(mm.ctx, &api.MessagePrototype{
Message: m,
ValidNonce: true,
}, true)
if err != nil {
return err
}
t.PopScene()
return nil
}
if executeNoop {
nop := types.Message{
To: builtin.BurntFundsActorAddr,
From: m.From,
Nonce: m.Nonce,
Value: big.Zero(),
}
nop.GasPremium = messagepool.ComputeMinRBF(m.GasPremium)
_, _, err := mm.srv.PublishMessage(mm.ctx, &api.MessagePrototype{
Message: nop,
ValidNonce: true,
}, true)
if err != nil {
return xerrors.Errorf("publishing noop message: %w", err)
}
t.PopScene()
return nil
}
if t.CurrentKey != nil {
if t.CurrentKey.Key() == tcell.KeyLeft {
t.PopScene()
return nil
}
if t.CurrentKey.Key() == tcell.KeyRune {
switch t.CurrentKey.Rune() {
case 'R', 'r':
t.PushScene(feeUI(baseFee, m.GasLimit, &maxFee, &executeReprice))
return nil
case 'N', 'n':
t.PushScene(confirmationScene(
&executeNoop,
"Are you sure you want to cancel the message by",
"replacing it with a message with no effects?"))
return nil
}
}
}
row := 0
defS := tcell.StyleDefault
display := func(f string, args ...interface{}) {
t.Label(0, row, fmt.Sprintf(f, args...), defS)
row++
}
display("Message CID: %s", m.Cid())
display("Signed Message CID: %s", mi.sm.Cid())
row++
display("From: %s", m.From)
display("To: %s", m.To)
row++
display("Nonce: %d", m.Nonce)
display("Value: %s", types.FIL(m.Value))
row++
display("GasLimit: %d", m.GasLimit)
display("GasPremium: %s", types.FIL(m.GasPremium).Short())
display("GasFeeCap %s", types.FIL(m.GasFeeCap).Short())
row++
display("Press R to reprice this message")
display("Press N to replace this message with no-operation message")
row++
t.FlexTable(row, 0, 0, &sel, &scroll, issues, issuesFlex, false)
return nil
}
}
func confirmationScene(yes *bool, ask ...string) func(*imtui.Tui) error {
return func(t *imtui.Tui) error {
row := 0
defS := tcell.StyleDefault
display := func(f string, args ...interface{}) {
t.Label(0, row, fmt.Sprintf(f, args...), defS)
row++
}
for _, a := range ask {
display(a)
}
row++
display("Enter to confirm")
display("Esc to cancel")
if t.CurrentKey != nil {
if t.CurrentKey.Key() == tcell.KeyEnter {
*yes = true
t.PopScene()
return nil
}
}
return nil
}
}

View File

@ -95,11 +95,13 @@ var msigCreateCmd = &cli.Command{
return ShowHelp(cctx, fmt.Errorf("multisigs must have at least one signer"))
}
api, closer, err := GetFullNodeAPI(cctx)
srv, err := GetFullNodeServices(cctx)
if err != nil {
return err
}
defer closer()
defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := ReqContext(cctx)
var addrs []address.Address
@ -146,13 +148,20 @@ var msigCreateCmd = &cli.Command{
gp := types.NewInt(1)
msgCid, err := api.MsigCreate(ctx, required, addrs, d, intVal, sendAddr, gp)
proto, err := api.MsigCreate(ctx, required, addrs, d, intVal, sendAddr, gp)
if err != nil {
return err
}
sm, err := InteractiveSend(ctx, cctx, srv, proto)
if err != nil {
return err
}
msgCid := sm.Cid()
// wait for it to get mined into a block
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")), build.Finality, true)
if err != nil {
return err
}
@ -364,11 +373,13 @@ var msigProposeCmd = &cli.Command{
return ShowHelp(cctx, fmt.Errorf("must either pass three or five arguments"))
}
api, closer, err := GetFullNodeAPI(cctx)
srv, err := GetFullNodeServices(cctx)
if err != nil {
return err
}
defer closer()
defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0))
@ -426,14 +437,21 @@ var msigProposeCmd = &cli.Command{
return fmt.Errorf("actor %s is not a multisig actor", msig)
}
msgCid, err := api.MsigPropose(ctx, msig, dest, types.BigInt(value), from, method, params)
proto, err := api.MsigPropose(ctx, msig, dest, types.BigInt(value), from, method, params)
if err != nil {
return err
}
sm, err := InteractiveSend(ctx, cctx, srv, proto)
if err != nil {
return err
}
msgCid := sm.Cid()
fmt.Println("send proposal in message: ", msgCid)
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")), build.Finality, true)
if err != nil {
return err
}
@ -481,11 +499,13 @@ var msigApproveCmd = &cli.Command{
return ShowHelp(cctx, fmt.Errorf("usage: msig approve <msig addr> <message ID> <proposer address> <desination> <value> [ <method> <params> ]"))
}
api, closer, err := GetFullNodeAPI(cctx)
srv, err := GetFullNodeServices(cctx)
if err != nil {
return err
}
defer closer()
defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0))
@ -515,10 +535,17 @@ var msigApproveCmd = &cli.Command{
var msgCid cid.Cid
if cctx.Args().Len() == 2 {
msgCid, err = api.MsigApprove(ctx, msig, txid, from)
proto, err := api.MsigApprove(ctx, msig, txid, from)
if err != nil {
return err
}
sm, err := InteractiveSend(ctx, cctx, srv, proto)
if err != nil {
return err
}
msgCid = sm.Cid()
} else {
proposer, err := address.NewFromString(cctx.Args().Get(2))
if err != nil {
@ -558,15 +585,22 @@ var msigApproveCmd = &cli.Command{
params = p
}
msgCid, err = api.MsigApproveTxnHash(ctx, msig, txid, proposer, dest, types.BigInt(value), from, method, params)
proto, err := api.MsigApproveTxnHash(ctx, msig, txid, proposer, dest, types.BigInt(value), from, method, params)
if err != nil {
return err
}
sm, err := InteractiveSend(ctx, cctx, srv, proto)
if err != nil {
return err
}
msgCid = sm.Cid()
}
fmt.Println("sent approval in message: ", msgCid)
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")), build.Finality, true)
if err != nil {
return err
}
@ -598,11 +632,13 @@ var msigRemoveProposeCmd = &cli.Command{
return ShowHelp(cctx, fmt.Errorf("must pass multisig address and signer address"))
}
api, closer, err := GetFullNodeAPI(cctx)
srv, err := GetFullNodeServices(cctx)
if err != nil {
return err
}
defer closer()
defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0))
@ -630,14 +666,21 @@ var msigRemoveProposeCmd = &cli.Command{
from = defaddr
}
msgCid, err := api.MsigRemoveSigner(ctx, msig, from, addr, cctx.Bool("decrease-threshold"))
proto, err := api.MsigRemoveSigner(ctx, msig, from, addr, cctx.Bool("decrease-threshold"))
if err != nil {
return err
}
sm, err := InteractiveSend(ctx, cctx, srv, proto)
if err != nil {
return err
}
msgCid := sm.Cid()
fmt.Println("sent remove proposal in message: ", msgCid)
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")), build.Finality, true)
if err != nil {
return err
}
@ -676,11 +719,13 @@ var msigAddProposeCmd = &cli.Command{
return ShowHelp(cctx, fmt.Errorf("must pass multisig address and signer address"))
}
api, closer, err := GetFullNodeAPI(cctx)
srv, err := GetFullNodeServices(cctx)
if err != nil {
return err
}
defer closer()
defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0))
@ -708,14 +753,21 @@ var msigAddProposeCmd = &cli.Command{
from = defaddr
}
msgCid, err := api.MsigAddPropose(ctx, msig, from, addr, cctx.Bool("increase-threshold"))
proto, err := api.MsigAddPropose(ctx, msig, from, addr, cctx.Bool("increase-threshold"))
if err != nil {
return err
}
sm, err := InteractiveSend(ctx, cctx, srv, proto)
if err != nil {
return err
}
msgCid := sm.Cid()
fmt.Fprintln(cctx.App.Writer, "sent add proposal in message: ", msgCid)
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")), build.Finality, true)
if err != nil {
return err
}
@ -743,11 +795,13 @@ var msigAddApproveCmd = &cli.Command{
return ShowHelp(cctx, fmt.Errorf("must pass multisig address, proposer address, transaction id, new signer address, whether to increase threshold"))
}
api, closer, err := GetFullNodeAPI(cctx)
srv, err := GetFullNodeServices(cctx)
if err != nil {
return err
}
defer closer()
defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0))
@ -790,14 +844,21 @@ var msigAddApproveCmd = &cli.Command{
from = defaddr
}
msgCid, err := api.MsigAddApprove(ctx, msig, from, txid, prop, newAdd, inc)
proto, err := api.MsigAddApprove(ctx, msig, from, txid, prop, newAdd, inc)
if err != nil {
return err
}
sm, err := InteractiveSend(ctx, cctx, srv, proto)
if err != nil {
return err
}
msgCid := sm.Cid()
fmt.Println("sent add approval in message: ", msgCid)
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")), build.Finality, true)
if err != nil {
return err
}
@ -825,11 +886,13 @@ var msigAddCancelCmd = &cli.Command{
return ShowHelp(cctx, fmt.Errorf("must pass multisig address, transaction id, new signer address, whether to increase threshold"))
}
api, closer, err := GetFullNodeAPI(cctx)
srv, err := GetFullNodeServices(cctx)
if err != nil {
return err
}
defer closer()
defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0))
@ -867,14 +930,21 @@ var msigAddCancelCmd = &cli.Command{
from = defaddr
}
msgCid, err := api.MsigAddCancel(ctx, msig, from, txid, newAdd, inc)
proto, err := api.MsigAddCancel(ctx, msig, from, txid, newAdd, inc)
if err != nil {
return err
}
sm, err := InteractiveSend(ctx, cctx, srv, proto)
if err != nil {
return err
}
msgCid := sm.Cid()
fmt.Println("sent add cancellation in message: ", msgCid)
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")), build.Finality, true)
if err != nil {
return err
}
@ -902,11 +972,13 @@ var msigSwapProposeCmd = &cli.Command{
return ShowHelp(cctx, fmt.Errorf("must pass multisig address, old signer address, new signer address"))
}
api, closer, err := GetFullNodeAPI(cctx)
srv, err := GetFullNodeServices(cctx)
if err != nil {
return err
}
defer closer()
defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0))
@ -939,14 +1011,21 @@ var msigSwapProposeCmd = &cli.Command{
from = defaddr
}
msgCid, err := api.MsigSwapPropose(ctx, msig, from, oldAdd, newAdd)
proto, err := api.MsigSwapPropose(ctx, msig, from, oldAdd, newAdd)
if err != nil {
return err
}
sm, err := InteractiveSend(ctx, cctx, srv, proto)
if err != nil {
return err
}
msgCid := sm.Cid()
fmt.Println("sent swap proposal in message: ", msgCid)
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")), build.Finality, true)
if err != nil {
return err
}
@ -974,11 +1053,13 @@ var msigSwapApproveCmd = &cli.Command{
return ShowHelp(cctx, fmt.Errorf("must pass multisig address, proposer address, transaction id, old signer address, new signer address"))
}
api, closer, err := GetFullNodeAPI(cctx)
srv, err := GetFullNodeServices(cctx)
if err != nil {
return err
}
defer closer()
defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0))
@ -1021,14 +1102,21 @@ var msigSwapApproveCmd = &cli.Command{
from = defaddr
}
msgCid, err := api.MsigSwapApprove(ctx, msig, from, txid, prop, oldAdd, newAdd)
proto, err := api.MsigSwapApprove(ctx, msig, from, txid, prop, oldAdd, newAdd)
if err != nil {
return err
}
sm, err := InteractiveSend(ctx, cctx, srv, proto)
if err != nil {
return err
}
msgCid := sm.Cid()
fmt.Println("sent swap approval in message: ", msgCid)
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")), build.Finality, true)
if err != nil {
return err
}
@ -1056,11 +1144,13 @@ var msigSwapCancelCmd = &cli.Command{
return ShowHelp(cctx, fmt.Errorf("must pass multisig address, transaction id, old signer address, new signer address"))
}
api, closer, err := GetFullNodeAPI(cctx)
srv, err := GetFullNodeServices(cctx)
if err != nil {
return err
}
defer closer()
defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0))
@ -1098,14 +1188,21 @@ var msigSwapCancelCmd = &cli.Command{
from = defaddr
}
msgCid, err := api.MsigSwapCancel(ctx, msig, from, txid, oldAdd, newAdd)
proto, err := api.MsigSwapCancel(ctx, msig, from, txid, oldAdd, newAdd)
if err != nil {
return err
}
sm, err := InteractiveSend(ctx, cctx, srv, proto)
if err != nil {
return err
}
msgCid := sm.Cid()
fmt.Println("sent swap cancellation in message: ", msgCid)
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")), build.Finality, true)
if err != nil {
return err
}
@ -1133,11 +1230,13 @@ var msigLockProposeCmd = &cli.Command{
return ShowHelp(cctx, fmt.Errorf("must pass multisig address, start epoch, unlock duration, and amount"))
}
api, closer, err := GetFullNodeAPI(cctx)
srv, err := GetFullNodeServices(cctx)
if err != nil {
return err
}
defer closer()
defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0))
@ -1185,14 +1284,21 @@ var msigLockProposeCmd = &cli.Command{
return actErr
}
msgCid, err := api.MsigPropose(ctx, msig, msig, big.Zero(), from, uint64(multisig.Methods.LockBalance), params)
proto, err := api.MsigPropose(ctx, msig, msig, big.Zero(), from, uint64(multisig.Methods.LockBalance), params)
if err != nil {
return err
}
sm, err := InteractiveSend(ctx, cctx, srv, proto)
if err != nil {
return err
}
msgCid := sm.Cid()
fmt.Println("sent lock proposal in message: ", msgCid)
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")), build.Finality, true)
if err != nil {
return err
}
@ -1220,11 +1326,13 @@ var msigLockApproveCmd = &cli.Command{
return ShowHelp(cctx, fmt.Errorf("must pass multisig address, proposer address, tx id, start epoch, unlock duration, and amount"))
}
api, closer, err := GetFullNodeAPI(cctx)
srv, err := GetFullNodeServices(cctx)
if err != nil {
return err
}
defer closer()
defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0))
@ -1282,14 +1390,21 @@ var msigLockApproveCmd = &cli.Command{
return actErr
}
msgCid, err := api.MsigApproveTxnHash(ctx, msig, txid, prop, msig, big.Zero(), from, uint64(multisig.Methods.LockBalance), params)
proto, err := api.MsigApproveTxnHash(ctx, msig, txid, prop, msig, big.Zero(), from, uint64(multisig.Methods.LockBalance), params)
if err != nil {
return err
}
sm, err := InteractiveSend(ctx, cctx, srv, proto)
if err != nil {
return err
}
msgCid := sm.Cid()
fmt.Println("sent lock approval in message: ", msgCid)
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")), build.Finality, true)
if err != nil {
return err
}
@ -1317,11 +1432,13 @@ var msigLockCancelCmd = &cli.Command{
return ShowHelp(cctx, fmt.Errorf("must pass multisig address, tx id, start epoch, unlock duration, and amount"))
}
api, closer, err := GetFullNodeAPI(cctx)
srv, err := GetFullNodeServices(cctx)
if err != nil {
return err
}
defer closer()
defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0))
@ -1374,14 +1491,21 @@ var msigLockCancelCmd = &cli.Command{
return actErr
}
msgCid, err := api.MsigCancel(ctx, msig, txid, msig, big.Zero(), from, uint64(multisig.Methods.LockBalance), params)
proto, err := api.MsigCancel(ctx, msig, txid, msig, big.Zero(), from, uint64(multisig.Methods.LockBalance), params)
if err != nil {
return err
}
sm, err := InteractiveSend(ctx, cctx, srv, proto)
if err != nil {
return err
}
msgCid := sm.Cid()
fmt.Println("sent lock cancellation in message: ", msgCid)
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")), build.Finality, true)
if err != nil {
return err
}
@ -1471,11 +1595,13 @@ var msigProposeThresholdCmd = &cli.Command{
return ShowHelp(cctx, fmt.Errorf("must pass multisig address and new threshold value"))
}
api, closer, err := GetFullNodeAPI(cctx)
srv, err := GetFullNodeServices(cctx)
if err != nil {
return err
}
defer closer()
defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0))
@ -1511,14 +1637,21 @@ var msigProposeThresholdCmd = &cli.Command{
return actErr
}
msgCid, err := api.MsigPropose(ctx, msig, msig, types.NewInt(0), from, uint64(multisig.Methods.ChangeNumApprovalsThreshold), params)
proto, err := api.MsigPropose(ctx, msig, msig, types.NewInt(0), from, uint64(multisig.Methods.ChangeNumApprovalsThreshold), params)
if err != nil {
return fmt.Errorf("failed to propose change of threshold: %w", err)
}
sm, err := InteractiveSend(ctx, cctx, srv, proto)
if err != nil {
return err
}
msgCid := sm.Cid()
fmt.Println("sent change threshold proposal in message: ", msgCid)
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")), build.Finality, true)
if err != nil {
return err
}

View File

@ -2,7 +2,6 @@ package cli
import (
"encoding/hex"
"errors"
"fmt"
"github.com/urfave/cli/v2"
@ -59,10 +58,14 @@ var sendCmd = &cli.Command{
},
&cli.BoolFlag{
Name: "force",
Usage: "must be specified for the action to take effect if maybe SysErrInsufficientFunds etc",
Usage: "Deprecated: use global 'force-send'",
},
},
Action: func(cctx *cli.Context) error {
if cctx.IsSet("force") {
fmt.Println("'force' flag is deprecated, use global flag 'force-send'")
}
if cctx.Args().Len() != 2 {
return ShowHelp(cctx, fmt.Errorf("'send' expects two arguments, target and amount"))
}
@ -137,23 +140,22 @@ var sendCmd = &cli.Command{
params.Params = decparams
}
params.Force = cctx.Bool("force")
if cctx.IsSet("nonce") {
n := cctx.Uint64("nonce")
params.Nonce = &n
}
msgCid, err := srv.Send(ctx, params)
proto, err := srv.MessageForSend(ctx, params)
if err != nil {
if errors.Is(err, ErrSendBalanceTooLow) {
return fmt.Errorf("--force must be specified for this action to have an effect; you have been warned: %w", err)
}
return xerrors.Errorf("executing send: %w", err)
return xerrors.Errorf("creating message prototype: %w", err)
}
fmt.Fprintf(cctx.App.Writer, "%s\n", msgCid)
sm, err := InteractiveSend(ctx, cctx, srv, proto)
if err != nil {
return err
}
fmt.Fprintf(cctx.App.Writer, "%s\n", sm.Cid())
return nil
},
}

View File

@ -2,24 +2,17 @@ package cli
import (
"bytes"
"errors"
"testing"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/api"
types "github.com/filecoin-project/lotus/chain/types"
gomock "github.com/golang/mock/gomock"
cid "github.com/ipfs/go-cid"
"github.com/stretchr/testify/assert"
ucli "github.com/urfave/cli/v2"
)
var arbtCid = (&types.Message{
From: mustAddr(address.NewIDAddress(2)),
To: mustAddr(address.NewIDAddress(1)),
Value: types.NewInt(1000),
}).Cid()
func mustAddr(a address.Address, err error) address.Address {
if err != nil {
panic(err)
@ -49,80 +42,26 @@ func TestSendCLI(t *testing.T) {
app, mockSrvcs, buf, done := newMockApp(t, sendCmd)
defer done()
gomock.InOrder(
mockSrvcs.EXPECT().Send(gomock.Any(), SendParams{
To: mustAddr(address.NewIDAddress(1)),
Val: oneFil,
}).Return(arbtCid, nil),
mockSrvcs.EXPECT().Close(),
)
err := app.Run([]string{"lotus", "send", "t01", "1"})
assert.NoError(t, err)
assert.EqualValues(t, arbtCid.String()+"\n", buf.String())
})
t.Run("ErrSendBalanceTooLow", func(t *testing.T) {
app, mockSrvcs, _, done := newMockApp(t, sendCmd)
defer done()
gomock.InOrder(
mockSrvcs.EXPECT().Send(gomock.Any(), SendParams{
To: mustAddr(address.NewIDAddress(1)),
Val: oneFil,
}).Return(cid.Undef, ErrSendBalanceTooLow),
mockSrvcs.EXPECT().Close(),
)
err := app.Run([]string{"lotus", "send", "t01", "1"})
assert.ErrorIs(t, err, ErrSendBalanceTooLow)
})
t.Run("generic-err-is-forwarded", func(t *testing.T) {
app, mockSrvcs, _, done := newMockApp(t, sendCmd)
defer done()
errMark := errors.New("something")
gomock.InOrder(
mockSrvcs.EXPECT().Send(gomock.Any(), SendParams{
To: mustAddr(address.NewIDAddress(1)),
Val: oneFil,
}).Return(cid.Undef, errMark),
mockSrvcs.EXPECT().Close(),
)
err := app.Run([]string{"lotus", "send", "t01", "1"})
assert.ErrorIs(t, err, errMark)
})
t.Run("from-specific", func(t *testing.T) {
app, mockSrvcs, buf, done := newMockApp(t, sendCmd)
defer done()
gomock.InOrder(
mockSrvcs.EXPECT().Send(gomock.Any(), SendParams{
To: mustAddr(address.NewIDAddress(1)),
From: mustAddr(address.NewIDAddress(2)),
Val: oneFil,
}).Return(arbtCid, nil),
mockSrvcs.EXPECT().Close(),
)
err := app.Run([]string{"lotus", "send", "--from=t02", "t01", "1"})
assert.NoError(t, err)
assert.EqualValues(t, arbtCid.String()+"\n", buf.String())
})
t.Run("nonce-specific", func(t *testing.T) {
app, mockSrvcs, buf, done := newMockApp(t, sendCmd)
defer done()
zero := uint64(0)
gomock.InOrder(
mockSrvcs.EXPECT().Send(gomock.Any(), SendParams{
arbtProto := &api.MessagePrototype{
Message: types.Message{
From: mustAddr(address.NewIDAddress(1)),
To: mustAddr(address.NewIDAddress(1)),
Nonce: &zero,
Val: oneFil,
}).Return(arbtCid, nil),
Value: oneFil,
},
}
sigMsg := fakeSign(&arbtProto.Message)
gomock.InOrder(
mockSrvcs.EXPECT().MessageForSend(gomock.Any(), SendParams{
To: mustAddr(address.NewIDAddress(1)),
Val: oneFil,
}).Return(arbtProto, nil),
mockSrvcs.EXPECT().PublishMessage(gomock.Any(), arbtProto, false).
Return(sigMsg, nil, nil),
mockSrvcs.EXPECT().Close(),
)
err := app.Run([]string{"lotus", "send", "--nonce=0", "t01", "1"})
err := app.Run([]string{"lotus", "send", "t01", "1"})
assert.NoError(t, err)
assert.EqualValues(t, arbtCid.String()+"\n", buf.String())
assert.EqualValues(t, sigMsg.Cid().String()+"\n", buf.String())
})
}

264
cli/sending_ui.go Normal file
View File

@ -0,0 +1,264 @@
package cli
import (
"context"
"errors"
"fmt"
"io"
"strings"
"github.com/Kubuxu/imtui"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
types "github.com/filecoin-project/lotus/chain/types"
"github.com/gdamore/tcell/v2"
cid "github.com/ipfs/go-cid"
"github.com/urfave/cli/v2"
"golang.org/x/xerrors"
)
func InteractiveSend(ctx context.Context, cctx *cli.Context, srv ServicesAPI,
proto *api.MessagePrototype) (*types.SignedMessage, error) {
msg, checks, err := srv.PublishMessage(ctx, proto, cctx.Bool("force") || cctx.Bool("force-send"))
printer := cctx.App.Writer
if xerrors.Is(err, ErrCheckFailed) {
if !cctx.Bool("interactive") {
fmt.Fprintf(printer, "Following checks have failed:\n")
printChecks(printer, checks, proto.Message.Cid())
} else {
proto, err = resolveChecks(ctx, srv, cctx.App.Writer, proto, checks)
if err != nil {
return nil, xerrors.Errorf("from UI: %w", err)
}
msg, _, err = srv.PublishMessage(ctx, proto, true)
}
}
if err != nil {
return nil, xerrors.Errorf("publishing message: %w", err)
}
return msg, nil
}
var interactiveSolves = map[api.CheckStatusCode]bool{
api.CheckStatusMessageMinBaseFee: true,
api.CheckStatusMessageBaseFee: true,
api.CheckStatusMessageBaseFeeLowerBound: true,
api.CheckStatusMessageBaseFeeUpperBound: true,
}
func baseFeeFromHints(hint map[string]interface{}) big.Int {
bHint, ok := hint["baseFee"]
if !ok {
return big.Zero()
}
bHintS, ok := bHint.(string)
if !ok {
return big.Zero()
}
var err error
baseFee, err := big.FromString(bHintS)
if err != nil {
return big.Zero()
}
return baseFee
}
func resolveChecks(ctx context.Context, s ServicesAPI, printer io.Writer,
proto *api.MessagePrototype, checkGroups [][]api.MessageCheckStatus,
) (*api.MessagePrototype, error) {
fmt.Fprintf(printer, "Following checks have failed:\n")
printChecks(printer, checkGroups, proto.Message.Cid())
if feeCapBad, baseFee := isFeeCapProblem(checkGroups, proto.Message.Cid()); feeCapBad {
fmt.Fprintf(printer, "Fee of the message can be adjusted\n")
if askUser(printer, "Do you wish to do that? [Yes/no]: ", true) {
var err error
proto, err = runFeeCapAdjustmentUI(proto, baseFee)
if err != nil {
return nil, err
}
}
checks, err := s.RunChecksForPrototype(ctx, proto)
if err != nil {
return nil, err
}
fmt.Fprintf(printer, "Following checks still failed:\n")
printChecks(printer, checks, proto.Message.Cid())
}
if !askUser(printer, "Do you wish to send this message? [yes/No]: ", false) {
return nil, ErrAbortedByUser
}
return proto, nil
}
var ErrAbortedByUser = errors.New("aborted by user")
func printChecks(printer io.Writer, checkGroups [][]api.MessageCheckStatus, protoCid cid.Cid) {
for _, checks := range checkGroups {
for _, c := range checks {
if c.OK {
continue
}
aboutProto := c.Cid.Equals(protoCid)
msgName := "current"
if !aboutProto {
msgName = c.Cid.String()
}
fmt.Fprintf(printer, "%s message failed a check %s: %s\n", msgName, c.Code, c.Err)
}
}
}
func askUser(printer io.Writer, q string, def bool) bool {
var resp string
fmt.Fprint(printer, q)
fmt.Scanln(&resp)
resp = strings.ToLower(resp)
if len(resp) == 0 {
return def
}
return resp[0] == 'y'
}
func isFeeCapProblem(checkGroups [][]api.MessageCheckStatus, protoCid cid.Cid) (bool, big.Int) {
baseFee := big.Zero()
yes := false
for _, checks := range checkGroups {
for _, c := range checks {
if c.OK {
continue
}
aboutProto := c.Cid.Equals(protoCid)
if aboutProto && interactiveSolves[c.Code] {
yes = true
if baseFee.IsZero() {
baseFee = baseFeeFromHints(c.Hint)
}
}
}
}
if baseFee.IsZero() {
// this will only be the case if failing check is: MessageMinBaseFee
baseFee = big.NewInt(build.MinimumBaseFee)
}
return yes, baseFee
}
func runFeeCapAdjustmentUI(proto *api.MessagePrototype, baseFee abi.TokenAmount) (*api.MessagePrototype, error) {
t, err := imtui.NewTui()
if err != nil {
return nil, err
}
maxFee := big.Mul(proto.Message.GasFeeCap, big.NewInt(proto.Message.GasLimit))
send := false
t.PushScene(feeUI(baseFee, proto.Message.GasLimit, &maxFee, &send))
err = t.Run()
if err != nil {
return nil, err
}
if !send {
return nil, fmt.Errorf("aborted by user")
}
proto.Message.GasFeeCap = big.Div(maxFee, big.NewInt(proto.Message.GasLimit))
return proto, nil
}
func feeUI(baseFee abi.TokenAmount, gasLimit int64, maxFee *abi.TokenAmount, send *bool) func(*imtui.Tui) error {
orignalMaxFee := *maxFee
required := big.Mul(baseFee, big.NewInt(gasLimit))
safe := big.Mul(required, big.NewInt(10))
price := fmt.Sprintf("%s", types.FIL(*maxFee).Unitless())
return func(t *imtui.Tui) error {
if t.CurrentKey != nil {
if t.CurrentKey.Key() == tcell.KeyRune {
pF, err := types.ParseFIL(price)
switch t.CurrentKey.Rune() {
case 's', 'S':
price = types.FIL(safe).Unitless()
case '+':
if err == nil {
p := big.Mul(big.Int(pF), types.NewInt(11))
p = big.Div(p, types.NewInt(10))
price = fmt.Sprintf("%s", types.FIL(p).Unitless())
}
case '-':
if err == nil {
p := big.Mul(big.Int(pF), types.NewInt(10))
p = big.Div(p, types.NewInt(11))
price = fmt.Sprintf("%s", types.FIL(p).Unitless())
}
default:
}
}
if t.CurrentKey.Key() == tcell.KeyEnter {
*send = true
t.PopScene()
return nil
}
}
defS := tcell.StyleDefault
row := 0
t.Label(0, row, "Fee of the message is too low.", defS)
row++
t.Label(0, row, fmt.Sprintf("Your configured maximum fee is: %s FIL",
types.FIL(orignalMaxFee).Unitless()), defS)
row++
t.Label(0, row, fmt.Sprintf("Required maximum fee for the message: %s FIL",
types.FIL(required).Unitless()), defS)
row++
w := t.Label(0, row, fmt.Sprintf("Safe maximum fee for the message: %s FIL",
types.FIL(safe).Unitless()), defS)
t.Label(w, row, " Press S to use it", defS)
row++
w = t.Label(0, row, "Current Maximum Fee: ", defS)
w += t.EditFieldFiltered(w, row, 14, &price, imtui.FilterDecimal, defS.Foreground(tcell.ColorWhite).Background(tcell.ColorBlack))
w += t.Label(w, row, " FIL", defS)
pF, err := types.ParseFIL(price)
*maxFee = abi.TokenAmount(pF)
if err != nil {
w += t.Label(w, row, " invalid price", defS.Foreground(tcell.ColorMaroon).Bold(true))
} else if maxFee.GreaterThanEqual(safe) {
w += t.Label(w, row, " SAFE", defS.Foreground(tcell.ColorDarkGreen).Bold(true))
} else if maxFee.GreaterThanEqual(required) {
w += t.Label(w, row, " low", defS.Foreground(tcell.ColorYellow).Bold(true))
over := big.Div(big.Mul(*maxFee, big.NewInt(100)), required)
w += t.Label(w, row,
fmt.Sprintf(" %.1fx over the minimum", float64(over.Int64())/100.0), defS)
} else {
w += t.Label(w, row, " too low", defS.Foreground(tcell.ColorRed).Bold(true))
}
row += 2
t.Label(0, row, fmt.Sprintf("Current Base Fee is: %s", types.FIL(baseFee).Nano()), defS)
row++
t.Label(0, row, fmt.Sprintf("Resulting FeeCap is: %s",
types.FIL(big.Div(*maxFee, big.NewInt(gasLimit))).Nano()), defS)
row++
t.Label(0, row, "You can use '+' and '-' to adjust the fee.", defS)
return nil
}
}

View File

@ -4,14 +4,14 @@ import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"reflect"
"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/v0api"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/stmgr"
types "github.com/filecoin-project/lotus/chain/types"
cid "github.com/ipfs/go-cid"
@ -22,12 +22,30 @@ import (
//go:generate go run github.com/golang/mock/mockgen -destination=servicesmock_test.go -package=cli -self_package github.com/filecoin-project/lotus/cli . ServicesAPI
type ServicesAPI interface {
// Sends executes a send given SendParams
Send(ctx context.Context, params SendParams) (cid.Cid, error)
FullNodeAPI() api.FullNode
GetBaseFee(ctx context.Context) (abi.TokenAmount, error)
// MessageForSend creates a prototype of a message based on SendParams
MessageForSend(ctx context.Context, params SendParams) (*api.MessagePrototype, error)
// DecodeTypedParamsFromJSON takes in information needed to identify a method and converts JSON
// parameters to bytes of their CBOR encoding
DecodeTypedParamsFromJSON(ctx context.Context, to address.Address, method abi.MethodNum, paramstr string) ([]byte, error)
RunChecksForPrototype(ctx context.Context, prototype *api.MessagePrototype) ([][]api.MessageCheckStatus, error)
// PublishMessage takes in a message prototype and publishes it
// before publishing the message, it runs checks on the node, message and mpool to verify that
// message is valid and won't be stuck.
// if `force` is true, it skips the checks
PublishMessage(ctx context.Context, prototype *api.MessagePrototype, force bool) (*types.SignedMessage, [][]api.MessageCheckStatus, error)
LocalAddresses(ctx context.Context) (address.Address, []address.Address, error)
MpoolPendingFilter(ctx context.Context, filter func(*types.SignedMessage) bool, tsk types.TipSetKey) ([]*types.SignedMessage, error)
MpoolCheckPendingMessages(ctx context.Context, a address.Address) ([][]api.MessageCheckStatus, error)
// Close ends the session of services and disconnects from RPC, using Services after Close is called
// most likely will result in an error
// Should not be called concurrently
@ -35,10 +53,14 @@ type ServicesAPI interface {
}
type ServicesImpl struct {
api v0api.FullNode
api api.FullNode
closer jsonrpc.ClientCloser
}
func (s *ServicesImpl) FullNodeAPI() api.FullNode {
return s.api
}
func (s *ServicesImpl) Close() error {
if s.closer == nil {
return xerrors.Errorf("Services already closed")
@ -48,6 +70,16 @@ func (s *ServicesImpl) Close() error {
return nil
}
func (s *ServicesImpl) GetBaseFee(ctx context.Context) (abi.TokenAmount, error) {
// not used but useful
ts, err := s.api.ChainHead(ctx)
if err != nil {
return big.Zero(), xerrors.Errorf("getting head: %w", err)
}
return ts.MinTicketBlock().ParentBaseFee, nil
}
func (s *ServicesImpl) DecodeTypedParamsFromJSON(ctx context.Context, to address.Address, method abi.MethodNum, paramstr string) ([]byte, error) {
act, err := s.api.StateGetActor(ctx, to, types.EmptyTSK)
if err != nil {
@ -72,6 +104,79 @@ func (s *ServicesImpl) DecodeTypedParamsFromJSON(ctx context.Context, to address
return buf.Bytes(), nil
}
type CheckInfo struct {
MessageTie cid.Cid
CurrentMessageTie bool
Check api.MessageCheckStatus
}
var ErrCheckFailed = fmt.Errorf("check has failed")
func (s *ServicesImpl) RunChecksForPrototype(ctx context.Context, prototype *api.MessagePrototype) ([][]api.MessageCheckStatus, error) {
var outChecks [][]api.MessageCheckStatus
checks, err := s.api.MpoolCheckMessages(ctx, []*api.MessagePrototype{prototype})
if err != nil {
return nil, xerrors.Errorf("message check: %w", err)
}
outChecks = append(outChecks, checks...)
checks, err = s.api.MpoolCheckPendingMessages(ctx, prototype.Message.From)
if err != nil {
return nil, xerrors.Errorf("pending mpool check: %w", err)
}
outChecks = append(outChecks, checks...)
return outChecks, nil
}
// PublishMessage modifies prototype to include gas estimation
// Errors with ErrCheckFailed if any of the checks fail
// First group of checks is related to the message prototype
func (s *ServicesImpl) PublishMessage(ctx context.Context,
prototype *api.MessagePrototype, force bool) (*types.SignedMessage, [][]api.MessageCheckStatus, error) {
gasedMsg, err := s.api.GasEstimateMessageGas(ctx, &prototype.Message, nil, types.EmptyTSK)
if err != nil {
return nil, nil, xerrors.Errorf("estimating gas: %w", err)
}
prototype.Message = *gasedMsg
if !force {
checks, err := s.RunChecksForPrototype(ctx, prototype)
if err != nil {
return nil, nil, xerrors.Errorf("running checks: %w", err)
}
for _, chks := range checks {
for _, c := range chks {
if !c.OK {
return nil, checks, ErrCheckFailed
}
}
}
}
if prototype.ValidNonce {
sm, err := s.api.WalletSignMessage(ctx, prototype.Message.From, &prototype.Message)
if err != nil {
return nil, nil, err
}
_, err = s.api.MpoolPush(ctx, sm)
if err != nil {
return nil, nil, err
}
return sm, nil, nil
}
sm, err := s.api.MpoolPushMessage(ctx, &prototype.Message, nil)
if err != nil {
return nil, nil, err
}
return sm, nil, nil
}
type SendParams struct {
To address.Address
From address.Address
@ -84,26 +189,18 @@ type SendParams struct {
Nonce *uint64
Method abi.MethodNum
Params []byte
Force bool
}
// This is specialised Send for Send command
// There might be room for generic Send that other commands can use to send their messages
// We will see
var ErrSendBalanceTooLow = errors.New("balance too low")
func (s *ServicesImpl) Send(ctx context.Context, params SendParams) (cid.Cid, error) {
func (s *ServicesImpl) MessageForSend(ctx context.Context, params SendParams) (*api.MessagePrototype, error) {
if params.From == address.Undef {
defaddr, err := s.api.WalletDefaultAddress(ctx)
if err != nil {
return cid.Undef, err
return nil, err
}
params.From = defaddr
}
msg := &types.Message{
msg := types.Message{
From: params.From,
To: params.To,
Value: params.Val,
@ -127,40 +224,53 @@ func (s *ServicesImpl) Send(ctx context.Context, params SendParams) (cid.Cid, er
} else {
msg.GasLimit = 0
}
if !params.Force {
// Funds insufficient check
fromBalance, err := s.api.WalletBalance(ctx, msg.From)
if err != nil {
return cid.Undef, err
}
totalCost := types.BigAdd(types.BigMul(msg.GasFeeCap, types.NewInt(uint64(msg.GasLimit))), msg.Value)
if fromBalance.LessThan(totalCost) {
return cid.Undef, xerrors.Errorf("From balance %s less than total cost %s: %w", types.FIL(fromBalance), types.FIL(totalCost), ErrSendBalanceTooLow)
}
}
validNonce := false
if params.Nonce != nil {
msg.Nonce = *params.Nonce
sm, err := s.api.WalletSignMessage(ctx, params.From, msg)
if err != nil {
return cid.Undef, err
}
_, err = s.api.MpoolPush(ctx, sm)
if err != nil {
return cid.Undef, err
}
return sm.Cid(), nil
validNonce = true
}
sm, err := s.api.MpoolPushMessage(ctx, msg, nil)
if err != nil {
return cid.Undef, err
prototype := &api.MessagePrototype{
Message: msg,
ValidNonce: validNonce,
}
return sm.Cid(), nil
return prototype, nil
}
func (s *ServicesImpl) MpoolPendingFilter(ctx context.Context, filter func(*types.SignedMessage) bool,
tsk types.TipSetKey) ([]*types.SignedMessage, error) {
msgs, err := s.api.MpoolPending(ctx, types.EmptyTSK)
if err != nil {
return nil, xerrors.Errorf("getting pending messages: %w", err)
}
out := []*types.SignedMessage{}
for _, sm := range msgs {
if filter(sm) {
out = append(out, sm)
}
}
return out, nil
}
func (s *ServicesImpl) LocalAddresses(ctx context.Context) (address.Address, []address.Address, error) {
def, err := s.api.WalletDefaultAddress(ctx)
if err != nil {
return address.Undef, nil, xerrors.Errorf("getting default addr: %w", err)
}
all, err := s.api.WalletList(ctx)
if err != nil {
return address.Undef, nil, xerrors.Errorf("getting list of addrs: %w", err)
}
return def, all, nil
}
func (s *ServicesImpl) MpoolCheckPendingMessages(ctx context.Context, a address.Address) ([][]api.MessageCheckStatus, error) {
checks, err := s.api.MpoolCheckPendingMessages(ctx, a)
if err != nil {
return nil, xerrors.Errorf("pending mpool check: %w", err)
}
return checks, nil
}

View File

@ -9,10 +9,9 @@ import (
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/lotus/api"
mocks "github.com/filecoin-project/lotus/api/v0api/v0mocks"
mocks "github.com/filecoin-project/lotus/api/mocks"
types "github.com/filecoin-project/lotus/chain/types"
gomock "github.com/golang/mock/gomock"
cid "github.com/ipfs/go-cid"
"github.com/stretchr/testify/assert"
)
@ -61,6 +60,7 @@ func setupMockSrvcs(t *testing.T) (*ServicesImpl, *mocks.MockFullNode) {
return srvcs, mockApi
}
// linter doesn't like dead code, so these are commented out.
func fakeSign(msg *types.Message) *types.SignedMessage {
return &types.SignedMessage{
Message: *msg,
@ -68,15 +68,15 @@ func fakeSign(msg *types.Message) *types.SignedMessage {
}
}
func makeMessageSigner() (*cid.Cid, interface{}) {
smCid := cid.Undef
return &smCid,
func(_ context.Context, msg *types.Message, _ *api.MessageSendSpec) (*types.SignedMessage, error) {
sm := fakeSign(msg)
smCid = sm.Cid()
return sm, nil
}
}
//func makeMessageSigner() (*cid.Cid, interface{}) {
//smCid := cid.Undef
//return &smCid,
//func(_ context.Context, msg *types.Message, _ *api.MessageSendSpec) (*types.SignedMessage, error) {
//sm := fakeSign(msg)
//smCid = sm.Cid()
//return sm, nil
//}
//}
type MessageMatcher SendParams
@ -84,11 +84,13 @@ var _ gomock.Matcher = MessageMatcher{}
// Matches returns whether x is a match.
func (mm MessageMatcher) Matches(x interface{}) bool {
m, ok := x.(*types.Message)
proto, ok := x.(*api.MessagePrototype)
if !ok {
return false
}
m := &proto.Message
if mm.From != address.Undef && mm.From != m.From {
return false
}
@ -151,47 +153,12 @@ func TestSendService(t *testing.T) {
t.Run("happy", func(t *testing.T) {
params := params
srvcs, mockApi := setupMockSrvcs(t)
srvcs, _ := setupMockSrvcs(t)
defer srvcs.Close() //nolint:errcheck
msgCid, sign := makeMessageSigner()
gomock.InOrder(
mockApi.EXPECT().WalletBalance(ctxM, params.From).Return(types.NewInt(balance), nil),
mockApi.EXPECT().MpoolPushMessage(ctxM, MessageMatcher(params), nil).DoAndReturn(sign),
)
c, err := srvcs.Send(ctx, params)
proto, err := srvcs.MessageForSend(ctx, params)
assert.NoError(t, err)
assert.Equal(t, *msgCid, c)
})
t.Run("balance-too-low", func(t *testing.T) {
params := params
srvcs, mockApi := setupMockSrvcs(t)
defer srvcs.Close() //nolint:errcheck
gomock.InOrder(
mockApi.EXPECT().WalletBalance(ctxM, a1).Return(types.NewInt(balance-200), nil),
// no MpoolPushMessage
)
c, err := srvcs.Send(ctx, params)
assert.Equal(t, c, cid.Undef)
assert.ErrorIs(t, err, ErrSendBalanceTooLow)
})
t.Run("force", func(t *testing.T) {
params := params
params.Force = true
srvcs, mockApi := setupMockSrvcs(t)
defer srvcs.Close() //nolint:errcheck
msgCid, sign := makeMessageSigner()
gomock.InOrder(
mockApi.EXPECT().WalletBalance(ctxM, a1).Return(types.NewInt(balance-200), nil).AnyTimes(),
mockApi.EXPECT().MpoolPushMessage(ctxM, MessageMatcher(params), nil).DoAndReturn(sign),
)
c, err := srvcs.Send(ctx, params)
assert.NoError(t, err)
assert.Equal(t, *msgCid, c)
assert.True(t, MessageMatcher(params).Matches(proto))
})
t.Run("default-from", func(t *testing.T) {
@ -202,16 +169,14 @@ func TestSendService(t *testing.T) {
srvcs, mockApi := setupMockSrvcs(t)
defer srvcs.Close() //nolint:errcheck
msgCid, sign := makeMessageSigner()
gomock.InOrder(
mockApi.EXPECT().WalletDefaultAddress(ctxM).Return(a1, nil),
mockApi.EXPECT().WalletBalance(ctxM, a1).Return(types.NewInt(balance), nil),
mockApi.EXPECT().MpoolPushMessage(ctxM, mm, nil).DoAndReturn(sign),
)
c, err := srvcs.Send(ctx, params)
proto, err := srvcs.MessageForSend(ctx, params)
assert.NoError(t, err)
assert.Equal(t, *msgCid, c)
assert.True(t, mm.Matches(proto))
})
t.Run("set-nonce", func(t *testing.T) {
@ -220,26 +185,12 @@ func TestSendService(t *testing.T) {
params.Nonce = &n
mm := MessageMatcher(params)
srvcs, mockApi := setupMockSrvcs(t)
srvcs, _ := setupMockSrvcs(t)
defer srvcs.Close() //nolint:errcheck
_, _ = mm, mockApi
var sm *types.SignedMessage
gomock.InOrder(
mockApi.EXPECT().WalletBalance(ctxM, a1).Return(types.NewInt(balance), nil),
mockApi.EXPECT().WalletSignMessage(ctxM, a1, mm).DoAndReturn(
func(_ context.Context, _ address.Address, msg *types.Message) (*types.SignedMessage, error) {
sm = fakeSign(msg)
// now we expect MpoolPush with that SignedMessage
mockApi.EXPECT().MpoolPush(ctxM, sm).Return(sm.Cid(), nil)
return sm, nil
}),
)
c, err := srvcs.Send(ctx, params)
proto, err := srvcs.MessageForSend(ctx, params)
assert.NoError(t, err)
assert.Equal(t, sm.Cid(), c)
assert.True(t, mm.Matches(proto))
})
t.Run("gas-params", func(t *testing.T) {
@ -251,16 +202,14 @@ func TestSendService(t *testing.T) {
gp := big.NewInt(10)
params.GasPremium = &gp
srvcs, mockApi := setupMockSrvcs(t)
defer srvcs.Close() //nolint:errcheck
msgCid, sign := makeMessageSigner()
gomock.InOrder(
mockApi.EXPECT().WalletBalance(ctxM, params.From).Return(types.NewInt(balance), nil),
mockApi.EXPECT().MpoolPushMessage(ctxM, MessageMatcher(params), nil).DoAndReturn(sign),
)
mm := MessageMatcher(params)
c, err := srvcs.Send(ctx, params)
srvcs, _ := setupMockSrvcs(t)
defer srvcs.Close() //nolint:errcheck
proto, err := srvcs.MessageForSend(ctx, params)
assert.NoError(t, err)
assert.Equal(t, *msgCid, c)
assert.True(t, mm.Matches(proto))
})
}

View File

@ -8,8 +8,10 @@ import (
context "context"
go_address "github.com/filecoin-project/go-address"
abi "github.com/filecoin-project/go-state-types/abi"
big "github.com/filecoin-project/go-state-types/big"
api "github.com/filecoin-project/lotus/api"
types "github.com/filecoin-project/lotus/chain/types"
gomock "github.com/golang/mock/gomock"
go_cid "github.com/ipfs/go-cid"
reflect "reflect"
)
@ -65,17 +67,123 @@ func (mr *MockServicesAPIMockRecorder) DecodeTypedParamsFromJSON(arg0, arg1, arg
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DecodeTypedParamsFromJSON", reflect.TypeOf((*MockServicesAPI)(nil).DecodeTypedParamsFromJSON), arg0, arg1, arg2, arg3)
}
// Send mocks base method
func (m *MockServicesAPI) Send(arg0 context.Context, arg1 SendParams) (go_cid.Cid, error) {
// FullNodeAPI mocks base method
func (m *MockServicesAPI) FullNodeAPI() api.FullNode {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Send", arg0, arg1)
ret0, _ := ret[0].(go_cid.Cid)
ret := m.ctrl.Call(m, "FullNodeAPI")
ret0, _ := ret[0].(api.FullNode)
return ret0
}
// FullNodeAPI indicates an expected call of FullNodeAPI
func (mr *MockServicesAPIMockRecorder) FullNodeAPI() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FullNodeAPI", reflect.TypeOf((*MockServicesAPI)(nil).FullNodeAPI))
}
// GetBaseFee mocks base method
func (m *MockServicesAPI) GetBaseFee(arg0 context.Context) (big.Int, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetBaseFee", arg0)
ret0, _ := ret[0].(big.Int)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Send indicates an expected call of Send
func (mr *MockServicesAPIMockRecorder) Send(arg0, arg1 interface{}) *gomock.Call {
// GetBaseFee indicates an expected call of GetBaseFee
func (mr *MockServicesAPIMockRecorder) GetBaseFee(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Send", reflect.TypeOf((*MockServicesAPI)(nil).Send), arg0, arg1)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBaseFee", reflect.TypeOf((*MockServicesAPI)(nil).GetBaseFee), arg0)
}
// LocalAddresses mocks base method
func (m *MockServicesAPI) LocalAddresses(arg0 context.Context) (go_address.Address, []go_address.Address, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "LocalAddresses", arg0)
ret0, _ := ret[0].(go_address.Address)
ret1, _ := ret[1].([]go_address.Address)
ret2, _ := ret[2].(error)
return ret0, ret1, ret2
}
// LocalAddresses indicates an expected call of LocalAddresses
func (mr *MockServicesAPIMockRecorder) LocalAddresses(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LocalAddresses", reflect.TypeOf((*MockServicesAPI)(nil).LocalAddresses), arg0)
}
// MessageForSend mocks base method
func (m *MockServicesAPI) MessageForSend(arg0 context.Context, arg1 SendParams) (*api.MessagePrototype, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MessageForSend", arg0, arg1)
ret0, _ := ret[0].(*api.MessagePrototype)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// MessageForSend indicates an expected call of MessageForSend
func (mr *MockServicesAPIMockRecorder) MessageForSend(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MessageForSend", reflect.TypeOf((*MockServicesAPI)(nil).MessageForSend), arg0, arg1)
}
// MpoolCheckPendingMessages mocks base method
func (m *MockServicesAPI) MpoolCheckPendingMessages(arg0 context.Context, arg1 go_address.Address) ([][]api.MessageCheckStatus, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MpoolCheckPendingMessages", arg0, arg1)
ret0, _ := ret[0].([][]api.MessageCheckStatus)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// MpoolCheckPendingMessages indicates an expected call of MpoolCheckPendingMessages
func (mr *MockServicesAPIMockRecorder) MpoolCheckPendingMessages(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MpoolCheckPendingMessages", reflect.TypeOf((*MockServicesAPI)(nil).MpoolCheckPendingMessages), arg0, arg1)
}
// MpoolPendingFilter mocks base method
func (m *MockServicesAPI) MpoolPendingFilter(arg0 context.Context, arg1 func(*types.SignedMessage) bool, arg2 types.TipSetKey) ([]*types.SignedMessage, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MpoolPendingFilter", arg0, arg1, arg2)
ret0, _ := ret[0].([]*types.SignedMessage)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// MpoolPendingFilter indicates an expected call of MpoolPendingFilter
func (mr *MockServicesAPIMockRecorder) MpoolPendingFilter(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MpoolPendingFilter", reflect.TypeOf((*MockServicesAPI)(nil).MpoolPendingFilter), arg0, arg1, arg2)
}
// PublishMessage mocks base method
func (m *MockServicesAPI) PublishMessage(arg0 context.Context, arg1 *api.MessagePrototype, arg2 bool) (*types.SignedMessage, [][]api.MessageCheckStatus, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "PublishMessage", arg0, arg1, arg2)
ret0, _ := ret[0].(*types.SignedMessage)
ret1, _ := ret[1].([][]api.MessageCheckStatus)
ret2, _ := ret[2].(error)
return ret0, ret1, ret2
}
// PublishMessage indicates an expected call of PublishMessage
func (mr *MockServicesAPIMockRecorder) PublishMessage(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PublishMessage", reflect.TypeOf((*MockServicesAPI)(nil).PublishMessage), arg0, arg1, arg2)
}
// RunChecksForPrototype mocks base method
func (m *MockServicesAPI) RunChecksForPrototype(arg0 context.Context, arg1 *api.MessagePrototype) ([][]api.MessageCheckStatus, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "RunChecksForPrototype", arg0, arg1)
ret0, _ := ret[0].([][]api.MessageCheckStatus)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// RunChecksForPrototype indicates an expected call of RunChecksForPrototype
func (mr *MockServicesAPIMockRecorder) RunChecksForPrototype(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RunChecksForPrototype", reflect.TypeOf((*MockServicesAPI)(nil).RunChecksForPrototype), arg0, arg1)
}

60
cli/status.go Normal file
View File

@ -0,0 +1,60 @@
package cli
import (
"fmt"
"github.com/urfave/cli/v2"
"github.com/filecoin-project/lotus/build"
)
var StatusCmd = &cli.Command{
Name: "status",
Usage: "Check node status",
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "chain",
Usage: "include chain health status",
},
},
Action: func(cctx *cli.Context) error {
apic, closer, err := GetFullNodeAPIV1(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
inclChainStatus := cctx.Bool("chain")
status, err := apic.NodeStatus(ctx, inclChainStatus)
if err != nil {
return err
}
fmt.Printf("Sync Epoch: %d\n", status.SyncStatus.Epoch)
fmt.Printf("Epochs Behind: %d\n", status.SyncStatus.Behind)
fmt.Printf("Peers to Publish Messages: %d\n", status.PeerStatus.PeersToPublishMsgs)
fmt.Printf("Peers to Publish Blocks: %d\n", status.PeerStatus.PeersToPublishBlocks)
if inclChainStatus && status.SyncStatus.Epoch > uint64(build.Finality) {
var ok100, okFin string
if status.ChainStatus.BlocksPerTipsetLast100 >= 4.75 {
ok100 = "[OK]"
} else {
ok100 = "[UNHEALTHY]"
}
if status.ChainStatus.BlocksPerTipsetLastFinality >= 4.75 {
okFin = "[OK]"
} else {
okFin = "[UNHEALTHY]"
}
fmt.Printf("Blocks per TipSet in last 100 epochs: %f %s\n", status.ChainStatus.BlocksPerTipsetLast100, ok100)
fmt.Printf("Blocks per TipSet in last finality: %f %s\n", status.ChainStatus.BlocksPerTipsetLastFinality, okFin)
}
return nil
},
}

View File

@ -56,7 +56,7 @@ type MockCLIClient struct {
func (c *MockCLIClient) RunCmd(input ...string) string {
out, err := c.RunCmdRaw(input...)
require.NoError(c.t, err)
require.NoError(c.t, err, "output:\n%s", out)
return out
}

View File

@ -9,4 +9,6 @@ func QuietMiningLogs() {
_ = log.SetLogLevel("sub", "ERROR")
_ = log.SetLogLevel("storageminer", "ERROR")
_ = log.SetLogLevel("pubsub", "ERROR")
_ = log.SetLogLevel("gen", "ERROR")
_ = log.SetLogLevel("dht/RtRefreshManager", "ERROR")
}

View File

@ -18,6 +18,8 @@ import (
"github.com/stretchr/testify/require"
"golang.org/x/xerrors"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-jsonrpc"
"github.com/filecoin-project/go-state-types/abi"
@ -102,7 +104,28 @@ func TestWalletMsig(t *testing.T) {
// 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))
proto, err := lite.MsigCreate(ctx, 2, msigAddrs, abi.ChainEpoch(50), amt, liteWalletAddr, types.NewInt(0))
require.NoError(t, err)
doSend := func(proto *api.MessagePrototype) (cid.Cid, error) {
if proto.ValidNonce {
sm, err := lite.WalletSignMessage(ctx, proto.Message.From, &proto.Message)
if err != nil {
return cid.Undef, err
}
return lite.MpoolPush(ctx, sm)
}
sm, err := lite.MpoolPushMessage(ctx, &proto.Message, nil)
if err != nil {
return cid.Undef, err
}
return sm.Cid(), nil
}
addProposal, err := doSend(proto)
require.NoError(t, err)
res, err := lite.StateWaitMsg(ctx, addProposal, 1, api.LookbackNoLimit, true)
@ -122,7 +145,10 @@ func TestWalletMsig(t *testing.T) {
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)
proto, err = lite.MsigAddPropose(ctx, msig, walletAddrs[0], walletAddrs[3], false)
require.NoError(t, err)
addProposal, err = doSend(proto)
require.NoError(t, err)
res, err = lite.StateWaitMsg(ctx, addProposal, 1, api.LookbackNoLimit, true)
@ -136,7 +162,10 @@ func TestWalletMsig(t *testing.T) {
// 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)
proto, err = lite.MsigAddApprove(ctx, msig, walletAddrs[1], txnID, walletAddrs[0], walletAddrs[3], false)
require.NoError(t, err)
approval1, err := doSend(proto)
require.NoError(t, err)
res, err = lite.StateWaitMsg(ctx, approval1, 1, api.LookbackNoLimit, true)
@ -304,7 +333,7 @@ func sendFunds(ctx context.Context, fromNode test.TestNode, fromAddr address.Add
return err
}
res, err := fromNode.StateWaitMsg(ctx, sm.Cid(), 1, api.LookbackNoLimit, true)
res, err := fromNode.StateWaitMsg(ctx, sm.Cid(), 3, api.LookbackNoLimit, true)
if err != nil {
return err
}

View File

@ -67,11 +67,13 @@ var verifRegAddVerifierCmd = &cli.Command{
return err
}
api, closer, err := lcli.GetFullNodeAPI(cctx)
srv, err := lcli.GetFullNodeServices(cctx)
if err != nil {
return err
}
defer closer()
defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := lcli.ReqContext(cctx)
vrk, err := api.StateVerifiedRegistryRootKey(ctx, types.EmptyTSK)
@ -79,14 +81,21 @@ var verifRegAddVerifierCmd = &cli.Command{
return err
}
smsg, err := api.MsigPropose(ctx, vrk, verifreg.Address, big.Zero(), sender, uint64(verifreg.Methods.AddVerifier), params)
proto, err := api.MsigPropose(ctx, vrk, verifreg.Address, big.Zero(), sender, uint64(verifreg.Methods.AddVerifier), params)
if err != nil {
return err
}
fmt.Printf("message sent, now waiting on cid: %s\n", smsg)
sm, _, err := srv.PublishMessage(ctx, proto, false)
if err != nil {
return err
}
mwait, err := api.StateWaitMsg(ctx, smsg, build.MessageConfidence)
msgCid := sm.Cid()
fmt.Printf("message sent, now waiting on cid: %s\n", msgCid)
mwait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")), build.Finality, true)
if err != nil {
return err
}

View File

@ -2,7 +2,9 @@ package main
import (
"context"
"os"
"github.com/mattn/go-isatty"
"github.com/urfave/cli/v2"
"go.opencensus.io/trace"
@ -52,6 +54,8 @@ func main() {
ctx, span := trace.StartSpan(context.Background(), "/cli")
defer span.End()
interactiveDef := isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd())
app := &cli.App{
Name: "lotus",
Usage: "Filecoin decentralized storage network client",
@ -64,10 +68,20 @@ func main() {
Hidden: true,
Value: "~/.lotus", // TODO: Consider XDG_DATA_HOME
},
&cli.BoolFlag{
Name: "interactive",
Usage: "setting to false will disable interactive functionality of commands",
Value: interactiveDef,
},
&cli.BoolFlag{
Name: "force-send",
Usage: "if true, will ignore pre-send checks",
},
},
Commands: append(local, lcli.Commands...),
}
app.Setup()
app.Metadata["traceContext"] = ctx
app.Metadata["repoType"] = repo.FullNode

View File

@ -82,6 +82,9 @@
* [MpoolBatchPush](#MpoolBatchPush)
* [MpoolBatchPushMessage](#MpoolBatchPushMessage)
* [MpoolBatchPushUntrusted](#MpoolBatchPushUntrusted)
* [MpoolCheckMessages](#MpoolCheckMessages)
* [MpoolCheckPendingMessages](#MpoolCheckPendingMessages)
* [MpoolCheckReplaceMessages](#MpoolCheckReplaceMessages)
* [MpoolClear](#MpoolClear)
* [MpoolGetConfig](#MpoolGetConfig)
* [MpoolGetNonce](#MpoolGetNonce)
@ -126,6 +129,8 @@
* [NetPeerInfo](#NetPeerInfo)
* [NetPeers](#NetPeers)
* [NetPubsubScores](#NetPubsubScores)
* [Node](#Node)
* [NodeStatus](#NodeStatus)
* [Paych](#Paych)
* [PaychAllocateLane](#PaychAllocateLane)
* [PaychAvailableFunds](#PaychAvailableFunds)
@ -1991,6 +1996,51 @@ Inputs:
Response: `null`
### MpoolCheckMessages
MpoolCheckMessages performs logical checks on a batch of messages
Perms: read
Inputs:
```json
[
null
]
```
Response: `null`
### MpoolCheckPendingMessages
MpoolCheckPendingMessages performs logical checks for all pending messages from a given address
Perms: read
Inputs:
```json
[
"f01234"
]
```
Response: `null`
### MpoolCheckReplaceMessages
MpoolCheckReplaceMessages performs logical checks on pending messages with replacement
Perms: read
Inputs:
```json
[
null
]
```
Response: `null`
### MpoolClear
MpoolClear clears pending messages from the mpool
@ -2324,7 +2374,22 @@ Inputs:
Response:
```json
{
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
"Message": {
"Version": 42,
"To": "f01234",
"From": "f01234",
"Nonce": 42,
"Value": "0",
"GasLimit": 9,
"GasFeeCap": "0",
"GasPremium": "0",
"Method": 1,
"Params": "Ynl0ZSBhcnJheQ==",
"CID": {
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
}
},
"ValidNonce": true
}
```
@ -2350,7 +2415,22 @@ Inputs:
Response:
```json
{
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
"Message": {
"Version": 42,
"To": "f01234",
"From": "f01234",
"Nonce": 42,
"Value": "0",
"GasLimit": 9,
"GasFeeCap": "0",
"GasPremium": "0",
"Method": 1,
"Params": "Ynl0ZSBhcnJheQ==",
"CID": {
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
}
},
"ValidNonce": true
}
```
@ -2375,7 +2455,22 @@ Inputs:
Response:
```json
{
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
"Message": {
"Version": 42,
"To": "f01234",
"From": "f01234",
"Nonce": 42,
"Value": "0",
"GasLimit": 9,
"GasFeeCap": "0",
"GasPremium": "0",
"Method": 1,
"Params": "Ynl0ZSBhcnJheQ==",
"CID": {
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
}
},
"ValidNonce": true
}
```
@ -2398,7 +2493,22 @@ Inputs:
Response:
```json
{
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
"Message": {
"Version": 42,
"To": "f01234",
"From": "f01234",
"Nonce": 42,
"Value": "0",
"GasLimit": 9,
"GasFeeCap": "0",
"GasPremium": "0",
"Method": 1,
"Params": "Ynl0ZSBhcnJheQ==",
"CID": {
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
}
},
"ValidNonce": true
}
```
@ -2430,7 +2540,22 @@ Inputs:
Response:
```json
{
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
"Message": {
"Version": 42,
"To": "f01234",
"From": "f01234",
"Nonce": 42,
"Value": "0",
"GasLimit": 9,
"GasFeeCap": "0",
"GasPremium": "0",
"Method": 1,
"Params": "Ynl0ZSBhcnJheQ==",
"CID": {
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
}
},
"ValidNonce": true
}
```
@ -2458,7 +2583,22 @@ Inputs:
Response:
```json
{
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
"Message": {
"Version": 42,
"To": "f01234",
"From": "f01234",
"Nonce": 42,
"Value": "0",
"GasLimit": 9,
"GasFeeCap": "0",
"GasPremium": "0",
"Method": 1,
"Params": "Ynl0ZSBhcnJheQ==",
"CID": {
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
}
},
"ValidNonce": true
}
```
@ -2485,7 +2625,22 @@ Inputs:
Response:
```json
{
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
"Message": {
"Version": 42,
"To": "f01234",
"From": "f01234",
"Nonce": 42,
"Value": "0",
"GasLimit": 9,
"GasFeeCap": "0",
"GasPremium": "0",
"Method": 1,
"Params": "Ynl0ZSBhcnJheQ==",
"CID": {
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
}
},
"ValidNonce": true
}
```
@ -2622,7 +2777,22 @@ Inputs:
Response:
```json
{
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
"Message": {
"Version": 42,
"To": "f01234",
"From": "f01234",
"Nonce": 42,
"Value": "0",
"GasLimit": 9,
"GasFeeCap": "0",
"GasPremium": "0",
"Method": 1,
"Params": "Ynl0ZSBhcnJheQ==",
"CID": {
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
}
},
"ValidNonce": true
}
```
@ -2649,7 +2819,22 @@ Inputs:
Response:
```json
{
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
"Message": {
"Version": 42,
"To": "f01234",
"From": "f01234",
"Nonce": 42,
"Value": "0",
"GasLimit": 9,
"GasFeeCap": "0",
"GasPremium": "0",
"Method": 1,
"Params": "Ynl0ZSBhcnJheQ==",
"CID": {
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
}
},
"ValidNonce": true
}
```
@ -2676,7 +2861,22 @@ Inputs:
Response:
```json
{
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
"Message": {
"Version": 42,
"To": "f01234",
"From": "f01234",
"Nonce": 42,
"Value": "0",
"GasLimit": 9,
"GasFeeCap": "0",
"GasPremium": "0",
"Method": 1,
"Params": "Ynl0ZSBhcnJheQ==",
"CID": {
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
}
},
"ValidNonce": true
}
```
@ -2702,7 +2902,22 @@ Inputs:
Response:
```json
{
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
"Message": {
"Version": 42,
"To": "f01234",
"From": "f01234",
"Nonce": 42,
"Value": "0",
"GasLimit": 9,
"GasFeeCap": "0",
"GasPremium": "0",
"Method": 1,
"Params": "Ynl0ZSBhcnJheQ==",
"CID": {
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
}
},
"ValidNonce": true
}
```
@ -2727,7 +2942,22 @@ Inputs:
Response:
```json
{
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
"Message": {
"Version": 42,
"To": "f01234",
"From": "f01234",
"Nonce": 42,
"Value": "0",
"GasLimit": 9,
"GasFeeCap": "0",
"GasPremium": "0",
"Method": 1,
"Params": "Ynl0ZSBhcnJheQ==",
"CID": {
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
}
},
"ValidNonce": true
}
```
@ -3000,6 +3230,40 @@ Inputs: `null`
Response: `null`
## Node
These methods are general node management and status commands
### NodeStatus
There are not yet any comments for this method.
Perms: read
Inputs:
```json
[
true
]
```
Response:
```json
{
"SyncStatus": {
"Epoch": 42,
"Behind": 42
},
"PeerStatus": {
"PeersToPublishMsgs": 123,
"PeersToPublishBlocks": 123
},
"ChainStatus": {
"BlocksPerTipsetLast100": 12.3,
"BlocksPerTipsetLastFinality": 12.3
}
}
```
## Paych
The Paych methods are for interacting with and managing payment channels

View File

@ -31,8 +31,12 @@ COMMANDS:
NETWORK:
net Manage P2P Network
sync Inspect or interact with the chain syncer
STATUS:
status Check node status
GLOBAL OPTIONS:
--interactive setting to false will disable interactive functionality of commands (default: false)
--force-send if true, will ignore pre-send checks (default: false)
--help, -h show help (default: false)
--version, -v print the version (default: false)
```
@ -136,7 +140,7 @@ OPTIONS:
--method value specify method to invoke (default: 0)
--params-json value specify invocation parameters in json
--params-hex value specify invocation parameters in hex
--force must be specified for the action to take effect if maybe SysErrInsufficientFunds etc (default: false)
--force Deprecated: use global 'force-send' (default: false)
--help, -h show help (default: false)
```
@ -1299,6 +1303,7 @@ COMMANDS:
find find a message in the mempool
config get or set current mpool configuration
gas-perf Check gas performance of messages in mempool
manage
help, h Shows a list of commands or help for one command
OPTIONS:
@ -1412,6 +1417,9 @@ OPTIONS:
--help, -h show help (default: false)
```
# nage
```
```
## lotus state
```
@ -2671,3 +2679,20 @@ OPTIONS:
--help, -h show help (default: false)
```
## lotus status
```
NAME:
lotus status - Check node status
USAGE:
lotus status [command options] [arguments...]
CATEGORY:
STATUS
OPTIONS:
--chain include chain health status (default: false)
--help, -h show help (default: false)
```

6
go.mod
View File

@ -8,6 +8,7 @@ require (
github.com/BurntSushi/toml v0.3.1
github.com/GeertJohan/go.rice v1.0.0
github.com/Gurpartap/async v0.0.0-20180927173644-4f7f499dd9ee
github.com/Kubuxu/imtui v0.0.0-20210401140320-41663d68d0fa
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
github.com/alecthomas/jsonschema v0.0.0-20200530073317-71f438968921
@ -50,6 +51,7 @@ require (
github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506
github.com/filecoin-project/test-vectors/schema v0.0.5
github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1
github.com/gdamore/tcell/v2 v2.2.0
github.com/go-kit/kit v0.10.0
github.com/go-ole/go-ole v1.2.4 // indirect
github.com/golang/mock v1.4.4
@ -86,7 +88,7 @@ require (
github.com/ipfs/go-ipfs-util v0.0.2
github.com/ipfs/go-ipld-cbor v0.0.5
github.com/ipfs/go-ipld-format v0.2.0
github.com/ipfs/go-log/v2 v2.1.2-0.20200626104915-0016c0b4b3e4
github.com/ipfs/go-log/v2 v2.1.2
github.com/ipfs/go-merkledag v0.3.2
github.com/ipfs/go-metrics-interface v0.0.1
github.com/ipfs/go-metrics-prometheus v0.0.2
@ -116,6 +118,7 @@ require (
github.com/libp2p/go-libp2p-yamux v0.4.1
github.com/libp2p/go-maddr-filter v0.1.0
github.com/mattn/go-colorable v0.1.6 // indirect
github.com/mattn/go-isatty v0.0.12
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1
github.com/mitchellh/go-homedir v1.1.0
github.com/multiformats/go-base32 v0.0.3
@ -150,6 +153,7 @@ require (
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68
golang.org/x/time v0.0.0-20191024005414-555d28b269f0
golang.org/x/tools v0.0.0-20201112185108-eeaa07dd7696
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/cheggaaa/pb.v1 v1.0.28

18
go.sum
View File

@ -42,6 +42,8 @@ github.com/Gurpartap/async v0.0.0-20180927173644-4f7f499dd9ee h1:8doiS7ib3zi6/K1
github.com/Gurpartap/async v0.0.0-20180927173644-4f7f499dd9ee/go.mod h1:W0GbEAA4uFNYOGG2cJpmFJ04E6SD1NLELPYZB57/7AY=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y=
github.com/Kubuxu/imtui v0.0.0-20210401140320-41663d68d0fa h1:1PPxEyGdIGVkX/kqMvLJ95a1dGS1Sz7tpNEgehEYYt0=
github.com/Kubuxu/imtui v0.0.0-20210401140320-41663d68d0fa/go.mod h1:WUmMvh9wMtqj1Xhf1hf3kp9RvL+y6odtdYxpyZjb90U=
github.com/Masterminds/glide v0.13.2/go.mod h1:STyF5vcenH/rUqTEv+/hBXlSTo7KYwg2oc2f4tzPWic=
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/Masterminds/vcs v1.13.0/go.mod h1:N09YCmOQr6RLxC6UNHzuVwAdodYbbnycGHSmwVJjcKA=
@ -330,6 +332,10 @@ github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWo
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1 h1:EzDjxMg43q1tA2c0MV3tNbaontnHLplHyFF6M5KiVP0=
github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1/go.mod h1:0eHX/BVySxPc6SE2mZRoppGq7qcEagxdmQnA3dzork8=
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
github.com/gdamore/tcell/v2 v2.2.0 h1:vSyEgKwraXPSOkvCk7IwOSyX+Pv3V2cV9CikJMXg4U4=
github.com/gdamore/tcell/v2 v2.2.0/go.mod h1:cTTuF84Dlj/RqmaCIV5p4w8uG1zWdk0SF6oBpwHp4fU=
github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs=
github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
github.com/ghemawat/stream v0.0.0-20171120220530-696b145b53b9/go.mod h1:106OIgooyS7OzLDOpUGgm9fA3bQENb/cFSyyBmMoJDs=
@ -672,8 +678,9 @@ github.com/ipfs/go-log/v2 v2.0.3/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBW
github.com/ipfs/go-log/v2 v2.0.5/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscwkWG+dw=
github.com/ipfs/go-log/v2 v2.0.8/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscwkWG+dw=
github.com/ipfs/go-log/v2 v2.1.1/go.mod h1:2v2nsGfZsvvAJz13SyFzf9ObaqwHiHxsPLEHntrv9KM=
github.com/ipfs/go-log/v2 v2.1.2-0.20200626104915-0016c0b4b3e4 h1:3bijxqzQ1O9yg7gd7Aqk80oaEvsJ+uXw0zSvi2qR3Jw=
github.com/ipfs/go-log/v2 v2.1.2-0.20200626104915-0016c0b4b3e4/go.mod h1:2v2nsGfZsvvAJz13SyFzf9ObaqwHiHxsPLEHntrv9KM=
github.com/ipfs/go-log/v2 v2.1.2 h1:a0dRiL098zY23vay1h3dimx6y94XchEUyt5h0l4VvQU=
github.com/ipfs/go-log/v2 v2.1.2/go.mod h1:2v2nsGfZsvvAJz13SyFzf9ObaqwHiHxsPLEHntrv9KM=
github.com/ipfs/go-merkledag v0.0.3/go.mod h1:Oc5kIXLHokkE1hWGMBHw+oxehkAaTOqtEb7Zbh6BhLA=
github.com/ipfs/go-merkledag v0.0.6/go.mod h1:QYPdnlvkOg7GnQRofu9XZimC5ZW5Wi3bKys/4GQQfto=
github.com/ipfs/go-merkledag v0.2.3/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk=
@ -1110,6 +1117,8 @@ github.com/lucas-clemente/quic-go v0.11.2/go.mod h1:PpMmPfPKO9nKJ/psF49ESTAGQSdf
github.com/lucas-clemente/quic-go v0.16.0/go.mod h1:I0+fcNTdb9eS1ZcjQZbDVPGchJ86chcIxPALn9lEJqE=
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/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac=
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
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=
@ -1143,8 +1152,9 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg=
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-xmlrpc v0.0.3/go.mod h1:mqc2dz7tP5x5BKlCahN/n+hs7OSZKJkS9JsHNBRlrxA=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
@ -1369,6 +1379,8 @@ github.com/raulk/go-watchdog v1.0.1/go.mod h1:lzSbAl5sh4rtI8tYHU01BWIDzgzqaQLj6R
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
@ -1814,6 +1826,8 @@ golang.org/x/sys v0.0.0-20200926100807-9d91bd62050c/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf h1:MZ2shdL+ZM/XzY3ZGOnh4Nlpnxz5GSOhOmtHo3iPU6M=
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

View File

@ -333,6 +333,7 @@ var ChainNode = Options(
// Lite node API
ApplyIf(isLiteNode,
Override(new(messagepool.Provider), messagepool.NewProviderLite),
Override(new(messagesigner.MpoolNonceAPI), From(new(modules.MpoolNonceAPI))),
Override(new(full.ChainModuleAPI), From(new(api.Gateway))),
Override(new(full.GasModuleAPI), From(new(api.Gateway))),
@ -343,6 +344,7 @@ var ChainNode = Options(
// Full node API / service startup
ApplyIf(isFullNode,
Override(new(messagepool.Provider), messagepool.NewProvider),
Override(new(messagesigner.MpoolNonceAPI), From(new(*messagepool.MessagePool))),
Override(new(full.ChainModuleAPI), From(new(full.ChainModule))),
Override(new(full.GasModuleAPI), From(new(full.GasModule))),

View File

@ -2,16 +2,21 @@ package impl
import (
"context"
"time"
"github.com/libp2p/go-libp2p-core/peer"
logging "github.com/ipfs/go-log/v2"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/node/impl/client"
"github.com/filecoin-project/lotus/node/impl/common"
"github.com/filecoin-project/lotus/node/impl/full"
"github.com/filecoin-project/lotus/node/impl/market"
"github.com/filecoin-project/lotus/node/impl/paych"
"github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/filecoin-project/lotus/node/modules/lp2p"
)
var log = logging.Logger("node")
@ -30,11 +35,86 @@ type FullNodeAPI struct {
full.SyncAPI
full.BeaconAPI
DS dtypes.MetadataDS
DS dtypes.MetadataDS
NetworkName dtypes.NetworkName
}
func (n *FullNodeAPI) CreateBackup(ctx context.Context, fpath string) error {
return backup(n.DS, fpath)
}
func (n *FullNodeAPI) NodeStatus(ctx context.Context, inclChainStatus bool) (status api.NodeStatus, err error) {
curTs, err := n.ChainHead(ctx)
if err != nil {
return status, err
}
status.SyncStatus.Epoch = uint64(curTs.Height())
timestamp := time.Unix(int64(curTs.MinTimestamp()), 0)
delta := time.Since(timestamp).Seconds()
status.SyncStatus.Behind = uint64(delta / 30)
// get peers in the messages and blocks topics
peersMsgs := make(map[peer.ID]struct{})
peersBlocks := make(map[peer.ID]struct{})
for _, p := range n.PubSub.ListPeers(build.MessagesTopic(n.NetworkName)) {
peersMsgs[p] = struct{}{}
}
for _, p := range n.PubSub.ListPeers(build.BlocksTopic(n.NetworkName)) {
peersBlocks[p] = struct{}{}
}
// get scores for all connected and recent peers
scores, err := n.NetPubsubScores(ctx)
if err != nil {
return status, err
}
for _, score := range scores {
if score.Score.Score > lp2p.PublishScoreThreshold {
_, inMsgs := peersMsgs[score.ID]
if inMsgs {
status.PeerStatus.PeersToPublishMsgs++
}
_, inBlocks := peersBlocks[score.ID]
if inBlocks {
status.PeerStatus.PeersToPublishBlocks++
}
}
}
if inclChainStatus && status.SyncStatus.Epoch > uint64(build.Finality) {
blockCnt := 0
ts := curTs
for i := 0; i < 100; i++ {
blockCnt += len(ts.Blocks())
tsk := ts.Parents()
ts, err = n.ChainGetTipSet(ctx, tsk)
if err != nil {
return status, err
}
}
status.ChainStatus.BlocksPerTipsetLast100 = float64(blockCnt) / 100
for i := 100; i < int(build.Finality); i++ {
blockCnt += len(ts.Blocks())
tsk := ts.Parents()
ts, err = n.ChainGetTipSet(ctx, tsk)
if err != nil {
return status, err
}
}
status.ChainStatus.BlocksPerTipsetLastFinality = float64(blockCnt) / float64(build.Finality)
}
return status, nil
}
var _ api.FullNode = &FullNodeAPI{}

View File

@ -225,6 +225,18 @@ func (a *MpoolAPI) MpoolBatchPushMessage(ctx context.Context, msgs []*types.Mess
return smsgs, nil
}
func (a *MpoolAPI) MpoolCheckMessages(ctx context.Context, protos []*api.MessagePrototype) ([][]api.MessageCheckStatus, error) {
return a.Mpool.CheckMessages(protos)
}
func (a *MpoolAPI) MpoolCheckPendingMessages(ctx context.Context, from address.Address) ([][]api.MessageCheckStatus, error) {
return a.Mpool.CheckPendingMessages(from)
}
func (a *MpoolAPI) MpoolCheckReplaceMessages(ctx context.Context, msgs []*types.Message) ([][]api.MessageCheckStatus, error) {
return a.Mpool.CheckReplaceMessages(msgs)
}
func (a *MpoolAPI) MpoolGetNonce(ctx context.Context, addr address.Address) (uint64, error) {
return a.Mpool.GetNonce(ctx, addr, types.EmptyTSK)
}

View File

@ -14,7 +14,6 @@ import (
multisig2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/multisig"
"github.com/ipfs/go-cid"
"go.uber.org/fx"
"golang.org/x/xerrors"
)
@ -37,134 +36,129 @@ func (a *MsigAPI) messageBuilder(ctx context.Context, from address.Address) (mul
// TODO: remove gp (gasPrice) from arguments
// TODO: Add "vesting start" to arguments.
func (a *MsigAPI) MsigCreate(ctx context.Context, req uint64, addrs []address.Address, duration abi.ChainEpoch, val types.BigInt, src address.Address, gp types.BigInt) (cid.Cid, error) {
func (a *MsigAPI) MsigCreate(ctx context.Context, req uint64, addrs []address.Address, duration abi.ChainEpoch, val types.BigInt, src address.Address, gp types.BigInt) (*api.MessagePrototype, error) {
mb, err := a.messageBuilder(ctx, src)
if err != nil {
return cid.Undef, err
return nil, err
}
msg, err := mb.Create(addrs, req, 0, duration, val)
if err != nil {
return cid.Undef, err
return nil, err
}
// send the message out to the network
smsg, err := a.MpoolAPI.MpoolPushMessage(ctx, msg, nil)
if err != nil {
return cid.Undef, err
}
return smsg.Cid(), nil
return &api.MessagePrototype{
Message: *msg,
ValidNonce: false,
}, nil
}
func (a *MsigAPI) MsigPropose(ctx context.Context, msig address.Address, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (cid.Cid, error) {
func (a *MsigAPI) MsigPropose(ctx context.Context, msig address.Address, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (*api.MessagePrototype, error) {
mb, err := a.messageBuilder(ctx, src)
if err != nil {
return cid.Undef, err
return nil, err
}
msg, err := mb.Propose(msig, to, amt, abi.MethodNum(method), params)
if err != nil {
return cid.Undef, xerrors.Errorf("failed to create proposal: %w", err)
return nil, xerrors.Errorf("failed to create proposal: %w", err)
}
smsg, err := a.MpoolAPI.MpoolPushMessage(ctx, msg, nil)
if err != nil {
return cid.Undef, xerrors.Errorf("failed to push message: %w", err)
}
return smsg.Cid(), nil
return &api.MessagePrototype{
Message: *msg,
ValidNonce: false,
}, nil
}
func (a *MsigAPI) MsigAddPropose(ctx context.Context, msig address.Address, src address.Address, newAdd address.Address, inc bool) (cid.Cid, error) {
func (a *MsigAPI) MsigAddPropose(ctx context.Context, msig address.Address, src address.Address, newAdd address.Address, inc bool) (*api.MessagePrototype, error) {
enc, actErr := serializeAddParams(newAdd, inc)
if actErr != nil {
return cid.Undef, actErr
return nil, actErr
}
return a.MsigPropose(ctx, msig, msig, big.Zero(), src, uint64(multisig.Methods.AddSigner), enc)
}
func (a *MsigAPI) MsigAddApprove(ctx context.Context, msig address.Address, src address.Address, txID uint64, proposer address.Address, newAdd address.Address, inc bool) (cid.Cid, error) {
func (a *MsigAPI) MsigAddApprove(ctx context.Context, msig address.Address, src address.Address, txID uint64, proposer address.Address, newAdd address.Address, inc bool) (*api.MessagePrototype, error) {
enc, actErr := serializeAddParams(newAdd, inc)
if actErr != nil {
return cid.Undef, actErr
return nil, actErr
}
return a.MsigApproveTxnHash(ctx, msig, txID, proposer, msig, big.Zero(), src, uint64(multisig.Methods.AddSigner), enc)
}
func (a *MsigAPI) MsigAddCancel(ctx context.Context, msig address.Address, src address.Address, txID uint64, newAdd address.Address, inc bool) (cid.Cid, error) {
func (a *MsigAPI) MsigAddCancel(ctx context.Context, msig address.Address, src address.Address, txID uint64, newAdd address.Address, inc bool) (*api.MessagePrototype, error) {
enc, actErr := serializeAddParams(newAdd, inc)
if actErr != nil {
return cid.Undef, actErr
return nil, actErr
}
return a.MsigCancel(ctx, msig, txID, msig, big.Zero(), src, uint64(multisig.Methods.AddSigner), enc)
}
func (a *MsigAPI) MsigSwapPropose(ctx context.Context, msig address.Address, src address.Address, oldAdd address.Address, newAdd address.Address) (cid.Cid, error) {
func (a *MsigAPI) MsigSwapPropose(ctx context.Context, msig address.Address, src address.Address, oldAdd address.Address, newAdd address.Address) (*api.MessagePrototype, error) {
enc, actErr := serializeSwapParams(oldAdd, newAdd)
if actErr != nil {
return cid.Undef, actErr
return nil, actErr
}
return a.MsigPropose(ctx, msig, msig, big.Zero(), src, uint64(multisig.Methods.SwapSigner), enc)
}
func (a *MsigAPI) MsigSwapApprove(ctx context.Context, msig address.Address, src address.Address, txID uint64, proposer address.Address, oldAdd address.Address, newAdd address.Address) (cid.Cid, error) {
func (a *MsigAPI) MsigSwapApprove(ctx context.Context, msig address.Address, src address.Address, txID uint64, proposer address.Address, oldAdd address.Address, newAdd address.Address) (*api.MessagePrototype, error) {
enc, actErr := serializeSwapParams(oldAdd, newAdd)
if actErr != nil {
return cid.Undef, actErr
return nil, actErr
}
return a.MsigApproveTxnHash(ctx, msig, txID, proposer, msig, big.Zero(), src, uint64(multisig.Methods.SwapSigner), enc)
}
func (a *MsigAPI) MsigSwapCancel(ctx context.Context, msig address.Address, src address.Address, txID uint64, oldAdd address.Address, newAdd address.Address) (cid.Cid, error) {
func (a *MsigAPI) MsigSwapCancel(ctx context.Context, msig address.Address, src address.Address, txID uint64, oldAdd address.Address, newAdd address.Address) (*api.MessagePrototype, error) {
enc, actErr := serializeSwapParams(oldAdd, newAdd)
if actErr != nil {
return cid.Undef, actErr
return nil, actErr
}
return a.MsigCancel(ctx, msig, txID, msig, big.Zero(), src, uint64(multisig.Methods.SwapSigner), enc)
}
func (a *MsigAPI) MsigApprove(ctx context.Context, msig address.Address, txID uint64, src address.Address) (cid.Cid, error) {
func (a *MsigAPI) MsigApprove(ctx context.Context, msig address.Address, txID uint64, src address.Address) (*api.MessagePrototype, error) {
return a.msigApproveOrCancelSimple(ctx, api.MsigApprove, msig, txID, src)
}
func (a *MsigAPI) MsigApproveTxnHash(ctx context.Context, msig address.Address, txID uint64, proposer address.Address, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (cid.Cid, error) {
func (a *MsigAPI) MsigApproveTxnHash(ctx context.Context, msig address.Address, txID uint64, proposer address.Address, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (*api.MessagePrototype, error) {
return a.msigApproveOrCancelTxnHash(ctx, api.MsigApprove, msig, txID, proposer, to, amt, src, method, params)
}
func (a *MsigAPI) MsigCancel(ctx context.Context, msig address.Address, txID uint64, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (cid.Cid, error) {
func (a *MsigAPI) MsigCancel(ctx context.Context, msig address.Address, txID uint64, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (*api.MessagePrototype, error) {
return a.msigApproveOrCancelTxnHash(ctx, api.MsigCancel, msig, txID, src, to, amt, src, method, params)
}
func (a *MsigAPI) MsigRemoveSigner(ctx context.Context, msig address.Address, proposer address.Address, toRemove address.Address, decrease bool) (cid.Cid, error) {
func (a *MsigAPI) MsigRemoveSigner(ctx context.Context, msig address.Address, proposer address.Address, toRemove address.Address, decrease bool) (*api.MessagePrototype, error) {
enc, actErr := serializeRemoveParams(toRemove, decrease)
if actErr != nil {
return cid.Undef, actErr
return nil, actErr
}
return a.MsigPropose(ctx, msig, msig, types.NewInt(0), proposer, uint64(multisig.Methods.RemoveSigner), enc)
}
func (a *MsigAPI) msigApproveOrCancelSimple(ctx context.Context, operation api.MsigProposeResponse, msig address.Address, txID uint64, src address.Address) (cid.Cid, error) {
func (a *MsigAPI) msigApproveOrCancelSimple(ctx context.Context, operation api.MsigProposeResponse, msig address.Address, txID uint64, src address.Address) (*api.MessagePrototype, error) {
if msig == address.Undef {
return cid.Undef, xerrors.Errorf("must provide multisig address")
return nil, xerrors.Errorf("must provide multisig address")
}
if src == address.Undef {
return cid.Undef, xerrors.Errorf("must provide source address")
return nil, xerrors.Errorf("must provide source address")
}
mb, err := a.messageBuilder(ctx, src)
if err != nil {
return cid.Undef, err
return nil, err
}
var msg *types.Message
@ -174,34 +168,31 @@ func (a *MsigAPI) msigApproveOrCancelSimple(ctx context.Context, operation api.M
case api.MsigCancel:
msg, err = mb.Cancel(msig, txID, nil)
default:
return cid.Undef, xerrors.Errorf("Invalid operation for msigApproveOrCancel")
return nil, xerrors.Errorf("Invalid operation for msigApproveOrCancel")
}
if err != nil {
return cid.Undef, err
return nil, err
}
smsg, err := a.MpoolAPI.MpoolPushMessage(ctx, msg, nil)
if err != nil {
return cid.Undef, err
}
return smsg.Cid(), nil
return &api.MessagePrototype{
Message: *msg,
ValidNonce: false,
}, nil
}
func (a *MsigAPI) msigApproveOrCancelTxnHash(ctx context.Context, operation api.MsigProposeResponse, msig address.Address, txID uint64, proposer address.Address, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (cid.Cid, error) {
func (a *MsigAPI) msigApproveOrCancelTxnHash(ctx context.Context, operation api.MsigProposeResponse, msig address.Address, txID uint64, proposer address.Address, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (*api.MessagePrototype, error) {
if msig == address.Undef {
return cid.Undef, xerrors.Errorf("must provide multisig address")
return nil, xerrors.Errorf("must provide multisig address")
}
if src == address.Undef {
return cid.Undef, xerrors.Errorf("must provide source address")
return nil, xerrors.Errorf("must provide source address")
}
if proposer.Protocol() != address.ID {
proposerID, err := a.StateAPI.StateLookupID(ctx, proposer, types.EmptyTSK)
if err != nil {
return cid.Undef, err
return nil, err
}
proposer = proposerID
}
@ -216,7 +207,7 @@ func (a *MsigAPI) msigApproveOrCancelTxnHash(ctx context.Context, operation api.
mb, err := a.messageBuilder(ctx, src)
if err != nil {
return cid.Undef, err
return nil, err
}
var msg *types.Message
@ -226,18 +217,16 @@ func (a *MsigAPI) msigApproveOrCancelTxnHash(ctx context.Context, operation api.
case api.MsigCancel:
msg, err = mb.Cancel(msig, txID, &p)
default:
return cid.Undef, xerrors.Errorf("Invalid operation for msigApproveOrCancel")
return nil, xerrors.Errorf("Invalid operation for msigApproveOrCancel")
}
if err != nil {
return cid.Undef, err
return nil, err
}
smsg, err := a.MpoolAPI.MpoolPushMessage(ctx, msg, nil)
if err != nil {
return cid.Undef, err
}
return smsg.Cid(), nil
return &api.MessagePrototype{
Message: *msg,
ValidNonce: false,
}, nil
}
func serializeAddParams(new address.Address, inc bool) ([]byte, error) {

View File

@ -426,7 +426,7 @@ func (a *StateAPI) StateReplay(ctx context.Context, tsk types.TipSetKey, mc cid.
}, nil
}
func (m *StateModule) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) {
func (m *StateModule) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (a *types.Actor, err error) {
ts, err := m.Chain.GetTipSetFromKey(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)

View File

@ -9,7 +9,6 @@ import (
"github.com/ipfs/go-blockservice"
"github.com/libp2p/go-libp2p-core/host"
"github.com/libp2p/go-libp2p-core/routing"
pubsub "github.com/libp2p/go-libp2p-pubsub"
"go.uber.org/fx"
"golang.org/x/xerrors"
@ -59,8 +58,7 @@ func ChainBlockService(bs dtypes.ExposedBlockstore, rem dtypes.ChainBitswap) dty
return blockservice.New(bs, rem)
}
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)
func MessagePool(lc fx.Lifecycle, mpp messagepool.Provider, ds dtypes.MetadataDS, nn dtypes.NetworkName, j journal.Journal) (*messagepool.MessagePool, error) {
mp, err := messagepool.New(mpp, ds, nn, j)
if err != nil {
return nil, xerrors.Errorf("constructing mpool: %w", err)

View File

@ -36,6 +36,15 @@ func init() {
pubsub.GossipSubHistoryLength = 10
pubsub.GossipSubGossipFactor = 0.1
}
const (
GossipScoreThreshold = -500
PublishScoreThreshold = -1000
GraylistScoreThreshold = -2500
AcceptPXScoreThreshold = 1000
OpportunisticGraftScoreThreshold = 3.5
)
func ScoreKeeper() *dtypes.ScoreKeeper {
return new(dtypes.ScoreKeeper)
}
@ -256,11 +265,11 @@ func GossipSub(in GossipIn) (service *pubsub.PubSub, err error) {
Topics: topicParams,
},
&pubsub.PeerScoreThresholds{
GossipThreshold: -500,
PublishThreshold: -1000,
GraylistThreshold: -2500,
AcceptPXThreshold: 1000,
OpportunisticGraftThreshold: 3.5,
GossipThreshold: GossipScoreThreshold,
PublishThreshold: PublishScoreThreshold,
GraylistThreshold: GraylistScoreThreshold,
AcceptPXThreshold: AcceptPXScoreThreshold,
OpportunisticGraftThreshold: OpportunisticGraftScoreThreshold,
},
),
pubsub.WithPeerScoreInspect(in.Sk.Update, 10*time.Second),

View File

@ -63,7 +63,7 @@ func (a *MpoolNonceAPI) GetNonce(ctx context.Context, addr address.Address, tsk
act, err := a.StateModule.StateGetActor(ctx, keyAddr, ts.Key())
if err != nil {
if strings.Contains(err.Error(), types.ErrActorNotFound.Error()) {
return 0, types.ErrActorNotFound
return 0, xerrors.Errorf("getting actor converted: %w", types.ErrActorNotFound)
}
return 0, xerrors.Errorf("getting actor: %w", err)
}
@ -96,4 +96,13 @@ func (a *MpoolNonceAPI) GetNonce(ctx context.Context, addr address.Address, tsk
return highestNonce, nil
}
func (a *MpoolNonceAPI) GetActor(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*types.Actor, error) {
act, err := a.StateModule.StateGetActor(ctx, addr, tsk)
if err != nil {
return nil, xerrors.Errorf("calling StateGetActor: %w", err)
}
return act, nil
}
var _ messagesigner.MpoolNonceAPI = (*MpoolNonceAPI)(nil)