Merge remote-tracking branch 'origin/master' into feat/stateless-offline-dealflow

This commit is contained in:
Peter Rabbitson 2021-05-11 04:54:22 +02:00
commit d54ed1b0c6
128 changed files with 7081 additions and 856 deletions

View File

@ -333,6 +333,10 @@ type-gen: api-gen
method-gen: api-gen method-gen: api-gen
(cd ./lotuspond/front/src/chain && go run ./methodgen.go) (cd ./lotuspond/front/src/chain && go run ./methodgen.go)
actors-gen:
go run ./chain/actors/agen
go fmt ./...
api-gen: api-gen:
go run ./gen/api go run ./gen/api
goimports -w api goimports -w api
@ -341,9 +345,9 @@ api-gen:
docsgen: docsgen-md docsgen-openrpc docsgen: docsgen-md docsgen-openrpc
docsgen-md-bin: api-gen docsgen-md-bin: api-gen actors-gen
go build $(GOFLAGS) -o docgen-md ./api/docgen/cmd go build $(GOFLAGS) -o docgen-md ./api/docgen/cmd
docsgen-openrpc-bin: api-gen docsgen-openrpc-bin: api-gen actors-gen
go build $(GOFLAGS) -o docgen-openrpc ./api/docgen-openrpc/cmd go build $(GOFLAGS) -o docgen-openrpc ./api/docgen-openrpc/cmd
docsgen-md: docsgen-md-full docsgen-md-storage docsgen-md-worker docsgen-md: docsgen-md-full docsgen-md-storage docsgen-md-worker
@ -367,7 +371,7 @@ docsgen-openrpc-worker: docsgen-openrpc-bin
.PHONY: docsgen docsgen-md-bin docsgen-openrpc-bin .PHONY: docsgen docsgen-md-bin docsgen-openrpc-bin
gen: type-gen method-gen docsgen api-gen gen: actors-gen type-gen method-gen docsgen api-gen
@echo ">>> IF YOU'VE MODIFIED THE CLI, REMEMBER TO ALSO MAKE docsgen-cli" @echo ">>> IF YOU'VE MODIFIED THE CLI, REMEMBER TO ALSO MAKE docsgen-cli"
.PHONY: gen .PHONY: gen

View File

@ -252,6 +252,13 @@ type FullNode interface {
// MpoolBatchPushMessage batch pushes a unsigned message to mempool. // MpoolBatchPushMessage batch pushes a unsigned message to mempool.
MpoolBatchPushMessage(context.Context, []*types.Message, *MessageSendSpec) ([]*types.SignedMessage, error) //perm:sign 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. // MpoolGetNonce gets next nonce for the specified sender.
// Note that this method may not be atomic. Use MpoolPushMessage instead. // Note that this method may not be atomic. Use MpoolPushMessage instead.
MpoolGetNonce(context.Context, address.Address) (uint64, error) //perm:read MpoolGetNonce(context.Context, address.Address) (uint64, error) //perm:read
@ -581,15 +588,16 @@ type FullNode interface {
// MsigCreate creates a multisig wallet // MsigCreate creates a multisig wallet
// It takes the following params: <required number of senders>, <approving addresses>, <unlock duration> // It takes the following params: <required number of senders>, <approving addresses>, <unlock duration>
//<initial balance>, <sender address of the create msg>, <gas price> //<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 // MsigPropose proposes a multisig message
// It takes the following params: <multisig address>, <recipient address>, <value to transfer>, // 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> // <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 // MsigApprove approves a previously-proposed multisig message by transaction ID
// It takes the following params: <multisig address>, <proposed transaction ID> <signer address> // 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 // MsigApproveTxnHash approves a previously-proposed multisig message, specified
// using both transaction ID and a hash of the parameters used in the // using both transaction ID and a hash of the parameters used in the
@ -597,43 +605,49 @@ type FullNode interface {
// exactly the transaction you think you are. // exactly the transaction you think you are.
// It takes the following params: <multisig address>, <proposed message ID>, <proposer address>, <recipient address>, <value to transfer>, // 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> // <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 // MsigCancel cancels a previously-proposed multisig message
// It takes the following params: <multisig address>, <proposed transaction ID>, <recipient address>, <value to transfer>, // 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> // <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 // MsigAddPropose proposes adding a signer in the multisig
// It takes the following params: <multisig address>, <sender address of the propose msg>, // It takes the following params: <multisig address>, <sender address of the propose msg>,
// <new signer>, <whether the number of required signers should be increased> // <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 // MsigAddApprove approves a previously proposed AddSigner message
// It takes the following params: <multisig address>, <sender address of the approve msg>, <proposed message ID>, // 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> // <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 // MsigAddCancel cancels a previously proposed AddSigner message
// It takes the following params: <multisig address>, <sender address of the cancel msg>, <proposed message ID>, // 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> // <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 // MsigSwapPropose proposes swapping 2 signers in the multisig
// It takes the following params: <multisig address>, <sender address of the propose msg>, // It takes the following params: <multisig address>, <sender address of the propose msg>,
// <old signer>, <new signer> // <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 // MsigSwapApprove approves a previously proposed SwapSigner
// It takes the following params: <multisig address>, <sender address of the approve msg>, <proposed message ID>, // It takes the following params: <multisig address>, <sender address of the approve msg>, <proposed message ID>,
// <proposer address>, <old signer>, <new signer> // <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 // MsigSwapCancel cancels a previously proposed SwapSigner message
// It takes the following params: <multisig address>, <sender address of the cancel msg>, <proposed message ID>, // It takes the following params: <multisig address>, <sender address of the cancel msg>, <proposed message ID>,
// <old signer>, <new signer> // <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. // MsigRemoveSigner proposes the removal of a signer from the multisig.
// It accepts the multisig to make the change on, the proposer address to // 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 // send the message from, the address to be removed, and a boolean
// indicating whether or not the signing threshold should be lowered by one // indicating whether or not the signing threshold should be lowered by one
// along with the address removal. // 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 adds funds to the market actor
MarketAddBalance(ctx context.Context, wallet, addr address.Address, amt types.BigInt) (cid.Cid, error) //perm:sign MarketAddBalance(ctx context.Context, wallet, addr address.Address, amt types.BigInt) (cid.Cid, error) //perm:sign
@ -666,6 +680,11 @@ type FullNode interface {
PaychVoucherList(context.Context, address.Address) ([]*paych.SignedVoucher, error) //perm:write PaychVoucherList(context.Context, address.Address) ([]*paych.SignedVoucher, error) //perm:write
PaychVoucherSubmit(context.Context, address.Address, *paych.SignedVoucher, []byte, []byte) (cid.Cid, error) //perm:sign 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 // CreateBackup creates node backup onder the specified file name. The
// method requires that the lotus daemon is running with the // method requires that the lotus daemon is running with the
// LOTUS_BACKUP_BASE_PATH environment variable set to some path, and that // 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{}{}}, "methods": []interface{}{}},
) )
addExample(api.CheckStatusCode(0))
addExample(map[string]interface{}{"abc": 123})
} }
func GetAPIType(name, pkg string) (i interface{}, t, permStruct, commonPermStruct reflect.Type) { func GetAPIType(name, pkg string) (i interface{}, t, permStruct, commonPermStruct reflect.Type) {

View File

@ -1083,6 +1083,51 @@ func (mr *MockFullNodeMockRecorder) MpoolBatchPushUntrusted(arg0, arg1 interface
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MpoolBatchPushUntrusted", reflect.TypeOf((*MockFullNode)(nil).MpoolBatchPushUntrusted), arg0, arg1) 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 // MpoolClear mocks base method
func (m *MockFullNode) MpoolClear(arg0 context.Context, arg1 bool) error { func (m *MockFullNode) MpoolClear(arg0 context.Context, arg1 bool) error {
m.ctrl.T.Helper() m.ctrl.T.Helper()
@ -1232,10 +1277,10 @@ func (mr *MockFullNodeMockRecorder) MpoolSub(arg0 interface{}) *gomock.Call {
} }
// MsigAddApprove mocks base method // 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() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MsigAddApprove", arg0, arg1, arg2, arg3, arg4, arg5, arg6) 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) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@ -1247,10 +1292,10 @@ func (mr *MockFullNodeMockRecorder) MsigAddApprove(arg0, arg1, arg2, arg3, arg4,
} }
// MsigAddCancel mocks base method // 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() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MsigAddCancel", arg0, arg1, arg2, arg3, arg4, arg5) 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) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@ -1262,10 +1307,10 @@ func (mr *MockFullNodeMockRecorder) MsigAddCancel(arg0, arg1, arg2, arg3, arg4,
} }
// MsigAddPropose mocks base method // 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() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MsigAddPropose", arg0, arg1, arg2, arg3, arg4) 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) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@ -1277,10 +1322,10 @@ func (mr *MockFullNodeMockRecorder) MsigAddPropose(arg0, arg1, arg2, arg3, arg4
} }
// MsigApprove mocks base method // 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() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MsigApprove", arg0, arg1, arg2, arg3) ret := m.ctrl.Call(m, "MsigApprove", arg0, arg1, arg2, arg3)
ret0, _ := ret[0].(cid.Cid) ret0, _ := ret[0].(*api.MessagePrototype)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@ -1292,10 +1337,10 @@ func (mr *MockFullNodeMockRecorder) MsigApprove(arg0, arg1, arg2, arg3 interface
} }
// MsigApproveTxnHash mocks base method // 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() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MsigApproveTxnHash", arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) 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) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@ -1307,10 +1352,10 @@ func (mr *MockFullNodeMockRecorder) MsigApproveTxnHash(arg0, arg1, arg2, arg3, a
} }
// MsigCancel mocks base method // 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() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MsigCancel", arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) 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) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@ -1322,10 +1367,10 @@ func (mr *MockFullNodeMockRecorder) MsigCancel(arg0, arg1, arg2, arg3, arg4, arg
} }
// MsigCreate mocks base method // 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() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MsigCreate", arg0, arg1, arg2, arg3, arg4, arg5, arg6) 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) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@ -1397,10 +1442,10 @@ func (mr *MockFullNodeMockRecorder) MsigGetVestingSchedule(arg0, arg1, arg2 inte
} }
// MsigPropose mocks base method // 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() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MsigPropose", arg0, arg1, arg2, arg3, arg4, arg5, arg6) 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) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@ -1412,10 +1457,10 @@ func (mr *MockFullNodeMockRecorder) MsigPropose(arg0, arg1, arg2, arg3, arg4, ar
} }
// MsigRemoveSigner mocks base method // 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() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MsigRemoveSigner", arg0, arg1, arg2, arg3, arg4) 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) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@ -1427,10 +1472,10 @@ func (mr *MockFullNodeMockRecorder) MsigRemoveSigner(arg0, arg1, arg2, arg3, arg
} }
// MsigSwapApprove mocks base method // 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() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MsigSwapApprove", arg0, arg1, arg2, arg3, arg4, arg5, arg6) 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) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@ -1442,10 +1487,10 @@ func (mr *MockFullNodeMockRecorder) MsigSwapApprove(arg0, arg1, arg2, arg3, arg4
} }
// MsigSwapCancel mocks base method // 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() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MsigSwapCancel", arg0, arg1, arg2, arg3, arg4, arg5) 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) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@ -1457,10 +1502,10 @@ func (mr *MockFullNodeMockRecorder) MsigSwapCancel(arg0, arg1, arg2, arg3, arg4,
} }
// MsigSwapPropose mocks base method // 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() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MsigSwapPropose", arg0, arg1, arg2, arg3, arg4) 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) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@ -1707,6 +1752,21 @@ func (mr *MockFullNodeMockRecorder) NetPubsubScores(arg0 interface{}) *gomock.Ca
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetPubsubScores", reflect.TypeOf((*MockFullNode)(nil).NetPubsubScores), arg0) 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 // PaychAllocateLane mocks base method
func (m *MockFullNode) PaychAllocateLane(arg0 context.Context, arg1 address.Address) (uint64, error) { func (m *MockFullNode) PaychAllocateLane(arg0 context.Context, arg1 address.Address) (uint64, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()

View File

@ -237,6 +237,12 @@ type FullNodeStruct struct {
MpoolBatchPushUntrusted func(p0 context.Context, p1 []*types.SignedMessage) ([]cid.Cid, error) `perm:"write"` 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"` MpoolClear func(p0 context.Context, p1 bool) error `perm:"write"`
MpoolGetConfig func(p0 context.Context) (*types.MpoolConfig, error) `perm:"read"` MpoolGetConfig func(p0 context.Context) (*types.MpoolConfig, error) `perm:"read"`
@ -257,19 +263,19 @@ type FullNodeStruct struct {
MpoolSub func(p0 context.Context) (<-chan MpoolUpdate, error) `perm:"read"` 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"` MsigGetAvailableBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.BigInt, error) `perm:"read"`
@ -279,15 +285,17 @@ type FullNodeStruct struct {
MsigGetVestingSchedule func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MsigVesting, error) `perm:"read"` 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"` PaychAllocateLane func(p0 context.Context, p1 address.Address) (uint64, error) `perm:"sign"`
@ -1517,6 +1525,30 @@ func (s *FullNodeStub) MpoolBatchPushUntrusted(p0 context.Context, p1 []*types.S
return *new([]cid.Cid), xerrors.New("method not supported") 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 { func (s *FullNodeStruct) MpoolClear(p0 context.Context, p1 bool) error {
return s.Internal.MpoolClear(p0, p1) return s.Internal.MpoolClear(p0, p1)
} }
@ -1597,60 +1629,60 @@ func (s *FullNodeStub) MpoolSub(p0 context.Context) (<-chan MpoolUpdate, error)
return nil, xerrors.New("method not supported") 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) 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) { 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 *new(cid.Cid), xerrors.New("method not supported") 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) 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) { func (s *FullNodeStub) MsigAddCancel(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 bool) (*MessagePrototype, error) {
return *new(cid.Cid), xerrors.New("method not supported") 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) 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) { func (s *FullNodeStub) MsigAddPropose(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (*MessagePrototype, error) {
return *new(cid.Cid), xerrors.New("method not supported") 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) 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) { func (s *FullNodeStub) MsigApprove(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address) (*MessagePrototype, error) {
return *new(cid.Cid), xerrors.New("method not supported") 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) 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) { 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 *new(cid.Cid), xerrors.New("method not supported") 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) 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) { 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 *new(cid.Cid), xerrors.New("method not supported") 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) 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) { 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 *new(cid.Cid), xerrors.New("method not supported") return nil, xerrors.New("method not supported")
} }
func (s *FullNodeStruct) MsigGetAvailableBalance(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.BigInt, error) { func (s *FullNodeStruct) MsigGetAvailableBalance(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.BigInt, error) {
@ -1685,44 +1717,52 @@ func (s *FullNodeStub) MsigGetVestingSchedule(p0 context.Context, p1 address.Add
return *new(MsigVesting), xerrors.New("method not supported") 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) 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) { 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 *new(cid.Cid), xerrors.New("method not supported") 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) 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) { func (s *FullNodeStub) MsigRemoveSigner(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (*MessagePrototype, error) {
return *new(cid.Cid), xerrors.New("method not supported") 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) 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) { 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 *new(cid.Cid), xerrors.New("method not supported") 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) 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) { func (s *FullNodeStub) MsigSwapCancel(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address) (*MessagePrototype, error) {
return *new(cid.Cid), xerrors.New("method not supported") 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) 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) { func (s *FullNodeStub) MsigSwapPropose(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 address.Address) (*MessagePrototype, error) {
return *new(cid.Cid), xerrors.New("method not supported") 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) { func (s *FullNodeStruct) PaychAllocateLane(p0 context.Context, p1 address.Address) (uint64, error) {

View File

@ -31,7 +31,7 @@ func TestCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration) {
func testCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration, upgradeHeight abi.ChainEpoch) { func testCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration, upgradeHeight abi.ChainEpoch) {
ctx := context.Background() ctx := context.Background()
n, sn := b(t, []FullNodeOpts{FullNodeWithActorsV4At(upgradeHeight)}, OneMiner) n, sn := b(t, []FullNodeOpts{FullNodeWithLatestActorsAt(upgradeHeight)}, OneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI) client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0] miner := sn[0]

View File

@ -63,7 +63,7 @@ func TestDeadlineToggling(t *testing.T, b APIBuilder, blocktime time.Duration) {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
n, sn := b(t, []FullNodeOpts{FullNodeWithActorsV4At(upgradeH)}, OneMiner) n, sn := b(t, []FullNodeOpts{FullNodeWithLatestActorsAt(upgradeH)}, OneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI) client := n[0].FullNode.(*impl.FullNodeAPI)
minerA := sn[0] minerA := sn[0]

View File

@ -206,7 +206,7 @@ func TestDealMining(t *testing.T, b APIBuilder, blocktime time.Duration, carExpo
func (ts *testSuite) testNonGenesisMiner(t *testing.T) { func (ts *testSuite) testNonGenesisMiner(t *testing.T) {
ctx := context.Background() ctx := context.Background()
n, sn := ts.makeNodes(t, []FullNodeOpts{ n, sn := ts.makeNodes(t, []FullNodeOpts{
FullNodeWithActorsV4At(-1), FullNodeWithLatestActorsAt(-1),
}, []StorageMiner{ }, []StorageMiner{
{Full: 0, Preseal: PresealGenesis}, {Full: 0, Preseal: PresealGenesis},
}) })

View File

@ -121,7 +121,7 @@ var OneMiner = []StorageMiner{{Full: 0, Preseal: PresealGenesis}}
var OneFull = DefaultFullOpts(1) var OneFull = DefaultFullOpts(1)
var TwoFull = DefaultFullOpts(2) var TwoFull = DefaultFullOpts(2)
var FullNodeWithActorsV4At = func(upgradeHeight abi.ChainEpoch) FullNodeOpts { var FullNodeWithLatestActorsAt = func(upgradeHeight abi.ChainEpoch) FullNodeOpts {
if upgradeHeight == -1 { if upgradeHeight == -1 {
upgradeHeight = 3 upgradeHeight = 3
} }

View File

@ -29,7 +29,7 @@ func SendFunds(ctx context.Context, t *testing.T, sender TestNode, addr address.
if err != nil { if err != nil {
t.Fatal(err) 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 { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -223,7 +223,7 @@ func testWindowPostUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration,
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
n, sn := b(t, []FullNodeOpts{FullNodeWithActorsV4At(upgradeHeight)}, OneMiner) n, sn := b(t, []FullNodeOpts{FullNodeWithLatestActorsAt(upgradeHeight)}, OneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI) client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0] miner := sn[0]
@ -442,7 +442,7 @@ func TestTerminate(t *testing.T, b APIBuilder, blocktime time.Duration) {
nSectors := uint64(2) nSectors := uint64(2)
n, sn := b(t, []FullNodeOpts{FullNodeWithActorsV4At(-1)}, []StorageMiner{{Full: 0, Preseal: int(nSectors)}}) n, sn := b(t, []FullNodeOpts{FullNodeWithLatestActorsAt(-1)}, []StorageMiner{{Full: 0, Preseal: int(nSectors)}})
client := n[0].FullNode.(*impl.FullNodeAPI) client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0] miner := sn[0]
@ -617,7 +617,7 @@ func TestWindowPostDispute(t *testing.T, b APIBuilder, blocktime time.Duration)
/// ///
// Then we're going to manually submit bad proofs. // Then we're going to manually submit bad proofs.
n, sn := b(t, []FullNodeOpts{ n, sn := b(t, []FullNodeOpts{
FullNodeWithActorsV4At(-1), FullNodeWithLatestActorsAt(-1),
}, []StorageMiner{ }, []StorageMiner{
{Full: 0, Preseal: PresealGenesis}, {Full: 0, Preseal: PresealGenesis},
{Full: 0}, {Full: 0},
@ -900,7 +900,7 @@ func TestWindowPostDisputeFails(t *testing.T, b APIBuilder, blocktime time.Durat
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
n, sn := b(t, []FullNodeOpts{FullNodeWithActorsV4At(-1)}, OneMiner) n, sn := b(t, []FullNodeOpts{FullNodeWithLatestActorsAt(-1)}, OneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI) client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0] miner := sn[0]

View File

@ -5,6 +5,8 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/filecoin-project/lotus/chain/types"
datatransfer "github.com/filecoin-project/go-data-transfer" datatransfer "github.com/filecoin-project/go-data-transfer"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
@ -116,3 +118,61 @@ type ConnMgrInfo struct {
Tags map[string]int Tags map[string]int
Conns map[string]time.Time 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 ( import (
"context" "context"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"golang.org/x/xerrors"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
@ -57,4 +59,129 @@ func (w *WrapperV1Full) Version(ctx context.Context) (api.APIVersion, error) {
return ver, nil 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{} 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/GeertJohan/go.rice/rice"
_ "github.com/golang/mock/mockgen" _ "github.com/golang/mock/mockgen"
_ "github.com/whyrusleeping/bencher" _ "github.com/whyrusleeping/bencher"
_ "golang.org/x/tools/cmd/stringer"
) )

218
chain/actors/agen/main.go Normal file
View File

@ -0,0 +1,218 @@
package main
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"text/template"
"golang.org/x/xerrors"
)
var latestVersion = 4
var versions = []int{0, 2, 3, latestVersion}
var versionImports = map[int]string{
0: "/",
2: "/v2/",
3: "/v3/",
latestVersion: "/v4/",
}
var actors = map[string][]int{
"account": versions,
"cron": versions,
"init": versions,
"market": versions,
"miner": versions,
"multisig": versions,
"paych": versions,
"power": versions,
"reward": versions,
"verifreg": versions,
}
func main() {
if err := generateAdapters(); err != nil {
fmt.Println(err)
return
}
if err := generatePolicy("chain/actors/policy/policy.go"); err != nil {
fmt.Println(err)
return
}
if err := generateBuiltin("chain/actors/builtin/builtin.go"); err != nil {
fmt.Println(err)
return
}
}
func generateAdapters() error {
for act, versions := range actors {
actDir := filepath.Join("chain/actors/builtin", act)
if err := generateState(actDir); err != nil {
return err
}
if err := generateMessages(actDir); err != nil {
return err
}
{
af, err := ioutil.ReadFile(filepath.Join(actDir, "actor.go.template"))
if err != nil {
return xerrors.Errorf("loading actor template: %w", err)
}
tpl := template.Must(template.New("").Funcs(template.FuncMap{
"import": func(v int) string { return versionImports[v] },
}).Parse(string(af)))
var b bytes.Buffer
err = tpl.Execute(&b, map[string]interface{}{
"versions": versions,
"latestVersion": latestVersion,
})
if err != nil {
return err
}
if err := ioutil.WriteFile(filepath.Join(actDir, fmt.Sprintf("%s.go", act)), b.Bytes(), 0666); err != nil {
return err
}
}
}
return nil
}
func generateState(actDir string) error {
af, err := ioutil.ReadFile(filepath.Join(actDir, "state.go.template"))
if err != nil {
if os.IsNotExist(err) {
return nil // skip
}
return xerrors.Errorf("loading state adapter template: %w", err)
}
for _, version := range versions {
tpl := template.Must(template.New("").Funcs(template.FuncMap{}).Parse(string(af)))
var b bytes.Buffer
err := tpl.Execute(&b, map[string]interface{}{
"v": version,
"import": versionImports[version],
})
if err != nil {
return err
}
if err := ioutil.WriteFile(filepath.Join(actDir, fmt.Sprintf("v%d.go", version)), b.Bytes(), 0666); err != nil {
return err
}
}
return nil
}
func generateMessages(actDir string) error {
af, err := ioutil.ReadFile(filepath.Join(actDir, "message.go.template"))
if err != nil {
if os.IsNotExist(err) {
return nil // skip
}
return xerrors.Errorf("loading message adapter template: %w", err)
}
for _, version := range versions {
tpl := template.Must(template.New("").Funcs(template.FuncMap{}).Parse(string(af)))
var b bytes.Buffer
err := tpl.Execute(&b, map[string]interface{}{
"v": version,
"import": versionImports[version],
})
if err != nil {
return err
}
if err := ioutil.WriteFile(filepath.Join(actDir, fmt.Sprintf("message%d.go", version)), b.Bytes(), 0666); err != nil {
return err
}
}
return nil
}
func generatePolicy(policyPath string) error {
pf, err := ioutil.ReadFile(policyPath + ".template")
if err != nil {
if os.IsNotExist(err) {
return nil // skip
}
return xerrors.Errorf("loading policy template file: %w", err)
}
tpl := template.Must(template.New("").Funcs(template.FuncMap{
"import": func(v int) string { return versionImports[v] },
}).Parse(string(pf)))
var b bytes.Buffer
err = tpl.Execute(&b, map[string]interface{}{
"versions": versions,
"latestVersion": latestVersion,
})
if err != nil {
return err
}
if err := ioutil.WriteFile(policyPath, b.Bytes(), 0666); err != nil {
return err
}
return nil
}
func generateBuiltin(builtinPath string) error {
bf, err := ioutil.ReadFile(builtinPath + ".template")
if err != nil {
if os.IsNotExist(err) {
return nil // skip
}
return xerrors.Errorf("loading builtin template file: %w", err)
}
tpl := template.Must(template.New("").Funcs(template.FuncMap{
"import": func(v int) string { return versionImports[v] },
}).Parse(string(bf)))
var b bytes.Buffer
err = tpl.Execute(&b, map[string]interface{}{
"versions": versions,
"latestVersion": latestVersion,
})
if err != nil {
return err
}
if err := ioutil.WriteFile(builtinPath, b.Bytes(), 0666); err != nil {
return err
}
return nil
}

View File

@ -12,21 +12,28 @@ import (
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
) )
func init() { func init() {
builtin.RegisterActorState(builtin0.AccountActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin0.AccountActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load0(store, root) return load0(store, root)
}) })
builtin.RegisterActorState(builtin2.AccountActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin2.AccountActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load2(store, root) return load2(store, root)
}) })
builtin.RegisterActorState(builtin3.AccountActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin3.AccountActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load3(store, root) return load3(store, root)
}) })
builtin.RegisterActorState(builtin4.AccountActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin4.AccountActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load4(store, root) return load4(store, root)
}) })
@ -36,14 +43,19 @@ var Methods = builtin4.MethodsAccount
func Load(store adt.Store, act *types.Actor) (State, error) { func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code { switch act.Code {
case builtin0.AccountActorCodeID: case builtin0.AccountActorCodeID:
return load0(store, act.Head) return load0(store, act.Head)
case builtin2.AccountActorCodeID: case builtin2.AccountActorCodeID:
return load2(store, act.Head) return load2(store, act.Head)
case builtin3.AccountActorCodeID: case builtin3.AccountActorCodeID:
return load3(store, act.Head) return load3(store, act.Head)
case builtin4.AccountActorCodeID: case builtin4.AccountActorCodeID:
return load4(store, act.Head) return load4(store, act.Head)
} }
return nil, xerrors.Errorf("unknown actor code %s", act.Code) return nil, xerrors.Errorf("unknown actor code %s", act.Code)
} }

View File

@ -0,0 +1,41 @@
package account
import (
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/cbor"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types"
{{range .versions}}
builtin{{.}} "github.com/filecoin-project/specs-actors{{import .}}actors/builtin"
{{end}}
)
func init() {
{{range .versions}}
builtin.RegisterActorState(builtin{{.}}.AccountActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load{{.}}(store, root)
})
{{end}}}
var Methods = builtin4.MethodsAccount
func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code {
{{range .versions}}
case builtin{{.}}.AccountActorCodeID:
return load{{.}}(store, act.Head)
{{end}}
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
type State interface {
cbor.Marshaler
PubkeyAddress() (address.Address, error)
}

View File

@ -0,0 +1,30 @@
package account
import (
"github.com/filecoin-project/go-address"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/lotus/chain/actors/adt"
account{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/builtin/account"
)
var _ State = (*state{{.v}})(nil)
func load{{.v}}(store adt.Store, root cid.Cid) (State, error) {
out := state{{.v}}{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state{{.v}} struct {
account{{.v}}.State
store adt.Store
}
func (s *state{{.v}}) PubkeyAddress() (address.Address, error) {
return s.Address, nil
}

View File

@ -6,9 +6,16 @@ import (
"golang.org/x/xerrors" "golang.org/x/xerrors"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
smoothing0 "github.com/filecoin-project/specs-actors/actors/util/smoothing"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
smoothing2 "github.com/filecoin-project/specs-actors/v2/actors/util/smoothing"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
smoothing3 "github.com/filecoin-project/specs-actors/v3/actors/util/smoothing"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
smoothing4 "github.com/filecoin-project/specs-actors/v4/actors/util/smoothing"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor" "github.com/filecoin-project/go-state-types/cbor"
@ -16,30 +23,25 @@ import (
"github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
smoothing0 "github.com/filecoin-project/specs-actors/actors/util/smoothing" miner4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/miner"
smoothing2 "github.com/filecoin-project/specs-actors/v2/actors/util/smoothing" proof4 "github.com/filecoin-project/specs-actors/v4/actors/runtime/proof"
smoothing3 "github.com/filecoin-project/specs-actors/v3/actors/util/smoothing"
smoothing4 "github.com/filecoin-project/specs-actors/v4/actors/util/smoothing"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
proof0 "github.com/filecoin-project/specs-actors/actors/runtime/proof"
) )
var SystemActorAddr = builtin0.SystemActorAddr var SystemActorAddr = builtin4.SystemActorAddr
var BurntFundsActorAddr = builtin0.BurntFundsActorAddr var BurntFundsActorAddr = builtin4.BurntFundsActorAddr
var CronActorAddr = builtin0.CronActorAddr var CronActorAddr = builtin4.CronActorAddr
var SaftAddress = makeAddress("t0122") var SaftAddress = makeAddress("t0122")
var ReserveAddress = makeAddress("t090") var ReserveAddress = makeAddress("t090")
var RootVerifierAddress = makeAddress("t080") var RootVerifierAddress = makeAddress("t080")
var ( var (
ExpectedLeadersPerEpoch = builtin0.ExpectedLeadersPerEpoch ExpectedLeadersPerEpoch = builtin4.ExpectedLeadersPerEpoch
) )
const ( const (
EpochDurationSeconds = builtin0.EpochDurationSeconds EpochDurationSeconds = builtin4.EpochDurationSeconds
EpochsInDay = builtin0.EpochsInDay EpochsInDay = builtin4.EpochsInDay
SecondsInDay = builtin0.SecondsInDay SecondsInDay = builtin4.SecondsInDay
) )
const ( const (
@ -47,31 +49,38 @@ const (
MethodConstructor = builtin4.MethodConstructor MethodConstructor = builtin4.MethodConstructor
) )
// These are all just type aliases across actor versions 0, 2, & 3. In the future, that might change // These are all just type aliases across actor versions. In the future, that might change
// and we might need to do something fancier. // and we might need to do something fancier.
type SectorInfo = proof0.SectorInfo type SectorInfo = proof4.SectorInfo
type PoStProof = proof0.PoStProof type PoStProof = proof4.PoStProof
type FilterEstimate = smoothing0.FilterEstimate type FilterEstimate = smoothing0.FilterEstimate
func FromV0FilterEstimate(v0 smoothing0.FilterEstimate) FilterEstimate { func QAPowerForWeight(size abi.SectorSize, duration abi.ChainEpoch, dealWeight, verifiedWeight abi.DealWeight) abi.StoragePower {
return (FilterEstimate)(v0) //nolint:unconvert return miner4.QAPowerForWeight(size, duration, dealWeight, verifiedWeight)
} }
// Doesn't change between actors v0, v2, and v3. func FromV0FilterEstimate(v0 smoothing0.FilterEstimate) FilterEstimate {
func QAPowerForWeight(size abi.SectorSize, duration abi.ChainEpoch, dealWeight, verifiedWeight abi.DealWeight) abi.StoragePower {
return miner0.QAPowerForWeight(size, duration, dealWeight, verifiedWeight) return (FilterEstimate)(v0) //nolint:unconvert
} }
func FromV2FilterEstimate(v2 smoothing2.FilterEstimate) FilterEstimate { func FromV2FilterEstimate(v2 smoothing2.FilterEstimate) FilterEstimate {
return (FilterEstimate)(v2) return (FilterEstimate)(v2)
} }
func FromV3FilterEstimate(v3 smoothing3.FilterEstimate) FilterEstimate { func FromV3FilterEstimate(v3 smoothing3.FilterEstimate) FilterEstimate {
return (FilterEstimate)(v3) return (FilterEstimate)(v3)
} }
func FromV4FilterEstimate(v4 smoothing4.FilterEstimate) FilterEstimate { func FromV4FilterEstimate(v4 smoothing4.FilterEstimate) FilterEstimate {
return (FilterEstimate)(v4) return (FilterEstimate)(v4)
} }
type ActorStateLoader func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) type ActorStateLoader func(store adt.Store, root cid.Cid) (cbor.Marshaler, error)
@ -92,52 +101,127 @@ func Load(store adt.Store, act *types.Actor) (cbor.Marshaler, error) {
func ActorNameByCode(c cid.Cid) string { func ActorNameByCode(c cid.Cid) string {
switch { switch {
case builtin0.IsBuiltinActor(c): case builtin0.IsBuiltinActor(c):
return builtin0.ActorNameByCode(c) return builtin0.ActorNameByCode(c)
case builtin2.IsBuiltinActor(c): case builtin2.IsBuiltinActor(c):
return builtin2.ActorNameByCode(c) return builtin2.ActorNameByCode(c)
case builtin3.IsBuiltinActor(c): case builtin3.IsBuiltinActor(c):
return builtin3.ActorNameByCode(c) return builtin3.ActorNameByCode(c)
case builtin4.IsBuiltinActor(c): case builtin4.IsBuiltinActor(c):
return builtin4.ActorNameByCode(c) return builtin4.ActorNameByCode(c)
default: default:
return "<unknown>" return "<unknown>"
} }
} }
func IsBuiltinActor(c cid.Cid) bool { func IsBuiltinActor(c cid.Cid) bool {
return builtin0.IsBuiltinActor(c) ||
builtin2.IsBuiltinActor(c) || if builtin0.IsBuiltinActor(c) {
builtin3.IsBuiltinActor(c) || return true
builtin4.IsBuiltinActor(c) }
if builtin2.IsBuiltinActor(c) {
return true
}
if builtin3.IsBuiltinActor(c) {
return true
}
if builtin4.IsBuiltinActor(c) {
return true
}
return false
} }
func IsAccountActor(c cid.Cid) bool { func IsAccountActor(c cid.Cid) bool {
return c == builtin0.AccountActorCodeID ||
c == builtin2.AccountActorCodeID || if c == builtin0.AccountActorCodeID {
c == builtin3.AccountActorCodeID || return true
c == builtin4.AccountActorCodeID }
if c == builtin2.AccountActorCodeID {
return true
}
if c == builtin3.AccountActorCodeID {
return true
}
if c == builtin4.AccountActorCodeID {
return true
}
return false
} }
func IsStorageMinerActor(c cid.Cid) bool { func IsStorageMinerActor(c cid.Cid) bool {
return c == builtin0.StorageMinerActorCodeID ||
c == builtin2.StorageMinerActorCodeID || if c == builtin0.StorageMinerActorCodeID {
c == builtin3.StorageMinerActorCodeID || return true
c == builtin4.StorageMinerActorCodeID }
if c == builtin2.StorageMinerActorCodeID {
return true
}
if c == builtin3.StorageMinerActorCodeID {
return true
}
if c == builtin4.StorageMinerActorCodeID {
return true
}
return false
} }
func IsMultisigActor(c cid.Cid) bool { func IsMultisigActor(c cid.Cid) bool {
return c == builtin0.MultisigActorCodeID ||
c == builtin2.MultisigActorCodeID || if c == builtin0.MultisigActorCodeID {
c == builtin3.MultisigActorCodeID || return true
c == builtin4.MultisigActorCodeID }
if c == builtin2.MultisigActorCodeID {
return true
}
if c == builtin3.MultisigActorCodeID {
return true
}
if c == builtin4.MultisigActorCodeID {
return true
}
return false
} }
func IsPaymentChannelActor(c cid.Cid) bool { func IsPaymentChannelActor(c cid.Cid) bool {
return c == builtin0.PaymentChannelActorCodeID ||
c == builtin2.PaymentChannelActorCodeID || if c == builtin0.PaymentChannelActorCodeID {
c == builtin3.PaymentChannelActorCodeID || return true
c == builtin4.PaymentChannelActorCodeID }
if c == builtin2.PaymentChannelActorCodeID {
return true
}
if c == builtin3.PaymentChannelActorCodeID {
return true
}
if c == builtin4.PaymentChannelActorCodeID {
return true
}
return false
} }
func makeAddress(addr string) address.Address { func makeAddress(addr string) address.Address {

View File

@ -0,0 +1,144 @@
package builtin
import (
"github.com/filecoin-project/go-address"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
{{range .versions}}
builtin{{.}} "github.com/filecoin-project/specs-actors{{import .}}actors/builtin"
smoothing{{.}} "github.com/filecoin-project/specs-actors{{import .}}actors/util/smoothing"
{{end}}
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/types"
miner{{.latestVersion}} "github.com/filecoin-project/specs-actors{{import .latestVersion}}actors/builtin/miner"
proof{{.latestVersion}} "github.com/filecoin-project/specs-actors{{import .latestVersion}}actors/runtime/proof"
)
var SystemActorAddr = builtin{{.latestVersion}}.SystemActorAddr
var BurntFundsActorAddr = builtin{{.latestVersion}}.BurntFundsActorAddr
var CronActorAddr = builtin{{.latestVersion}}.CronActorAddr
var SaftAddress = makeAddress("t0122")
var ReserveAddress = makeAddress("t090")
var RootVerifierAddress = makeAddress("t080")
var (
ExpectedLeadersPerEpoch = builtin{{.latestVersion}}.ExpectedLeadersPerEpoch
)
const (
EpochDurationSeconds = builtin{{.latestVersion}}.EpochDurationSeconds
EpochsInDay = builtin{{.latestVersion}}.EpochsInDay
SecondsInDay = builtin{{.latestVersion}}.SecondsInDay
)
const (
MethodSend = builtin{{.latestVersion}}.MethodSend
MethodConstructor = builtin{{.latestVersion}}.MethodConstructor
)
// These are all just type aliases across actor versions. In the future, that might change
// and we might need to do something fancier.
type SectorInfo = proof{{.latestVersion}}.SectorInfo
type PoStProof = proof{{.latestVersion}}.PoStProof
type FilterEstimate = smoothing0.FilterEstimate
func QAPowerForWeight(size abi.SectorSize, duration abi.ChainEpoch, dealWeight, verifiedWeight abi.DealWeight) abi.StoragePower {
return miner{{.latestVersion}}.QAPowerForWeight(size, duration, dealWeight, verifiedWeight)
}
{{range .versions}}
func FromV{{.}}FilterEstimate(v{{.}} smoothing{{.}}.FilterEstimate) FilterEstimate {
{{if (eq . 0)}}
return (FilterEstimate)(v{{.}}) //nolint:unconvert
{{else}}
return (FilterEstimate)(v{{.}})
{{end}}
}
{{end}}
type ActorStateLoader func(store adt.Store, root cid.Cid) (cbor.Marshaler, error)
var ActorStateLoaders = make(map[cid.Cid]ActorStateLoader)
func RegisterActorState(code cid.Cid, loader ActorStateLoader) {
ActorStateLoaders[code] = loader
}
func Load(store adt.Store, act *types.Actor) (cbor.Marshaler, error) {
loader, found := ActorStateLoaders[act.Code]
if !found {
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
return loader(store, act.Head)
}
func ActorNameByCode(c cid.Cid) string {
switch {
{{range .versions}}
case builtin{{.}}.IsBuiltinActor(c):
return builtin{{.}}.ActorNameByCode(c)
{{end}}
default:
return "<unknown>"
}
}
func IsBuiltinActor(c cid.Cid) bool {
{{range .versions}}
if builtin{{.}}.IsBuiltinActor(c) {
return true
}
{{end}}
return false
}
func IsAccountActor(c cid.Cid) bool {
{{range .versions}}
if c == builtin{{.}}.AccountActorCodeID {
return true
}
{{end}}
return false
}
func IsStorageMinerActor(c cid.Cid) bool {
{{range .versions}}
if c == builtin{{.}}.StorageMinerActorCodeID {
return true
}
{{end}}
return false
}
func IsMultisigActor(c cid.Cid) bool {
{{range .versions}}
if c == builtin{{.}}.MultisigActorCodeID {
return true
}
{{end}}
return false
}
func IsPaymentChannelActor(c cid.Cid) bool {
{{range .versions}}
if c == builtin{{.}}.PaymentChannelActorCodeID {
return true
}
{{end}}
return false
}
func makeAddress(addr string) address.Address {
ret, err := address.NewFromString(addr)
if err != nil {
panic(err)
}
return ret
}

View File

@ -0,0 +1,10 @@
package cron
import (
builtin{{.latestVersion}} "github.com/filecoin-project/specs-actors{{import .latestVersion}}actors/builtin"
)
var (
Address = builtin{{.latestVersion}}.CronActorAddr
Methods = builtin{{.latestVersion}}.MethodsCron
)

View File

@ -0,0 +1,60 @@
package init
import (
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/modules/dtypes"
{{range .versions}}
builtin{{.}} "github.com/filecoin-project/specs-actors{{import .}}actors/builtin"
{{end}}
)
func init() {
{{range .versions}}
builtin.RegisterActorState(builtin{{.}}.InitActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load{{.}}(store, root)
})
{{end}}}
var (
Address = builtin{{.latestVersion}}.InitActorAddr
Methods = builtin{{.latestVersion}}.MethodsInit
)
func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code {
{{range .versions}}
case builtin{{.}}.InitActorCodeID:
return load{{.}}(store, act.Head)
{{end}}
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
type State interface {
cbor.Marshaler
ResolveAddress(address address.Address) (address.Address, bool, error)
MapAddressToNewID(address address.Address) (address.Address, error)
NetworkName() (dtypes.NetworkName, error)
ForEachActor(func(id abi.ActorID, address address.Address) error) error
// Remove exists to support tooling that manipulates state for testing.
// It should not be used in production code, as init actor entries are
// immutable.
Remove(addrs ...address.Address) error
// Sets the network's name. This should only be used on upgrade/fork.
SetNetworkName(name string) error
addressMap() (adt.Map, error)
}

View File

@ -14,21 +14,28 @@ import (
"github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/dtypes"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
) )
func init() { func init() {
builtin.RegisterActorState(builtin0.InitActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin0.InitActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load0(store, root) return load0(store, root)
}) })
builtin.RegisterActorState(builtin2.InitActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin2.InitActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load2(store, root) return load2(store, root)
}) })
builtin.RegisterActorState(builtin3.InitActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin3.InitActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load3(store, root) return load3(store, root)
}) })
builtin.RegisterActorState(builtin4.InitActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin4.InitActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load4(store, root) return load4(store, root)
}) })
@ -41,14 +48,19 @@ var (
func Load(store adt.Store, act *types.Actor) (State, error) { func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code { switch act.Code {
case builtin0.InitActorCodeID: case builtin0.InitActorCodeID:
return load0(store, act.Head) return load0(store, act.Head)
case builtin2.InitActorCodeID: case builtin2.InitActorCodeID:
return load2(store, act.Head) return load2(store, act.Head)
case builtin3.InitActorCodeID: case builtin3.InitActorCodeID:
return load3(store, act.Head) return load3(store, act.Head)
case builtin4.InitActorCodeID: case builtin4.InitActorCodeID:
return load4(store, act.Head) return load4(store, act.Head)
} }
return nil, xerrors.Errorf("unknown actor code %s", act.Code) return nil, xerrors.Errorf("unknown actor code %s", act.Code)
} }

View File

@ -0,0 +1,89 @@
package init
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/node/modules/dtypes"
{{if (ge .v 3)}}
builtin{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/builtin"
{{end}}
init{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/builtin/init"
adt{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/util/adt"
)
var _ State = (*state{{.v}})(nil)
func load{{.v}}(store adt.Store, root cid.Cid) (State, error) {
out := state{{.v}}{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state{{.v}} struct {
init{{.v}}.State
store adt.Store
}
func (s *state{{.v}}) ResolveAddress(address address.Address) (address.Address, bool, error) {
return s.State.ResolveAddress(s.store, address)
}
func (s *state{{.v}}) MapAddressToNewID(address address.Address) (address.Address, error) {
return s.State.MapAddressToNewID(s.store, address)
}
func (s *state{{.v}}) ForEachActor(cb func(id abi.ActorID, address address.Address) error) error {
addrs, err := adt{{.v}}.AsMap(s.store, s.State.AddressMap{{if (ge .v 3)}}, builtin{{.v}}.DefaultHamtBitwidth{{end}})
if err != nil {
return err
}
var actorID cbg.CborInt
return addrs.ForEach(&actorID, func(key string) error {
addr, err := address.NewFromBytes([]byte(key))
if err != nil {
return err
}
return cb(abi.ActorID(actorID), addr)
})
}
func (s *state{{.v}}) NetworkName() (dtypes.NetworkName, error) {
return dtypes.NetworkName(s.State.NetworkName), nil
}
func (s *state{{.v}}) SetNetworkName(name string) error {
s.State.NetworkName = name
return nil
}
func (s *state{{.v}}) Remove(addrs ...address.Address) (err error) {
m, err := adt{{.v}}.AsMap(s.store, s.State.AddressMap{{if (ge .v 3)}}, builtin{{.v}}.DefaultHamtBitwidth{{end}})
if err != nil {
return err
}
for _, addr := range addrs {
if err = m.Delete(abi.AddrKey(addr)); err != nil {
return xerrors.Errorf("failed to delete entry for address: %s; err: %w", addr, err)
}
}
amr, err := m.Root()
if err != nil {
return xerrors.Errorf("failed to get address map root: %w", err)
}
s.State.AddressMap = amr
return nil
}
func (s *state{{.v}}) addressMap() (adt.Map, error) {
return adt{{.v}}.AsMap(s.store, s.AddressMap{{if (ge .v 3)}}, builtin{{.v}}.DefaultHamtBitwidth{{end}})
}

View File

@ -3,7 +3,6 @@ package init
import ( import (
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors" "golang.org/x/xerrors"
@ -11,6 +10,8 @@ import (
"github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/dtypes"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
init3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/init" init3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/init"
adt3 "github.com/filecoin-project/specs-actors/v3/actors/util/adt" adt3 "github.com/filecoin-project/specs-actors/v3/actors/util/adt"
) )

View File

@ -3,7 +3,6 @@ package init
import ( import (
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors" "golang.org/x/xerrors"
@ -11,6 +10,8 @@ import (
"github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/dtypes"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
init4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/init" init4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/init"
adt4 "github.com/filecoin-project/specs-actors/v4/actors/util/adt" adt4 "github.com/filecoin-project/specs-actors/v4/actors/util/adt"
) )

View File

@ -0,0 +1,159 @@
package market
import (
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/cbor"
"github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
market0 "github.com/filecoin-project/specs-actors/actors/builtin/market"
{{range .versions}}
builtin{{.}} "github.com/filecoin-project/specs-actors{{import .}}actors/builtin"
{{end}}
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types"
)
func init() {
{{range .versions}}
builtin.RegisterActorState(builtin{{.}}.StorageMarketActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load{{.}}(store, root)
})
{{end}}}
var (
Address = builtin{{.latestVersion}}.StorageMarketActorAddr
Methods = builtin{{.latestVersion}}.MethodsMarket
)
func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code {
{{range .versions}}
case builtin{{.}}.StorageMarketActorCodeID:
return load{{.}}(store, act.Head)
{{end}}
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
type State interface {
cbor.Marshaler
BalancesChanged(State) (bool, error)
EscrowTable() (BalanceTable, error)
LockedTable() (BalanceTable, error)
TotalLocked() (abi.TokenAmount, error)
StatesChanged(State) (bool, error)
States() (DealStates, error)
ProposalsChanged(State) (bool, error)
Proposals() (DealProposals, error)
VerifyDealsForActivation(
minerAddr address.Address, deals []abi.DealID, currEpoch, sectorExpiry abi.ChainEpoch,
) (weight, verifiedWeight abi.DealWeight, err error)
NextID() (abi.DealID, error)
}
type BalanceTable interface {
ForEach(cb func(address.Address, abi.TokenAmount) error) error
Get(key address.Address) (abi.TokenAmount, error)
}
type DealStates interface {
ForEach(cb func(id abi.DealID, ds DealState) error) error
Get(id abi.DealID) (*DealState, bool, error)
array() adt.Array
decode(*cbg.Deferred) (*DealState, error)
}
type DealProposals interface {
ForEach(cb func(id abi.DealID, dp DealProposal) error) error
Get(id abi.DealID) (*DealProposal, bool, error)
array() adt.Array
decode(*cbg.Deferred) (*DealProposal, error)
}
type PublishStorageDealsParams = market0.PublishStorageDealsParams
type PublishStorageDealsReturn = market0.PublishStorageDealsReturn
type VerifyDealsForActivationParams = market0.VerifyDealsForActivationParams
type WithdrawBalanceParams = market0.WithdrawBalanceParams
type ClientDealProposal = market0.ClientDealProposal
type DealState struct {
SectorStartEpoch abi.ChainEpoch // -1 if not yet included in proven sector
LastUpdatedEpoch abi.ChainEpoch // -1 if deal state never updated
SlashEpoch abi.ChainEpoch // -1 if deal never slashed
}
type DealProposal struct {
PieceCID cid.Cid
PieceSize abi.PaddedPieceSize
VerifiedDeal bool
Client address.Address
Provider address.Address
Label string
StartEpoch abi.ChainEpoch
EndEpoch abi.ChainEpoch
StoragePricePerEpoch abi.TokenAmount
ProviderCollateral abi.TokenAmount
ClientCollateral abi.TokenAmount
}
type DealStateChanges struct {
Added []DealIDState
Modified []DealStateChange
Removed []DealIDState
}
type DealIDState struct {
ID abi.DealID
Deal DealState
}
// DealStateChange is a change in deal state from -> to
type DealStateChange struct {
ID abi.DealID
From *DealState
To *DealState
}
type DealProposalChanges struct {
Added []ProposalIDState
Removed []ProposalIDState
}
type ProposalIDState struct {
ID abi.DealID
Proposal DealProposal
}
func EmptyDealState() *DealState {
return &DealState{
SectorStartEpoch: -1,
SlashEpoch: -1,
LastUpdatedEpoch: -1,
}
}
// returns the earned fees and pending fees for a given deal
func (deal DealProposal) GetDealFees(height abi.ChainEpoch) (abi.TokenAmount, abi.TokenAmount) {
tf := big.Mul(deal.StoragePricePerEpoch, big.NewInt(int64(deal.EndEpoch-deal.StartEpoch)))
ef := big.Mul(deal.StoragePricePerEpoch, big.NewInt(int64(height-deal.StartEpoch)))
if ef.LessThan(big.Zero()) {
ef = big.Zero()
}
if ef.GreaterThan(tf) {
ef = tf
}
return ef, big.Sub(tf, ef)
}

View File

@ -1,19 +1,23 @@
package market package market
import ( import (
"github.com/filecoin-project/go-state-types/big"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/cbor" "github.com/filecoin-project/go-state-types/cbor"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
market0 "github.com/filecoin-project/specs-actors/actors/builtin/market" market0 "github.com/filecoin-project/specs-actors/actors/builtin/market"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/adt"
@ -22,15 +26,19 @@ import (
) )
func init() { func init() {
builtin.RegisterActorState(builtin0.StorageMarketActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin0.StorageMarketActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load0(store, root) return load0(store, root)
}) })
builtin.RegisterActorState(builtin2.StorageMarketActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin2.StorageMarketActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load2(store, root) return load2(store, root)
}) })
builtin.RegisterActorState(builtin3.StorageMarketActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin3.StorageMarketActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load3(store, root) return load3(store, root)
}) })
builtin.RegisterActorState(builtin4.StorageMarketActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin4.StorageMarketActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load4(store, root) return load4(store, root)
}) })
@ -41,16 +49,21 @@ var (
Methods = builtin4.MethodsMarket Methods = builtin4.MethodsMarket
) )
func Load(store adt.Store, act *types.Actor) (st State, err error) { func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code { switch act.Code {
case builtin0.StorageMarketActorCodeID: case builtin0.StorageMarketActorCodeID:
return load0(store, act.Head) return load0(store, act.Head)
case builtin2.StorageMarketActorCodeID: case builtin2.StorageMarketActorCodeID:
return load2(store, act.Head) return load2(store, act.Head)
case builtin3.StorageMarketActorCodeID: case builtin3.StorageMarketActorCodeID:
return load3(store, act.Head) return load3(store, act.Head)
case builtin4.StorageMarketActorCodeID: case builtin4.StorageMarketActorCodeID:
return load4(store, act.Head) return load4(store, act.Head)
} }
return nil, xerrors.Errorf("unknown actor code %s", act.Code) return nil, xerrors.Errorf("unknown actor code %s", act.Code)
} }

View File

@ -0,0 +1,209 @@
package market
import (
"bytes"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/types"
market{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/builtin/market"
adt{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/util/adt"
)
var _ State = (*state{{.v}})(nil)
func load{{.v}}(store adt.Store, root cid.Cid) (State, error) {
out := state{{.v}}{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state{{.v}} struct {
market{{.v}}.State
store adt.Store
}
func (s *state{{.v}}) TotalLocked() (abi.TokenAmount, error) {
fml := types.BigAdd(s.TotalClientLockedCollateral, s.TotalProviderLockedCollateral)
fml = types.BigAdd(fml, s.TotalClientStorageFee)
return fml, nil
}
func (s *state{{.v}}) BalancesChanged(otherState State) (bool, error) {
otherState{{.v}}, ok := otherState.(*state{{.v}})
if !ok {
// there's no way to compare different versions of the state, so let's
// just say that means the state of balances has changed
return true, nil
}
return !s.State.EscrowTable.Equals(otherState{{.v}}.State.EscrowTable) || !s.State.LockedTable.Equals(otherState{{.v}}.State.LockedTable), nil
}
func (s *state{{.v}}) StatesChanged(otherState State) (bool, error) {
otherState{{.v}}, ok := otherState.(*state{{.v}})
if !ok {
// there's no way to compare different versions of the state, so let's
// just say that means the state of balances has changed
return true, nil
}
return !s.State.States.Equals(otherState{{.v}}.State.States), nil
}
func (s *state{{.v}}) States() (DealStates, error) {
stateArray, err := adt{{.v}}.AsArray(s.store, s.State.States{{if (ge .v 3)}}, market{{.v}}.StatesAmtBitwidth{{end}})
if err != nil {
return nil, err
}
return &dealStates{{.v}}{stateArray}, nil
}
func (s *state{{.v}}) ProposalsChanged(otherState State) (bool, error) {
otherState{{.v}}, ok := otherState.(*state{{.v}})
if !ok {
// there's no way to compare different versions of the state, so let's
// just say that means the state of balances has changed
return true, nil
}
return !s.State.Proposals.Equals(otherState{{.v}}.State.Proposals), nil
}
func (s *state{{.v}}) Proposals() (DealProposals, error) {
proposalArray, err := adt{{.v}}.AsArray(s.store, s.State.Proposals{{if (ge .v 3)}}, market{{.v}}.ProposalsAmtBitwidth{{end}})
if err != nil {
return nil, err
}
return &dealProposals{{.v}}{proposalArray}, nil
}
func (s *state{{.v}}) EscrowTable() (BalanceTable, error) {
bt, err := adt{{.v}}.AsBalanceTable(s.store, s.State.EscrowTable)
if err != nil {
return nil, err
}
return &balanceTable{{.v}}{bt}, nil
}
func (s *state{{.v}}) LockedTable() (BalanceTable, error) {
bt, err := adt{{.v}}.AsBalanceTable(s.store, s.State.LockedTable)
if err != nil {
return nil, err
}
return &balanceTable{{.v}}{bt}, nil
}
func (s *state{{.v}}) VerifyDealsForActivation(
minerAddr address.Address, deals []abi.DealID, currEpoch, sectorExpiry abi.ChainEpoch,
) (weight, verifiedWeight abi.DealWeight, err error) {
w, vw{{if (ge .v 2)}}, _{{end}}, err := market{{.v}}.ValidateDealsForActivation(&s.State, s.store, deals, minerAddr, sectorExpiry, currEpoch)
return w, vw, err
}
func (s *state{{.v}}) NextID() (abi.DealID, error) {
return s.State.NextID, nil
}
type balanceTable{{.v}} struct {
*adt{{.v}}.BalanceTable
}
func (bt *balanceTable{{.v}}) ForEach(cb func(address.Address, abi.TokenAmount) error) error {
asMap := (*adt{{.v}}.Map)(bt.BalanceTable)
var ta abi.TokenAmount
return asMap.ForEach(&ta, func(key string) error {
a, err := address.NewFromBytes([]byte(key))
if err != nil {
return err
}
return cb(a, ta)
})
}
type dealStates{{.v}} struct {
adt.Array
}
func (s *dealStates{{.v}}) Get(dealID abi.DealID) (*DealState, bool, error) {
var deal{{.v}} market{{.v}}.DealState
found, err := s.Array.Get(uint64(dealID), &deal{{.v}})
if err != nil {
return nil, false, err
}
if !found {
return nil, false, nil
}
deal := fromV{{.v}}DealState(deal{{.v}})
return &deal, true, nil
}
func (s *dealStates{{.v}}) ForEach(cb func(dealID abi.DealID, ds DealState) error) error {
var ds{{.v}} market{{.v}}.DealState
return s.Array.ForEach(&ds{{.v}}, func(idx int64) error {
return cb(abi.DealID(idx), fromV{{.v}}DealState(ds{{.v}}))
})
}
func (s *dealStates{{.v}}) decode(val *cbg.Deferred) (*DealState, error) {
var ds{{.v}} market{{.v}}.DealState
if err := ds{{.v}}.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
return nil, err
}
ds := fromV{{.v}}DealState(ds{{.v}})
return &ds, nil
}
func (s *dealStates{{.v}}) array() adt.Array {
return s.Array
}
func fromV{{.v}}DealState(v{{.v}} market{{.v}}.DealState) DealState {
return (DealState)(v{{.v}})
}
type dealProposals{{.v}} struct {
adt.Array
}
func (s *dealProposals{{.v}}) Get(dealID abi.DealID) (*DealProposal, bool, error) {
var proposal{{.v}} market{{.v}}.DealProposal
found, err := s.Array.Get(uint64(dealID), &proposal{{.v}})
if err != nil {
return nil, false, err
}
if !found {
return nil, false, nil
}
proposal := fromV{{.v}}DealProposal(proposal{{.v}})
return &proposal, true, nil
}
func (s *dealProposals{{.v}}) ForEach(cb func(dealID abi.DealID, dp DealProposal) error) error {
var dp{{.v}} market{{.v}}.DealProposal
return s.Array.ForEach(&dp{{.v}}, func(idx int64) error {
return cb(abi.DealID(idx), fromV{{.v}}DealProposal(dp{{.v}}))
})
}
func (s *dealProposals{{.v}}) decode(val *cbg.Deferred) (*DealProposal, error) {
var dp{{.v}} market{{.v}}.DealProposal
if err := dp{{.v}}.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
return nil, err
}
dp := fromV{{.v}}DealProposal(dp{{.v}})
return &dp, nil
}
func (s *dealProposals{{.v}}) array() adt.Array {
return s.Array
}
func fromV{{.v}}DealProposal(v{{.v}} market{{.v}}.DealProposal) DealProposal {
return (DealProposal)(v{{.v}})
}

View File

@ -102,7 +102,8 @@ func (s *state0) LockedTable() (BalanceTable, error) {
func (s *state0) VerifyDealsForActivation( func (s *state0) VerifyDealsForActivation(
minerAddr address.Address, deals []abi.DealID, currEpoch, sectorExpiry abi.ChainEpoch, minerAddr address.Address, deals []abi.DealID, currEpoch, sectorExpiry abi.ChainEpoch,
) (weight, verifiedWeight abi.DealWeight, err error) { ) (weight, verifiedWeight abi.DealWeight, err error) {
return market0.ValidateDealsForActivation(&s.State, s.store, deals, minerAddr, sectorExpiry, currEpoch) w, vw, err := market0.ValidateDealsForActivation(&s.State, s.store, deals, minerAddr, sectorExpiry, currEpoch)
return w, vw, err
} }
func (s *state0) NextID() (abi.DealID, error) { func (s *state0) NextID() (abi.DealID, error) {

View File

@ -144,18 +144,18 @@ func (s *dealStates2) Get(dealID abi.DealID) (*DealState, bool, error) {
} }
func (s *dealStates2) ForEach(cb func(dealID abi.DealID, ds DealState) error) error { func (s *dealStates2) ForEach(cb func(dealID abi.DealID, ds DealState) error) error {
var ds1 market2.DealState var ds2 market2.DealState
return s.Array.ForEach(&ds1, func(idx int64) error { return s.Array.ForEach(&ds2, func(idx int64) error {
return cb(abi.DealID(idx), fromV2DealState(ds1)) return cb(abi.DealID(idx), fromV2DealState(ds2))
}) })
} }
func (s *dealStates2) decode(val *cbg.Deferred) (*DealState, error) { func (s *dealStates2) decode(val *cbg.Deferred) (*DealState, error) {
var ds1 market2.DealState var ds2 market2.DealState
if err := ds1.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil { if err := ds2.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
return nil, err return nil, err
} }
ds := fromV2DealState(ds1) ds := fromV2DealState(ds2)
return &ds, nil return &ds, nil
} }
@ -163,8 +163,8 @@ func (s *dealStates2) array() adt.Array {
return s.Array return s.Array
} }
func fromV2DealState(v1 market2.DealState) DealState { func fromV2DealState(v2 market2.DealState) DealState {
return (DealState)(v1) return (DealState)(v2)
} }
type dealProposals2 struct { type dealProposals2 struct {
@ -185,18 +185,18 @@ func (s *dealProposals2) Get(dealID abi.DealID) (*DealProposal, bool, error) {
} }
func (s *dealProposals2) ForEach(cb func(dealID abi.DealID, dp DealProposal) error) error { func (s *dealProposals2) ForEach(cb func(dealID abi.DealID, dp DealProposal) error) error {
var dp1 market2.DealProposal var dp2 market2.DealProposal
return s.Array.ForEach(&dp1, func(idx int64) error { return s.Array.ForEach(&dp2, func(idx int64) error {
return cb(abi.DealID(idx), fromV2DealProposal(dp1)) return cb(abi.DealID(idx), fromV2DealProposal(dp2))
}) })
} }
func (s *dealProposals2) decode(val *cbg.Deferred) (*DealProposal, error) { func (s *dealProposals2) decode(val *cbg.Deferred) (*DealProposal, error) {
var dp1 market2.DealProposal var dp2 market2.DealProposal
if err := dp1.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil { if err := dp2.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
return nil, err return nil, err
} }
dp := fromV2DealProposal(dp1) dp := fromV2DealProposal(dp2)
return &dp, nil return &dp, nil
} }
@ -204,6 +204,6 @@ func (s *dealProposals2) array() adt.Array {
return s.Array return s.Array
} }
func fromV2DealProposal(v1 market2.DealProposal) DealProposal { func fromV2DealProposal(v2 market2.DealProposal) DealProposal {
return (DealProposal)(v1) return (DealProposal)(v2)
} }

View File

@ -38,23 +38,23 @@ func (s *state3) TotalLocked() (abi.TokenAmount, error) {
} }
func (s *state3) BalancesChanged(otherState State) (bool, error) { func (s *state3) BalancesChanged(otherState State) (bool, error) {
otherState2, ok := otherState.(*state3) otherState3, ok := otherState.(*state3)
if !ok { if !ok {
// there's no way to compare different versions of the state, so let's // there's no way to compare different versions of the state, so let's
// just say that means the state of balances has changed // just say that means the state of balances has changed
return true, nil return true, nil
} }
return !s.State.EscrowTable.Equals(otherState2.State.EscrowTable) || !s.State.LockedTable.Equals(otherState2.State.LockedTable), nil return !s.State.EscrowTable.Equals(otherState3.State.EscrowTable) || !s.State.LockedTable.Equals(otherState3.State.LockedTable), nil
} }
func (s *state3) StatesChanged(otherState State) (bool, error) { func (s *state3) StatesChanged(otherState State) (bool, error) {
otherState2, ok := otherState.(*state3) otherState3, ok := otherState.(*state3)
if !ok { if !ok {
// there's no way to compare different versions of the state, so let's // there's no way to compare different versions of the state, so let's
// just say that means the state of balances has changed // just say that means the state of balances has changed
return true, nil return true, nil
} }
return !s.State.States.Equals(otherState2.State.States), nil return !s.State.States.Equals(otherState3.State.States), nil
} }
func (s *state3) States() (DealStates, error) { func (s *state3) States() (DealStates, error) {
@ -66,13 +66,13 @@ func (s *state3) States() (DealStates, error) {
} }
func (s *state3) ProposalsChanged(otherState State) (bool, error) { func (s *state3) ProposalsChanged(otherState State) (bool, error) {
otherState2, ok := otherState.(*state3) otherState3, ok := otherState.(*state3)
if !ok { if !ok {
// there's no way to compare different versions of the state, so let's // there's no way to compare different versions of the state, so let's
// just say that means the state of balances has changed // just say that means the state of balances has changed
return true, nil return true, nil
} }
return !s.State.Proposals.Equals(otherState2.State.Proposals), nil return !s.State.Proposals.Equals(otherState3.State.Proposals), nil
} }
func (s *state3) Proposals() (DealProposals, error) { func (s *state3) Proposals() (DealProposals, error) {
@ -131,31 +131,31 @@ type dealStates3 struct {
} }
func (s *dealStates3) Get(dealID abi.DealID) (*DealState, bool, error) { func (s *dealStates3) Get(dealID abi.DealID) (*DealState, bool, error) {
var deal2 market3.DealState var deal3 market3.DealState
found, err := s.Array.Get(uint64(dealID), &deal2) found, err := s.Array.Get(uint64(dealID), &deal3)
if err != nil { if err != nil {
return nil, false, err return nil, false, err
} }
if !found { if !found {
return nil, false, nil return nil, false, nil
} }
deal := fromV3DealState(deal2) deal := fromV3DealState(deal3)
return &deal, true, nil return &deal, true, nil
} }
func (s *dealStates3) ForEach(cb func(dealID abi.DealID, ds DealState) error) error { func (s *dealStates3) ForEach(cb func(dealID abi.DealID, ds DealState) error) error {
var ds1 market3.DealState var ds3 market3.DealState
return s.Array.ForEach(&ds1, func(idx int64) error { return s.Array.ForEach(&ds3, func(idx int64) error {
return cb(abi.DealID(idx), fromV3DealState(ds1)) return cb(abi.DealID(idx), fromV3DealState(ds3))
}) })
} }
func (s *dealStates3) decode(val *cbg.Deferred) (*DealState, error) { func (s *dealStates3) decode(val *cbg.Deferred) (*DealState, error) {
var ds1 market3.DealState var ds3 market3.DealState
if err := ds1.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil { if err := ds3.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
return nil, err return nil, err
} }
ds := fromV3DealState(ds1) ds := fromV3DealState(ds3)
return &ds, nil return &ds, nil
} }
@ -163,8 +163,8 @@ func (s *dealStates3) array() adt.Array {
return s.Array return s.Array
} }
func fromV3DealState(v1 market3.DealState) DealState { func fromV3DealState(v3 market3.DealState) DealState {
return (DealState)(v1) return (DealState)(v3)
} }
type dealProposals3 struct { type dealProposals3 struct {
@ -172,31 +172,31 @@ type dealProposals3 struct {
} }
func (s *dealProposals3) Get(dealID abi.DealID) (*DealProposal, bool, error) { func (s *dealProposals3) Get(dealID abi.DealID) (*DealProposal, bool, error) {
var proposal2 market3.DealProposal var proposal3 market3.DealProposal
found, err := s.Array.Get(uint64(dealID), &proposal2) found, err := s.Array.Get(uint64(dealID), &proposal3)
if err != nil { if err != nil {
return nil, false, err return nil, false, err
} }
if !found { if !found {
return nil, false, nil return nil, false, nil
} }
proposal := fromV3DealProposal(proposal2) proposal := fromV3DealProposal(proposal3)
return &proposal, true, nil return &proposal, true, nil
} }
func (s *dealProposals3) ForEach(cb func(dealID abi.DealID, dp DealProposal) error) error { func (s *dealProposals3) ForEach(cb func(dealID abi.DealID, dp DealProposal) error) error {
var dp1 market3.DealProposal var dp3 market3.DealProposal
return s.Array.ForEach(&dp1, func(idx int64) error { return s.Array.ForEach(&dp3, func(idx int64) error {
return cb(abi.DealID(idx), fromV3DealProposal(dp1)) return cb(abi.DealID(idx), fromV3DealProposal(dp3))
}) })
} }
func (s *dealProposals3) decode(val *cbg.Deferred) (*DealProposal, error) { func (s *dealProposals3) decode(val *cbg.Deferred) (*DealProposal, error) {
var dp1 market3.DealProposal var dp3 market3.DealProposal
if err := dp1.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil { if err := dp3.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
return nil, err return nil, err
} }
dp := fromV3DealProposal(dp1) dp := fromV3DealProposal(dp3)
return &dp, nil return &dp, nil
} }
@ -204,6 +204,6 @@ func (s *dealProposals3) array() adt.Array {
return s.Array return s.Array
} }
func fromV3DealProposal(v1 market3.DealProposal) DealProposal { func fromV3DealProposal(v3 market3.DealProposal) DealProposal {
return (DealProposal)(v1) return (DealProposal)(v3)
} }

View File

@ -38,23 +38,23 @@ func (s *state4) TotalLocked() (abi.TokenAmount, error) {
} }
func (s *state4) BalancesChanged(otherState State) (bool, error) { func (s *state4) BalancesChanged(otherState State) (bool, error) {
otherState2, ok := otherState.(*state4) otherState4, ok := otherState.(*state4)
if !ok { if !ok {
// there's no way to compare different versions of the state, so let's // there's no way to compare different versions of the state, so let's
// just say that means the state of balances has changed // just say that means the state of balances has changed
return true, nil return true, nil
} }
return !s.State.EscrowTable.Equals(otherState2.State.EscrowTable) || !s.State.LockedTable.Equals(otherState2.State.LockedTable), nil return !s.State.EscrowTable.Equals(otherState4.State.EscrowTable) || !s.State.LockedTable.Equals(otherState4.State.LockedTable), nil
} }
func (s *state4) StatesChanged(otherState State) (bool, error) { func (s *state4) StatesChanged(otherState State) (bool, error) {
otherState2, ok := otherState.(*state4) otherState4, ok := otherState.(*state4)
if !ok { if !ok {
// there's no way to compare different versions of the state, so let's // there's no way to compare different versions of the state, so let's
// just say that means the state of balances has changed // just say that means the state of balances has changed
return true, nil return true, nil
} }
return !s.State.States.Equals(otherState2.State.States), nil return !s.State.States.Equals(otherState4.State.States), nil
} }
func (s *state4) States() (DealStates, error) { func (s *state4) States() (DealStates, error) {
@ -66,13 +66,13 @@ func (s *state4) States() (DealStates, error) {
} }
func (s *state4) ProposalsChanged(otherState State) (bool, error) { func (s *state4) ProposalsChanged(otherState State) (bool, error) {
otherState2, ok := otherState.(*state4) otherState4, ok := otherState.(*state4)
if !ok { if !ok {
// there's no way to compare different versions of the state, so let's // there's no way to compare different versions of the state, so let's
// just say that means the state of balances has changed // just say that means the state of balances has changed
return true, nil return true, nil
} }
return !s.State.Proposals.Equals(otherState2.State.Proposals), nil return !s.State.Proposals.Equals(otherState4.State.Proposals), nil
} }
func (s *state4) Proposals() (DealProposals, error) { func (s *state4) Proposals() (DealProposals, error) {
@ -131,31 +131,31 @@ type dealStates4 struct {
} }
func (s *dealStates4) Get(dealID abi.DealID) (*DealState, bool, error) { func (s *dealStates4) Get(dealID abi.DealID) (*DealState, bool, error) {
var deal2 market4.DealState var deal4 market4.DealState
found, err := s.Array.Get(uint64(dealID), &deal2) found, err := s.Array.Get(uint64(dealID), &deal4)
if err != nil { if err != nil {
return nil, false, err return nil, false, err
} }
if !found { if !found {
return nil, false, nil return nil, false, nil
} }
deal := fromV4DealState(deal2) deal := fromV4DealState(deal4)
return &deal, true, nil return &deal, true, nil
} }
func (s *dealStates4) ForEach(cb func(dealID abi.DealID, ds DealState) error) error { func (s *dealStates4) ForEach(cb func(dealID abi.DealID, ds DealState) error) error {
var ds1 market4.DealState var ds4 market4.DealState
return s.Array.ForEach(&ds1, func(idx int64) error { return s.Array.ForEach(&ds4, func(idx int64) error {
return cb(abi.DealID(idx), fromV4DealState(ds1)) return cb(abi.DealID(idx), fromV4DealState(ds4))
}) })
} }
func (s *dealStates4) decode(val *cbg.Deferred) (*DealState, error) { func (s *dealStates4) decode(val *cbg.Deferred) (*DealState, error) {
var ds1 market4.DealState var ds4 market4.DealState
if err := ds1.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil { if err := ds4.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
return nil, err return nil, err
} }
ds := fromV4DealState(ds1) ds := fromV4DealState(ds4)
return &ds, nil return &ds, nil
} }
@ -172,31 +172,31 @@ type dealProposals4 struct {
} }
func (s *dealProposals4) Get(dealID abi.DealID) (*DealProposal, bool, error) { func (s *dealProposals4) Get(dealID abi.DealID) (*DealProposal, bool, error) {
var proposal2 market4.DealProposal var proposal4 market4.DealProposal
found, err := s.Array.Get(uint64(dealID), &proposal2) found, err := s.Array.Get(uint64(dealID), &proposal4)
if err != nil { if err != nil {
return nil, false, err return nil, false, err
} }
if !found { if !found {
return nil, false, nil return nil, false, nil
} }
proposal := fromV4DealProposal(proposal2) proposal := fromV4DealProposal(proposal4)
return &proposal, true, nil return &proposal, true, nil
} }
func (s *dealProposals4) ForEach(cb func(dealID abi.DealID, dp DealProposal) error) error { func (s *dealProposals4) ForEach(cb func(dealID abi.DealID, dp DealProposal) error) error {
var dp1 market4.DealProposal var dp4 market4.DealProposal
return s.Array.ForEach(&dp1, func(idx int64) error { return s.Array.ForEach(&dp4, func(idx int64) error {
return cb(abi.DealID(idx), fromV4DealProposal(dp1)) return cb(abi.DealID(idx), fromV4DealProposal(dp4))
}) })
} }
func (s *dealProposals4) decode(val *cbg.Deferred) (*DealProposal, error) { func (s *dealProposals4) decode(val *cbg.Deferred) (*DealProposal, error) {
var dp1 market4.DealProposal var dp4 market4.DealProposal
if err := dp1.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil { if err := dp4.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
return nil, err return nil, err
} }
dp := fromV4DealProposal(dp1) dp := fromV4DealProposal(dp4)
return &dp, nil return &dp, nil
} }

View File

@ -0,0 +1,270 @@
package miner
import (
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/network"
"github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p-core/peer"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-bitfield"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor"
"github.com/filecoin-project/go-state-types/dline"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner"
miner3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/miner"
{{range .versions}}
builtin{{.}} "github.com/filecoin-project/specs-actors{{import .}}actors/builtin"
{{end}}
)
func init() {
{{range .versions}}
builtin.RegisterActorState(builtin{{.}}.StorageMinerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load{{.}}(store, root)
})
{{end}}
}
var Methods = builtin{{.latestVersion}}.MethodsMiner
// Unchanged between v0, v2, v3, and v4 actors
var WPoStProvingPeriod = miner0.WPoStProvingPeriod
var WPoStPeriodDeadlines = miner0.WPoStPeriodDeadlines
var WPoStChallengeWindow = miner0.WPoStChallengeWindow
var WPoStChallengeLookback = miner0.WPoStChallengeLookback
var FaultDeclarationCutoff = miner0.FaultDeclarationCutoff
const MinSectorExpiration = miner0.MinSectorExpiration
// Not used / checked in v0
// TODO: Abstract over network versions
var DeclarationsMax = miner2.DeclarationsMax
var AddressedSectorsMax = miner2.AddressedSectorsMax
func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code {
{{range .versions}}
case builtin{{.}}.StorageMinerActorCodeID:
return load{{.}}(store, act.Head)
{{end}}
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
type State interface {
cbor.Marshaler
// Total available balance to spend.
AvailableBalance(abi.TokenAmount) (abi.TokenAmount, error)
// Funds that will vest by the given epoch.
VestedFunds(abi.ChainEpoch) (abi.TokenAmount, error)
// Funds locked for various reasons.
LockedFunds() (LockedFunds, error)
FeeDebt() (abi.TokenAmount, error)
GetSector(abi.SectorNumber) (*SectorOnChainInfo, error)
FindSector(abi.SectorNumber) (*SectorLocation, error)
GetSectorExpiration(abi.SectorNumber) (*SectorExpiration, error)
GetPrecommittedSector(abi.SectorNumber) (*SectorPreCommitOnChainInfo, error)
LoadSectors(sectorNos *bitfield.BitField) ([]*SectorOnChainInfo, error)
NumLiveSectors() (uint64, error)
IsAllocated(abi.SectorNumber) (bool, error)
LoadDeadline(idx uint64) (Deadline, error)
ForEachDeadline(cb func(idx uint64, dl Deadline) error) error
NumDeadlines() (uint64, error)
DeadlinesChanged(State) (bool, error)
Info() (MinerInfo, error)
MinerInfoChanged(State) (bool, error)
DeadlineInfo(epoch abi.ChainEpoch) (*dline.Info, error)
DeadlineCronActive() (bool, error)
// Diff helpers. Used by Diff* functions internally.
sectors() (adt.Array, error)
decodeSectorOnChainInfo(*cbg.Deferred) (SectorOnChainInfo, error)
precommits() (adt.Map, error)
decodeSectorPreCommitOnChainInfo(*cbg.Deferred) (SectorPreCommitOnChainInfo, error)
}
type Deadline interface {
LoadPartition(idx uint64) (Partition, error)
ForEachPartition(cb func(idx uint64, part Partition) error) error
PartitionsPoSted() (bitfield.BitField, error)
PartitionsChanged(Deadline) (bool, error)
DisputableProofCount() (uint64, error)
}
type Partition interface {
AllSectors() (bitfield.BitField, error)
FaultySectors() (bitfield.BitField, error)
RecoveringSectors() (bitfield.BitField, error)
LiveSectors() (bitfield.BitField, error)
ActiveSectors() (bitfield.BitField, error)
}
type SectorOnChainInfo struct {
SectorNumber abi.SectorNumber
SealProof abi.RegisteredSealProof
SealedCID cid.Cid
DealIDs []abi.DealID
Activation abi.ChainEpoch
Expiration abi.ChainEpoch
DealWeight abi.DealWeight
VerifiedDealWeight abi.DealWeight
InitialPledge abi.TokenAmount
ExpectedDayReward abi.TokenAmount
ExpectedStoragePledge abi.TokenAmount
}
type SectorPreCommitInfo = miner0.SectorPreCommitInfo
type SectorPreCommitOnChainInfo struct {
Info SectorPreCommitInfo
PreCommitDeposit abi.TokenAmount
PreCommitEpoch abi.ChainEpoch
DealWeight abi.DealWeight
VerifiedDealWeight abi.DealWeight
}
type PoStPartition = miner0.PoStPartition
type RecoveryDeclaration = miner0.RecoveryDeclaration
type FaultDeclaration = miner0.FaultDeclaration
// Params
type DeclareFaultsParams = miner0.DeclareFaultsParams
type DeclareFaultsRecoveredParams = miner0.DeclareFaultsRecoveredParams
type SubmitWindowedPoStParams = miner0.SubmitWindowedPoStParams
type ProveCommitSectorParams = miner0.ProveCommitSectorParams
type DisputeWindowedPoStParams = miner3.DisputeWindowedPoStParams
func PreferredSealProofTypeFromWindowPoStType(nver network.Version, proof abi.RegisteredPoStProof) (abi.RegisteredSealProof, error) {
// We added support for the new proofs in network version 7, and removed support for the old
// ones in network version 8.
if nver < network.Version7 {
switch proof {
case abi.RegisteredPoStProof_StackedDrgWindow2KiBV1:
return abi.RegisteredSealProof_StackedDrg2KiBV1, nil
case abi.RegisteredPoStProof_StackedDrgWindow8MiBV1:
return abi.RegisteredSealProof_StackedDrg8MiBV1, nil
case abi.RegisteredPoStProof_StackedDrgWindow512MiBV1:
return abi.RegisteredSealProof_StackedDrg512MiBV1, nil
case abi.RegisteredPoStProof_StackedDrgWindow32GiBV1:
return abi.RegisteredSealProof_StackedDrg32GiBV1, nil
case abi.RegisteredPoStProof_StackedDrgWindow64GiBV1:
return abi.RegisteredSealProof_StackedDrg64GiBV1, nil
default:
return -1, xerrors.Errorf("unrecognized window post type: %d", proof)
}
}
switch proof {
case abi.RegisteredPoStProof_StackedDrgWindow2KiBV1:
return abi.RegisteredSealProof_StackedDrg2KiBV1_1, nil
case abi.RegisteredPoStProof_StackedDrgWindow8MiBV1:
return abi.RegisteredSealProof_StackedDrg8MiBV1_1, nil
case abi.RegisteredPoStProof_StackedDrgWindow512MiBV1:
return abi.RegisteredSealProof_StackedDrg512MiBV1_1, nil
case abi.RegisteredPoStProof_StackedDrgWindow32GiBV1:
return abi.RegisteredSealProof_StackedDrg32GiBV1_1, nil
case abi.RegisteredPoStProof_StackedDrgWindow64GiBV1:
return abi.RegisteredSealProof_StackedDrg64GiBV1_1, nil
default:
return -1, xerrors.Errorf("unrecognized window post type: %d", proof)
}
}
func WinningPoStProofTypeFromWindowPoStProofType(nver network.Version, proof abi.RegisteredPoStProof) (abi.RegisteredPoStProof, error) {
switch proof {
case abi.RegisteredPoStProof_StackedDrgWindow2KiBV1:
return abi.RegisteredPoStProof_StackedDrgWinning2KiBV1, nil
case abi.RegisteredPoStProof_StackedDrgWindow8MiBV1:
return abi.RegisteredPoStProof_StackedDrgWinning8MiBV1, nil
case abi.RegisteredPoStProof_StackedDrgWindow512MiBV1:
return abi.RegisteredPoStProof_StackedDrgWinning512MiBV1, nil
case abi.RegisteredPoStProof_StackedDrgWindow32GiBV1:
return abi.RegisteredPoStProof_StackedDrgWinning32GiBV1, nil
case abi.RegisteredPoStProof_StackedDrgWindow64GiBV1:
return abi.RegisteredPoStProof_StackedDrgWinning64GiBV1, nil
default:
return -1, xerrors.Errorf("unknown proof type %d", proof)
}
}
type MinerInfo struct {
Owner address.Address // Must be an ID-address.
Worker address.Address // Must be an ID-address.
NewWorker address.Address // Must be an ID-address.
ControlAddresses []address.Address // Must be an ID-addresses.
WorkerChangeEpoch abi.ChainEpoch
PeerId *peer.ID
Multiaddrs []abi.Multiaddrs
WindowPoStProofType abi.RegisteredPoStProof
SectorSize abi.SectorSize
WindowPoStPartitionSectors uint64
ConsensusFaultElapsed abi.ChainEpoch
}
func (mi MinerInfo) IsController(addr address.Address) bool {
if addr == mi.Owner || addr == mi.Worker {
return true
}
for _, ca := range mi.ControlAddresses {
if addr == ca {
return true
}
}
return false
}
type SectorExpiration struct {
OnTime abi.ChainEpoch
// non-zero if sector is faulty, epoch at which it will be permanently
// removed if it doesn't recover
Early abi.ChainEpoch
}
type SectorLocation struct {
Deadline uint64
Partition uint64
}
type SectorChanges struct {
Added []SectorOnChainInfo
Extended []SectorExtensions
Removed []SectorOnChainInfo
}
type SectorExtensions struct {
From SectorOnChainInfo
To SectorOnChainInfo
}
type PreCommitChanges struct {
Added []SectorPreCommitOnChainInfo
Removed []SectorPreCommitOnChainInfo
}
type LockedFunds struct {
VestingFunds abi.TokenAmount
InitialPledgeRequirement abi.TokenAmount
PreCommitDeposits abi.TokenAmount
}
func (lf LockedFunds) TotalLockedFunds() abi.TokenAmount {
return big.Add(lf.VestingFunds, big.Add(lf.InitialPledgeRequirement, lf.PreCommitDeposits))
}

View File

@ -18,28 +18,37 @@ import (
"github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner" miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
miner3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/miner" miner3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/miner"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
) )
func init() { func init() {
builtin.RegisterActorState(builtin0.StorageMinerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin0.StorageMinerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load0(store, root) return load0(store, root)
}) })
builtin.RegisterActorState(builtin2.StorageMinerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin2.StorageMinerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load2(store, root) return load2(store, root)
}) })
builtin.RegisterActorState(builtin3.StorageMinerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin3.StorageMinerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load3(store, root) return load3(store, root)
}) })
builtin.RegisterActorState(builtin4.StorageMinerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin4.StorageMinerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load4(store, root) return load4(store, root)
}) })
} }
var Methods = builtin4.MethodsMiner var Methods = builtin4.MethodsMiner
@ -58,16 +67,21 @@ const MinSectorExpiration = miner0.MinSectorExpiration
var DeclarationsMax = miner2.DeclarationsMax var DeclarationsMax = miner2.DeclarationsMax
var AddressedSectorsMax = miner2.AddressedSectorsMax var AddressedSectorsMax = miner2.AddressedSectorsMax
func Load(store adt.Store, act *types.Actor) (st State, err error) { func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code { switch act.Code {
case builtin0.StorageMinerActorCodeID: case builtin0.StorageMinerActorCodeID:
return load0(store, act.Head) return load0(store, act.Head)
case builtin2.StorageMinerActorCodeID: case builtin2.StorageMinerActorCodeID:
return load2(store, act.Head) return load2(store, act.Head)
case builtin3.StorageMinerActorCodeID: case builtin3.StorageMinerActorCodeID:
return load3(store, act.Head) return load3(store, act.Head)
case builtin4.StorageMinerActorCodeID: case builtin4.StorageMinerActorCodeID:
return load4(store, act.Head) return load4(store, act.Head)
} }
return nil, xerrors.Errorf("unknown actor code %s", act.Code) return nil, xerrors.Errorf("unknown actor code %s", act.Code)
} }

View File

@ -0,0 +1,460 @@
package miner
import (
"bytes"
"errors"
{{if (le .v 1)}}
"github.com/filecoin-project/go-state-types/big"
{{end}}
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-bitfield"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/dline"
"github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p-core/peer"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/actors/adt"
{{if (ge .v 3)}}
builtin{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/builtin"
{{end}}
miner{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/builtin/miner"
adt{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/util/adt"
)
var _ State = (*state{{.v}})(nil)
func load{{.v}}(store adt.Store, root cid.Cid) (State, error) {
out := state{{.v}}{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state{{.v}} struct {
miner{{.v}}.State
store adt.Store
}
type deadline{{.v}} struct {
miner{{.v}}.Deadline
store adt.Store
}
type partition{{.v}} struct {
miner{{.v}}.Partition
store adt.Store
}
func (s *state{{.v}}) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmount, err error) {
defer func() {
if r := recover(); r != nil {
err = xerrors.Errorf("failed to get available balance: %w", r)
available = abi.NewTokenAmount(0)
}
}()
// this panics if the miner doesnt have enough funds to cover their locked pledge
available{{if (ge .v 2)}}, err{{end}} = s.GetAvailableBalance(bal)
return available, err
}
func (s *state{{.v}}) VestedFunds(epoch abi.ChainEpoch) (abi.TokenAmount, error) {
return s.CheckVestedFunds(s.store, epoch)
}
func (s *state{{.v}}) LockedFunds() (LockedFunds, error) {
return LockedFunds{
VestingFunds: s.State.LockedFunds,
InitialPledgeRequirement: s.State.InitialPledge{{if (le .v 1)}}Requirement{{end}},
PreCommitDeposits: s.State.PreCommitDeposits,
}, nil
}
func (s *state{{.v}}) FeeDebt() (abi.TokenAmount, error) {
return {{if (ge .v 2)}}s.State.FeeDebt{{else}}big.Zero(){{end}}, nil
}
func (s *state{{.v}}) InitialPledge() (abi.TokenAmount, error) {
return s.State.InitialPledge{{if (le .v 1)}}Requirement{{end}}, nil
}
func (s *state{{.v}}) PreCommitDeposits() (abi.TokenAmount, error) {
return s.State.PreCommitDeposits, nil
}
func (s *state{{.v}}) GetSector(num abi.SectorNumber) (*SectorOnChainInfo, error) {
info, ok, err := s.State.GetSector(s.store, num)
if !ok || err != nil {
return nil, err
}
ret := fromV{{.v}}SectorOnChainInfo(*info)
return &ret, nil
}
func (s *state{{.v}}) FindSector(num abi.SectorNumber) (*SectorLocation, error) {
dlIdx, partIdx, err := s.State.FindSector(s.store, num)
if err != nil {
return nil, err
}
return &SectorLocation{
Deadline: dlIdx,
Partition: partIdx,
}, nil
}
func (s *state{{.v}}) NumLiveSectors() (uint64, error) {
dls, err := s.State.LoadDeadlines(s.store)
if err != nil {
return 0, err
}
var total uint64
if err := dls.ForEach(s.store, func(dlIdx uint64, dl *miner{{.v}}.Deadline) error {
total += dl.LiveSectors
return nil
}); err != nil {
return 0, err
}
return total, nil
}
// GetSectorExpiration returns the effective expiration of the given sector.
//
// If the sector does not expire early, the Early expiration field is 0.
func (s *state{{.v}}) GetSectorExpiration(num abi.SectorNumber) (*SectorExpiration, error) {
dls, err := s.State.LoadDeadlines(s.store)
if err != nil {
return nil, err
}
// NOTE: this can be optimized significantly.
// 1. If the sector is non-faulty, it will either expire on-time (can be
// learned from the sector info), or in the next quantized expiration
// epoch (i.e., the first element in the partition's expiration queue.
// 2. If it's faulty, it will expire early within the first 14 entries
// of the expiration queue.
stopErr := errors.New("stop")
out := SectorExpiration{}
err = dls.ForEach(s.store, func(dlIdx uint64, dl *miner{{.v}}.Deadline) error {
partitions, err := dl.PartitionsArray(s.store)
if err != nil {
return err
}
quant := s.State.QuantSpecForDeadline(dlIdx)
var part miner{{.v}}.Partition
return partitions.ForEach(&part, func(partIdx int64) error {
if found, err := part.Sectors.IsSet(uint64(num)); err != nil {
return err
} else if !found {
return nil
}
if found, err := part.Terminated.IsSet(uint64(num)); err != nil {
return err
} else if found {
// already terminated
return stopErr
}
q, err := miner{{.v}}.LoadExpirationQueue(s.store, part.ExpirationsEpochs, quant{{if (ge .v 3)}}, miner{{.v}}.PartitionExpirationAmtBitwidth{{end}})
if err != nil {
return err
}
var exp miner{{.v}}.ExpirationSet
return q.ForEach(&exp, func(epoch int64) error {
if early, err := exp.EarlySectors.IsSet(uint64(num)); err != nil {
return err
} else if early {
out.Early = abi.ChainEpoch(epoch)
return nil
}
if onTime, err := exp.OnTimeSectors.IsSet(uint64(num)); err != nil {
return err
} else if onTime {
out.OnTime = abi.ChainEpoch(epoch)
return stopErr
}
return nil
})
})
})
if err == stopErr {
err = nil
}
if err != nil {
return nil, err
}
if out.Early == 0 && out.OnTime == 0 {
return nil, xerrors.Errorf("failed to find sector %d", num)
}
return &out, nil
}
func (s *state{{.v}}) GetPrecommittedSector(num abi.SectorNumber) (*SectorPreCommitOnChainInfo, error) {
info, ok, err := s.State.GetPrecommittedSector(s.store, num)
if !ok || err != nil {
return nil, err
}
ret := fromV{{.v}}SectorPreCommitOnChainInfo(*info)
return &ret, nil
}
func (s *state{{.v}}) LoadSectors(snos *bitfield.BitField) ([]*SectorOnChainInfo, error) {
sectors, err := miner{{.v}}.LoadSectors(s.store, s.State.Sectors)
if err != nil {
return nil, err
}
// If no sector numbers are specified, load all.
if snos == nil {
infos := make([]*SectorOnChainInfo, 0, sectors.Length())
var info{{.v}} miner{{.v}}.SectorOnChainInfo
if err := sectors.ForEach(&info{{.v}}, func(_ int64) error {
info := fromV{{.v}}SectorOnChainInfo(info{{.v}})
infos = append(infos, &info)
return nil
}); err != nil {
return nil, err
}
return infos, nil
}
// Otherwise, load selected.
infos{{.v}}, err := sectors.Load(*snos)
if err != nil {
return nil, err
}
infos := make([]*SectorOnChainInfo, len(infos{{.v}}))
for i, info{{.v}} := range infos{{.v}} {
info := fromV{{.v}}SectorOnChainInfo(*info{{.v}})
infos[i] = &info
}
return infos, nil
}
func (s *state{{.v}}) IsAllocated(num abi.SectorNumber) (bool, error) {
var allocatedSectors bitfield.BitField
if err := s.store.Get(s.store.Context(), s.State.AllocatedSectors, &allocatedSectors); err != nil {
return false, err
}
return allocatedSectors.IsSet(uint64(num))
}
func (s *state{{.v}}) LoadDeadline(idx uint64) (Deadline, error) {
dls, err := s.State.LoadDeadlines(s.store)
if err != nil {
return nil, err
}
dl, err := dls.LoadDeadline(s.store, idx)
if err != nil {
return nil, err
}
return &deadline{{.v}}{*dl, s.store}, nil
}
func (s *state{{.v}}) ForEachDeadline(cb func(uint64, Deadline) error) error {
dls, err := s.State.LoadDeadlines(s.store)
if err != nil {
return err
}
return dls.ForEach(s.store, func(i uint64, dl *miner{{.v}}.Deadline) error {
return cb(i, &deadline{{.v}}{*dl, s.store})
})
}
func (s *state{{.v}}) NumDeadlines() (uint64, error) {
return miner{{.v}}.WPoStPeriodDeadlines, nil
}
func (s *state{{.v}}) DeadlinesChanged(other State) (bool, error) {
other{{.v}}, ok := other.(*state{{.v}})
if !ok {
// treat an upgrade as a change, always
return true, nil
}
return !s.State.Deadlines.Equals(other{{.v}}.Deadlines), nil
}
func (s *state{{.v}}) MinerInfoChanged(other State) (bool, error) {
other0, ok := other.(*state{{.v}})
if !ok {
// treat an upgrade as a change, always
return true, nil
}
return !s.State.Info.Equals(other0.State.Info), nil
}
func (s *state{{.v}}) Info() (MinerInfo, error) {
info, err := s.State.GetInfo(s.store)
if err != nil {
return MinerInfo{}, err
}
var pid *peer.ID
if peerID, err := peer.IDFromBytes(info.PeerId); err == nil {
pid = &peerID
}
{{if (le .v 2)}}
wpp, err := info.SealProofType.RegisteredWindowPoStProof()
if err != nil {
return MinerInfo{}, err
}
{{end}}
mi := MinerInfo{
Owner: info.Owner,
Worker: info.Worker,
ControlAddresses: info.ControlAddresses,
NewWorker: address.Undef,
WorkerChangeEpoch: -1,
PeerId: pid,
Multiaddrs: info.Multiaddrs,
WindowPoStProofType: {{if (ge .v 3)}}info.WindowPoStProofType{{else}}wpp{{end}},
SectorSize: info.SectorSize,
WindowPoStPartitionSectors: info.WindowPoStPartitionSectors,
ConsensusFaultElapsed: {{if (ge .v 2)}}info.ConsensusFaultElapsed{{else}}-1{{end}},
}
if info.PendingWorkerKey != nil {
mi.NewWorker = info.PendingWorkerKey.NewWorker
mi.WorkerChangeEpoch = info.PendingWorkerKey.EffectiveAt
}
return mi, nil
}
func (s *state{{.v}}) DeadlineInfo(epoch abi.ChainEpoch) (*dline.Info, error) {
return s.State.{{if (ge .v 4)}}Recorded{{end}}DeadlineInfo(epoch), nil
}
func (s *state{{.v}}) DeadlineCronActive() (bool, error) {
return {{if (ge .v 4)}}s.State.DeadlineCronActive{{else}}true{{end}}, nil{{if (lt .v 4)}} // always active in this version{{end}}
}
func (s *state{{.v}}) sectors() (adt.Array, error) {
return adt{{.v}}.AsArray(s.store, s.Sectors{{if (ge .v 3)}}, miner{{.v}}.SectorsAmtBitwidth{{end}})
}
func (s *state{{.v}}) decodeSectorOnChainInfo(val *cbg.Deferred) (SectorOnChainInfo, error) {
var si miner{{.v}}.SectorOnChainInfo
err := si.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return SectorOnChainInfo{}, err
}
return fromV{{.v}}SectorOnChainInfo(si), nil
}
func (s *state{{.v}}) precommits() (adt.Map, error) {
return adt{{.v}}.AsMap(s.store, s.PreCommittedSectors{{if (ge .v 3)}}, builtin{{.v}}.DefaultHamtBitwidth{{end}})
}
func (s *state{{.v}}) decodeSectorPreCommitOnChainInfo(val *cbg.Deferred) (SectorPreCommitOnChainInfo, error) {
var sp miner{{.v}}.SectorPreCommitOnChainInfo
err := sp.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return SectorPreCommitOnChainInfo{}, err
}
return fromV{{.v}}SectorPreCommitOnChainInfo(sp), nil
}
func (d *deadline{{.v}}) LoadPartition(idx uint64) (Partition, error) {
p, err := d.Deadline.LoadPartition(d.store, idx)
if err != nil {
return nil, err
}
return &partition{{.v}}{*p, d.store}, nil
}
func (d *deadline{{.v}}) ForEachPartition(cb func(uint64, Partition) error) error {
ps, err := d.Deadline.PartitionsArray(d.store)
if err != nil {
return err
}
var part miner{{.v}}.Partition
return ps.ForEach(&part, func(i int64) error {
return cb(uint64(i), &partition{{.v}}{part, d.store})
})
}
func (d *deadline{{.v}}) PartitionsChanged(other Deadline) (bool, error) {
other{{.v}}, ok := other.(*deadline{{.v}})
if !ok {
// treat an upgrade as a change, always
return true, nil
}
return !d.Deadline.Partitions.Equals(other{{.v}}.Deadline.Partitions), nil
}
func (d *deadline{{.v}}) PartitionsPoSted() (bitfield.BitField, error) {
return d.Deadline.{{if (ge .v 3)}}PartitionsPoSted{{else}}PostSubmissions{{end}}, nil
}
func (d *deadline{{.v}}) DisputableProofCount() (uint64, error) {
{{if (ge .v 3)}}
ops, err := d.OptimisticProofsSnapshotArray(d.store)
if err != nil {
return 0, err
}
return ops.Length(), nil
{{else}}
// field doesn't exist until v3
return 0, nil
{{end}}
}
func (p *partition{{.v}}) AllSectors() (bitfield.BitField, error) {
return p.Partition.Sectors, nil
}
func (p *partition{{.v}}) FaultySectors() (bitfield.BitField, error) {
return p.Partition.Faults, nil
}
func (p *partition{{.v}}) RecoveringSectors() (bitfield.BitField, error) {
return p.Partition.Recoveries, nil
}
func fromV{{.v}}SectorOnChainInfo(v{{.v}} miner{{.v}}.SectorOnChainInfo) SectorOnChainInfo {
{{if (ge .v 2)}}
return SectorOnChainInfo{
SectorNumber: v{{.v}}.SectorNumber,
SealProof: v{{.v}}.SealProof,
SealedCID: v{{.v}}.SealedCID,
DealIDs: v{{.v}}.DealIDs,
Activation: v{{.v}}.Activation,
Expiration: v{{.v}}.Expiration,
DealWeight: v{{.v}}.DealWeight,
VerifiedDealWeight: v{{.v}}.VerifiedDealWeight,
InitialPledge: v{{.v}}.InitialPledge,
ExpectedDayReward: v{{.v}}.ExpectedDayReward,
ExpectedStoragePledge: v{{.v}}.ExpectedStoragePledge,
}
{{else}}
return (SectorOnChainInfo)(v0)
{{end}}
}
func fromV{{.v}}SectorPreCommitOnChainInfo(v{{.v}} miner{{.v}}.SectorPreCommitOnChainInfo) SectorPreCommitOnChainInfo {
{{if (ge .v 2)}}
return SectorPreCommitOnChainInfo{
Info: (SectorPreCommitInfo)(v{{.v}}.Info),
PreCommitDeposit: v{{.v}}.PreCommitDeposit,
PreCommitEpoch: v{{.v}}.PreCommitEpoch,
DealWeight: v{{.v}}.DealWeight,
VerifiedDealWeight: v{{.v}}.VerifiedDealWeight,
}
{{else}}
return (SectorPreCommitOnChainInfo)(v0)
{{end}}
}

View File

@ -196,6 +196,7 @@ func (s *state0) GetPrecommittedSector(num abi.SectorNumber) (*SectorPreCommitOn
} }
ret := fromV0SectorPreCommitOnChainInfo(*info) ret := fromV0SectorPreCommitOnChainInfo(*info)
return &ret, nil return &ret, nil
} }
@ -396,8 +397,10 @@ func (d *deadline0) PartitionsPoSted() (bitfield.BitField, error) {
} }
func (d *deadline0) DisputableProofCount() (uint64, error) { func (d *deadline0) DisputableProofCount() (uint64, error) {
// field doesn't exist until v3 // field doesn't exist until v3
return 0, nil return 0, nil
} }
func (p *partition0) AllSectors() (bitfield.BitField, error) { func (p *partition0) AllSectors() (bitfield.BitField, error) {
@ -413,9 +416,13 @@ func (p *partition0) RecoveringSectors() (bitfield.BitField, error) {
} }
func fromV0SectorOnChainInfo(v0 miner0.SectorOnChainInfo) SectorOnChainInfo { func fromV0SectorOnChainInfo(v0 miner0.SectorOnChainInfo) SectorOnChainInfo {
return (SectorOnChainInfo)(v0) return (SectorOnChainInfo)(v0)
} }
func fromV0SectorPreCommitOnChainInfo(v0 miner0.SectorPreCommitOnChainInfo) SectorPreCommitOnChainInfo { func fromV0SectorPreCommitOnChainInfo(v0 miner0.SectorPreCommitOnChainInfo) SectorPreCommitOnChainInfo {
return (SectorPreCommitOnChainInfo)(v0) return (SectorPreCommitOnChainInfo)(v0)
} }

View File

@ -395,8 +395,10 @@ func (d *deadline2) PartitionsPoSted() (bitfield.BitField, error) {
} }
func (d *deadline2) DisputableProofCount() (uint64, error) { func (d *deadline2) DisputableProofCount() (uint64, error) {
// field doesn't exist until v3 // field doesn't exist until v3
return 0, nil return 0, nil
} }
func (p *partition2) AllSectors() (bitfield.BitField, error) { func (p *partition2) AllSectors() (bitfield.BitField, error) {
@ -412,6 +414,7 @@ func (p *partition2) RecoveringSectors() (bitfield.BitField, error) {
} }
func fromV2SectorOnChainInfo(v2 miner2.SectorOnChainInfo) SectorOnChainInfo { func fromV2SectorOnChainInfo(v2 miner2.SectorOnChainInfo) SectorOnChainInfo {
return SectorOnChainInfo{ return SectorOnChainInfo{
SectorNumber: v2.SectorNumber, SectorNumber: v2.SectorNumber,
SealProof: v2.SealProof, SealProof: v2.SealProof,
@ -425,9 +428,11 @@ func fromV2SectorOnChainInfo(v2 miner2.SectorOnChainInfo) SectorOnChainInfo {
ExpectedDayReward: v2.ExpectedDayReward, ExpectedDayReward: v2.ExpectedDayReward,
ExpectedStoragePledge: v2.ExpectedStoragePledge, ExpectedStoragePledge: v2.ExpectedStoragePledge,
} }
} }
func fromV2SectorPreCommitOnChainInfo(v2 miner2.SectorPreCommitOnChainInfo) SectorPreCommitOnChainInfo { func fromV2SectorPreCommitOnChainInfo(v2 miner2.SectorPreCommitOnChainInfo) SectorPreCommitOnChainInfo {
return SectorPreCommitOnChainInfo{ return SectorPreCommitOnChainInfo{
Info: (SectorPreCommitInfo)(v2.Info), Info: (SectorPreCommitInfo)(v2.Info),
PreCommitDeposit: v2.PreCommitDeposit, PreCommitDeposit: v2.PreCommitDeposit,
@ -435,4 +440,5 @@ func fromV2SectorPreCommitOnChainInfo(v2 miner2.SectorPreCommitOnChainInfo) Sect
DealWeight: v2.DealWeight, DealWeight: v2.DealWeight,
VerifiedDealWeight: v2.VerifiedDealWeight, VerifiedDealWeight: v2.VerifiedDealWeight,
} }
} }

View File

@ -16,6 +16,7 @@ import (
"github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/adt"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
miner3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/miner" miner3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/miner"
adt3 "github.com/filecoin-project/specs-actors/v3/actors/util/adt" adt3 "github.com/filecoin-project/specs-actors/v3/actors/util/adt"
) )
@ -208,9 +209,9 @@ func (s *state3) LoadSectors(snos *bitfield.BitField) ([]*SectorOnChainInfo, err
// If no sector numbers are specified, load all. // If no sector numbers are specified, load all.
if snos == nil { if snos == nil {
infos := make([]*SectorOnChainInfo, 0, sectors.Length()) infos := make([]*SectorOnChainInfo, 0, sectors.Length())
var info2 miner3.SectorOnChainInfo var info3 miner3.SectorOnChainInfo
if err := sectors.ForEach(&info2, func(_ int64) error { if err := sectors.ForEach(&info3, func(_ int64) error {
info := fromV3SectorOnChainInfo(info2) info := fromV3SectorOnChainInfo(info3)
infos = append(infos, &info) infos = append(infos, &info)
return nil return nil
}); err != nil { }); err != nil {
@ -220,13 +221,13 @@ func (s *state3) LoadSectors(snos *bitfield.BitField) ([]*SectorOnChainInfo, err
} }
// Otherwise, load selected. // Otherwise, load selected.
infos2, err := sectors.Load(*snos) infos3, err := sectors.Load(*snos)
if err != nil { if err != nil {
return nil, err return nil, err
} }
infos := make([]*SectorOnChainInfo, len(infos2)) infos := make([]*SectorOnChainInfo, len(infos3))
for i, info2 := range infos2 { for i, info3 := range infos3 {
info := fromV3SectorOnChainInfo(*info2) info := fromV3SectorOnChainInfo(*info3)
infos[i] = &info infos[i] = &info
} }
return infos, nil return infos, nil
@ -268,13 +269,13 @@ func (s *state3) NumDeadlines() (uint64, error) {
} }
func (s *state3) DeadlinesChanged(other State) (bool, error) { func (s *state3) DeadlinesChanged(other State) (bool, error) {
other2, ok := other.(*state3) other3, ok := other.(*state3)
if !ok { if !ok {
// treat an upgrade as a change, always // treat an upgrade as a change, always
return true, nil return true, nil
} }
return !s.State.Deadlines.Equals(other2.Deadlines), nil return !s.State.Deadlines.Equals(other3.Deadlines), nil
} }
func (s *state3) MinerInfoChanged(other State) (bool, error) { func (s *state3) MinerInfoChanged(other State) (bool, error) {
@ -377,13 +378,13 @@ func (d *deadline3) ForEachPartition(cb func(uint64, Partition) error) error {
} }
func (d *deadline3) PartitionsChanged(other Deadline) (bool, error) { func (d *deadline3) PartitionsChanged(other Deadline) (bool, error) {
other2, ok := other.(*deadline3) other3, ok := other.(*deadline3)
if !ok { if !ok {
// treat an upgrade as a change, always // treat an upgrade as a change, always
return true, nil return true, nil
} }
return !d.Deadline.Partitions.Equals(other2.Deadline.Partitions), nil return !d.Deadline.Partitions.Equals(other3.Deadline.Partitions), nil
} }
func (d *deadline3) PartitionsPoSted() (bitfield.BitField, error) { func (d *deadline3) PartitionsPoSted() (bitfield.BitField, error) {
@ -391,12 +392,14 @@ func (d *deadline3) PartitionsPoSted() (bitfield.BitField, error) {
} }
func (d *deadline3) DisputableProofCount() (uint64, error) { func (d *deadline3) DisputableProofCount() (uint64, error) {
ops, err := d.OptimisticProofsSnapshotArray(d.store) ops, err := d.OptimisticProofsSnapshotArray(d.store)
if err != nil { if err != nil {
return 0, err return 0, err
} }
return ops.Length(), nil return ops.Length(), nil
} }
func (p *partition3) AllSectors() (bitfield.BitField, error) { func (p *partition3) AllSectors() (bitfield.BitField, error) {
@ -412,6 +415,7 @@ func (p *partition3) RecoveringSectors() (bitfield.BitField, error) {
} }
func fromV3SectorOnChainInfo(v3 miner3.SectorOnChainInfo) SectorOnChainInfo { func fromV3SectorOnChainInfo(v3 miner3.SectorOnChainInfo) SectorOnChainInfo {
return SectorOnChainInfo{ return SectorOnChainInfo{
SectorNumber: v3.SectorNumber, SectorNumber: v3.SectorNumber,
SealProof: v3.SealProof, SealProof: v3.SealProof,
@ -425,9 +429,11 @@ func fromV3SectorOnChainInfo(v3 miner3.SectorOnChainInfo) SectorOnChainInfo {
ExpectedDayReward: v3.ExpectedDayReward, ExpectedDayReward: v3.ExpectedDayReward,
ExpectedStoragePledge: v3.ExpectedStoragePledge, ExpectedStoragePledge: v3.ExpectedStoragePledge,
} }
} }
func fromV3SectorPreCommitOnChainInfo(v3 miner3.SectorPreCommitOnChainInfo) SectorPreCommitOnChainInfo { func fromV3SectorPreCommitOnChainInfo(v3 miner3.SectorPreCommitOnChainInfo) SectorPreCommitOnChainInfo {
return SectorPreCommitOnChainInfo{ return SectorPreCommitOnChainInfo{
Info: (SectorPreCommitInfo)(v3.Info), Info: (SectorPreCommitInfo)(v3.Info),
PreCommitDeposit: v3.PreCommitDeposit, PreCommitDeposit: v3.PreCommitDeposit,
@ -435,4 +441,5 @@ func fromV3SectorPreCommitOnChainInfo(v3 miner3.SectorPreCommitOnChainInfo) Sect
DealWeight: v3.DealWeight, DealWeight: v3.DealWeight,
VerifiedDealWeight: v3.VerifiedDealWeight, VerifiedDealWeight: v3.VerifiedDealWeight,
} }
} }

View File

@ -16,6 +16,7 @@ import (
"github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/adt"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
miner4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/miner" miner4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/miner"
adt4 "github.com/filecoin-project/specs-actors/v4/actors/util/adt" adt4 "github.com/filecoin-project/specs-actors/v4/actors/util/adt"
) )
@ -208,9 +209,9 @@ func (s *state4) LoadSectors(snos *bitfield.BitField) ([]*SectorOnChainInfo, err
// If no sector numbers are specified, load all. // If no sector numbers are specified, load all.
if snos == nil { if snos == nil {
infos := make([]*SectorOnChainInfo, 0, sectors.Length()) infos := make([]*SectorOnChainInfo, 0, sectors.Length())
var info2 miner4.SectorOnChainInfo var info4 miner4.SectorOnChainInfo
if err := sectors.ForEach(&info2, func(_ int64) error { if err := sectors.ForEach(&info4, func(_ int64) error {
info := fromV4SectorOnChainInfo(info2) info := fromV4SectorOnChainInfo(info4)
infos = append(infos, &info) infos = append(infos, &info)
return nil return nil
}); err != nil { }); err != nil {
@ -220,13 +221,13 @@ func (s *state4) LoadSectors(snos *bitfield.BitField) ([]*SectorOnChainInfo, err
} }
// Otherwise, load selected. // Otherwise, load selected.
infos2, err := sectors.Load(*snos) infos4, err := sectors.Load(*snos)
if err != nil { if err != nil {
return nil, err return nil, err
} }
infos := make([]*SectorOnChainInfo, len(infos2)) infos := make([]*SectorOnChainInfo, len(infos4))
for i, info2 := range infos2 { for i, info4 := range infos4 {
info := fromV4SectorOnChainInfo(*info2) info := fromV4SectorOnChainInfo(*info4)
infos[i] = &info infos[i] = &info
} }
return infos, nil return infos, nil
@ -268,13 +269,13 @@ func (s *state4) NumDeadlines() (uint64, error) {
} }
func (s *state4) DeadlinesChanged(other State) (bool, error) { func (s *state4) DeadlinesChanged(other State) (bool, error) {
other2, ok := other.(*state4) other4, ok := other.(*state4)
if !ok { if !ok {
// treat an upgrade as a change, always // treat an upgrade as a change, always
return true, nil return true, nil
} }
return !s.State.Deadlines.Equals(other2.Deadlines), nil return !s.State.Deadlines.Equals(other4.Deadlines), nil
} }
func (s *state4) MinerInfoChanged(other State) (bool, error) { func (s *state4) MinerInfoChanged(other State) (bool, error) {
@ -377,13 +378,13 @@ func (d *deadline4) ForEachPartition(cb func(uint64, Partition) error) error {
} }
func (d *deadline4) PartitionsChanged(other Deadline) (bool, error) { func (d *deadline4) PartitionsChanged(other Deadline) (bool, error) {
other2, ok := other.(*deadline4) other4, ok := other.(*deadline4)
if !ok { if !ok {
// treat an upgrade as a change, always // treat an upgrade as a change, always
return true, nil return true, nil
} }
return !d.Deadline.Partitions.Equals(other2.Deadline.Partitions), nil return !d.Deadline.Partitions.Equals(other4.Deadline.Partitions), nil
} }
func (d *deadline4) PartitionsPoSted() (bitfield.BitField, error) { func (d *deadline4) PartitionsPoSted() (bitfield.BitField, error) {
@ -391,12 +392,14 @@ func (d *deadline4) PartitionsPoSted() (bitfield.BitField, error) {
} }
func (d *deadline4) DisputableProofCount() (uint64, error) { func (d *deadline4) DisputableProofCount() (uint64, error) {
ops, err := d.OptimisticProofsSnapshotArray(d.store) ops, err := d.OptimisticProofsSnapshotArray(d.store)
if err != nil { if err != nil {
return 0, err return 0, err
} }
return ops.Length(), nil return ops.Length(), nil
} }
func (p *partition4) AllSectors() (bitfield.BitField, error) { func (p *partition4) AllSectors() (bitfield.BitField, error) {
@ -412,6 +415,7 @@ func (p *partition4) RecoveringSectors() (bitfield.BitField, error) {
} }
func fromV4SectorOnChainInfo(v4 miner4.SectorOnChainInfo) SectorOnChainInfo { func fromV4SectorOnChainInfo(v4 miner4.SectorOnChainInfo) SectorOnChainInfo {
return SectorOnChainInfo{ return SectorOnChainInfo{
SectorNumber: v4.SectorNumber, SectorNumber: v4.SectorNumber,
SealProof: v4.SealProof, SealProof: v4.SealProof,
@ -425,9 +429,11 @@ func fromV4SectorOnChainInfo(v4 miner4.SectorOnChainInfo) SectorOnChainInfo {
ExpectedDayReward: v4.ExpectedDayReward, ExpectedDayReward: v4.ExpectedDayReward,
ExpectedStoragePledge: v4.ExpectedStoragePledge, ExpectedStoragePledge: v4.ExpectedStoragePledge,
} }
} }
func fromV4SectorPreCommitOnChainInfo(v4 miner4.SectorPreCommitOnChainInfo) SectorPreCommitOnChainInfo { func fromV4SectorPreCommitOnChainInfo(v4 miner4.SectorPreCommitOnChainInfo) SectorPreCommitOnChainInfo {
return SectorPreCommitOnChainInfo{ return SectorPreCommitOnChainInfo{
Info: (SectorPreCommitInfo)(v4.Info), Info: (SectorPreCommitInfo)(v4.Info),
PreCommitDeposit: v4.PreCommitDeposit, PreCommitDeposit: v4.PreCommitDeposit,
@ -435,4 +441,5 @@ func fromV4SectorPreCommitOnChainInfo(v4 miner4.SectorPreCommitOnChainInfo) Sect
DealWeight: v4.DealWeight, DealWeight: v4.DealWeight,
VerifiedDealWeight: v4.VerifiedDealWeight, VerifiedDealWeight: v4.VerifiedDealWeight,
} }
} }

View File

@ -0,0 +1,117 @@
package multisig
import (
"fmt"
"github.com/minio/blake2b-simd"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor"
"github.com/ipfs/go-cid"
msig{{.latestVersion}} "github.com/filecoin-project/specs-actors/v4/actors/builtin/multisig"
{{range .versions}}
builtin{{.}} "github.com/filecoin-project/specs-actors{{import .}}actors/builtin"
{{end}}
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types"
)
func init() {
{{range .versions}}
builtin.RegisterActorState(builtin{{.}}.MultisigActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load{{.}}(store, root)
})
{{end}}}
func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code {
{{range .versions}}
case builtin{{.}}.MultisigActorCodeID:
return load{{.}}(store, act.Head)
{{end}}
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
type State interface {
cbor.Marshaler
LockedBalance(epoch abi.ChainEpoch) (abi.TokenAmount, error)
StartEpoch() (abi.ChainEpoch, error)
UnlockDuration() (abi.ChainEpoch, error)
InitialBalance() (abi.TokenAmount, error)
Threshold() (uint64, error)
Signers() ([]address.Address, error)
ForEachPendingTxn(func(id int64, txn Transaction) error) error
PendingTxnChanged(State) (bool, error)
transactions() (adt.Map, error)
decodeTransaction(val *cbg.Deferred) (Transaction, error)
}
type Transaction = msig{{.latestVersion}}.Transaction
var Methods = builtin{{.latestVersion}}.MethodsMultisig
func Message(version actors.Version, from address.Address) MessageBuilder {
switch version {
{{range .versions}}
case actors.Version{{.}}:
return message{{.}}{{"{"}}{{if (ge . 2)}}message0{from}{{else}}from{{end}}}
{{end}} default:
panic(fmt.Sprintf("unsupported actors version: %d", version))
}
}
type MessageBuilder interface {
// Create a new multisig with the specified parameters.
Create(signers []address.Address, threshold uint64,
vestingStart, vestingDuration abi.ChainEpoch,
initialAmount abi.TokenAmount) (*types.Message, error)
// Propose a transaction to the given multisig.
Propose(msig, target address.Address, amt abi.TokenAmount,
method abi.MethodNum, params []byte) (*types.Message, error)
// Approve a multisig transaction. The "hash" is optional.
Approve(msig address.Address, txID uint64, hash *ProposalHashData) (*types.Message, error)
// Cancel a multisig transaction. The "hash" is optional.
Cancel(msig address.Address, txID uint64, hash *ProposalHashData) (*types.Message, error)
}
// this type is the same between v0 and v2
type ProposalHashData = msig{{.latestVersion}}.ProposalHashData
type ProposeReturn = msig{{.latestVersion}}.ProposeReturn
type ProposeParams = msig{{.latestVersion}}.ProposeParams
func txnParams(id uint64, data *ProposalHashData) ([]byte, error) {
params := msig{{.latestVersion}}.TxnIDParams{ID: msig{{.latestVersion}}.TxnID(id)}
if data != nil {
if data.Requester.Protocol() != address.ID {
return nil, xerrors.Errorf("proposer address must be an ID address, was %s", data.Requester)
}
if data.Value.Sign() == -1 {
return nil, xerrors.Errorf("proposal value must be non-negative, was %s", data.Value)
}
if data.To == address.Undef {
return nil, xerrors.Errorf("proposed destination address must be set")
}
pser, err := data.Serialize()
if err != nil {
return nil, err
}
hash := blake2b.Sum256(pser)
params.ProposalHash = hash[:]
}
return actors.SerializeParams(&params)
}

View File

@ -1,79 +0,0 @@
package multisig
import (
"fmt"
"github.com/minio/blake2b-simd"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
multisig4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/multisig"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/types"
)
var Methods = builtin4.MethodsMultisig
func Message(version actors.Version, from address.Address) MessageBuilder {
switch version {
case actors.Version0:
return message0{from}
case actors.Version2:
return message2{message0{from}}
case actors.Version3:
return message3{message0{from}}
case actors.Version4:
return message4{message0{from}}
default:
panic(fmt.Sprintf("unsupported actors version: %d", version))
}
}
type MessageBuilder interface {
// Create a new multisig with the specified parameters.
Create(signers []address.Address, threshold uint64,
vestingStart, vestingDuration abi.ChainEpoch,
initialAmount abi.TokenAmount) (*types.Message, error)
// Propose a transaction to the given multisig.
Propose(msig, target address.Address, amt abi.TokenAmount,
method abi.MethodNum, params []byte) (*types.Message, error)
// Approve a multisig transaction. The "hash" is optional.
Approve(msig address.Address, txID uint64, hash *ProposalHashData) (*types.Message, error)
// Cancel a multisig transaction. The "hash" is optional.
Cancel(msig address.Address, txID uint64, hash *ProposalHashData) (*types.Message, error)
}
// this type is the same between v0 and v2
type ProposalHashData = multisig4.ProposalHashData
type ProposeReturn = multisig4.ProposeReturn
type ProposeParams = multisig4.ProposeParams
func txnParams(id uint64, data *ProposalHashData) ([]byte, error) {
params := multisig4.TxnIDParams{ID: multisig4.TxnID(id)}
if data != nil {
if data.Requester.Protocol() != address.ID {
return nil, xerrors.Errorf("proposer address must be an ID address, was %s", data.Requester)
}
if data.Value.Sign() == -1 {
return nil, xerrors.Errorf("proposal value must be non-negative, was %s", data.Value)
}
if data.To == address.Undef {
return nil, xerrors.Errorf("proposed destination address must be set")
}
pser, err := data.Serialize()
if err != nil {
return nil, err
}
hash := blake2b.Sum256(pser)
params.ProposalHash = hash[:]
}
return actors.SerializeParams(&params)
}

View File

@ -0,0 +1,146 @@
package multisig
import (
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
builtin{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/builtin"
init{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/builtin/init"
multisig{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/builtin/multisig"
"github.com/filecoin-project/lotus/chain/actors"
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
"github.com/filecoin-project/lotus/chain/types"
)
type message{{.v}} struct{ {{if (ge .v 2)}}message0{{else}}from address.Address{{end}} }
func (m message{{.v}}) Create(
signers []address.Address, threshold uint64,
unlockStart, unlockDuration abi.ChainEpoch,
initialAmount abi.TokenAmount,
) (*types.Message, error) {
lenAddrs := uint64(len(signers))
if lenAddrs < threshold {
return nil, xerrors.Errorf("cannot require signing of more addresses than provided for multisig")
}
if threshold == 0 {
threshold = lenAddrs
}
if m.from == address.Undef {
return nil, xerrors.Errorf("must provide source address")
}
{{if (le .v 1)}}
if unlockStart != 0 {
return nil, xerrors.Errorf("actors v0 does not support a non-zero vesting start time")
}
{{end}}
// Set up constructor parameters for multisig
msigParams := &multisig{{.v}}.ConstructorParams{
Signers: signers,
NumApprovalsThreshold: threshold,
UnlockDuration: unlockDuration,{{if (ge .v 2)}}
StartEpoch: unlockStart,{{end}}
}
enc, actErr := actors.SerializeParams(msigParams)
if actErr != nil {
return nil, actErr
}
// new actors are created by invoking 'exec' on the init actor with the constructor params
execParams := &init{{.v}}.ExecParams{
CodeCID: builtin{{.v}}.MultisigActorCodeID,
ConstructorParams: enc,
}
enc, actErr = actors.SerializeParams(execParams)
if actErr != nil {
return nil, actErr
}
return &types.Message{
To: init_.Address,
From: m.from,
Method: builtin{{.v}}.MethodsInit.Exec,
Params: enc,
Value: initialAmount,
}, nil
}
{{if (le .v 1)}}
func (m message0) Propose(msig, to address.Address, amt abi.TokenAmount,
method abi.MethodNum, params []byte) (*types.Message, error) {
if msig == address.Undef {
return nil, xerrors.Errorf("must provide a multisig address for proposal")
}
if to == address.Undef {
return nil, xerrors.Errorf("must provide a target address for proposal")
}
if amt.Sign() == -1 {
return nil, xerrors.Errorf("must provide a non-negative amount for proposed send")
}
if m.from == address.Undef {
return nil, xerrors.Errorf("must provide source address")
}
enc, actErr := actors.SerializeParams(&multisig0.ProposeParams{
To: to,
Value: amt,
Method: method,
Params: params,
})
if actErr != nil {
return nil, xerrors.Errorf("failed to serialize parameters: %w", actErr)
}
return &types.Message{
To: msig,
From: m.from,
Value: abi.NewTokenAmount(0),
Method: builtin0.MethodsMultisig.Propose,
Params: enc,
}, nil
}
func (m message0) Approve(msig address.Address, txID uint64, hashData *ProposalHashData) (*types.Message, error) {
enc, err := txnParams(txID, hashData)
if err != nil {
return nil, err
}
return &types.Message{
To: msig,
From: m.from,
Value: types.NewInt(0),
Method: builtin0.MethodsMultisig.Approve,
Params: enc,
}, nil
}
func (m message0) Cancel(msig address.Address, txID uint64, hashData *ProposalHashData) (*types.Message, error) {
enc, err := txnParams(txID, hashData)
if err != nil {
return nil, err
}
return &types.Message{
To: msig,
From: m.from,
Value: types.NewInt(0),
Method: builtin0.MethodsMultisig.Cancel,
Params: enc,
}, nil
}
{{end}}

View File

@ -0,0 +1,152 @@
package multisig
import (
"fmt"
"github.com/minio/blake2b-simd"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor"
"github.com/ipfs/go-cid"
msig4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/multisig"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types"
)
func init() {
builtin.RegisterActorState(builtin0.MultisigActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load0(store, root)
})
builtin.RegisterActorState(builtin2.MultisigActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load2(store, root)
})
builtin.RegisterActorState(builtin3.MultisigActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load3(store, root)
})
builtin.RegisterActorState(builtin4.MultisigActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load4(store, root)
})
}
func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code {
case builtin0.MultisigActorCodeID:
return load0(store, act.Head)
case builtin2.MultisigActorCodeID:
return load2(store, act.Head)
case builtin3.MultisigActorCodeID:
return load3(store, act.Head)
case builtin4.MultisigActorCodeID:
return load4(store, act.Head)
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
type State interface {
cbor.Marshaler
LockedBalance(epoch abi.ChainEpoch) (abi.TokenAmount, error)
StartEpoch() (abi.ChainEpoch, error)
UnlockDuration() (abi.ChainEpoch, error)
InitialBalance() (abi.TokenAmount, error)
Threshold() (uint64, error)
Signers() ([]address.Address, error)
ForEachPendingTxn(func(id int64, txn Transaction) error) error
PendingTxnChanged(State) (bool, error)
transactions() (adt.Map, error)
decodeTransaction(val *cbg.Deferred) (Transaction, error)
}
type Transaction = msig4.Transaction
var Methods = builtin4.MethodsMultisig
func Message(version actors.Version, from address.Address) MessageBuilder {
switch version {
case actors.Version0:
return message0{from}
case actors.Version2:
return message2{message0{from}}
case actors.Version3:
return message3{message0{from}}
case actors.Version4:
return message4{message0{from}}
default:
panic(fmt.Sprintf("unsupported actors version: %d", version))
}
}
type MessageBuilder interface {
// Create a new multisig with the specified parameters.
Create(signers []address.Address, threshold uint64,
vestingStart, vestingDuration abi.ChainEpoch,
initialAmount abi.TokenAmount) (*types.Message, error)
// Propose a transaction to the given multisig.
Propose(msig, target address.Address, amt abi.TokenAmount,
method abi.MethodNum, params []byte) (*types.Message, error)
// Approve a multisig transaction. The "hash" is optional.
Approve(msig address.Address, txID uint64, hash *ProposalHashData) (*types.Message, error)
// Cancel a multisig transaction. The "hash" is optional.
Cancel(msig address.Address, txID uint64, hash *ProposalHashData) (*types.Message, error)
}
// this type is the same between v0 and v2
type ProposalHashData = msig4.ProposalHashData
type ProposeReturn = msig4.ProposeReturn
type ProposeParams = msig4.ProposeParams
func txnParams(id uint64, data *ProposalHashData) ([]byte, error) {
params := msig4.TxnIDParams{ID: msig4.TxnID(id)}
if data != nil {
if data.Requester.Protocol() != address.ID {
return nil, xerrors.Errorf("proposer address must be an ID address, was %s", data.Requester)
}
if data.Value.Sign() == -1 {
return nil, xerrors.Errorf("proposal value must be non-negative, was %s", data.Value)
}
if data.To == address.Undef {
return nil, xerrors.Errorf("proposed destination address must be set")
}
pser, err := data.Serialize()
if err != nil {
return nil, err
}
hash := blake2b.Sum256(pser)
params.ProposalHash = hash[:]
}
return actors.SerializeParams(&params)
}

View File

@ -1,69 +0,0 @@
package multisig
import (
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor"
"github.com/ipfs/go-cid"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types"
)
func init() {
builtin.RegisterActorState(builtin0.MultisigActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load0(store, root)
})
builtin.RegisterActorState(builtin2.MultisigActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load2(store, root)
})
builtin.RegisterActorState(builtin3.MultisigActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load3(store, root)
})
builtin.RegisterActorState(builtin4.MultisigActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load4(store, root)
})
}
func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code {
case builtin0.MultisigActorCodeID:
return load0(store, act.Head)
case builtin2.MultisigActorCodeID:
return load2(store, act.Head)
case builtin3.MultisigActorCodeID:
return load3(store, act.Head)
case builtin4.MultisigActorCodeID:
return load4(store, act.Head)
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
type State interface {
cbor.Marshaler
LockedBalance(epoch abi.ChainEpoch) (abi.TokenAmount, error)
StartEpoch() (abi.ChainEpoch, error)
UnlockDuration() (abi.ChainEpoch, error)
InitialBalance() (abi.TokenAmount, error)
Threshold() (uint64, error)
Signers() ([]address.Address, error)
ForEachPendingTxn(func(id int64, txn Transaction) error) error
PendingTxnChanged(State) (bool, error)
transactions() (adt.Map, error)
decodeTransaction(val *cbg.Deferred) (Transaction, error)
}
type Transaction = msig0.Transaction

View File

@ -0,0 +1,97 @@
package multisig
import (
"bytes"
"encoding/binary"
adt{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/util/adt"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/actors/adt"
{{if (ge .v 3)}}
builtin{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/builtin"
{{end}}
msig{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/builtin/multisig"
)
var _ State = (*state{{.v}})(nil)
func load{{.v}}(store adt.Store, root cid.Cid) (State, error) {
out := state{{.v}}{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state{{.v}} struct {
msig{{.v}}.State
store adt.Store
}
func (s *state{{.v}}) LockedBalance(currEpoch abi.ChainEpoch) (abi.TokenAmount, error) {
return s.State.AmountLocked(currEpoch - s.State.StartEpoch), nil
}
func (s *state{{.v}}) StartEpoch() (abi.ChainEpoch, error) {
return s.State.StartEpoch, nil
}
func (s *state{{.v}}) UnlockDuration() (abi.ChainEpoch, error) {
return s.State.UnlockDuration, nil
}
func (s *state{{.v}}) InitialBalance() (abi.TokenAmount, error) {
return s.State.InitialBalance, nil
}
func (s *state{{.v}}) Threshold() (uint64, error) {
return s.State.NumApprovalsThreshold, nil
}
func (s *state{{.v}}) Signers() ([]address.Address, error) {
return s.State.Signers, nil
}
func (s *state{{.v}}) ForEachPendingTxn(cb func(id int64, txn Transaction) error) error {
arr, err := adt{{.v}}.AsMap(s.store, s.State.PendingTxns{{if (ge .v 3)}}, builtin{{.v}}.DefaultHamtBitwidth{{end}})
if err != nil {
return err
}
var out msig{{.v}}.Transaction
return arr.ForEach(&out, func(key string) error {
txid, n := binary.Varint([]byte(key))
if n <= 0 {
return xerrors.Errorf("invalid pending transaction key: %v", key)
}
return cb(txid, (Transaction)(out)) //nolint:unconvert
})
}
func (s *state{{.v}}) PendingTxnChanged(other State) (bool, error) {
other{{.v}}, ok := other.(*state{{.v}})
if !ok {
// treat an upgrade as a change, always
return true, nil
}
return !s.State.PendingTxns.Equals(other{{.v}}.PendingTxns), nil
}
func (s *state{{.v}}) transactions() (adt.Map, error) {
return adt{{.v}}.AsMap(s.store, s.PendingTxns{{if (ge .v 3)}}, builtin{{.v}}.DefaultHamtBitwidth{{end}})
}
func (s *state{{.v}}) decodeTransaction(val *cbg.Deferred) (Transaction, error) {
var tx msig{{.v}}.Transaction
if err := tx.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
return Transaction{}, err
}
return tx, nil
}

View File

@ -4,6 +4,8 @@ import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
@ -13,8 +15,6 @@ import (
"github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/adt"
msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig" msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
multisig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
) )
var _ State = (*state0)(nil) var _ State = (*state0)(nil)
@ -86,7 +86,7 @@ func (s *state0) transactions() (adt.Map, error) {
} }
func (s *state0) decodeTransaction(val *cbg.Deferred) (Transaction, error) { func (s *state0) decodeTransaction(val *cbg.Deferred) (Transaction, error) {
var tx multisig0.Transaction var tx msig0.Transaction
if err := tx.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil { if err := tx.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
return Transaction{}, err return Transaction{}, err
} }

View File

@ -4,6 +4,8 @@ import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
@ -13,7 +15,6 @@ import (
"github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/adt"
msig2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/multisig" msig2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/multisig"
adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt"
) )
var _ State = (*state2)(nil) var _ State = (*state2)(nil)

View File

@ -15,6 +15,7 @@ import (
"github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/adt"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
msig3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/multisig" msig3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/multisig"
) )
@ -74,12 +75,12 @@ func (s *state3) ForEachPendingTxn(cb func(id int64, txn Transaction) error) err
} }
func (s *state3) PendingTxnChanged(other State) (bool, error) { func (s *state3) PendingTxnChanged(other State) (bool, error) {
other2, ok := other.(*state3) other3, ok := other.(*state3)
if !ok { if !ok {
// treat an upgrade as a change, always // treat an upgrade as a change, always
return true, nil return true, nil
} }
return !s.State.PendingTxns.Equals(other2.PendingTxns), nil return !s.State.PendingTxns.Equals(other3.PendingTxns), nil
} }
func (s *state3) transactions() (adt.Map, error) { func (s *state3) transactions() (adt.Map, error) {

View File

@ -15,6 +15,7 @@ import (
"github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/adt"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
msig4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/multisig" msig4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/multisig"
) )
@ -69,17 +70,17 @@ func (s *state4) ForEachPendingTxn(cb func(id int64, txn Transaction) error) err
if n <= 0 { if n <= 0 {
return xerrors.Errorf("invalid pending transaction key: %v", key) return xerrors.Errorf("invalid pending transaction key: %v", key)
} }
return cb(txid, (Transaction)(out)) return cb(txid, (Transaction)(out)) //nolint:unconvert
}) })
} }
func (s *state4) PendingTxnChanged(other State) (bool, error) { func (s *state4) PendingTxnChanged(other State) (bool, error) {
other2, ok := other.(*state4) other4, ok := other.(*state4)
if !ok { if !ok {
// treat an upgrade as a change, always // treat an upgrade as a change, always
return true, nil return true, nil
} }
return !s.State.PendingTxns.Equals(other2.PendingTxns), nil return !s.State.PendingTxns.Equals(other4.PendingTxns), nil
} }
func (s *state4) transactions() (adt.Map, error) { func (s *state4) transactions() (adt.Map, error) {

View File

@ -0,0 +1,109 @@
package paych
import (
"encoding/base64"
"fmt"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
big "github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/cbor"
"github.com/ipfs/go-cid"
ipldcbor "github.com/ipfs/go-ipld-cbor"
paych0 "github.com/filecoin-project/specs-actors/actors/builtin/paych"
{{range .versions}}
builtin{{.}} "github.com/filecoin-project/specs-actors{{import .}}actors/builtin"
{{end}}
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types"
)
func init() {
{{range .versions}}
builtin.RegisterActorState(builtin{{.}}.PaymentChannelActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load{{.}}(store, root)
})
{{end}}}
// Load returns an abstract copy of payment channel state, irregardless of actor version
func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code {
{{range .versions}}
case builtin{{.}}.PaymentChannelActorCodeID:
return load{{.}}(store, act.Head)
{{end}}
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
// State is an abstract version of payment channel state that works across
// versions
type State interface {
cbor.Marshaler
// Channel owner, who has funded the actor
From() (address.Address, error)
// Recipient of payouts from channel
To() (address.Address, error)
// Height at which the channel can be `Collected`
SettlingAt() (abi.ChainEpoch, error)
// Amount successfully redeemed through the payment channel, paid out on `Collect()`
ToSend() (abi.TokenAmount, error)
// Get total number of lanes
LaneCount() (uint64, error)
// Iterate lane states
ForEachLaneState(cb func(idx uint64, dl LaneState) error) error
}
// LaneState is an abstract copy of the state of a single lane
type LaneState interface {
Redeemed() (big.Int, error)
Nonce() (uint64, error)
}
type SignedVoucher = paych0.SignedVoucher
type ModVerifyParams = paych0.ModVerifyParams
// DecodeSignedVoucher decodes base64 encoded signed voucher.
func DecodeSignedVoucher(s string) (*SignedVoucher, error) {
data, err := base64.RawURLEncoding.DecodeString(s)
if err != nil {
return nil, err
}
var sv SignedVoucher
if err := ipldcbor.DecodeInto(data, &sv); err != nil {
return nil, err
}
return &sv, nil
}
var Methods = builtin{{.latestVersion}}.MethodsPaych
func Message(version actors.Version, from address.Address) MessageBuilder {
switch version {
{{range .versions}}
case actors.Version{{.}}:
return message{{.}}{from}
{{end}}
default:
panic(fmt.Sprintf("unsupported actors version: %d", version))
}
}
type MessageBuilder interface {
Create(to address.Address, initialAmount abi.TokenAmount) (*types.Message, error)
Update(paych address.Address, voucher *SignedVoucher, secret []byte) (*types.Message, error)
Settle(paych address.Address) (*types.Message, error)
Collect(paych address.Address) (*types.Message, error)
}

View File

@ -1,36 +0,0 @@
package paych
import (
"fmt"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/types"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
)
var Methods = builtin4.MethodsPaych
func Message(version actors.Version, from address.Address) MessageBuilder {
switch version {
case actors.Version0:
return message0{from}
case actors.Version2:
return message2{from}
case actors.Version3:
return message3{from}
case actors.Version4:
return message4{from}
default:
panic(fmt.Sprintf("unsupported actors version: %d", version))
}
}
type MessageBuilder interface {
Create(to address.Address, initialAmount abi.TokenAmount) (*types.Message, error)
Update(paych address.Address, voucher *SignedVoucher, secret []byte) (*types.Message, error)
Settle(paych address.Address) (*types.Message, error)
Collect(paych address.Address) (*types.Message, error)
}

View File

@ -0,0 +1,74 @@
package paych
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
builtin{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/builtin"
init{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/builtin/init"
paych{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/builtin/paych"
"github.com/filecoin-project/lotus/chain/actors"
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
"github.com/filecoin-project/lotus/chain/types"
)
type message{{.v}} struct{ from address.Address }
func (m message{{.v}}) Create(to address.Address, initialAmount abi.TokenAmount) (*types.Message, error) {
params, aerr := actors.SerializeParams(&paych{{.v}}.ConstructorParams{From: m.from, To: to})
if aerr != nil {
return nil, aerr
}
enc, aerr := actors.SerializeParams(&init{{.v}}.ExecParams{
CodeCID: builtin{{.v}}.PaymentChannelActorCodeID,
ConstructorParams: params,
})
if aerr != nil {
return nil, aerr
}
return &types.Message{
To: init_.Address,
From: m.from,
Value: initialAmount,
Method: builtin{{.v}}.MethodsInit.Exec,
Params: enc,
}, nil
}
func (m message{{.v}}) Update(paych address.Address, sv *SignedVoucher, secret []byte) (*types.Message, error) {
params, aerr := actors.SerializeParams(&paych{{.v}}.UpdateChannelStateParams{
Sv: *sv,
Secret: secret,
})
if aerr != nil {
return nil, aerr
}
return &types.Message{
To: paych,
From: m.from,
Value: abi.NewTokenAmount(0),
Method: builtin{{.v}}.MethodsPaych.UpdateChannelState,
Params: params,
}, nil
}
func (m message{{.v}}) Settle(paych address.Address) (*types.Message, error) {
return &types.Message{
To: paych,
From: m.from,
Value: abi.NewTokenAmount(0),
Method: builtin{{.v}}.MethodsPaych.Settle,
}, nil
}
func (m message{{.v}}) Collect(paych address.Address) (*types.Message, error) {
return &types.Message{
To: paych,
From: m.from,
Value: abi.NewTokenAmount(0),
Method: builtin{{.v}}.MethodsPaych.Collect,
}, nil
}

View File

@ -2,6 +2,7 @@ package paych
import ( import (
"encoding/base64" "encoding/base64"
"fmt"
"golang.org/x/xerrors" "golang.org/x/xerrors"
@ -12,27 +13,36 @@ import (
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
ipldcbor "github.com/ipfs/go-ipld-cbor" ipldcbor "github.com/ipfs/go-ipld-cbor"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
paych0 "github.com/filecoin-project/specs-actors/actors/builtin/paych" paych0 "github.com/filecoin-project/specs-actors/actors/builtin/paych"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
) )
func init() { func init() {
builtin.RegisterActorState(builtin0.PaymentChannelActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin0.PaymentChannelActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load0(store, root) return load0(store, root)
}) })
builtin.RegisterActorState(builtin2.PaymentChannelActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin2.PaymentChannelActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load2(store, root) return load2(store, root)
}) })
builtin.RegisterActorState(builtin3.PaymentChannelActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin3.PaymentChannelActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load3(store, root) return load3(store, root)
}) })
builtin.RegisterActorState(builtin4.PaymentChannelActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin4.PaymentChannelActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load4(store, root) return load4(store, root)
}) })
@ -41,14 +51,19 @@ func init() {
// Load returns an abstract copy of payment channel state, irregardless of actor version // Load returns an abstract copy of payment channel state, irregardless of actor version
func Load(store adt.Store, act *types.Actor) (State, error) { func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code { switch act.Code {
case builtin0.PaymentChannelActorCodeID: case builtin0.PaymentChannelActorCodeID:
return load0(store, act.Head) return load0(store, act.Head)
case builtin2.PaymentChannelActorCodeID: case builtin2.PaymentChannelActorCodeID:
return load2(store, act.Head) return load2(store, act.Head)
case builtin3.PaymentChannelActorCodeID: case builtin3.PaymentChannelActorCodeID:
return load3(store, act.Head) return load3(store, act.Head)
case builtin4.PaymentChannelActorCodeID: case builtin4.PaymentChannelActorCodeID:
return load4(store, act.Head) return load4(store, act.Head)
} }
return nil, xerrors.Errorf("unknown actor code %s", act.Code) return nil, xerrors.Errorf("unknown actor code %s", act.Code)
} }
@ -98,3 +113,32 @@ func DecodeSignedVoucher(s string) (*SignedVoucher, error) {
return &sv, nil return &sv, nil
} }
var Methods = builtin4.MethodsPaych
func Message(version actors.Version, from address.Address) MessageBuilder {
switch version {
case actors.Version0:
return message0{from}
case actors.Version2:
return message2{from}
case actors.Version3:
return message3{from}
case actors.Version4:
return message4{from}
default:
panic(fmt.Sprintf("unsupported actors version: %d", version))
}
}
type MessageBuilder interface {
Create(to address.Address, initialAmount abi.TokenAmount) (*types.Message, error)
Update(paych address.Address, voucher *SignedVoucher, secret []byte) (*types.Message, error)
Settle(paych address.Address) (*types.Message, error)
Collect(paych address.Address) (*types.Message, error)
}

View File

@ -0,0 +1,104 @@
package paych
import (
"github.com/ipfs/go-cid"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/lotus/chain/actors/adt"
paych{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/builtin/paych"
adt{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/util/adt"
)
var _ State = (*state{{.v}})(nil)
func load{{.v}}(store adt.Store, root cid.Cid) (State, error) {
out := state{{.v}}{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state{{.v}} struct {
paych{{.v}}.State
store adt.Store
lsAmt *adt{{.v}}.Array
}
// Channel owner, who has funded the actor
func (s *state{{.v}}) From() (address.Address, error) {
return s.State.From, nil
}
// Recipient of payouts from channel
func (s *state{{.v}}) To() (address.Address, error) {
return s.State.To, nil
}
// Height at which the channel can be `Collected`
func (s *state{{.v}}) SettlingAt() (abi.ChainEpoch, error) {
return s.State.SettlingAt, nil
}
// Amount successfully redeemed through the payment channel, paid out on `Collect()`
func (s *state{{.v}}) ToSend() (abi.TokenAmount, error) {
return s.State.ToSend, nil
}
func (s *state{{.v}}) getOrLoadLsAmt() (*adt{{.v}}.Array, error) {
if s.lsAmt != nil {
return s.lsAmt, nil
}
// Get the lane state from the chain
lsamt, err := adt{{.v}}.AsArray(s.store, s.State.LaneStates{{if (ge .v 3)}}, paych{{.v}}.LaneStatesAmtBitwidth{{end}})
if err != nil {
return nil, err
}
s.lsAmt = lsamt
return lsamt, nil
}
// Get total number of lanes
func (s *state{{.v}}) LaneCount() (uint64, error) {
lsamt, err := s.getOrLoadLsAmt()
if err != nil {
return 0, err
}
return lsamt.Length(), nil
}
// Iterate lane states
func (s *state{{.v}}) ForEachLaneState(cb func(idx uint64, dl LaneState) error) error {
// Get the lane state from the chain
lsamt, err := s.getOrLoadLsAmt()
if err != nil {
return err
}
// Note: we use a map instead of an array to store laneStates because the
// client sets the lane ID (the index) and potentially they could use a
// very large index.
var ls paych{{.v}}.LaneState
return lsamt.ForEach(&ls, func(i int64) error {
return cb(uint64(i), &laneState{{.v}}{ls})
})
}
type laneState{{.v}} struct {
paych{{.v}}.LaneState
}
func (ls *laneState{{.v}}) Redeemed() (big.Int, error) {
return ls.LaneState.Redeemed, nil
}
func (ls *laneState{{.v}}) Nonce() (uint64, error) {
return ls.LaneState.Nonce, nil
}

View File

@ -0,0 +1,78 @@
package power
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/big"
"github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types"
{{range .versions}}
builtin{{.}} "github.com/filecoin-project/specs-actors{{import .}}actors/builtin"
{{end}}
)
func init() {
{{range .versions}}
builtin.RegisterActorState(builtin{{.}}.StoragePowerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load{{.}}(store, root)
})
{{end}}}
var (
Address = builtin{{.latestVersion}}.StoragePowerActorAddr
Methods = builtin{{.latestVersion}}.MethodsPower
)
func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code {
{{range .versions}}
case builtin{{.}}.StoragePowerActorCodeID:
return load{{.}}(store, act.Head)
{{end}}
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
type State interface {
cbor.Marshaler
TotalLocked() (abi.TokenAmount, error)
TotalPower() (Claim, error)
TotalCommitted() (Claim, error)
TotalPowerSmoothed() (builtin.FilterEstimate, error)
// MinerCounts returns the number of miners. Participating is the number
// with power above the minimum miner threshold.
MinerCounts() (participating, total uint64, err error)
MinerPower(address.Address) (Claim, bool, error)
MinerNominalPowerMeetsConsensusMinimum(address.Address) (bool, error)
ListAllMiners() ([]address.Address, error)
ForEachClaim(func(miner address.Address, claim Claim) error) error
ClaimsChanged(State) (bool, error)
// Diff helpers. Used by Diff* functions internally.
claims() (adt.Map, error)
decodeClaim(*cbg.Deferred) (Claim, error)
}
type Claim struct {
// Sum of raw byte power for a miner's sectors.
RawBytePower abi.StoragePower
// Sum of quality adjusted power for a miner's sectors.
QualityAdjPower abi.StoragePower
}
func AddClaims(a Claim, b Claim) Claim {
return Claim{
RawBytePower: big.Add(a.RawBytePower, b.RawBytePower),
QualityAdjPower: big.Add(a.QualityAdjPower, b.QualityAdjPower),
}
}

View File

@ -15,21 +15,28 @@ import (
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
) )
func init() { func init() {
builtin.RegisterActorState(builtin0.StoragePowerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin0.StoragePowerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load0(store, root) return load0(store, root)
}) })
builtin.RegisterActorState(builtin2.StoragePowerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin2.StoragePowerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load2(store, root) return load2(store, root)
}) })
builtin.RegisterActorState(builtin3.StoragePowerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin3.StoragePowerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load3(store, root) return load3(store, root)
}) })
builtin.RegisterActorState(builtin4.StoragePowerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin4.StoragePowerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load4(store, root) return load4(store, root)
}) })
@ -40,16 +47,21 @@ var (
Methods = builtin4.MethodsPower Methods = builtin4.MethodsPower
) )
func Load(store adt.Store, act *types.Actor) (st State, err error) { func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code { switch act.Code {
case builtin0.StoragePowerActorCodeID: case builtin0.StoragePowerActorCodeID:
return load0(store, act.Head) return load0(store, act.Head)
case builtin2.StoragePowerActorCodeID: case builtin2.StoragePowerActorCodeID:
return load2(store, act.Head) return load2(store, act.Head)
case builtin3.StoragePowerActorCodeID: case builtin3.StoragePowerActorCodeID:
return load3(store, act.Head) return load3(store, act.Head)
case builtin4.StoragePowerActorCodeID: case builtin4.StoragePowerActorCodeID:
return load4(store, act.Head) return load4(store, act.Head)
} }
return nil, xerrors.Errorf("unknown actor code %s", act.Code) return nil, xerrors.Errorf("unknown actor code %s", act.Code)
} }

View File

@ -0,0 +1,151 @@
package power
import (
"bytes"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
{{if (ge .v 3)}}
builtin{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/builtin"
{{end}}
power{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/builtin/power"
adt{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/util/adt"
)
var _ State = (*state{{.v}})(nil)
func load{{.v}}(store adt.Store, root cid.Cid) (State, error) {
out := state{{.v}}{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state{{.v}} struct {
power{{.v}}.State
store adt.Store
}
func (s *state{{.v}}) TotalLocked() (abi.TokenAmount, error) {
return s.TotalPledgeCollateral, nil
}
func (s *state{{.v}}) TotalPower() (Claim, error) {
return Claim{
RawBytePower: s.TotalRawBytePower,
QualityAdjPower: s.TotalQualityAdjPower,
}, nil
}
// Committed power to the network. Includes miners below the minimum threshold.
func (s *state{{.v}}) TotalCommitted() (Claim, error) {
return Claim{
RawBytePower: s.TotalBytesCommitted,
QualityAdjPower: s.TotalQABytesCommitted,
}, nil
}
func (s *state{{.v}}) MinerPower(addr address.Address) (Claim, bool, error) {
claims, err := s.claims()
if err != nil {
return Claim{}, false, err
}
var claim power{{.v}}.Claim
ok, err := claims.Get(abi.AddrKey(addr), &claim)
if err != nil {
return Claim{}, false, err
}
return Claim{
RawBytePower: claim.RawBytePower,
QualityAdjPower: claim.QualityAdjPower,
}, ok, nil
}
func (s *state{{.v}}) MinerNominalPowerMeetsConsensusMinimum(a address.Address) (bool, error) {
return s.State.MinerNominalPowerMeetsConsensusMinimum(s.store, a)
}
func (s *state{{.v}}) TotalPowerSmoothed() (builtin.FilterEstimate, error) {
return builtin.FromV{{.v}}FilterEstimate({{if (le .v 1)}}*{{end}}s.State.ThisEpochQAPowerSmoothed), nil
}
func (s *state{{.v}}) MinerCounts() (uint64, uint64, error) {
return uint64(s.State.MinerAboveMinPowerCount), uint64(s.State.MinerCount), nil
}
func (s *state{{.v}}) ListAllMiners() ([]address.Address, error) {
claims, err := s.claims()
if err != nil {
return nil, err
}
var miners []address.Address
err = claims.ForEach(nil, func(k string) error {
a, err := address.NewFromBytes([]byte(k))
if err != nil {
return err
}
miners = append(miners, a)
return nil
})
if err != nil {
return nil, err
}
return miners, nil
}
func (s *state{{.v}}) ForEachClaim(cb func(miner address.Address, claim Claim) error) error {
claims, err := s.claims()
if err != nil {
return err
}
var claim power{{.v}}.Claim
return claims.ForEach(&claim, func(k string) error {
a, err := address.NewFromBytes([]byte(k))
if err != nil {
return err
}
return cb(a, Claim{
RawBytePower: claim.RawBytePower,
QualityAdjPower: claim.QualityAdjPower,
})
})
}
func (s *state{{.v}}) ClaimsChanged(other State) (bool, error) {
other{{.v}}, ok := other.(*state{{.v}})
if !ok {
// treat an upgrade as a change, always
return true, nil
}
return !s.State.Claims.Equals(other{{.v}}.State.Claims), nil
}
func (s *state{{.v}}) claims() (adt.Map, error) {
return adt{{.v}}.AsMap(s.store, s.Claims{{if (ge .v 3)}}, builtin{{.v}}.DefaultHamtBitwidth{{end}})
}
func (s *state{{.v}}) decodeClaim(val *cbg.Deferred) (Claim, error) {
var ci power{{.v}}.Claim
if err := ci.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
return Claim{}, err
}
return fromV{{.v}}Claim(ci), nil
}
func fromV{{.v}}Claim(v{{.v}} power{{.v}}.Claim) Claim {
return Claim{
RawBytePower: v{{.v}}.RawBytePower,
QualityAdjPower: v{{.v}}.QualityAdjPower,
}
}

View File

@ -51,7 +51,7 @@ func (s *state0) TotalCommitted() (Claim, error) {
} }
func (s *state0) MinerPower(addr address.Address) (Claim, bool, error) { func (s *state0) MinerPower(addr address.Address) (Claim, bool, error) {
claims, err := adt0.AsMap(s.store, s.Claims) claims, err := s.claims()
if err != nil { if err != nil {
return Claim{}, false, err return Claim{}, false, err
} }
@ -79,7 +79,7 @@ func (s *state0) MinerCounts() (uint64, uint64, error) {
} }
func (s *state0) ListAllMiners() ([]address.Address, error) { func (s *state0) ListAllMiners() ([]address.Address, error) {
claims, err := adt0.AsMap(s.store, s.Claims) claims, err := s.claims()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -101,7 +101,7 @@ func (s *state0) ListAllMiners() ([]address.Address, error) {
} }
func (s *state0) ForEachClaim(cb func(miner address.Address, claim Claim) error) error { func (s *state0) ForEachClaim(cb func(miner address.Address, claim Claim) error) error {
claims, err := adt0.AsMap(s.store, s.Claims) claims, err := s.claims()
if err != nil { if err != nil {
return err return err
} }
@ -141,5 +141,8 @@ func (s *state0) decodeClaim(val *cbg.Deferred) (Claim, error) {
} }
func fromV0Claim(v0 power0.Claim) Claim { func fromV0Claim(v0 power0.Claim) Claim {
return (Claim)(v0) return Claim{
RawBytePower: v0.RawBytePower,
QualityAdjPower: v0.QualityAdjPower,
}
} }

View File

@ -51,7 +51,7 @@ func (s *state2) TotalCommitted() (Claim, error) {
} }
func (s *state2) MinerPower(addr address.Address) (Claim, bool, error) { func (s *state2) MinerPower(addr address.Address) (Claim, bool, error) {
claims, err := adt2.AsMap(s.store, s.Claims) claims, err := s.claims()
if err != nil { if err != nil {
return Claim{}, false, err return Claim{}, false, err
} }
@ -79,7 +79,7 @@ func (s *state2) MinerCounts() (uint64, uint64, error) {
} }
func (s *state2) ListAllMiners() ([]address.Address, error) { func (s *state2) ListAllMiners() ([]address.Address, error) {
claims, err := adt2.AsMap(s.store, s.Claims) claims, err := s.claims()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -101,7 +101,7 @@ func (s *state2) ListAllMiners() ([]address.Address, error) {
} }
func (s *state2) ForEachClaim(cb func(miner address.Address, claim Claim) error) error { func (s *state2) ForEachClaim(cb func(miner address.Address, claim Claim) error) error {
claims, err := adt2.AsMap(s.store, s.Claims) claims, err := s.claims()
if err != nil { if err != nil {
return err return err
} }

View File

@ -12,6 +12,7 @@ import (
"github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/actors/builtin"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
power3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/power" power3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/power"
adt3 "github.com/filecoin-project/specs-actors/v3/actors/util/adt" adt3 "github.com/filecoin-project/specs-actors/v3/actors/util/adt"
) )
@ -121,12 +122,12 @@ func (s *state3) ForEachClaim(cb func(miner address.Address, claim Claim) error)
} }
func (s *state3) ClaimsChanged(other State) (bool, error) { func (s *state3) ClaimsChanged(other State) (bool, error) {
other2, ok := other.(*state3) other3, ok := other.(*state3)
if !ok { if !ok {
// treat an upgrade as a change, always // treat an upgrade as a change, always
return true, nil return true, nil
} }
return !s.State.Claims.Equals(other2.State.Claims), nil return !s.State.Claims.Equals(other3.State.Claims), nil
} }
func (s *state3) claims() (adt.Map, error) { func (s *state3) claims() (adt.Map, error) {

View File

@ -12,6 +12,7 @@ import (
"github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/actors/builtin"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
power4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/power" power4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/power"
adt4 "github.com/filecoin-project/specs-actors/v4/actors/util/adt" adt4 "github.com/filecoin-project/specs-actors/v4/actors/util/adt"
) )
@ -121,12 +122,12 @@ func (s *state4) ForEachClaim(cb func(miner address.Address, claim Claim) error)
} }
func (s *state4) ClaimsChanged(other State) (bool, error) { func (s *state4) ClaimsChanged(other State) (bool, error) {
other2, ok := other.(*state4) other4, ok := other.(*state4)
if !ok { if !ok {
// treat an upgrade as a change, always // treat an upgrade as a change, always
return true, nil return true, nil
} }
return !s.State.Claims.Equals(other2.State.Claims), nil return !s.State.Claims.Equals(other4.State.Claims), nil
} }
func (s *state4) claims() (adt.Map, error) { func (s *state4) claims() (adt.Map, error) {

View File

@ -0,0 +1,60 @@
package reward
import (
"github.com/filecoin-project/go-state-types/abi"
reward0 "github.com/filecoin-project/specs-actors/actors/builtin/reward"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-state-types/cbor"
{{range .versions}}
builtin{{.}} "github.com/filecoin-project/specs-actors{{import .}}actors/builtin"
{{end}}
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types"
)
func init() {
{{range .versions}}
builtin.RegisterActorState(builtin{{.}}.RewardActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load{{.}}(store, root)
})
{{end}}}
var (
Address = builtin{{.latestVersion}}.RewardActorAddr
Methods = builtin{{.latestVersion}}.MethodsReward
)
func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code {
{{range .versions}}
case builtin{{.}}.RewardActorCodeID:
return load{{.}}(store, act.Head)
{{end}}
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
type State interface {
cbor.Marshaler
ThisEpochBaselinePower() (abi.StoragePower, error)
ThisEpochReward() (abi.StoragePower, error)
ThisEpochRewardSmoothed() (builtin.FilterEstimate, error)
EffectiveBaselinePower() (abi.StoragePower, error)
EffectiveNetworkTime() (abi.ChainEpoch, error)
TotalStoragePowerReward() (abi.TokenAmount, error)
CumsumBaseline() (abi.StoragePower, error)
CumsumRealized() (abi.StoragePower, error)
InitialPledgeForPower(abi.StoragePower, abi.TokenAmount, *builtin.FilterEstimate, abi.TokenAmount) (abi.TokenAmount, error)
PreCommitDepositForPower(builtin.FilterEstimate, abi.StoragePower) (abi.TokenAmount, error)
}
type AwardBlockRewardParams = reward0.AwardBlockRewardParams

View File

@ -7,9 +7,13 @@ import (
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/go-state-types/cbor" "github.com/filecoin-project/go-state-types/cbor"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/adt"
@ -18,15 +22,19 @@ import (
) )
func init() { func init() {
builtin.RegisterActorState(builtin0.RewardActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin0.RewardActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load0(store, root) return load0(store, root)
}) })
builtin.RegisterActorState(builtin2.RewardActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin2.RewardActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load2(store, root) return load2(store, root)
}) })
builtin.RegisterActorState(builtin3.RewardActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin3.RewardActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load3(store, root) return load3(store, root)
}) })
builtin.RegisterActorState(builtin4.RewardActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin4.RewardActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load4(store, root) return load4(store, root)
}) })
@ -37,16 +45,21 @@ var (
Methods = builtin4.MethodsReward Methods = builtin4.MethodsReward
) )
func Load(store adt.Store, act *types.Actor) (st State, err error) { func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code { switch act.Code {
case builtin0.RewardActorCodeID: case builtin0.RewardActorCodeID:
return load0(store, act.Head) return load0(store, act.Head)
case builtin2.RewardActorCodeID: case builtin2.RewardActorCodeID:
return load2(store, act.Head) return load2(store, act.Head)
case builtin3.RewardActorCodeID: case builtin3.RewardActorCodeID:
return load3(store, act.Head) return load3(store, act.Head)
case builtin4.RewardActorCodeID: case builtin4.RewardActorCodeID:
return load4(store, act.Head) return load4(store, act.Head)
} }
return nil, xerrors.Errorf("unknown actor code %s", act.Code) return nil, xerrors.Errorf("unknown actor code %s", act.Code)
} }

View File

@ -0,0 +1,103 @@
package reward
import (
"github.com/filecoin-project/go-state-types/abi"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
miner{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/builtin/miner"
reward{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/builtin/reward"
smoothing{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/util/smoothing"
)
var _ State = (*state{{.v}})(nil)
func load{{.v}}(store adt.Store, root cid.Cid) (State, error) {
out := state{{.v}}{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state{{.v}} struct {
reward{{.v}}.State
store adt.Store
}
func (s *state{{.v}}) ThisEpochReward() (abi.TokenAmount, error) {
return s.State.ThisEpochReward, nil
}
func (s *state{{.v}}) ThisEpochRewardSmoothed() (builtin.FilterEstimate, error) {
{{if (ge .v 2)}}
return builtin.FilterEstimate{
PositionEstimate: s.State.ThisEpochRewardSmoothed.PositionEstimate,
VelocityEstimate: s.State.ThisEpochRewardSmoothed.VelocityEstimate,
}, nil
{{else}}
return builtin.FromV0FilterEstimate(*s.State.ThisEpochRewardSmoothed), nil
{{end}}
}
func (s *state{{.v}}) ThisEpochBaselinePower() (abi.StoragePower, error) {
return s.State.ThisEpochBaselinePower, nil
}
func (s *state{{.v}}) TotalStoragePowerReward() (abi.TokenAmount, error) {
return s.State.{{if (ge .v 2)}}TotalStoragePowerReward{{else}}TotalMined{{end}}, nil
}
func (s *state{{.v}}) EffectiveBaselinePower() (abi.StoragePower, error) {
return s.State.EffectiveBaselinePower, nil
}
func (s *state{{.v}}) EffectiveNetworkTime() (abi.ChainEpoch, error) {
return s.State.EffectiveNetworkTime, nil
}
func (s *state{{.v}}) CumsumBaseline() (reward{{.v}}.Spacetime, error) {
return s.State.CumsumBaseline, nil
}
func (s *state{{.v}}) CumsumRealized() (reward{{.v}}.Spacetime, error) {
return s.State.CumsumRealized, nil
}
{{if (ge .v 2)}}
func (s *state{{.v}}) InitialPledgeForPower(qaPower abi.StoragePower, networkTotalPledge abi.TokenAmount, networkQAPower *builtin.FilterEstimate, circSupply abi.TokenAmount) (abi.TokenAmount, error) {
return miner{{.v}}.InitialPledgeForPower(
qaPower,
s.State.ThisEpochBaselinePower,
s.State.ThisEpochRewardSmoothed,
smoothing{{.v}}.FilterEstimate{
PositionEstimate: networkQAPower.PositionEstimate,
VelocityEstimate: networkQAPower.VelocityEstimate,
},
circSupply,
), nil
}
{{else}}
func (s *state0) InitialPledgeForPower(sectorWeight abi.StoragePower, networkTotalPledge abi.TokenAmount, networkQAPower *builtin.FilterEstimate, circSupply abi.TokenAmount) (abi.TokenAmount, error) {
return miner0.InitialPledgeForPower(
sectorWeight,
s.State.ThisEpochBaselinePower,
networkTotalPledge,
s.State.ThisEpochRewardSmoothed,
&smoothing0.FilterEstimate{
PositionEstimate: networkQAPower.PositionEstimate,
VelocityEstimate: networkQAPower.VelocityEstimate,
},
circSupply), nil
}
{{end}}
func (s *state{{.v}}) PreCommitDepositForPower(networkQAPower builtin.FilterEstimate, sectorWeight abi.StoragePower) (abi.TokenAmount, error) {
return miner{{.v}}.PreCommitDepositForPower(s.State.ThisEpochRewardSmoothed,
{{if (le .v 0)}}&{{end}}smoothing{{.v}}.FilterEstimate{
PositionEstimate: networkQAPower.PositionEstimate,
VelocityEstimate: networkQAPower.VelocityEstimate,
},
sectorWeight), nil
}

View File

@ -28,12 +28,14 @@ type state0 struct {
store adt.Store store adt.Store
} }
func (s *state0) ThisEpochReward() (abi.StoragePower, error) { func (s *state0) ThisEpochReward() (abi.TokenAmount, error) {
return s.State.ThisEpochReward, nil return s.State.ThisEpochReward, nil
} }
func (s *state0) ThisEpochRewardSmoothed() (builtin.FilterEstimate, error) { func (s *state0) ThisEpochRewardSmoothed() (builtin.FilterEstimate, error) {
return builtin.FromV0FilterEstimate(*s.State.ThisEpochRewardSmoothed), nil return builtin.FromV0FilterEstimate(*s.State.ThisEpochRewardSmoothed), nil
} }
func (s *state0) ThisEpochBaselinePower() (abi.StoragePower, error) { func (s *state0) ThisEpochBaselinePower() (abi.StoragePower, error) {
@ -52,11 +54,11 @@ func (s *state0) EffectiveNetworkTime() (abi.ChainEpoch, error) {
return s.State.EffectiveNetworkTime, nil return s.State.EffectiveNetworkTime, nil
} }
func (s *state0) CumsumBaseline() (abi.StoragePower, error) { func (s *state0) CumsumBaseline() (reward0.Spacetime, error) {
return s.State.CumsumBaseline, nil return s.State.CumsumBaseline, nil
} }
func (s *state0) CumsumRealized() (abi.StoragePower, error) { func (s *state0) CumsumRealized() (reward0.Spacetime, error) {
return s.State.CumsumRealized, nil return s.State.CumsumRealized, nil
} }

View File

@ -33,10 +33,12 @@ func (s *state2) ThisEpochReward() (abi.TokenAmount, error) {
} }
func (s *state2) ThisEpochRewardSmoothed() (builtin.FilterEstimate, error) { func (s *state2) ThisEpochRewardSmoothed() (builtin.FilterEstimate, error) {
return builtin.FilterEstimate{ return builtin.FilterEstimate{
PositionEstimate: s.State.ThisEpochRewardSmoothed.PositionEstimate, PositionEstimate: s.State.ThisEpochRewardSmoothed.PositionEstimate,
VelocityEstimate: s.State.ThisEpochRewardSmoothed.VelocityEstimate, VelocityEstimate: s.State.ThisEpochRewardSmoothed.VelocityEstimate,
}, nil }, nil
} }
func (s *state2) ThisEpochBaselinePower() (abi.StoragePower, error) { func (s *state2) ThisEpochBaselinePower() (abi.StoragePower, error) {

View File

@ -33,10 +33,12 @@ func (s *state3) ThisEpochReward() (abi.TokenAmount, error) {
} }
func (s *state3) ThisEpochRewardSmoothed() (builtin.FilterEstimate, error) { func (s *state3) ThisEpochRewardSmoothed() (builtin.FilterEstimate, error) {
return builtin.FilterEstimate{ return builtin.FilterEstimate{
PositionEstimate: s.State.ThisEpochRewardSmoothed.PositionEstimate, PositionEstimate: s.State.ThisEpochRewardSmoothed.PositionEstimate,
VelocityEstimate: s.State.ThisEpochRewardSmoothed.VelocityEstimate, VelocityEstimate: s.State.ThisEpochRewardSmoothed.VelocityEstimate,
}, nil }, nil
} }
func (s *state3) ThisEpochBaselinePower() (abi.StoragePower, error) { func (s *state3) ThisEpochBaselinePower() (abi.StoragePower, error) {

View File

@ -33,10 +33,12 @@ func (s *state4) ThisEpochReward() (abi.TokenAmount, error) {
} }
func (s *state4) ThisEpochRewardSmoothed() (builtin.FilterEstimate, error) { func (s *state4) ThisEpochRewardSmoothed() (builtin.FilterEstimate, error) {
return builtin.FilterEstimate{ return builtin.FilterEstimate{
PositionEstimate: s.State.ThisEpochRewardSmoothed.PositionEstimate, PositionEstimate: s.State.ThisEpochRewardSmoothed.PositionEstimate,
VelocityEstimate: s.State.ThisEpochRewardSmoothed.VelocityEstimate, VelocityEstimate: s.State.ThisEpochRewardSmoothed.VelocityEstimate,
}, nil }, nil
} }
func (s *state4) ThisEpochBaselinePower() (abi.StoragePower, error) { func (s *state4) ThisEpochBaselinePower() (abi.StoragePower, error) {

View File

@ -0,0 +1,51 @@
package verifreg
import (
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor"
{{range .versions}}
builtin{{.}} "github.com/filecoin-project/specs-actors{{import .}}actors/builtin"
{{end}}
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types"
)
func init() {
{{range .versions}}
builtin.RegisterActorState(builtin{{.}}.VerifiedRegistryActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load{{.}}(store, root)
})
{{end}}
}
var (
Address = builtin{{.latestVersion}}.VerifiedRegistryActorAddr
Methods = builtin{{.latestVersion}}.MethodsVerifiedRegistry
)
func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code {
{{range .versions}}
case builtin{{.}}.VerifiedRegistryActorCodeID:
return load{{.}}(store, act.Head)
{{end}}
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
type State interface {
cbor.Marshaler
RootKey() (address.Address, error)
VerifiedClientDataCap(address.Address) (bool, abi.StoragePower, error)
VerifierDataCap(address.Address) (bool, abi.StoragePower, error)
ForEachVerifier(func(addr address.Address, dcap abi.StoragePower) error) error
ForEachClient(func(addr address.Address, dcap abi.StoragePower) error) error
}

View File

@ -0,0 +1,58 @@
package verifreg
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/adt"
{{if (ge .v 3)}} builtin{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/builtin"
{{end}} verifreg{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/builtin/verifreg"
adt{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/util/adt"
)
var _ State = (*state{{.v}})(nil)
func load{{.v}}(store adt.Store, root cid.Cid) (State, error) {
out := state{{.v}}{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state{{.v}} struct {
verifreg{{.v}}.State
store adt.Store
}
func (s *state{{.v}}) RootKey() (address.Address, error) {
return s.State.RootKey, nil
}
func (s *state{{.v}}) VerifiedClientDataCap(addr address.Address) (bool, abi.StoragePower, error) {
return getDataCap(s.store, actors.Version{{.v}}, s.verifiedClients, addr)
}
func (s *state{{.v}}) VerifierDataCap(addr address.Address) (bool, abi.StoragePower, error) {
return getDataCap(s.store, actors.Version{{.v}}, s.verifiers, addr)
}
func (s *state{{.v}}) ForEachVerifier(cb func(addr address.Address, dcap abi.StoragePower) error) error {
return forEachCap(s.store, actors.Version{{.v}}, s.verifiers, cb)
}
func (s *state{{.v}}) ForEachClient(cb func(addr address.Address, dcap abi.StoragePower) error) error {
return forEachCap(s.store, actors.Version{{.v}}, s.verifiedClients, cb)
}
func (s *state{{.v}}) verifiedClients() (adt.Map, error) {
return adt{{.v}}.AsMap(s.store, s.VerifiedClients{{if (ge .v 3)}}, builtin{{.v}}.DefaultHamtBitwidth{{end}})
}
func (s *state{{.v}}) verifiers() (adt.Map, error) {
return adt{{.v}}.AsMap(s.store, s.Verifiers{{if (ge .v 3)}}, builtin{{.v}}.DefaultHamtBitwidth{{end}})
}

View File

@ -8,9 +8,13 @@ import (
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor" "github.com/filecoin-project/go-state-types/cbor"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/adt"
@ -19,18 +23,23 @@ import (
) )
func init() { func init() {
builtin.RegisterActorState(builtin0.VerifiedRegistryActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin0.VerifiedRegistryActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load0(store, root) return load0(store, root)
}) })
builtin.RegisterActorState(builtin2.VerifiedRegistryActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin2.VerifiedRegistryActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load2(store, root) return load2(store, root)
}) })
builtin.RegisterActorState(builtin3.VerifiedRegistryActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin3.VerifiedRegistryActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load3(store, root) return load3(store, root)
}) })
builtin.RegisterActorState(builtin4.VerifiedRegistryActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin4.VerifiedRegistryActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load4(store, root) return load4(store, root)
}) })
} }
var ( var (
@ -40,14 +49,19 @@ var (
func Load(store adt.Store, act *types.Actor) (State, error) { func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code { switch act.Code {
case builtin0.VerifiedRegistryActorCodeID: case builtin0.VerifiedRegistryActorCodeID:
return load0(store, act.Head) return load0(store, act.Head)
case builtin2.VerifiedRegistryActorCodeID: case builtin2.VerifiedRegistryActorCodeID:
return load2(store, act.Head) return load2(store, act.Head)
case builtin3.VerifiedRegistryActorCodeID: case builtin3.VerifiedRegistryActorCodeID:
return load3(store, act.Head) return load3(store, act.Head)
case builtin4.VerifiedRegistryActorCodeID: case builtin4.VerifiedRegistryActorCodeID:
return load4(store, act.Head) return load4(store, act.Head)
} }
return nil, xerrors.Errorf("unknown actor code %s", act.Code) return nil, xerrors.Errorf("unknown actor code %s", act.Code)
} }

View File

@ -25,8 +25,9 @@ import (
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
market4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/market" market4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/market"
miner4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/miner" miner4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/miner"
paych4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/paych"
verifreg4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/verifreg" verifreg4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/verifreg"
paych4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/paych"
) )
const ( const (
@ -39,7 +40,9 @@ const (
// SetSupportedProofTypes sets supported proof types, across all actor versions. // SetSupportedProofTypes sets supported proof types, across all actor versions.
// This should only be used for testing. // This should only be used for testing.
func SetSupportedProofTypes(types ...abi.RegisteredSealProof) { func SetSupportedProofTypes(types ...abi.RegisteredSealProof) {
miner0.SupportedProofTypes = make(map[abi.RegisteredSealProof]struct{}, len(types)) miner0.SupportedProofTypes = make(map[abi.RegisteredSealProof]struct{}, len(types))
miner2.PreCommitSealProofTypesV0 = make(map[abi.RegisteredSealProof]struct{}, len(types)) miner2.PreCommitSealProofTypesV0 = make(map[abi.RegisteredSealProof]struct{}, len(types))
miner2.PreCommitSealProofTypesV7 = make(map[abi.RegisteredSealProof]struct{}, len(types)*2) miner2.PreCommitSealProofTypesV7 = make(map[abi.RegisteredSealProof]struct{}, len(types)*2)
miner2.PreCommitSealProofTypesV8 = make(map[abi.RegisteredSealProof]struct{}, len(types)) miner2.PreCommitSealProofTypesV8 = make(map[abi.RegisteredSealProof]struct{}, len(types))
@ -63,6 +66,7 @@ func AddSupportedProofTypes(types ...abi.RegisteredSealProof) {
panic("must specify v1 proof types only") panic("must specify v1 proof types only")
} }
// Set for all miner versions. // Set for all miner versions.
miner0.SupportedProofTypes[t] = struct{}{} miner0.SupportedProofTypes[t] = struct{}{}
miner2.PreCommitSealProofTypesV0[t] = struct{}{} miner2.PreCommitSealProofTypesV0[t] = struct{}{}
@ -79,6 +83,7 @@ func AddSupportedProofTypes(types ...abi.RegisteredSealProof) {
miner4.PreCommitSealProofTypesV7[t] = struct{}{} miner4.PreCommitSealProofTypesV7[t] = struct{}{}
miner4.PreCommitSealProofTypesV7[t+abi.RegisteredSealProof_StackedDrg2KiBV1_1] = struct{}{} miner4.PreCommitSealProofTypesV7[t+abi.RegisteredSealProof_StackedDrg2KiBV1_1] = struct{}{}
miner4.PreCommitSealProofTypesV8[t+abi.RegisteredSealProof_StackedDrg2KiBV1_1] = struct{}{} miner4.PreCommitSealProofTypesV8[t+abi.RegisteredSealProof_StackedDrg2KiBV1_1] = struct{}{}
} }
} }
@ -86,22 +91,29 @@ func AddSupportedProofTypes(types ...abi.RegisteredSealProof) {
// actors versions. Use for testing. // actors versions. Use for testing.
func SetPreCommitChallengeDelay(delay abi.ChainEpoch) { func SetPreCommitChallengeDelay(delay abi.ChainEpoch) {
// Set for all miner versions. // Set for all miner versions.
miner0.PreCommitChallengeDelay = delay miner0.PreCommitChallengeDelay = delay
miner2.PreCommitChallengeDelay = delay miner2.PreCommitChallengeDelay = delay
miner3.PreCommitChallengeDelay = delay miner3.PreCommitChallengeDelay = delay
miner4.PreCommitChallengeDelay = delay miner4.PreCommitChallengeDelay = delay
} }
// TODO: this function shouldn't really exist. Instead, the API should expose the precommit delay. // TODO: this function shouldn't really exist. Instead, the API should expose the precommit delay.
func GetPreCommitChallengeDelay() abi.ChainEpoch { func GetPreCommitChallengeDelay() abi.ChainEpoch {
return miner0.PreCommitChallengeDelay return miner4.PreCommitChallengeDelay
} }
// SetConsensusMinerMinPower sets the minimum power of an individual miner must // SetConsensusMinerMinPower sets the minimum power of an individual miner must
// meet for leader election, across all actor versions. This should only be used // meet for leader election, across all actor versions. This should only be used
// for testing. // for testing.
func SetConsensusMinerMinPower(p abi.StoragePower) { func SetConsensusMinerMinPower(p abi.StoragePower) {
power0.ConsensusMinerMinPower = p power0.ConsensusMinerMinPower = p
for _, policy := range builtin2.SealProofPolicies { for _, policy := range builtin2.SealProofPolicies {
policy.ConsensusMinerMinPower = p policy.ConsensusMinerMinPower = p
} }
@ -113,27 +125,42 @@ func SetConsensusMinerMinPower(p abi.StoragePower) {
for _, policy := range builtin4.PoStProofPolicies { for _, policy := range builtin4.PoStProofPolicies {
policy.ConsensusMinerMinPower = p policy.ConsensusMinerMinPower = p
} }
} }
// SetMinVerifiedDealSize sets the minimum size of a verified deal. This should // SetMinVerifiedDealSize sets the minimum size of a verified deal. This should
// only be used for testing. // only be used for testing.
func SetMinVerifiedDealSize(size abi.StoragePower) { func SetMinVerifiedDealSize(size abi.StoragePower) {
verifreg0.MinVerifiedDealSize = size verifreg0.MinVerifiedDealSize = size
verifreg2.MinVerifiedDealSize = size verifreg2.MinVerifiedDealSize = size
verifreg3.MinVerifiedDealSize = size verifreg3.MinVerifiedDealSize = size
verifreg4.MinVerifiedDealSize = size verifreg4.MinVerifiedDealSize = size
} }
func GetMaxProveCommitDuration(ver actors.Version, t abi.RegisteredSealProof) abi.ChainEpoch { func GetMaxProveCommitDuration(ver actors.Version, t abi.RegisteredSealProof) abi.ChainEpoch {
switch ver { switch ver {
case actors.Version0: case actors.Version0:
return miner0.MaxSealDuration[t] return miner0.MaxSealDuration[t]
case actors.Version2: case actors.Version2:
return miner2.MaxProveCommitDuration[t] return miner2.MaxProveCommitDuration[t]
case actors.Version3: case actors.Version3:
return miner3.MaxProveCommitDuration[t] return miner3.MaxProveCommitDuration[t]
case actors.Version4: case actors.Version4:
return miner4.MaxProveCommitDuration[t] return miner4.MaxProveCommitDuration[t]
default: default:
panic("unsupported actors version") panic("unsupported actors version")
} }
@ -145,26 +172,36 @@ func DealProviderCollateralBounds(
circulatingFil abi.TokenAmount, nwVer network.Version, circulatingFil abi.TokenAmount, nwVer network.Version,
) (min, max abi.TokenAmount) { ) (min, max abi.TokenAmount) {
switch actors.VersionForNetwork(nwVer) { switch actors.VersionForNetwork(nwVer) {
case actors.Version0: case actors.Version0:
return market0.DealProviderCollateralBounds(size, verified, rawBytePower, qaPower, baselinePower, circulatingFil, nwVer) return market0.DealProviderCollateralBounds(size, verified, rawBytePower, qaPower, baselinePower, circulatingFil, nwVer)
case actors.Version2: case actors.Version2:
return market2.DealProviderCollateralBounds(size, verified, rawBytePower, qaPower, baselinePower, circulatingFil) return market2.DealProviderCollateralBounds(size, verified, rawBytePower, qaPower, baselinePower, circulatingFil)
case actors.Version3: case actors.Version3:
return market3.DealProviderCollateralBounds(size, verified, rawBytePower, qaPower, baselinePower, circulatingFil) return market3.DealProviderCollateralBounds(size, verified, rawBytePower, qaPower, baselinePower, circulatingFil)
case actors.Version4: case actors.Version4:
return market4.DealProviderCollateralBounds(size, verified, rawBytePower, qaPower, baselinePower, circulatingFil) return market4.DealProviderCollateralBounds(size, verified, rawBytePower, qaPower, baselinePower, circulatingFil)
default: default:
panic("unsupported actors version") panic("unsupported actors version")
} }
} }
func DealDurationBounds(pieceSize abi.PaddedPieceSize) (min, max abi.ChainEpoch) { func DealDurationBounds(pieceSize abi.PaddedPieceSize) (min, max abi.ChainEpoch) {
return market2.DealDurationBounds(pieceSize) return market4.DealDurationBounds(pieceSize)
} }
// Sets the challenge window and scales the proving period to match (such that // Sets the challenge window and scales the proving period to match (such that
// there are always 48 challenge windows in a proving period). // there are always 48 challenge windows in a proving period).
func SetWPoStChallengeWindow(period abi.ChainEpoch) { func SetWPoStChallengeWindow(period abi.ChainEpoch) {
miner0.WPoStChallengeWindow = period miner0.WPoStChallengeWindow = period
miner0.WPoStProvingPeriod = period * abi.ChainEpoch(miner0.WPoStPeriodDeadlines) miner0.WPoStProvingPeriod = period * abi.ChainEpoch(miner0.WPoStPeriodDeadlines)
@ -173,13 +210,18 @@ func SetWPoStChallengeWindow(period abi.ChainEpoch) {
miner3.WPoStChallengeWindow = period miner3.WPoStChallengeWindow = period
miner3.WPoStProvingPeriod = period * abi.ChainEpoch(miner3.WPoStPeriodDeadlines) miner3.WPoStProvingPeriod = period * abi.ChainEpoch(miner3.WPoStPeriodDeadlines)
// by default, this is 2x finality which is 30 periods. // by default, this is 2x finality which is 30 periods.
// scale it if we're scaling the challenge period. // scale it if we're scaling the challenge period.
miner3.WPoStDisputeWindow = period * 30 miner3.WPoStDisputeWindow = period * 30
miner4.WPoStChallengeWindow = period miner4.WPoStChallengeWindow = period
miner4.WPoStProvingPeriod = period * abi.ChainEpoch(miner4.WPoStPeriodDeadlines) miner4.WPoStProvingPeriod = period * abi.ChainEpoch(miner4.WPoStPeriodDeadlines)
miner4.WPoStDisputeWindow = period * 30 // see the miner3 comment
// by default, this is 2x finality which is 30 periods.
// scale it if we're scaling the challenge period.
miner4.WPoStDisputeWindow = period * 30
} }
func GetWinningPoStSectorSetLookback(nwVer network.Version) abi.ChainEpoch { func GetWinningPoStSectorSetLookback(nwVer network.Version) abi.ChainEpoch {
@ -187,16 +229,17 @@ func GetWinningPoStSectorSetLookback(nwVer network.Version) abi.ChainEpoch {
return 10 return 10
} }
// NOTE: if this ever changes, adjust it in a (*Miner).mineOne() logline as well
return ChainFinality return ChainFinality
} }
func GetMaxSectorExpirationExtension() abi.ChainEpoch { func GetMaxSectorExpirationExtension() abi.ChainEpoch {
return miner0.MaxSectorExpirationExtension return miner4.MaxSectorExpirationExtension
} }
// TODO: we'll probably need to abstract over this better in the future. // TODO: we'll probably need to abstract over this better in the future.
func GetMaxPoStPartitions(p abi.RegisteredPoStProof) (int, error) { func GetMaxPoStPartitions(p abi.RegisteredPoStProof) (int, error) {
sectorsPerPart, err := builtin3.PoStProofWindowPoStPartitionSectors(p) sectorsPerPart, err := builtin4.PoStProofWindowPoStPartitionSectors(p)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -232,14 +275,19 @@ func GetSectorMaxLifetime(proof abi.RegisteredSealProof, nwVer network.Version)
func GetAddressedSectorsMax(nwVer network.Version) int { func GetAddressedSectorsMax(nwVer network.Version) int {
switch actors.VersionForNetwork(nwVer) { switch actors.VersionForNetwork(nwVer) {
case actors.Version0: case actors.Version0:
return miner0.AddressedSectorsMax return miner0.AddressedSectorsMax
case actors.Version2: case actors.Version2:
return miner2.AddressedSectorsMax return miner2.AddressedSectorsMax
case actors.Version3: case actors.Version3:
return miner3.AddressedSectorsMax return miner3.AddressedSectorsMax
case actors.Version4: case actors.Version4:
return miner4.AddressedSectorsMax return miner4.AddressedSectorsMax
default: default:
panic("unsupported network version") panic("unsupported network version")
} }
@ -247,15 +295,24 @@ func GetAddressedSectorsMax(nwVer network.Version) int {
func GetDeclarationsMax(nwVer network.Version) int { func GetDeclarationsMax(nwVer network.Version) int {
switch actors.VersionForNetwork(nwVer) { switch actors.VersionForNetwork(nwVer) {
case actors.Version0: case actors.Version0:
// TODO: Should we instead panic here since the concept doesn't exist yet? // TODO: Should we instead panic here since the concept doesn't exist yet?
return miner0.AddressedPartitionsMax return miner0.AddressedPartitionsMax
case actors.Version2: case actors.Version2:
return miner2.DeclarationsMax return miner2.DeclarationsMax
case actors.Version3: case actors.Version3:
return miner3.DeclarationsMax return miner3.DeclarationsMax
case actors.Version4: case actors.Version4:
return miner4.DeclarationsMax return miner4.DeclarationsMax
default: default:
panic("unsupported network version") panic("unsupported network version")
} }

View File

@ -0,0 +1,233 @@
package policy
import (
"sort"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/chain/actors"
{{range .versions}}
{{if (ge . 2)}} builtin{{.}} "github.com/filecoin-project/specs-actors{{import .}}actors/builtin" {{end}}
market{{.}} "github.com/filecoin-project/specs-actors{{import .}}actors/builtin/market"
miner{{.}} "github.com/filecoin-project/specs-actors{{import .}}actors/builtin/miner"
verifreg{{.}} "github.com/filecoin-project/specs-actors{{import .}}actors/builtin/verifreg"
{{if (eq . 0)}} power{{.}} "github.com/filecoin-project/specs-actors{{import .}}actors/builtin/power" {{end}}
{{end}}
paych{{.latestVersion}} "github.com/filecoin-project/specs-actors{{import .latestVersion}}actors/builtin/paych"
)
const (
ChainFinality = miner{{.latestVersion}}.ChainFinality
SealRandomnessLookback = ChainFinality
PaychSettleDelay = paych{{.latestVersion}}.SettleDelay
MaxPreCommitRandomnessLookback = builtin{{.latestVersion}}.EpochsInDay + SealRandomnessLookback
)
// SetSupportedProofTypes sets supported proof types, across all actor versions.
// This should only be used for testing.
func SetSupportedProofTypes(types ...abi.RegisteredSealProof) {
{{range .versions}}
{{if (eq . 0)}}
miner{{.}}.SupportedProofTypes = make(map[abi.RegisteredSealProof]struct{}, len(types))
{{else}}
miner{{.}}.PreCommitSealProofTypesV0 = make(map[abi.RegisteredSealProof]struct{}, len(types))
miner{{.}}.PreCommitSealProofTypesV7 = make(map[abi.RegisteredSealProof]struct{}, len(types)*2)
miner{{.}}.PreCommitSealProofTypesV8 = make(map[abi.RegisteredSealProof]struct{}, len(types))
{{end}}
{{end}}
AddSupportedProofTypes(types...)
}
// AddSupportedProofTypes sets supported proof types, across all actor versions.
// This should only be used for testing.
func AddSupportedProofTypes(types ...abi.RegisteredSealProof) {
for _, t := range types {
if t >= abi.RegisteredSealProof_StackedDrg2KiBV1_1 {
panic("must specify v1 proof types only")
}
// Set for all miner versions.
{{range .versions}}
{{if (eq . 0)}}
miner{{.}}.SupportedProofTypes[t] = struct{}{}
{{else}}
miner{{.}}.PreCommitSealProofTypesV0[t] = struct{}{}
miner{{.}}.PreCommitSealProofTypesV7[t] = struct{}{}
miner{{.}}.PreCommitSealProofTypesV7[t+abi.RegisteredSealProof_StackedDrg2KiBV1_1] = struct{}{}
miner{{.}}.PreCommitSealProofTypesV8[t+abi.RegisteredSealProof_StackedDrg2KiBV1_1] = struct{}{}
{{end}}
{{end}}
}
}
// SetPreCommitChallengeDelay sets the pre-commit challenge delay across all
// actors versions. Use for testing.
func SetPreCommitChallengeDelay(delay abi.ChainEpoch) {
// Set for all miner versions.
{{range .versions}}
miner{{.}}.PreCommitChallengeDelay = delay
{{end}}
}
// TODO: this function shouldn't really exist. Instead, the API should expose the precommit delay.
func GetPreCommitChallengeDelay() abi.ChainEpoch {
return miner{{.latestVersion}}.PreCommitChallengeDelay
}
// SetConsensusMinerMinPower sets the minimum power of an individual miner must
// meet for leader election, across all actor versions. This should only be used
// for testing.
func SetConsensusMinerMinPower(p abi.StoragePower) {
{{range .versions}}
{{if (eq . 0)}}
power{{.}}.ConsensusMinerMinPower = p
{{else if (eq . 2)}}
for _, policy := range builtin{{.}}.SealProofPolicies {
policy.ConsensusMinerMinPower = p
}
{{else}}
for _, policy := range builtin{{.}}.PoStProofPolicies {
policy.ConsensusMinerMinPower = p
}
{{end}}
{{end}}
}
// SetMinVerifiedDealSize sets the minimum size of a verified deal. This should
// only be used for testing.
func SetMinVerifiedDealSize(size abi.StoragePower) {
{{range .versions}}
verifreg{{.}}.MinVerifiedDealSize = size
{{end}}
}
func GetMaxProveCommitDuration(ver actors.Version, t abi.RegisteredSealProof) abi.ChainEpoch {
switch ver {
{{range .versions}}
case actors.Version{{.}}:
{{if (eq . 0)}}
return miner{{.}}.MaxSealDuration[t]
{{else}}
return miner{{.}}.MaxProveCommitDuration[t]
{{end}}
{{end}}
default:
panic("unsupported actors version")
}
}
func DealProviderCollateralBounds(
size abi.PaddedPieceSize, verified bool,
rawBytePower, qaPower, baselinePower abi.StoragePower,
circulatingFil abi.TokenAmount, nwVer network.Version,
) (min, max abi.TokenAmount) {
switch actors.VersionForNetwork(nwVer) {
{{range .versions}}
case actors.Version{{.}}:
{{if (eq . 0)}}
return market{{.}}.DealProviderCollateralBounds(size, verified, rawBytePower, qaPower, baselinePower, circulatingFil, nwVer)
{{else}}
return market{{.}}.DealProviderCollateralBounds(size, verified, rawBytePower, qaPower, baselinePower, circulatingFil)
{{end}}
{{end}}
default:
panic("unsupported actors version")
}
}
func DealDurationBounds(pieceSize abi.PaddedPieceSize) (min, max abi.ChainEpoch) {
return market{{.latestVersion}}.DealDurationBounds(pieceSize)
}
// Sets the challenge window and scales the proving period to match (such that
// there are always 48 challenge windows in a proving period).
func SetWPoStChallengeWindow(period abi.ChainEpoch) {
{{range .versions}}
miner{{.}}.WPoStChallengeWindow = period
miner{{.}}.WPoStProvingPeriod = period * abi.ChainEpoch(miner{{.}}.WPoStPeriodDeadlines)
{{if (ge . 3)}}
// by default, this is 2x finality which is 30 periods.
// scale it if we're scaling the challenge period.
miner{{.}}.WPoStDisputeWindow = period * 30
{{end}}
{{end}}
}
func GetWinningPoStSectorSetLookback(nwVer network.Version) abi.ChainEpoch {
if nwVer <= network.Version3 {
return 10
}
// NOTE: if this ever changes, adjust it in a (*Miner).mineOne() logline as well
return ChainFinality
}
func GetMaxSectorExpirationExtension() abi.ChainEpoch {
return miner{{.latestVersion}}.MaxSectorExpirationExtension
}
// TODO: we'll probably need to abstract over this better in the future.
func GetMaxPoStPartitions(p abi.RegisteredPoStProof) (int, error) {
sectorsPerPart, err := builtin{{.latestVersion}}.PoStProofWindowPoStPartitionSectors(p)
if err != nil {
return 0, err
}
return int(miner{{.latestVersion}}.AddressedSectorsMax / sectorsPerPart), nil
}
func GetDefaultSectorSize() abi.SectorSize {
// supported sector sizes are the same across versions.
szs := make([]abi.SectorSize, 0, len(miner{{.latestVersion}}.PreCommitSealProofTypesV8))
for spt := range miner{{.latestVersion}}.PreCommitSealProofTypesV8 {
ss, err := spt.SectorSize()
if err != nil {
panic(err)
}
szs = append(szs, ss)
}
sort.Slice(szs, func(i, j int) bool {
return szs[i] < szs[j]
})
return szs[0]
}
func GetSectorMaxLifetime(proof abi.RegisteredSealProof, nwVer network.Version) abi.ChainEpoch {
if nwVer <= network.Version10 {
return builtin{{.latestVersion}}.SealProofPoliciesV0[proof].SectorMaxLifetime
}
return builtin{{.latestVersion}}.SealProofPoliciesV11[proof].SectorMaxLifetime
}
func GetAddressedSectorsMax(nwVer network.Version) int {
switch actors.VersionForNetwork(nwVer) {
{{range .versions}}
case actors.Version{{.}}:
return miner{{.}}.AddressedSectorsMax
{{end}}
default:
panic("unsupported network version")
}
}
func GetDeclarationsMax(nwVer network.Version) int {
switch actors.VersionForNetwork(nwVer) {
{{range .versions}}
case actors.Version{{.}}:
{{if (eq . 0)}}
// TODO: Should we instead panic here since the concept doesn't exist yet?
return miner{{.}}.AddressedPartitionsMax
{{else}}
return miner{{.}}.DeclarationsMax
{{end}}
{{end}}
default:
panic("unsupported network version")
}
}

View File

@ -3,6 +3,7 @@ package gen
import ( import (
"bytes" "bytes"
"context" "context"
"encoding/base64"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
@ -610,6 +611,8 @@ func (wpp *wppProvider) ComputeProof(context.Context, []proof2.SectorInfo, abi.P
return ValidWpostForTesting, nil return ValidWpostForTesting, nil
} }
var b64 = base64.URLEncoding.WithPadding(base64.NoPadding)
func IsRoundWinner(ctx context.Context, ts *types.TipSet, round abi.ChainEpoch, func IsRoundWinner(ctx context.Context, ts *types.TipSet, round abi.ChainEpoch,
miner address.Address, brand types.BeaconEntry, mbi *api.MiningBaseInfo, a MiningCheckAPI) (*types.ElectionProof, error) { miner address.Address, brand types.BeaconEntry, mbi *api.MiningBaseInfo, a MiningCheckAPI) (*types.ElectionProof, error) {
@ -631,6 +634,15 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round abi.ChainEpoch,
ep := &types.ElectionProof{VRFProof: vrfout} ep := &types.ElectionProof{VRFProof: vrfout}
j := ep.ComputeWinCount(mbi.MinerPower, mbi.NetworkPower) j := ep.ComputeWinCount(mbi.MinerPower, mbi.NetworkPower)
ep.WinCount = j ep.WinCount = j
log.Infow("completed winAttemptVRF",
"beaconRound", brand.Round,
"beaconDataB64", b64.EncodeToString(brand.Data),
"electionRandB64", b64.EncodeToString(electionRand),
"vrfB64", b64.EncodeToString(vrfout),
"winCount", j,
)
if j < 1 { if j < 1 {
return nil, nil return nil, nil
} }

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) 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) { func (mp *MessagePool) getNonceLocked(addr address.Address, curTs *types.TipSet) (uint64, error) {
stateNonce, err := mp.getStateNonce(addr, curTs) // sanity check stateNonce, err := mp.getStateNonce(addr, curTs) // sanity check
if err != nil { if err != nil {
@ -825,8 +832,8 @@ func (mp *MessagePool) getNonceLocked(addr address.Address, curTs *types.TipSet)
return stateNonce, nil return stateNonce, nil
} }
func (mp *MessagePool) getStateNonce(addr address.Address, curTs *types.TipSet) (uint64, error) { func (mp *MessagePool) getStateNonce(addr address.Address, ts *types.TipSet) (uint64, error) {
act, err := mp.api.GetActorAfter(addr, curTs) act, err := mp.api.GetActorAfter(addr, ts)
if err != nil { if err != nil {
return 0, err 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) { func (tma *testMpoolAPI) PutMessage(m types.ChainMsg) (cid.Cid, error) {
return cid.Undef, nil return cid.Undef, nil
} }
func (tma *testMpoolAPI) IsLite() bool {
return false
}
func (tma *testMpoolAPI) PubSubPublish(string, []byte) error { func (tma *testMpoolAPI) PubSubPublish(string, []byte) error {
tma.published++ tma.published++

View File

@ -9,6 +9,7 @@ import (
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/messagesigner"
"github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
@ -30,17 +31,28 @@ type Provider interface {
MessagesForTipset(*types.TipSet) ([]types.ChainMsg, error) MessagesForTipset(*types.TipSet) ([]types.ChainMsg, error)
LoadTipSet(tsk types.TipSetKey) (*types.TipSet, error) LoadTipSet(tsk types.TipSetKey) (*types.TipSet, error)
ChainComputeBaseFee(ctx context.Context, ts *types.TipSet) (types.BigInt, error) ChainComputeBaseFee(ctx context.Context, ts *types.TipSet) (types.BigInt, error)
IsLite() bool
} }
type mpoolProvider struct { type mpoolProvider struct {
sm *stmgr.StateManager sm *stmgr.StateManager
ps *pubsub.PubSub ps *pubsub.PubSub
lite messagesigner.MpoolNonceAPI
} }
func NewProvider(sm *stmgr.StateManager, ps *pubsub.PubSub) Provider { func NewProvider(sm *stmgr.StateManager, ps *pubsub.PubSub) Provider {
return &mpoolProvider{sm: sm, ps: ps} 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 { func (mpp *mpoolProvider) SubscribeHeadChanges(cb func(rev, app []*types.TipSet) error) *types.TipSet {
mpp.sm.ChainStore().SubscribeHeadChanges( mpp.sm.ChainStore().SubscribeHeadChanges(
store.WrapHeadChangeCoalescer( 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) { 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) stcid, _, err := mpp.sm.TipSetState(context.TODO(), ts)
if err != nil { if err != nil {
return nil, xerrors.Errorf("computing tipset state for GetActor: %w", err) 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 { type MpoolNonceAPI interface {
GetNonce(context.Context, address.Address, types.TipSetKey) (uint64, error) 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 // 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 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) { func TestMessageSignerSignMessage(t *testing.T) {
ctx := context.Background() 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" 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) { func (f FIL) Format(s fmt.State, ch rune) {
switch ch { switch ch {
case 's', 'v': case 's', 'v':

View File

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

View File

@ -34,7 +34,7 @@ func GetFullNodeServices(ctx *cli.Context) (ServicesAPI, error) {
return tn.(ServicesAPI), nil return tn.(ServicesAPI), nil
} }
api, c, err := GetFullNodeAPI(ctx) api, c, err := GetFullNodeAPIV1(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -81,6 +81,7 @@ var Commands = []*cli.Command{
WithCategory("developer", FetchParamCmd), WithCategory("developer", FetchParamCmd),
WithCategory("network", NetCmd), WithCategory("network", NetCmd),
WithCategory("network", SyncCmd), WithCategory("network", SyncCmd),
WithCategory("status", StatusCmd),
PprofCmd, PprofCmd,
VersionCmd, 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, MpoolFindCmd,
MpoolConfig, MpoolConfig,
MpoolGasPerfCmd, 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")) return ShowHelp(cctx, fmt.Errorf("multisigs must have at least one signer"))
} }
api, closer, err := GetFullNodeAPI(cctx) srv, err := GetFullNodeServices(cctx)
if err != nil { if err != nil {
return err return err
} }
defer closer() defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
var addrs []address.Address var addrs []address.Address
@ -146,13 +148,20 @@ var msigCreateCmd = &cli.Command{
gp := types.NewInt(1) 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 { if err != nil {
return err 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 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 { if err != nil {
return err return err
} }
@ -364,11 +373,13 @@ var msigProposeCmd = &cli.Command{
return ShowHelp(cctx, fmt.Errorf("must either pass three or five arguments")) return ShowHelp(cctx, fmt.Errorf("must either pass three or five arguments"))
} }
api, closer, err := GetFullNodeAPI(cctx) srv, err := GetFullNodeServices(cctx)
if err != nil { if err != nil {
return err return err
} }
defer closer() defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0)) 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) 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 { if err != nil {
return err return err
} }
sm, err := InteractiveSend(ctx, cctx, srv, proto)
if err != nil {
return err
}
msgCid := sm.Cid()
fmt.Println("send proposal in message: ", msgCid) 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 { if err != nil {
return err 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> ]")) 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 { if err != nil {
return err return err
} }
defer closer() defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0)) msig, err := address.NewFromString(cctx.Args().Get(0))
@ -515,10 +535,17 @@ var msigApproveCmd = &cli.Command{
var msgCid cid.Cid var msgCid cid.Cid
if cctx.Args().Len() == 2 { if cctx.Args().Len() == 2 {
msgCid, err = api.MsigApprove(ctx, msig, txid, from) proto, err := api.MsigApprove(ctx, msig, txid, from)
if err != nil { if err != nil {
return err return err
} }
sm, err := InteractiveSend(ctx, cctx, srv, proto)
if err != nil {
return err
}
msgCid = sm.Cid()
} else { } else {
proposer, err := address.NewFromString(cctx.Args().Get(2)) proposer, err := address.NewFromString(cctx.Args().Get(2))
if err != nil { if err != nil {
@ -558,15 +585,22 @@ var msigApproveCmd = &cli.Command{
params = p 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 { if err != nil {
return err return err
} }
sm, err := InteractiveSend(ctx, cctx, srv, proto)
if err != nil {
return err
}
msgCid = sm.Cid()
} }
fmt.Println("sent approval in message: ", msgCid) 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 { if err != nil {
return err return err
} }
@ -598,11 +632,13 @@ var msigRemoveProposeCmd = &cli.Command{
return ShowHelp(cctx, fmt.Errorf("must pass multisig address and signer address")) return ShowHelp(cctx, fmt.Errorf("must pass multisig address and signer address"))
} }
api, closer, err := GetFullNodeAPI(cctx) srv, err := GetFullNodeServices(cctx)
if err != nil { if err != nil {
return err return err
} }
defer closer() defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0)) msig, err := address.NewFromString(cctx.Args().Get(0))
@ -630,14 +666,21 @@ var msigRemoveProposeCmd = &cli.Command{
from = defaddr 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 { if err != nil {
return err 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) 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 { if err != nil {
return err return err
} }
@ -676,11 +719,13 @@ var msigAddProposeCmd = &cli.Command{
return ShowHelp(cctx, fmt.Errorf("must pass multisig address and signer address")) return ShowHelp(cctx, fmt.Errorf("must pass multisig address and signer address"))
} }
api, closer, err := GetFullNodeAPI(cctx) srv, err := GetFullNodeServices(cctx)
if err != nil { if err != nil {
return err return err
} }
defer closer() defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0)) msig, err := address.NewFromString(cctx.Args().Get(0))
@ -708,14 +753,21 @@ var msigAddProposeCmd = &cli.Command{
from = defaddr 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 { if err != nil {
return err 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) 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 { if err != nil {
return err 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")) 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 { if err != nil {
return err return err
} }
defer closer() defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0)) msig, err := address.NewFromString(cctx.Args().Get(0))
@ -790,14 +844,21 @@ var msigAddApproveCmd = &cli.Command{
from = defaddr 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 { if err != nil {
return err 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) 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 { if err != nil {
return err 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")) 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 { if err != nil {
return err return err
} }
defer closer() defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0)) msig, err := address.NewFromString(cctx.Args().Get(0))
@ -867,14 +930,21 @@ var msigAddCancelCmd = &cli.Command{
from = defaddr 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 { if err != nil {
return err 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) 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 { if err != nil {
return err 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")) 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 { if err != nil {
return err return err
} }
defer closer() defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0)) msig, err := address.NewFromString(cctx.Args().Get(0))
@ -939,14 +1011,21 @@ var msigSwapProposeCmd = &cli.Command{
from = defaddr from = defaddr
} }
msgCid, err := api.MsigSwapPropose(ctx, msig, from, oldAdd, newAdd) proto, err := api.MsigSwapPropose(ctx, msig, from, oldAdd, newAdd)
if err != nil { if err != nil {
return err 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) 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 { if err != nil {
return err 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")) 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 { if err != nil {
return err return err
} }
defer closer() defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0)) msig, err := address.NewFromString(cctx.Args().Get(0))
@ -1021,14 +1102,21 @@ var msigSwapApproveCmd = &cli.Command{
from = defaddr 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 { if err != nil {
return err 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) 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 { if err != nil {
return err 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")) 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 { if err != nil {
return err return err
} }
defer closer() defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0)) msig, err := address.NewFromString(cctx.Args().Get(0))
@ -1098,14 +1188,21 @@ var msigSwapCancelCmd = &cli.Command{
from = defaddr 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 { if err != nil {
return err 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) 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 { if err != nil {
return err 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")) 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 { if err != nil {
return err return err
} }
defer closer() defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0)) msig, err := address.NewFromString(cctx.Args().Get(0))
@ -1185,14 +1284,21 @@ var msigLockProposeCmd = &cli.Command{
return actErr 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 { if err != nil {
return err 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) 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 { if err != nil {
return err 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")) 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 { if err != nil {
return err return err
} }
defer closer() defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0)) msig, err := address.NewFromString(cctx.Args().Get(0))
@ -1282,14 +1390,21 @@ var msigLockApproveCmd = &cli.Command{
return actErr 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 { if err != nil {
return err 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) 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 { if err != nil {
return err 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")) 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 { if err != nil {
return err return err
} }
defer closer() defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0)) msig, err := address.NewFromString(cctx.Args().Get(0))
@ -1374,14 +1491,21 @@ var msigLockCancelCmd = &cli.Command{
return actErr 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 { if err != nil {
return err 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) 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 { if err != nil {
return err return err
} }
@ -1471,11 +1595,13 @@ var msigProposeThresholdCmd = &cli.Command{
return ShowHelp(cctx, fmt.Errorf("must pass multisig address and new threshold value")) 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 { if err != nil {
return err return err
} }
defer closer() defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
msig, err := address.NewFromString(cctx.Args().Get(0)) msig, err := address.NewFromString(cctx.Args().Get(0))
@ -1511,14 +1637,21 @@ var msigProposeThresholdCmd = &cli.Command{
return actErr 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 { if err != nil {
return fmt.Errorf("failed to propose change of threshold: %w", err) 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) 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 { if err != nil {
return err return err
} }

View File

@ -2,7 +2,6 @@ package cli
import ( import (
"encoding/hex" "encoding/hex"
"errors"
"fmt" "fmt"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
@ -59,10 +58,14 @@ var sendCmd = &cli.Command{
}, },
&cli.BoolFlag{ &cli.BoolFlag{
Name: "force", 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 { 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 { if cctx.Args().Len() != 2 {
return ShowHelp(cctx, fmt.Errorf("'send' expects two arguments, target and amount")) return ShowHelp(cctx, fmt.Errorf("'send' expects two arguments, target and amount"))
} }
@ -137,23 +140,22 @@ var sendCmd = &cli.Command{
params.Params = decparams params.Params = decparams
} }
params.Force = cctx.Bool("force")
if cctx.IsSet("nonce") { if cctx.IsSet("nonce") {
n := cctx.Uint64("nonce") n := cctx.Uint64("nonce")
params.Nonce = &n params.Nonce = &n
} }
msgCid, err := srv.Send(ctx, params) proto, err := srv.MessageForSend(ctx, params)
if err != nil { if err != nil {
if errors.Is(err, ErrSendBalanceTooLow) { return xerrors.Errorf("creating message prototype: %w", err)
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)
} }
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 return nil
}, },
} }

View File

@ -2,24 +2,17 @@ package cli
import ( import (
"bytes" "bytes"
"errors"
"testing" "testing"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/api"
types "github.com/filecoin-project/lotus/chain/types" types "github.com/filecoin-project/lotus/chain/types"
gomock "github.com/golang/mock/gomock" gomock "github.com/golang/mock/gomock"
cid "github.com/ipfs/go-cid"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
ucli "github.com/urfave/cli/v2" 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 { func mustAddr(a address.Address, err error) address.Address {
if err != nil { if err != nil {
panic(err) panic(err)
@ -49,80 +42,26 @@ func TestSendCLI(t *testing.T) {
app, mockSrvcs, buf, done := newMockApp(t, sendCmd) app, mockSrvcs, buf, done := newMockApp(t, sendCmd)
defer done() defer done()
gomock.InOrder( arbtProto := &api.MessagePrototype{
mockSrvcs.EXPECT().Send(gomock.Any(), SendParams{ Message: types.Message{
To: mustAddr(address.NewIDAddress(1)), From: 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{
To: mustAddr(address.NewIDAddress(1)), To: mustAddr(address.NewIDAddress(1)),
Nonce: &zero, Value: oneFil,
Val: oneFil, },
}).Return(arbtCid, nil), }
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(), 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.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" "bytes"
"context" "context"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"reflect" "reflect"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-jsonrpc" "github.com/filecoin-project/go-jsonrpc"
"github.com/filecoin-project/go-state-types/abi" "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" "github.com/filecoin-project/lotus/chain/stmgr"
types "github.com/filecoin-project/lotus/chain/types" types "github.com/filecoin-project/lotus/chain/types"
cid "github.com/ipfs/go-cid" 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 //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 { type ServicesAPI interface {
// Sends executes a send given SendParams FullNodeAPI() api.FullNode
Send(ctx context.Context, params SendParams) (cid.Cid, error)
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 // DecodeTypedParamsFromJSON takes in information needed to identify a method and converts JSON
// parameters to bytes of their CBOR encoding // parameters to bytes of their CBOR encoding
DecodeTypedParamsFromJSON(ctx context.Context, to address.Address, method abi.MethodNum, paramstr string) ([]byte, error) 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 // Close ends the session of services and disconnects from RPC, using Services after Close is called
// most likely will result in an error // most likely will result in an error
// Should not be called concurrently // Should not be called concurrently
@ -35,10 +53,14 @@ type ServicesAPI interface {
} }
type ServicesImpl struct { type ServicesImpl struct {
api v0api.FullNode api api.FullNode
closer jsonrpc.ClientCloser closer jsonrpc.ClientCloser
} }
func (s *ServicesImpl) FullNodeAPI() api.FullNode {
return s.api
}
func (s *ServicesImpl) Close() error { func (s *ServicesImpl) Close() error {
if s.closer == nil { if s.closer == nil {
return xerrors.Errorf("Services already closed") return xerrors.Errorf("Services already closed")
@ -48,6 +70,16 @@ func (s *ServicesImpl) Close() error {
return nil 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) { 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) act, err := s.api.StateGetActor(ctx, to, types.EmptyTSK)
if err != nil { if err != nil {
@ -72,6 +104,79 @@ func (s *ServicesImpl) DecodeTypedParamsFromJSON(ctx context.Context, to address
return buf.Bytes(), nil 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 { type SendParams struct {
To address.Address To address.Address
From address.Address From address.Address
@ -84,26 +189,18 @@ type SendParams struct {
Nonce *uint64 Nonce *uint64
Method abi.MethodNum Method abi.MethodNum
Params []byte Params []byte
Force bool
} }
// This is specialised Send for Send command func (s *ServicesImpl) MessageForSend(ctx context.Context, params SendParams) (*api.MessagePrototype, error) {
// 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) {
if params.From == address.Undef { if params.From == address.Undef {
defaddr, err := s.api.WalletDefaultAddress(ctx) defaddr, err := s.api.WalletDefaultAddress(ctx)
if err != nil { if err != nil {
return cid.Undef, err return nil, err
} }
params.From = defaddr params.From = defaddr
} }
msg := &types.Message{ msg := types.Message{
From: params.From, From: params.From,
To: params.To, To: params.To,
Value: params.Val, Value: params.Val,
@ -127,40 +224,53 @@ func (s *ServicesImpl) Send(ctx context.Context, params SendParams) (cid.Cid, er
} else { } else {
msg.GasLimit = 0 msg.GasLimit = 0
} }
validNonce := false
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)
}
}
if params.Nonce != nil { if params.Nonce != nil {
msg.Nonce = *params.Nonce msg.Nonce = *params.Nonce
sm, err := s.api.WalletSignMessage(ctx, params.From, msg) validNonce = true
if err != nil {
return cid.Undef, err
}
_, err = s.api.MpoolPush(ctx, sm)
if err != nil {
return cid.Undef, err
}
return sm.Cid(), nil
} }
sm, err := s.api.MpoolPushMessage(ctx, msg, nil) prototype := &api.MessagePrototype{
if err != nil { Message: msg,
return cid.Undef, err ValidNonce: validNonce,
} }
return prototype, nil
return sm.Cid(), 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
} }

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