feat(paych): convert paych actor
build abstraction for paych actor and switch to using it in payment channel manager and state predicates
This commit is contained in:
parent
4e01fad0d4
commit
05c11531b1
89
chain/actors/builtin/paych/mock/mock.go
Normal file
89
chain/actors/builtin/paych/mock/mock.go
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
package mock
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"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/builtin/paych"
|
||||||
|
)
|
||||||
|
|
||||||
|
type mockState struct {
|
||||||
|
from address.Address
|
||||||
|
to address.Address
|
||||||
|
settlingAt abi.ChainEpoch
|
||||||
|
toSend abi.TokenAmount
|
||||||
|
lanes map[uint64]paych.LaneState
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockLaneState struct {
|
||||||
|
redeemed big.Int
|
||||||
|
nonce uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockPayChState constructs a state for a payment channel with the set fixed values
|
||||||
|
// that satisfies the paych.State interface.
|
||||||
|
func NewMockPayChState(from address.Address,
|
||||||
|
to address.Address,
|
||||||
|
settlingAt abi.ChainEpoch,
|
||||||
|
toSend abi.TokenAmount,
|
||||||
|
lanes map[uint64]paych.LaneState,
|
||||||
|
) paych.State {
|
||||||
|
return &mockState{from, to, settlingAt, toSend, lanes}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockLaneState constructs a state for a payment channel lane with the set fixed values
|
||||||
|
// that satisfies the paych.LaneState interface. Useful for populating lanes when
|
||||||
|
// calling NewMockPayChState
|
||||||
|
func NewMockLaneState(redeemed big.Int, nonce uint64) paych.LaneState {
|
||||||
|
return &mockLaneState{redeemed, nonce}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ms *mockState) MarshalCBOR(io.Writer) error {
|
||||||
|
panic("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Channel owner, who has funded the actor
|
||||||
|
func (ms *mockState) From() address.Address {
|
||||||
|
return ms.from
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recipient of payouts from channel
|
||||||
|
func (ms *mockState) To() address.Address {
|
||||||
|
return ms.to
|
||||||
|
}
|
||||||
|
|
||||||
|
// Height at which the channel can be `Collected`
|
||||||
|
func (ms *mockState) SettlingAt() abi.ChainEpoch {
|
||||||
|
return ms.settlingAt
|
||||||
|
}
|
||||||
|
|
||||||
|
// Amount successfully redeemed through the payment channel, paid out on `Collect()`
|
||||||
|
func (ms *mockState) ToSend() abi.TokenAmount {
|
||||||
|
return ms.toSend
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get total number of lanes
|
||||||
|
func (ms *mockState) LaneCount() (uint64, error) {
|
||||||
|
return uint64(len(ms.lanes)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate lane states
|
||||||
|
func (ms *mockState) ForEachLaneState(cb func(idx uint64, dl paych.LaneState) error) error {
|
||||||
|
var lastErr error
|
||||||
|
for lane, state := range ms.lanes {
|
||||||
|
if err := cb(lane, state); err != nil {
|
||||||
|
lastErr = err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lastErr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mls *mockLaneState) Redeemed() big.Int {
|
||||||
|
return mls.redeemed
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mls *mockLaneState) Nonce() uint64 {
|
||||||
|
return mls.nonce
|
||||||
|
}
|
56
chain/actors/builtin/paych/paych.go
Normal file
56
chain/actors/builtin/paych/paych.go
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
package paych
|
||||||
|
|
||||||
|
import (
|
||||||
|
"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"
|
||||||
|
v0builtin "github.com/filecoin-project/specs-actors/actors/builtin"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||||
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
case v0builtin.PaymentChannelActorCodeID:
|
||||||
|
out := v0State{store: store}
|
||||||
|
err := store.Get(store.Context(), act.Head, &out)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &out, nil
|
||||||
|
}
|
||||||
|
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
|
||||||
|
// Recipient of payouts from channel
|
||||||
|
To() address.Address
|
||||||
|
|
||||||
|
// Height at which the channel can be `Collected`
|
||||||
|
SettlingAt() abi.ChainEpoch
|
||||||
|
|
||||||
|
// Amount successfully redeemed through the payment channel, paid out on `Collect()`
|
||||||
|
ToSend() abi.TokenAmount
|
||||||
|
|
||||||
|
// 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
|
||||||
|
Nonce() uint64
|
||||||
|
}
|
89
chain/actors/builtin/paych/v0.go
Normal file
89
chain/actors/builtin/paych/v0.go
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
package paych
|
||||||
|
|
||||||
|
import (
|
||||||
|
"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/lotus/chain/actors/adt"
|
||||||
|
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
||||||
|
v0adt "github.com/filecoin-project/specs-actors/actors/util/adt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type v0State struct {
|
||||||
|
paych.State
|
||||||
|
store adt.Store
|
||||||
|
lsAmt *v0adt.Array
|
||||||
|
}
|
||||||
|
|
||||||
|
// Channel owner, who has funded the actor
|
||||||
|
func (s *v0State) From() address.Address {
|
||||||
|
return s.State.From
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recipient of payouts from channel
|
||||||
|
func (s *v0State) To() address.Address {
|
||||||
|
return s.State.From
|
||||||
|
}
|
||||||
|
|
||||||
|
// Height at which the channel can be `Collected`
|
||||||
|
func (s *v0State) SettlingAt() abi.ChainEpoch {
|
||||||
|
return s.State.SettlingAt
|
||||||
|
}
|
||||||
|
|
||||||
|
// Amount successfully redeemed through the payment channel, paid out on `Collect()`
|
||||||
|
func (s *v0State) ToSend() abi.TokenAmount {
|
||||||
|
return s.State.ToSend
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *v0State) getOrLoadLsAmt() (*v0adt.Array, error) {
|
||||||
|
if s.lsAmt != nil {
|
||||||
|
return s.lsAmt, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the lane state from the chain
|
||||||
|
lsamt, err := v0adt.AsArray(s.store, s.State.LaneStates)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
s.lsAmt = lsamt
|
||||||
|
return lsamt, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get total number of lanes
|
||||||
|
func (s *v0State) LaneCount() (uint64, error) {
|
||||||
|
lsamt, err := s.getOrLoadLsAmt()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return lsamt.Length(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate lane states
|
||||||
|
func (s *v0State) 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.LaneState
|
||||||
|
return lsamt.ForEach(&ls, func(i int64) error {
|
||||||
|
return cb(uint64(i), &v0LaneState{ls})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type v0LaneState struct {
|
||||||
|
paych.LaneState
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ls *v0LaneState) Redeemed() big.Int {
|
||||||
|
return ls.LaneState.Redeemed
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ls *v0LaneState) Nonce() uint64 {
|
||||||
|
return ls.LaneState.Nonce
|
||||||
|
}
|
@ -7,13 +7,12 @@ 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"
|
||||||
"github.com/filecoin-project/go-state-types/big"
|
"github.com/filecoin-project/go-state-types/big"
|
||||||
|
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||||
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
|
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin/market"
|
"github.com/filecoin-project/specs-actors/actors/builtin/market"
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/util/adt"
|
"github.com/filecoin-project/specs-actors/actors/util/adt"
|
||||||
"github.com/ipfs/go-cid"
|
|
||||||
cbor "github.com/ipfs/go-ipld-cbor"
|
cbor "github.com/ipfs/go-ipld-cbor"
|
||||||
typegen "github.com/whyrusleeping/cbor-gen"
|
typegen "github.com/whyrusleeping/cbor-gen"
|
||||||
|
|
||||||
@ -49,7 +48,7 @@ func NewStatePredicates(api ChainAPI) *StatePredicates {
|
|||||||
// - err
|
// - err
|
||||||
type DiffTipSetKeyFunc func(ctx context.Context, oldState, newState types.TipSetKey) (changed bool, user UserData, err error)
|
type DiffTipSetKeyFunc func(ctx context.Context, oldState, newState types.TipSetKey) (changed bool, user UserData, err error)
|
||||||
|
|
||||||
type DiffActorStateFunc func(ctx context.Context, oldActorStateHead, newActorStateHead cid.Cid) (changed bool, user UserData, err error)
|
type DiffActorStateFunc func(ctx context.Context, oldActorState *types.Actor, newActorState *types.Actor) (changed bool, user UserData, err error)
|
||||||
|
|
||||||
// OnActorStateChanged calls diffStateFunc when the state changes for the given actor
|
// OnActorStateChanged calls diffStateFunc when the state changes for the given actor
|
||||||
func (sp *StatePredicates) OnActorStateChanged(addr address.Address, diffStateFunc DiffActorStateFunc) DiffTipSetKeyFunc {
|
func (sp *StatePredicates) OnActorStateChanged(addr address.Address, diffStateFunc DiffActorStateFunc) DiffTipSetKeyFunc {
|
||||||
@ -66,7 +65,7 @@ func (sp *StatePredicates) OnActorStateChanged(addr address.Address, diffStateFu
|
|||||||
if oldActor.Head.Equals(newActor.Head) {
|
if oldActor.Head.Equals(newActor.Head) {
|
||||||
return false, nil, nil
|
return false, nil, nil
|
||||||
}
|
}
|
||||||
return diffStateFunc(ctx, oldActor.Head, newActor.Head)
|
return diffStateFunc(ctx, oldActor, newActor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,13 +73,13 @@ type DiffStorageMarketStateFunc func(ctx context.Context, oldState *market.State
|
|||||||
|
|
||||||
// OnStorageMarketActorChanged calls diffStorageMarketState when the state changes for the market actor
|
// OnStorageMarketActorChanged calls diffStorageMarketState when the state changes for the market actor
|
||||||
func (sp *StatePredicates) OnStorageMarketActorChanged(diffStorageMarketState DiffStorageMarketStateFunc) DiffTipSetKeyFunc {
|
func (sp *StatePredicates) OnStorageMarketActorChanged(diffStorageMarketState DiffStorageMarketStateFunc) DiffTipSetKeyFunc {
|
||||||
return sp.OnActorStateChanged(builtin.StorageMarketActorAddr, func(ctx context.Context, oldActorStateHead, newActorStateHead cid.Cid) (changed bool, user UserData, err error) {
|
return sp.OnActorStateChanged(builtin.StorageMarketActorAddr, func(ctx context.Context, oldActorState, newActorState *types.Actor) (changed bool, user UserData, err error) {
|
||||||
var oldState market.State
|
var oldState market.State
|
||||||
if err := sp.cst.Get(ctx, oldActorStateHead, &oldState); err != nil {
|
if err := sp.cst.Get(ctx, oldActorState.Head, &oldState); err != nil {
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
}
|
}
|
||||||
var newState market.State
|
var newState market.State
|
||||||
if err := sp.cst.Get(ctx, newActorStateHead, &newState); err != nil {
|
if err := sp.cst.Get(ctx, newActorState.Head, &newState); err != nil {
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
}
|
}
|
||||||
return diffStorageMarketState(ctx, &oldState, &newState)
|
return diffStorageMarketState(ctx, &oldState, &newState)
|
||||||
@ -408,13 +407,13 @@ func (sp *StatePredicates) AvailableBalanceChangedForAddresses(getAddrs func() [
|
|||||||
type DiffMinerActorStateFunc func(ctx context.Context, oldState *miner.State, newState *miner.State) (changed bool, user UserData, err error)
|
type DiffMinerActorStateFunc func(ctx context.Context, oldState *miner.State, newState *miner.State) (changed bool, user UserData, err error)
|
||||||
|
|
||||||
func (sp *StatePredicates) OnInitActorChange(diffInitActorState DiffInitActorStateFunc) DiffTipSetKeyFunc {
|
func (sp *StatePredicates) OnInitActorChange(diffInitActorState DiffInitActorStateFunc) DiffTipSetKeyFunc {
|
||||||
return sp.OnActorStateChanged(builtin.InitActorAddr, func(ctx context.Context, oldActorStateHead, newActorStateHead cid.Cid) (changed bool, user UserData, err error) {
|
return sp.OnActorStateChanged(builtin.InitActorAddr, func(ctx context.Context, oldActorState, newActorState *types.Actor) (changed bool, user UserData, err error) {
|
||||||
var oldState init_.State
|
var oldState init_.State
|
||||||
if err := sp.cst.Get(ctx, oldActorStateHead, &oldState); err != nil {
|
if err := sp.cst.Get(ctx, oldActorState.Head, &oldState); err != nil {
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
}
|
}
|
||||||
var newState init_.State
|
var newState init_.State
|
||||||
if err := sp.cst.Get(ctx, newActorStateHead, &newState); err != nil {
|
if err := sp.cst.Get(ctx, newActorState.Head, &newState); err != nil {
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
}
|
}
|
||||||
return diffInitActorState(ctx, &oldState, &newState)
|
return diffInitActorState(ctx, &oldState, &newState)
|
||||||
@ -423,13 +422,13 @@ func (sp *StatePredicates) OnInitActorChange(diffInitActorState DiffInitActorSta
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (sp *StatePredicates) OnMinerActorChange(minerAddr address.Address, diffMinerActorState DiffMinerActorStateFunc) DiffTipSetKeyFunc {
|
func (sp *StatePredicates) OnMinerActorChange(minerAddr address.Address, diffMinerActorState DiffMinerActorStateFunc) DiffTipSetKeyFunc {
|
||||||
return sp.OnActorStateChanged(minerAddr, func(ctx context.Context, oldActorStateHead, newActorStateHead cid.Cid) (changed bool, user UserData, err error) {
|
return sp.OnActorStateChanged(minerAddr, func(ctx context.Context, oldActorState, newActorState *types.Actor) (changed bool, user UserData, err error) {
|
||||||
var oldState miner.State
|
var oldState miner.State
|
||||||
if err := sp.cst.Get(ctx, oldActorStateHead, &oldState); err != nil {
|
if err := sp.cst.Get(ctx, oldActorState.Head, &oldState); err != nil {
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
}
|
}
|
||||||
var newState miner.State
|
var newState miner.State
|
||||||
if err := sp.cst.Get(ctx, newActorStateHead, &newState); err != nil {
|
if err := sp.cst.Get(ctx, newActorState.Head, &newState); err != nil {
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
}
|
}
|
||||||
return diffMinerActorState(ctx, &oldState, &newState)
|
return diffMinerActorState(ctx, &oldState, &newState)
|
||||||
@ -608,20 +607,20 @@ func (sp *StatePredicates) OnMinerPreCommitChange() DiffMinerActorStateFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DiffPaymentChannelStateFunc is function that compares two states for the payment channel
|
// DiffPaymentChannelStateFunc is function that compares two states for the payment channel
|
||||||
type DiffPaymentChannelStateFunc func(ctx context.Context, oldState *paych.State, newState *paych.State) (changed bool, user UserData, err error)
|
type DiffPaymentChannelStateFunc func(ctx context.Context, oldState paych.State, newState paych.State) (changed bool, user UserData, err error)
|
||||||
|
|
||||||
// OnPaymentChannelActorChanged calls diffPaymentChannelState when the state changes for the the payment channel actor
|
// OnPaymentChannelActorChanged calls diffPaymentChannelState when the state changes for the the payment channel actor
|
||||||
func (sp *StatePredicates) OnPaymentChannelActorChanged(paychAddr address.Address, diffPaymentChannelState DiffPaymentChannelStateFunc) DiffTipSetKeyFunc {
|
func (sp *StatePredicates) OnPaymentChannelActorChanged(paychAddr address.Address, diffPaymentChannelState DiffPaymentChannelStateFunc) DiffTipSetKeyFunc {
|
||||||
return sp.OnActorStateChanged(paychAddr, func(ctx context.Context, oldActorStateHead, newActorStateHead cid.Cid) (changed bool, user UserData, err error) {
|
return sp.OnActorStateChanged(paychAddr, func(ctx context.Context, oldActorState, newActorState *types.Actor) (changed bool, user UserData, err error) {
|
||||||
var oldState paych.State
|
oldState, err := paych.Load(adt.WrapStore(ctx, sp.cst), oldActorState)
|
||||||
if err := sp.cst.Get(ctx, oldActorStateHead, &oldState); err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
}
|
}
|
||||||
var newState paych.State
|
newState, err := paych.Load(adt.WrapStore(ctx, sp.cst), newActorState)
|
||||||
if err := sp.cst.Get(ctx, newActorStateHead, &newState); err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
}
|
}
|
||||||
return diffPaymentChannelState(ctx, &oldState, &newState)
|
return diffPaymentChannelState(ctx, oldState, newState)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -633,13 +632,13 @@ type PayChToSendChange struct {
|
|||||||
|
|
||||||
// OnToSendAmountChanges monitors changes on the total amount to send from one party to the other on a payment channel
|
// OnToSendAmountChanges monitors changes on the total amount to send from one party to the other on a payment channel
|
||||||
func (sp *StatePredicates) OnToSendAmountChanges() DiffPaymentChannelStateFunc {
|
func (sp *StatePredicates) OnToSendAmountChanges() DiffPaymentChannelStateFunc {
|
||||||
return func(ctx context.Context, oldState *paych.State, newState *paych.State) (changed bool, user UserData, err error) {
|
return func(ctx context.Context, oldState paych.State, newState paych.State) (changed bool, user UserData, err error) {
|
||||||
if oldState.ToSend.Equals(newState.ToSend) {
|
if oldState.ToSend().Equals(newState.ToSend()) {
|
||||||
return false, nil, nil
|
return false, nil, nil
|
||||||
}
|
}
|
||||||
return true, &PayChToSendChange{
|
return true, &PayChToSendChange{
|
||||||
OldToSend: oldState.ToSend,
|
OldToSend: oldState.ToSend(),
|
||||||
NewToSend: newState.ToSend,
|
NewToSend: newState.ToSend(),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -221,7 +221,7 @@ func TestMarketPredicates(t *testing.T) {
|
|||||||
// Test that OnActorStateChanged does not call the callback if the state has not changed
|
// Test that OnActorStateChanged does not call the callback if the state has not changed
|
||||||
mockAddr, err := address.NewFromString("t01")
|
mockAddr, err := address.NewFromString("t01")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
actorDiffFn := preds.OnActorStateChanged(mockAddr, func(context.Context, cid.Cid, cid.Cid) (bool, UserData, error) {
|
actorDiffFn := preds.OnActorStateChanged(mockAddr, func(context.Context, *types.Actor, *types.Actor) (bool, UserData, error) {
|
||||||
t.Fatal("No state change so this should not be called")
|
t.Fatal("No state change so this should not be called")
|
||||||
return false, nil, nil
|
return false, nil, nil
|
||||||
})
|
})
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/build"
|
"github.com/filecoin-project/lotus/build"
|
||||||
"github.com/filecoin-project/lotus/chain/actors"
|
"github.com/filecoin-project/lotus/chain/actors"
|
||||||
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
|
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
|
||||||
|
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
|
||||||
"github.com/filecoin-project/lotus/chain/actors/builtin/power"
|
"github.com/filecoin-project/lotus/chain/actors/builtin/power"
|
||||||
"github.com/filecoin-project/lotus/chain/state"
|
"github.com/filecoin-project/lotus/chain/state"
|
||||||
"github.com/filecoin-project/lotus/chain/store"
|
"github.com/filecoin-project/lotus/chain/store"
|
||||||
@ -1145,3 +1146,21 @@ func (sm *StateManager) GetNtwkVersion(ctx context.Context, height abi.ChainEpoc
|
|||||||
|
|
||||||
return build.NewestNetworkVersion
|
return build.NewestNetworkVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sm *StateManager) GetPaychState(ctx context.Context, addr address.Address, ts *types.TipSet) (*types.Actor, paych.State, error) {
|
||||||
|
st, err := sm.ParentState(ts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
act, err := st.GetActor(addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
actState, err := paych.Load(sm.cs.Store(ctx), act)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return act, actState, nil
|
||||||
|
}
|
||||||
|
@ -24,7 +24,8 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/chain/events"
|
"github.com/filecoin-project/lotus/chain/events"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/api/apibstore"
|
"github.com/filecoin-project/lotus/api/apibstore"
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||||
|
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
|
||||||
cbor "github.com/ipfs/go-ipld-cbor"
|
cbor "github.com/ipfs/go-ipld-cbor"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
@ -88,7 +89,7 @@ func TestPaymentChannels(t *testing.T) {
|
|||||||
|
|
||||||
// Wait for the chain to reach the settle height
|
// Wait for the chain to reach the settle height
|
||||||
chState := getPaychState(ctx, t, paymentReceiver, chAddr)
|
chState := getPaychState(ctx, t, paymentReceiver, chAddr)
|
||||||
waitForHeight(ctx, t, paymentReceiver, chState.SettlingAt)
|
waitForHeight(ctx, t, paymentReceiver, chState.SettlingAt())
|
||||||
|
|
||||||
// receiver: paych collect <channel>
|
// receiver: paych collect <channel>
|
||||||
cmd = []string{chAddr.String()}
|
cmd = []string{chAddr.String()}
|
||||||
@ -540,8 +541,7 @@ func getPaychState(ctx context.Context, t *testing.T, node test.TestNode, chAddr
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
store := cbor.NewCborStore(apibstore.NewAPIBlockstore(node))
|
store := cbor.NewCborStore(apibstore.NewAPIBlockstore(node))
|
||||||
var chState paych.State
|
chState, err := paych.Load(adt.WrapStore(ctx, store), act)
|
||||||
err = store.Get(ctx, act.Head, &chState)
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
return chState
|
return chState
|
||||||
|
@ -4,28 +4,23 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-state-types/crypto"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/node/modules/helpers"
|
|
||||||
|
|
||||||
"github.com/ipfs/go-datastore"
|
|
||||||
|
|
||||||
xerrors "golang.org/x/xerrors"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/util/adt"
|
|
||||||
|
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
|
"github.com/ipfs/go-datastore"
|
||||||
logging "github.com/ipfs/go-log/v2"
|
logging "github.com/ipfs/go-log/v2"
|
||||||
"go.uber.org/fx"
|
"go.uber.org/fx"
|
||||||
|
xerrors "golang.org/x/xerrors"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
|
"github.com/filecoin-project/go-state-types/crypto"
|
||||||
|
v0paych "github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/api"
|
||||||
|
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||||
|
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
|
||||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/filecoin-project/lotus/node/impl/full"
|
"github.com/filecoin-project/lotus/node/impl/full"
|
||||||
|
"github.com/filecoin-project/lotus/node/modules/helpers"
|
||||||
)
|
)
|
||||||
|
|
||||||
var log = logging.Logger("paych")
|
var log = logging.Logger("paych")
|
||||||
@ -40,9 +35,9 @@ type PaychAPI struct {
|
|||||||
|
|
||||||
// stateManagerAPI defines the methods needed from StateManager
|
// stateManagerAPI defines the methods needed from StateManager
|
||||||
type stateManagerAPI interface {
|
type stateManagerAPI interface {
|
||||||
LoadActorState(ctx context.Context, a address.Address, out interface{}, ts *types.TipSet) (*types.Actor, error)
|
ResolveToKeyAddress(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error)
|
||||||
|
GetPaychState(ctx context.Context, addr address.Address, ts *types.TipSet) (*types.Actor, paych.State, error)
|
||||||
Call(ctx context.Context, msg *types.Message, ts *types.TipSet) (*api.InvocResult, error)
|
Call(ctx context.Context, msg *types.Message, ts *types.TipSet) (*api.InvocResult, error)
|
||||||
AdtStore(ctx context.Context) adt.Store
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// paychAPI defines the API methods needed by the payment channel manager
|
// paychAPI defines the API methods needed by the payment channel manager
|
||||||
@ -226,7 +221,7 @@ func (pm *Manager) GetChannelInfo(addr address.Address) (*ChannelInfo, error) {
|
|||||||
return ca.getChannelInfo(addr)
|
return ca.getChannelInfo(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pm *Manager) CreateVoucher(ctx context.Context, ch address.Address, voucher paych.SignedVoucher) (*api.VoucherCreateResult, error) {
|
func (pm *Manager) CreateVoucher(ctx context.Context, ch address.Address, voucher v0paych.SignedVoucher) (*api.VoucherCreateResult, error) {
|
||||||
ca, err := pm.accessorByAddress(ch)
|
ca, err := pm.accessorByAddress(ch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -238,7 +233,7 @@ func (pm *Manager) CreateVoucher(ctx context.Context, ch address.Address, vouche
|
|||||||
// CheckVoucherValid checks if the given voucher is valid (is or could become spendable at some point).
|
// CheckVoucherValid checks if the given voucher is valid (is or could become spendable at some point).
|
||||||
// If the channel is not in the store, fetches the channel from state (and checks that
|
// If the channel is not in the store, fetches the channel from state (and checks that
|
||||||
// the channel To address is owned by the wallet).
|
// the channel To address is owned by the wallet).
|
||||||
func (pm *Manager) CheckVoucherValid(ctx context.Context, ch address.Address, sv *paych.SignedVoucher) error {
|
func (pm *Manager) CheckVoucherValid(ctx context.Context, ch address.Address, sv *v0paych.SignedVoucher) error {
|
||||||
// Get an accessor for the channel, creating it from state if necessary
|
// Get an accessor for the channel, creating it from state if necessary
|
||||||
ca, err := pm.inboundChannelAccessor(ctx, ch)
|
ca, err := pm.inboundChannelAccessor(ctx, ch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -250,7 +245,7 @@ func (pm *Manager) CheckVoucherValid(ctx context.Context, ch address.Address, sv
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CheckVoucherSpendable checks if the given voucher is currently spendable
|
// CheckVoucherSpendable checks if the given voucher is currently spendable
|
||||||
func (pm *Manager) CheckVoucherSpendable(ctx context.Context, ch address.Address, sv *paych.SignedVoucher, secret []byte, proof []byte) (bool, error) {
|
func (pm *Manager) CheckVoucherSpendable(ctx context.Context, ch address.Address, sv *v0paych.SignedVoucher, secret []byte, proof []byte) (bool, error) {
|
||||||
ca, err := pm.accessorByAddress(ch)
|
ca, err := pm.accessorByAddress(ch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@ -261,7 +256,7 @@ func (pm *Manager) CheckVoucherSpendable(ctx context.Context, ch address.Address
|
|||||||
|
|
||||||
// AddVoucherOutbound adds a voucher for an outbound channel.
|
// AddVoucherOutbound adds a voucher for an outbound channel.
|
||||||
// Returns an error if the channel is not already in the store.
|
// Returns an error if the channel is not already in the store.
|
||||||
func (pm *Manager) AddVoucherOutbound(ctx context.Context, ch address.Address, sv *paych.SignedVoucher, proof []byte, minDelta types.BigInt) (types.BigInt, error) {
|
func (pm *Manager) AddVoucherOutbound(ctx context.Context, ch address.Address, sv *v0paych.SignedVoucher, proof []byte, minDelta types.BigInt) (types.BigInt, error) {
|
||||||
ca, err := pm.accessorByAddress(ch)
|
ca, err := pm.accessorByAddress(ch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.NewInt(0), err
|
return types.NewInt(0), err
|
||||||
@ -272,7 +267,7 @@ func (pm *Manager) AddVoucherOutbound(ctx context.Context, ch address.Address, s
|
|||||||
// AddVoucherInbound adds a voucher for an inbound channel.
|
// AddVoucherInbound adds a voucher for an inbound channel.
|
||||||
// If the channel is not in the store, fetches the channel from state (and checks that
|
// If the channel is not in the store, fetches the channel from state (and checks that
|
||||||
// the channel To address is owned by the wallet).
|
// the channel To address is owned by the wallet).
|
||||||
func (pm *Manager) AddVoucherInbound(ctx context.Context, ch address.Address, sv *paych.SignedVoucher, proof []byte, minDelta types.BigInt) (types.BigInt, error) {
|
func (pm *Manager) AddVoucherInbound(ctx context.Context, ch address.Address, sv *v0paych.SignedVoucher, proof []byte, minDelta types.BigInt) (types.BigInt, error) {
|
||||||
// Get an accessor for the channel, creating it from state if necessary
|
// Get an accessor for the channel, creating it from state if necessary
|
||||||
ca, err := pm.inboundChannelAccessor(ctx, ch)
|
ca, err := pm.inboundChannelAccessor(ctx, ch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -341,7 +336,7 @@ func (pm *Manager) trackInboundChannel(ctx context.Context, ch address.Address)
|
|||||||
return pm.store.TrackChannel(stateCi)
|
return pm.store.TrackChannel(stateCi)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pm *Manager) SubmitVoucher(ctx context.Context, ch address.Address, sv *paych.SignedVoucher, secret []byte, proof []byte) (cid.Cid, error) {
|
func (pm *Manager) SubmitVoucher(ctx context.Context, ch address.Address, sv *v0paych.SignedVoucher, secret []byte, proof []byte) (cid.Cid, error) {
|
||||||
ca, err := pm.accessorByAddress(ch)
|
ca, err := pm.accessorByAddress(ch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Undef, err
|
return cid.Undef, err
|
||||||
|
@ -2,23 +2,18 @@ package paychmgr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"errors"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/lib/sigs"
|
"github.com/ipfs/go-cid"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-state-types/crypto"
|
|
||||||
|
|
||||||
cbornode "github.com/ipfs/go-ipld-cbor"
|
|
||||||
|
|
||||||
"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/crypto"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
"github.com/filecoin-project/lotus/api"
|
||||||
|
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin/account"
|
"github.com/filecoin-project/lotus/lib/sigs"
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
|
||||||
"github.com/ipfs/go-cid"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type mockManagerAPI struct {
|
type mockManagerAPI struct {
|
||||||
@ -40,29 +35,23 @@ type mockPchState struct {
|
|||||||
|
|
||||||
type mockStateManager struct {
|
type mockStateManager struct {
|
||||||
lk sync.Mutex
|
lk sync.Mutex
|
||||||
accountState map[address.Address]account.State
|
accountState map[address.Address]address.Address
|
||||||
paychState map[address.Address]mockPchState
|
paychState map[address.Address]mockPchState
|
||||||
store adt.Store
|
|
||||||
response *api.InvocResult
|
response *api.InvocResult
|
||||||
lastCall *types.Message
|
lastCall *types.Message
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMockStateManager() *mockStateManager {
|
func newMockStateManager() *mockStateManager {
|
||||||
return &mockStateManager{
|
return &mockStateManager{
|
||||||
accountState: make(map[address.Address]account.State),
|
accountState: make(map[address.Address]address.Address),
|
||||||
paychState: make(map[address.Address]mockPchState),
|
paychState: make(map[address.Address]mockPchState),
|
||||||
store: adt.WrapStore(context.Background(), cbornode.NewMemCborStore()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sm *mockStateManager) AdtStore(ctx context.Context) adt.Store {
|
func (sm *mockStateManager) setAccountAddress(a address.Address, lookup address.Address) {
|
||||||
return sm.store
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sm *mockStateManager) setAccountState(a address.Address, state account.State) {
|
|
||||||
sm.lk.Lock()
|
sm.lk.Lock()
|
||||||
defer sm.lk.Unlock()
|
defer sm.lk.Unlock()
|
||||||
sm.accountState[a] = state
|
sm.accountState[a] = lookup
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sm *mockStateManager) setPaychState(a address.Address, actor *types.Actor, state paych.State) {
|
func (sm *mockStateManager) setPaychState(a address.Address, actor *types.Actor, state paych.State) {
|
||||||
@ -71,31 +60,24 @@ func (sm *mockStateManager) setPaychState(a address.Address, actor *types.Actor,
|
|||||||
sm.paychState[a] = mockPchState{actor, state}
|
sm.paychState[a] = mockPchState{actor, state}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sm *mockStateManager) storeLaneStates(laneStates map[uint64]paych.LaneState) (cid.Cid, error) {
|
func (sm *mockStateManager) ResolveToKeyAddress(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
|
||||||
arr := adt.MakeEmptyArray(sm.store)
|
|
||||||
for i, ls := range laneStates {
|
|
||||||
ls := ls
|
|
||||||
if err := arr.Set(i, &ls); err != nil {
|
|
||||||
return cid.Undef, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return arr.Root()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sm *mockStateManager) LoadActorState(ctx context.Context, a address.Address, out interface{}, ts *types.TipSet) (*types.Actor, error) {
|
|
||||||
sm.lk.Lock()
|
sm.lk.Lock()
|
||||||
defer sm.lk.Unlock()
|
defer sm.lk.Unlock()
|
||||||
|
keyAddr, ok := sm.accountState[addr]
|
||||||
|
if !ok {
|
||||||
|
return address.Undef, errors.New("not found")
|
||||||
|
}
|
||||||
|
return keyAddr, nil
|
||||||
|
}
|
||||||
|
|
||||||
if outState, ok := out.(*account.State); ok {
|
func (sm *mockStateManager) GetPaychState(ctx context.Context, addr address.Address, ts *types.TipSet) (*types.Actor, paych.State, error) {
|
||||||
*outState = sm.accountState[a]
|
sm.lk.Lock()
|
||||||
return nil, nil
|
defer sm.lk.Unlock()
|
||||||
|
info, ok := sm.paychState[addr]
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, errors.New("not found")
|
||||||
}
|
}
|
||||||
if outState, ok := out.(*paych.State); ok {
|
return info.actor, info.state, nil
|
||||||
info := sm.paychState[a]
|
|
||||||
*outState = info.state
|
|
||||||
return info.actor, nil
|
|
||||||
}
|
|
||||||
panic(fmt.Sprintf("unexpected state type %v", out))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sm *mockStateManager) setCallResponse(response *api.InvocResult) {
|
func (sm *mockStateManager) setCallResponse(response *api.InvocResult) {
|
||||||
|
@ -4,9 +4,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -5,22 +5,20 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/util/adt"
|
|
||||||
|
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
cborutil "github.com/filecoin-project/go-cbor-util"
|
cborutil "github.com/filecoin-project/go-cbor-util"
|
||||||
"github.com/filecoin-project/go-state-types/big"
|
"github.com/filecoin-project/go-state-types/big"
|
||||||
|
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||||
|
v0paych "github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/api"
|
||||||
"github.com/filecoin-project/lotus/chain/actors"
|
"github.com/filecoin-project/lotus/chain/actors"
|
||||||
|
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/filecoin-project/lotus/lib/sigs"
|
"github.com/filecoin-project/lotus/lib/sigs"
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin/account"
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
|
||||||
"golang.org/x/xerrors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// insufficientFundsErr indicates that there are not enough funds in the
|
// insufficientFundsErr indicates that there are not enough funds in the
|
||||||
@ -45,6 +43,19 @@ func (e *ErrInsufficientFunds) Shortfall() types.BigInt {
|
|||||||
return e.shortfall
|
return e.shortfall
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type laneState struct {
|
||||||
|
redeemed big.Int
|
||||||
|
nonce uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ls laneState) Redeemed() big.Int {
|
||||||
|
return ls.redeemed
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ls laneState) Nonce() uint64 {
|
||||||
|
return ls.nonce
|
||||||
|
}
|
||||||
|
|
||||||
// channelAccessor is used to simplify locking when accessing a channel
|
// channelAccessor is used to simplify locking when accessing a channel
|
||||||
type channelAccessor struct {
|
type channelAccessor struct {
|
||||||
from address.Address
|
from address.Address
|
||||||
@ -92,7 +103,7 @@ func (ca *channelAccessor) outboundActiveByFromTo(from, to address.Address) (*Ch
|
|||||||
// nonce, signing the voucher and storing it in the local datastore.
|
// nonce, signing the voucher and storing it in the local datastore.
|
||||||
// If there are not enough funds in the channel to create the voucher, returns
|
// If there are not enough funds in the channel to create the voucher, returns
|
||||||
// the shortfall in funds.
|
// the shortfall in funds.
|
||||||
func (ca *channelAccessor) createVoucher(ctx context.Context, ch address.Address, voucher paych.SignedVoucher) (*api.VoucherCreateResult, error) {
|
func (ca *channelAccessor) createVoucher(ctx context.Context, ch address.Address, voucher v0paych.SignedVoucher) (*api.VoucherCreateResult, error) {
|
||||||
ca.lk.Lock()
|
ca.lk.Lock()
|
||||||
defer ca.lk.Unlock()
|
defer ca.lk.Unlock()
|
||||||
|
|
||||||
@ -151,14 +162,14 @@ func (ca *channelAccessor) nextNonceForLane(ci *ChannelInfo, lane uint64) uint64
|
|||||||
return maxnonce + 1
|
return maxnonce + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ca *channelAccessor) checkVoucherValid(ctx context.Context, ch address.Address, sv *paych.SignedVoucher) (map[uint64]*paych.LaneState, error) {
|
func (ca *channelAccessor) checkVoucherValid(ctx context.Context, ch address.Address, sv *v0paych.SignedVoucher) (map[uint64]paych.LaneState, error) {
|
||||||
ca.lk.Lock()
|
ca.lk.Lock()
|
||||||
defer ca.lk.Unlock()
|
defer ca.lk.Unlock()
|
||||||
|
|
||||||
return ca.checkVoucherValidUnlocked(ctx, ch, sv)
|
return ca.checkVoucherValidUnlocked(ctx, ch, sv)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ca *channelAccessor) checkVoucherValidUnlocked(ctx context.Context, ch address.Address, sv *paych.SignedVoucher) (map[uint64]*paych.LaneState, error) {
|
func (ca *channelAccessor) checkVoucherValidUnlocked(ctx context.Context, ch address.Address, sv *v0paych.SignedVoucher) (map[uint64]paych.LaneState, error) {
|
||||||
if sv.ChannelAddr != ch {
|
if sv.ChannelAddr != ch {
|
||||||
return nil, xerrors.Errorf("voucher ChannelAddr doesn't match channel address, got %s, expected %s", sv.ChannelAddr, ch)
|
return nil, xerrors.Errorf("voucher ChannelAddr doesn't match channel address, got %s, expected %s", sv.ChannelAddr, ch)
|
||||||
}
|
}
|
||||||
@ -170,12 +181,10 @@ func (ca *channelAccessor) checkVoucherValidUnlocked(ctx context.Context, ch add
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load channel "From" account actor state
|
// Load channel "From" account actor state
|
||||||
var actState account.State
|
from, err := ca.api.ResolveToKeyAddress(ctx, pchState.From(), nil)
|
||||||
_, err = ca.api.LoadActorState(ctx, pchState.From, &actState, nil)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
from := actState.Address
|
|
||||||
|
|
||||||
// verify voucher signature
|
// verify voucher signature
|
||||||
vb, err := sv.SigningBytes()
|
vb, err := sv.SigningBytes()
|
||||||
@ -199,12 +208,12 @@ func (ca *channelAccessor) checkVoucherValidUnlocked(ctx context.Context, ch add
|
|||||||
// If the new voucher nonce value is less than the highest known
|
// If the new voucher nonce value is less than the highest known
|
||||||
// nonce for the lane
|
// nonce for the lane
|
||||||
ls, lsExists := laneStates[sv.Lane]
|
ls, lsExists := laneStates[sv.Lane]
|
||||||
if lsExists && sv.Nonce <= ls.Nonce {
|
if lsExists && sv.Nonce <= ls.Nonce() {
|
||||||
return nil, fmt.Errorf("nonce too low")
|
return nil, fmt.Errorf("nonce too low")
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the voucher amount is less than the highest known voucher amount
|
// If the voucher amount is less than the highest known voucher amount
|
||||||
if lsExists && sv.Amount.LessThanEqual(ls.Redeemed) {
|
if lsExists && sv.Amount.LessThanEqual(ls.Redeemed()) {
|
||||||
return nil, fmt.Errorf("voucher amount is lower than amount for voucher with lower nonce")
|
return nil, fmt.Errorf("voucher amount is lower than amount for voucher with lower nonce")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,7 +239,7 @@ func (ca *channelAccessor) checkVoucherValidUnlocked(ctx context.Context, ch add
|
|||||||
|
|
||||||
// Total required balance = total redeemed + toSend
|
// Total required balance = total redeemed + toSend
|
||||||
// Must not exceed actor balance
|
// Must not exceed actor balance
|
||||||
newTotal := types.BigAdd(totalRedeemed, pchState.ToSend)
|
newTotal := types.BigAdd(totalRedeemed, pchState.ToSend())
|
||||||
if act.Balance.LessThan(newTotal) {
|
if act.Balance.LessThan(newTotal) {
|
||||||
return nil, newErrInsufficientFunds(types.BigSub(newTotal, act.Balance))
|
return nil, newErrInsufficientFunds(types.BigSub(newTotal, act.Balance))
|
||||||
}
|
}
|
||||||
@ -242,7 +251,7 @@ func (ca *channelAccessor) checkVoucherValidUnlocked(ctx context.Context, ch add
|
|||||||
return laneStates, nil
|
return laneStates, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ca *channelAccessor) checkVoucherSpendable(ctx context.Context, ch address.Address, sv *paych.SignedVoucher, secret []byte, proof []byte) (bool, error) {
|
func (ca *channelAccessor) checkVoucherSpendable(ctx context.Context, ch address.Address, sv *v0paych.SignedVoucher, secret []byte, proof []byte) (bool, error) {
|
||||||
ca.lk.Lock()
|
ca.lk.Lock()
|
||||||
defer ca.lk.Unlock()
|
defer ca.lk.Unlock()
|
||||||
|
|
||||||
@ -281,7 +290,7 @@ func (ca *channelAccessor) checkVoucherSpendable(ctx context.Context, ch address
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enc, err := actors.SerializeParams(&paych.UpdateChannelStateParams{
|
enc, err := actors.SerializeParams(&v0paych.UpdateChannelStateParams{
|
||||||
Sv: *sv,
|
Sv: *sv,
|
||||||
Secret: secret,
|
Secret: secret,
|
||||||
Proof: proof,
|
Proof: proof,
|
||||||
@ -308,22 +317,22 @@ func (ca *channelAccessor) checkVoucherSpendable(ctx context.Context, ch address
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ca *channelAccessor) getPaychRecipient(ctx context.Context, ch address.Address) (address.Address, error) {
|
func (ca *channelAccessor) getPaychRecipient(ctx context.Context, ch address.Address) (address.Address, error) {
|
||||||
var state paych.State
|
_, state, err := ca.api.GetPaychState(ctx, ch, nil)
|
||||||
if _, err := ca.api.LoadActorState(ctx, ch, &state, nil); err != nil {
|
if err != nil {
|
||||||
return address.Address{}, err
|
return address.Address{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return state.To, nil
|
return state.To(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ca *channelAccessor) addVoucher(ctx context.Context, ch address.Address, sv *paych.SignedVoucher, proof []byte, minDelta types.BigInt) (types.BigInt, error) {
|
func (ca *channelAccessor) addVoucher(ctx context.Context, ch address.Address, sv *v0paych.SignedVoucher, proof []byte, minDelta types.BigInt) (types.BigInt, error) {
|
||||||
ca.lk.Lock()
|
ca.lk.Lock()
|
||||||
defer ca.lk.Unlock()
|
defer ca.lk.Unlock()
|
||||||
|
|
||||||
return ca.addVoucherUnlocked(ctx, ch, sv, proof, minDelta)
|
return ca.addVoucherUnlocked(ctx, ch, sv, proof, minDelta)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ca *channelAccessor) addVoucherUnlocked(ctx context.Context, ch address.Address, sv *paych.SignedVoucher, proof []byte, minDelta types.BigInt) (types.BigInt, error) {
|
func (ca *channelAccessor) addVoucherUnlocked(ctx context.Context, ch address.Address, sv *v0paych.SignedVoucher, proof []byte, minDelta types.BigInt) (types.BigInt, error) {
|
||||||
ci, err := ca.store.ByAddress(ch)
|
ci, err := ca.store.ByAddress(ch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.BigInt{}, err
|
return types.BigInt{}, err
|
||||||
@ -367,7 +376,7 @@ func (ca *channelAccessor) addVoucherUnlocked(ctx context.Context, ch address.Ad
|
|||||||
laneState, exists := laneStates[sv.Lane]
|
laneState, exists := laneStates[sv.Lane]
|
||||||
redeemed := big.NewInt(0)
|
redeemed := big.NewInt(0)
|
||||||
if exists {
|
if exists {
|
||||||
redeemed = laneState.Redeemed
|
redeemed = laneState.Redeemed()
|
||||||
}
|
}
|
||||||
|
|
||||||
delta := types.BigSub(sv.Amount, redeemed)
|
delta := types.BigSub(sv.Amount, redeemed)
|
||||||
@ -387,7 +396,7 @@ func (ca *channelAccessor) addVoucherUnlocked(ctx context.Context, ch address.Ad
|
|||||||
return delta, ca.store.putChannelInfo(ci)
|
return delta, ca.store.putChannelInfo(ci)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ca *channelAccessor) submitVoucher(ctx context.Context, ch address.Address, sv *paych.SignedVoucher, secret []byte, proof []byte) (cid.Cid, error) {
|
func (ca *channelAccessor) submitVoucher(ctx context.Context, ch address.Address, sv *v0paych.SignedVoucher, secret []byte, proof []byte) (cid.Cid, error) {
|
||||||
ca.lk.Lock()
|
ca.lk.Lock()
|
||||||
defer ca.lk.Unlock()
|
defer ca.lk.Unlock()
|
||||||
|
|
||||||
@ -428,7 +437,7 @@ func (ca *channelAccessor) submitVoucher(ctx context.Context, ch address.Address
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enc, err := actors.SerializeParams(&paych.UpdateChannelStateParams{
|
enc, err := actors.SerializeParams(&v0paych.UpdateChannelStateParams{
|
||||||
Sv: *sv,
|
Sv: *sv,
|
||||||
Secret: secret,
|
Secret: secret,
|
||||||
Proof: proof,
|
Proof: proof,
|
||||||
@ -487,13 +496,11 @@ func (ca *channelAccessor) listVouchers(ctx context.Context, ch address.Address)
|
|||||||
|
|
||||||
// laneState gets the LaneStates from chain, then applies all vouchers in
|
// laneState gets the LaneStates from chain, then applies all vouchers in
|
||||||
// the data store over the chain state
|
// the data store over the chain state
|
||||||
func (ca *channelAccessor) laneState(ctx context.Context, state *paych.State, ch address.Address) (map[uint64]*paych.LaneState, error) {
|
func (ca *channelAccessor) laneState(ctx context.Context, state paych.State, ch address.Address) (map[uint64]paych.LaneState, error) {
|
||||||
// TODO: we probably want to call UpdateChannelState with all vouchers to be fully correct
|
// TODO: we probably want to call UpdateChannelState with all vouchers to be fully correct
|
||||||
// (but technically dont't need to)
|
// (but technically dont't need to)
|
||||||
|
|
||||||
// Get the lane state from the chain
|
laneCount, err := state.LaneCount()
|
||||||
store := ca.api.AdtStore(ctx)
|
|
||||||
lsamt, err := adt.AsArray(store, state.LaneStates)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -501,11 +508,9 @@ func (ca *channelAccessor) laneState(ctx context.Context, state *paych.State, ch
|
|||||||
// Note: we use a map instead of an array to store laneStates because the
|
// 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
|
// client sets the lane ID (the index) and potentially they could use a
|
||||||
// very large index.
|
// very large index.
|
||||||
var ls paych.LaneState
|
laneStates := make(map[uint64]paych.LaneState, laneCount)
|
||||||
laneStates := make(map[uint64]*paych.LaneState, lsamt.Length())
|
err = state.ForEachLaneState(func(idx uint64, ls paych.LaneState) error {
|
||||||
err = lsamt.ForEach(&ls, func(i int64) error {
|
laneStates[idx] = ls
|
||||||
current := ls
|
|
||||||
laneStates[uint64(i)] = ¤t
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -526,27 +531,19 @@ func (ca *channelAccessor) laneState(ctx context.Context, state *paych.State, ch
|
|||||||
// If there's a voucher for a lane that isn't in chain state just
|
// If there's a voucher for a lane that isn't in chain state just
|
||||||
// create it
|
// create it
|
||||||
ls, ok := laneStates[v.Voucher.Lane]
|
ls, ok := laneStates[v.Voucher.Lane]
|
||||||
if !ok {
|
|
||||||
ls = &paych.LaneState{
|
|
||||||
Redeemed: types.NewInt(0),
|
|
||||||
Nonce: 0,
|
|
||||||
}
|
|
||||||
laneStates[v.Voucher.Lane] = ls
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.Voucher.Nonce < ls.Nonce {
|
if ok && v.Voucher.Nonce < ls.Nonce() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
ls.Nonce = v.Voucher.Nonce
|
laneStates[v.Voucher.Lane] = laneState{v.Voucher.Amount, v.Voucher.Nonce}
|
||||||
ls.Redeemed = v.Voucher.Amount
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return laneStates, nil
|
return laneStates, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the total redeemed amount across all lanes, after applying the voucher
|
// Get the total redeemed amount across all lanes, after applying the voucher
|
||||||
func (ca *channelAccessor) totalRedeemedWithVoucher(laneStates map[uint64]*paych.LaneState, sv *paych.SignedVoucher) (big.Int, error) {
|
func (ca *channelAccessor) totalRedeemedWithVoucher(laneStates map[uint64]paych.LaneState, sv *v0paych.SignedVoucher) (big.Int, error) {
|
||||||
// TODO: merges
|
// TODO: merges
|
||||||
if len(sv.Merges) != 0 {
|
if len(sv.Merges) != 0 {
|
||||||
return big.Int{}, xerrors.Errorf("dont currently support paych lane merges")
|
return big.Int{}, xerrors.Errorf("dont currently support paych lane merges")
|
||||||
@ -554,17 +551,17 @@ func (ca *channelAccessor) totalRedeemedWithVoucher(laneStates map[uint64]*paych
|
|||||||
|
|
||||||
total := big.NewInt(0)
|
total := big.NewInt(0)
|
||||||
for _, ls := range laneStates {
|
for _, ls := range laneStates {
|
||||||
total = big.Add(total, ls.Redeemed)
|
total = big.Add(total, ls.Redeemed())
|
||||||
}
|
}
|
||||||
|
|
||||||
lane, ok := laneStates[sv.Lane]
|
lane, ok := laneStates[sv.Lane]
|
||||||
if ok {
|
if ok {
|
||||||
// If the voucher is for an existing lane, and the voucher nonce
|
// If the voucher is for an existing lane, and the voucher nonce
|
||||||
// is higher than the lane nonce
|
// is higher than the lane nonce
|
||||||
if sv.Nonce > lane.Nonce {
|
if sv.Nonce > lane.Nonce() {
|
||||||
// Add the delta between the redeemed amount and the voucher
|
// Add the delta between the redeemed amount and the voucher
|
||||||
// amount to the total
|
// amount to the total
|
||||||
delta := big.Sub(sv.Amount, lane.Redeemed)
|
delta := big.Sub(sv.Amount, lane.Redeemed())
|
||||||
total = big.Add(total, delta)
|
total = big.Add(total, delta)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -5,31 +5,24 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/util/adt"
|
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-state-types/crypto"
|
|
||||||
"github.com/filecoin-project/lotus/lib/sigs"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/go-state-types/big"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
|
||||||
tutils "github.com/filecoin-project/specs-actors/support/testing"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin/account"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
|
||||||
|
|
||||||
ds "github.com/ipfs/go-datastore"
|
ds "github.com/ipfs/go-datastore"
|
||||||
ds_sync "github.com/ipfs/go-datastore/sync"
|
ds_sync "github.com/ipfs/go-datastore/sync"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"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/crypto"
|
||||||
|
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||||
|
v0paych "github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
||||||
|
tutils "github.com/filecoin-project/specs-actors/support/testing"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/api"
|
||||||
|
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
|
||||||
|
paychmock "github.com/filecoin-project/lotus/chain/actors/builtin/paych/mock"
|
||||||
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
"github.com/filecoin-project/lotus/lib/sigs"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCheckVoucherValid(t *testing.T) {
|
func TestCheckVoucherValid(t *testing.T) {
|
||||||
@ -46,8 +39,8 @@ func TestCheckVoucherValid(t *testing.T) {
|
|||||||
toAcct := tutils.NewActorAddr(t, "toAct")
|
toAcct := tutils.NewActorAddr(t, "toAct")
|
||||||
|
|
||||||
mock := newMockManagerAPI()
|
mock := newMockManagerAPI()
|
||||||
mock.setAccountState(fromAcct, account.State{Address: from})
|
mock.setAccountAddress(fromAcct, from)
|
||||||
mock.setAccountState(toAcct, account.State{Address: to})
|
mock.setAccountAddress(toAcct, to)
|
||||||
|
|
||||||
tcases := []struct {
|
tcases := []struct {
|
||||||
name string
|
name string
|
||||||
@ -96,10 +89,7 @@ func TestCheckVoucherValid(t *testing.T) {
|
|||||||
voucherLane: 1,
|
voucherLane: 1,
|
||||||
voucherNonce: 2,
|
voucherNonce: 2,
|
||||||
laneStates: map[uint64]paych.LaneState{
|
laneStates: map[uint64]paych.LaneState{
|
||||||
1: {
|
1: paychmock.NewMockLaneState(big.NewInt(2), 3),
|
||||||
Redeemed: big.NewInt(2),
|
|
||||||
Nonce: 3,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
name: "passes when nonce higher",
|
name: "passes when nonce higher",
|
||||||
@ -110,10 +100,7 @@ func TestCheckVoucherValid(t *testing.T) {
|
|||||||
voucherLane: 1,
|
voucherLane: 1,
|
||||||
voucherNonce: 3,
|
voucherNonce: 3,
|
||||||
laneStates: map[uint64]paych.LaneState{
|
laneStates: map[uint64]paych.LaneState{
|
||||||
1: {
|
1: paychmock.NewMockLaneState(big.NewInt(2), 2),
|
||||||
Redeemed: big.NewInt(2),
|
|
||||||
Nonce: 2,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
name: "passes when nonce for different lane",
|
name: "passes when nonce for different lane",
|
||||||
@ -124,10 +111,7 @@ func TestCheckVoucherValid(t *testing.T) {
|
|||||||
voucherLane: 2,
|
voucherLane: 2,
|
||||||
voucherNonce: 2,
|
voucherNonce: 2,
|
||||||
laneStates: map[uint64]paych.LaneState{
|
laneStates: map[uint64]paych.LaneState{
|
||||||
1: {
|
1: paychmock.NewMockLaneState(big.NewInt(2), 3),
|
||||||
Redeemed: big.NewInt(2),
|
|
||||||
Nonce: 3,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
name: "fails when voucher has higher nonce but lower value than lane state",
|
name: "fails when voucher has higher nonce but lower value than lane state",
|
||||||
@ -139,10 +123,7 @@ func TestCheckVoucherValid(t *testing.T) {
|
|||||||
voucherLane: 1,
|
voucherLane: 1,
|
||||||
voucherNonce: 3,
|
voucherNonce: 3,
|
||||||
laneStates: map[uint64]paych.LaneState{
|
laneStates: map[uint64]paych.LaneState{
|
||||||
1: {
|
1: paychmock.NewMockLaneState(big.NewInt(6), 2),
|
||||||
Redeemed: big.NewInt(6),
|
|
||||||
Nonce: 2,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
name: "fails when voucher + ToSend > balance",
|
name: "fails when voucher + ToSend > balance",
|
||||||
@ -168,10 +149,7 @@ func TestCheckVoucherValid(t *testing.T) {
|
|||||||
voucherNonce: 2,
|
voucherNonce: 2,
|
||||||
laneStates: map[uint64]paych.LaneState{
|
laneStates: map[uint64]paych.LaneState{
|
||||||
// Lane 1 (same as voucher lane 1)
|
// Lane 1 (same as voucher lane 1)
|
||||||
1: {
|
1: paychmock.NewMockLaneState(big.NewInt(4), 1),
|
||||||
Redeemed: big.NewInt(4),
|
|
||||||
Nonce: 1,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
// required balance = toSend + total redeemed
|
// required balance = toSend + total redeemed
|
||||||
@ -188,10 +166,7 @@ func TestCheckVoucherValid(t *testing.T) {
|
|||||||
voucherNonce: 1,
|
voucherNonce: 1,
|
||||||
laneStates: map[uint64]paych.LaneState{
|
laneStates: map[uint64]paych.LaneState{
|
||||||
// Lane 2 (different from voucher lane 1)
|
// Lane 2 (different from voucher lane 1)
|
||||||
2: {
|
2: paychmock.NewMockLaneState(big.NewInt(4), 1),
|
||||||
Redeemed: big.NewInt(4),
|
|
||||||
Nonce: 1,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
|
|
||||||
@ -208,18 +183,8 @@ func TestCheckVoucherValid(t *testing.T) {
|
|||||||
Balance: tcase.actorBalance,
|
Balance: tcase.actorBalance,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the state of the channel's lanes
|
mock.setPaychState(ch, act, paychmock.NewMockPayChState(
|
||||||
laneStates, err := mock.storeLaneStates(tcase.laneStates)
|
fromAcct, toAcct, abi.ChainEpoch(0), tcase.toSend, tcase.laneStates))
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
mock.setPaychState(ch, act, paych.State{
|
|
||||||
From: fromAcct,
|
|
||||||
To: toAcct,
|
|
||||||
ToSend: tcase.toSend,
|
|
||||||
SettlingAt: abi.ChainEpoch(0),
|
|
||||||
MinSettleHeight: abi.ChainEpoch(0),
|
|
||||||
LaneStates: laneStates,
|
|
||||||
})
|
|
||||||
|
|
||||||
// Create a manager
|
// Create a manager
|
||||||
mgr, err := newManager(store, mock)
|
mgr, err := newManager(store, mock)
|
||||||
@ -255,22 +220,16 @@ func TestCheckVoucherValidCountingAllLanes(t *testing.T) {
|
|||||||
minDelta := big.NewInt(0)
|
minDelta := big.NewInt(0)
|
||||||
|
|
||||||
mock := newMockManagerAPI()
|
mock := newMockManagerAPI()
|
||||||
mock.setAccountState(fromAcct, account.State{Address: from})
|
mock.setAccountAddress(fromAcct, from)
|
||||||
mock.setAccountState(toAcct, account.State{Address: to})
|
mock.setAccountAddress(toAcct, to)
|
||||||
|
|
||||||
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
|
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
|
||||||
|
|
||||||
actorBalance := big.NewInt(10)
|
actorBalance := big.NewInt(10)
|
||||||
toSend := big.NewInt(1)
|
toSend := big.NewInt(1)
|
||||||
laneStates := map[uint64]paych.LaneState{
|
laneStates := map[uint64]paych.LaneState{
|
||||||
1: {
|
1: paychmock.NewMockLaneState(big.NewInt(3), 1),
|
||||||
Nonce: 1,
|
2: paychmock.NewMockLaneState(big.NewInt(4), 1),
|
||||||
Redeemed: big.NewInt(3),
|
|
||||||
},
|
|
||||||
2: {
|
|
||||||
Nonce: 1,
|
|
||||||
Redeemed: big.NewInt(4),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
act := &types.Actor{
|
act := &types.Actor{
|
||||||
@ -280,16 +239,7 @@ func TestCheckVoucherValidCountingAllLanes(t *testing.T) {
|
|||||||
Balance: actorBalance,
|
Balance: actorBalance,
|
||||||
}
|
}
|
||||||
|
|
||||||
lsCid, err := mock.storeLaneStates(laneStates)
|
mock.setPaychState(ch, act, paychmock.NewMockPayChState(fromAcct, toAcct, abi.ChainEpoch(0), toSend, laneStates))
|
||||||
require.NoError(t, err)
|
|
||||||
mock.setPaychState(ch, act, paych.State{
|
|
||||||
From: fromAcct,
|
|
||||||
To: toAcct,
|
|
||||||
ToSend: toSend,
|
|
||||||
SettlingAt: abi.ChainEpoch(0),
|
|
||||||
MinSettleHeight: abi.ChainEpoch(0),
|
|
||||||
LaneStates: lsCid,
|
|
||||||
})
|
|
||||||
|
|
||||||
mgr, err := newManager(store, mock)
|
mgr, err := newManager(store, mock)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -389,7 +339,7 @@ func TestCreateVoucher(t *testing.T) {
|
|||||||
|
|
||||||
// Create a voucher in lane 1
|
// Create a voucher in lane 1
|
||||||
voucherLane1Amt := big.NewInt(5)
|
voucherLane1Amt := big.NewInt(5)
|
||||||
voucher := paych.SignedVoucher{
|
voucher := v0paych.SignedVoucher{
|
||||||
Lane: 1,
|
Lane: 1,
|
||||||
Amount: voucherLane1Amt,
|
Amount: voucherLane1Amt,
|
||||||
}
|
}
|
||||||
@ -404,7 +354,7 @@ func TestCreateVoucher(t *testing.T) {
|
|||||||
|
|
||||||
// Create a voucher in lane 1 again, with a higher amount
|
// Create a voucher in lane 1 again, with a higher amount
|
||||||
voucherLane1Amt = big.NewInt(8)
|
voucherLane1Amt = big.NewInt(8)
|
||||||
voucher = paych.SignedVoucher{
|
voucher = v0paych.SignedVoucher{
|
||||||
Lane: 1,
|
Lane: 1,
|
||||||
Amount: voucherLane1Amt,
|
Amount: voucherLane1Amt,
|
||||||
}
|
}
|
||||||
@ -419,7 +369,7 @@ func TestCreateVoucher(t *testing.T) {
|
|||||||
// Create a voucher in lane 2 that covers all the remaining funds
|
// Create a voucher in lane 2 that covers all the remaining funds
|
||||||
// in the channel
|
// in the channel
|
||||||
voucherLane2Amt := big.Sub(s.amt, voucherLane1Amt)
|
voucherLane2Amt := big.Sub(s.amt, voucherLane1Amt)
|
||||||
voucher = paych.SignedVoucher{
|
voucher = v0paych.SignedVoucher{
|
||||||
Lane: 2,
|
Lane: 2,
|
||||||
Amount: voucherLane2Amt,
|
Amount: voucherLane2Amt,
|
||||||
}
|
}
|
||||||
@ -433,7 +383,7 @@ func TestCreateVoucher(t *testing.T) {
|
|||||||
// Create a voucher in lane 2 that exceeds the remaining funds in the
|
// Create a voucher in lane 2 that exceeds the remaining funds in the
|
||||||
// channel
|
// channel
|
||||||
voucherLane2Amt = big.Add(voucherLane2Amt, big.NewInt(1))
|
voucherLane2Amt = big.Add(voucherLane2Amt, big.NewInt(1))
|
||||||
voucher = paych.SignedVoucher{
|
voucher = v0paych.SignedVoucher{
|
||||||
Lane: 2,
|
Lane: 2,
|
||||||
Amount: voucherLane2Amt,
|
Amount: voucherLane2Amt,
|
||||||
}
|
}
|
||||||
@ -567,8 +517,8 @@ func TestAllocateLaneWithExistingLaneState(t *testing.T) {
|
|||||||
toAcct := tutils.NewActorAddr(t, "toAct")
|
toAcct := tutils.NewActorAddr(t, "toAct")
|
||||||
|
|
||||||
mock := newMockManagerAPI()
|
mock := newMockManagerAPI()
|
||||||
mock.setAccountState(fromAcct, account.State{Address: from})
|
mock.setAccountAddress(fromAcct, from)
|
||||||
mock.setAccountState(toAcct, account.State{Address: to})
|
mock.setAccountAddress(toAcct, to)
|
||||||
mock.addWalletAddress(to)
|
mock.addWalletAddress(to)
|
||||||
|
|
||||||
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
|
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
|
||||||
@ -584,16 +534,7 @@ func TestAllocateLaneWithExistingLaneState(t *testing.T) {
|
|||||||
Balance: actorBalance,
|
Balance: actorBalance,
|
||||||
}
|
}
|
||||||
|
|
||||||
arr, err := adt.MakeEmptyArray(mock.store).Root()
|
mock.setPaychState(ch, act, paychmock.NewMockPayChState(fromAcct, toAcct, abi.ChainEpoch(0), toSend, make(map[uint64]paych.LaneState)))
|
||||||
require.NoError(t, err)
|
|
||||||
mock.setPaychState(ch, act, paych.State{
|
|
||||||
From: fromAcct,
|
|
||||||
To: toAcct,
|
|
||||||
ToSend: toSend,
|
|
||||||
SettlingAt: abi.ChainEpoch(0),
|
|
||||||
MinSettleHeight: abi.ChainEpoch(0),
|
|
||||||
LaneStates: arr,
|
|
||||||
})
|
|
||||||
|
|
||||||
mgr, err := newManager(store, mock)
|
mgr, err := newManager(store, mock)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -681,19 +622,10 @@ func TestAddVoucherInboundWalletKey(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mock := newMockManagerAPI()
|
mock := newMockManagerAPI()
|
||||||
arr, err := adt.MakeEmptyArray(mock.store).Root()
|
mock.setAccountAddress(fromAcct, from)
|
||||||
require.NoError(t, err)
|
mock.setAccountAddress(toAcct, to)
|
||||||
mock.setAccountState(fromAcct, account.State{Address: from})
|
|
||||||
mock.setAccountState(toAcct, account.State{Address: to})
|
|
||||||
|
|
||||||
mock.setPaychState(ch, act, paych.State{
|
mock.setPaychState(ch, act, paychmock.NewMockPayChState(fromAcct, toAcct, abi.ChainEpoch(0), types.NewInt(0), make(map[uint64]paych.LaneState)))
|
||||||
From: fromAcct,
|
|
||||||
To: toAcct,
|
|
||||||
ToSend: types.NewInt(0),
|
|
||||||
SettlingAt: abi.ChainEpoch(0),
|
|
||||||
MinSettleHeight: abi.ChainEpoch(0),
|
|
||||||
LaneStates: arr,
|
|
||||||
})
|
|
||||||
|
|
||||||
// Create a manager
|
// Create a manager
|
||||||
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
|
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
|
||||||
@ -840,7 +772,7 @@ func TestCheckSpendable(t *testing.T) {
|
|||||||
|
|
||||||
// Check that the secret and proof were passed through correctly
|
// Check that the secret and proof were passed through correctly
|
||||||
lastCall := s.mock.getLastCall()
|
lastCall := s.mock.getLastCall()
|
||||||
var p paych.UpdateChannelStateParams
|
var p v0paych.UpdateChannelStateParams
|
||||||
err = p.UnmarshalCBOR(bytes.NewReader(lastCall.Params))
|
err = p.UnmarshalCBOR(bytes.NewReader(lastCall.Params))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, otherProof, p.Proof)
|
require.Equal(t, otherProof, p.Proof)
|
||||||
@ -854,7 +786,7 @@ func TestCheckSpendable(t *testing.T) {
|
|||||||
require.True(t, spendable)
|
require.True(t, spendable)
|
||||||
|
|
||||||
lastCall = s.mock.getLastCall()
|
lastCall = s.mock.getLastCall()
|
||||||
var p2 paych.UpdateChannelStateParams
|
var p2 v0paych.UpdateChannelStateParams
|
||||||
err = p2.UnmarshalCBOR(bytes.NewReader(lastCall.Params))
|
err = p2.UnmarshalCBOR(bytes.NewReader(lastCall.Params))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, proof, p2.Proof)
|
require.Equal(t, proof, p2.Proof)
|
||||||
@ -911,7 +843,7 @@ func TestSubmitVoucher(t *testing.T) {
|
|||||||
|
|
||||||
// Check that the secret and proof were passed through correctly
|
// Check that the secret and proof were passed through correctly
|
||||||
msg := s.mock.pushedMessages(submitCid)
|
msg := s.mock.pushedMessages(submitCid)
|
||||||
var p paych.UpdateChannelStateParams
|
var p v0paych.UpdateChannelStateParams
|
||||||
err = p.UnmarshalCBOR(bytes.NewReader(msg.Message.Params))
|
err = p.UnmarshalCBOR(bytes.NewReader(msg.Message.Params))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, submitProof, p.Proof)
|
require.Equal(t, submitProof, p.Proof)
|
||||||
@ -931,7 +863,7 @@ func TestSubmitVoucher(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
msg = s.mock.pushedMessages(submitCid)
|
msg = s.mock.pushedMessages(submitCid)
|
||||||
var p2 paych.UpdateChannelStateParams
|
var p2 v0paych.UpdateChannelStateParams
|
||||||
err = p2.UnmarshalCBOR(bytes.NewReader(msg.Message.Params))
|
err = p2.UnmarshalCBOR(bytes.NewReader(msg.Message.Params))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, addVoucherProof2, p2.Proof)
|
require.Equal(t, addVoucherProof2, p2.Proof)
|
||||||
@ -947,7 +879,7 @@ func TestSubmitVoucher(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
msg = s.mock.pushedMessages(submitCid)
|
msg = s.mock.pushedMessages(submitCid)
|
||||||
var p3 paych.UpdateChannelStateParams
|
var p3 v0paych.UpdateChannelStateParams
|
||||||
err = p3.UnmarshalCBOR(bytes.NewReader(msg.Message.Params))
|
err = p3.UnmarshalCBOR(bytes.NewReader(msg.Message.Params))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, proof3, p3.Proof)
|
require.Equal(t, proof3, p3.Proof)
|
||||||
@ -986,10 +918,8 @@ func testSetupMgrWithChannel(ctx context.Context, t *testing.T) *testScaffold {
|
|||||||
toAcct := tutils.NewActorAddr(t, "toAct")
|
toAcct := tutils.NewActorAddr(t, "toAct")
|
||||||
|
|
||||||
mock := newMockManagerAPI()
|
mock := newMockManagerAPI()
|
||||||
arr, err := adt.MakeEmptyArray(mock.store).Root()
|
mock.setAccountAddress(fromAcct, from)
|
||||||
require.NoError(t, err)
|
mock.setAccountAddress(toAcct, to)
|
||||||
mock.setAccountState(fromAcct, account.State{Address: from})
|
|
||||||
mock.setAccountState(toAcct, account.State{Address: to})
|
|
||||||
|
|
||||||
// Create channel in state
|
// Create channel in state
|
||||||
balance := big.NewInt(20)
|
balance := big.NewInt(20)
|
||||||
@ -999,14 +929,7 @@ func testSetupMgrWithChannel(ctx context.Context, t *testing.T) *testScaffold {
|
|||||||
Nonce: 0,
|
Nonce: 0,
|
||||||
Balance: balance,
|
Balance: balance,
|
||||||
}
|
}
|
||||||
mock.setPaychState(ch, act, paych.State{
|
mock.setPaychState(ch, act, paychmock.NewMockPayChState(fromAcct, toAcct, abi.ChainEpoch(0), big.NewInt(0), make(map[uint64]paych.LaneState)))
|
||||||
From: fromAcct,
|
|
||||||
To: toAcct,
|
|
||||||
ToSend: big.NewInt(0),
|
|
||||||
SettlingAt: abi.ChainEpoch(0),
|
|
||||||
MinSettleHeight: abi.ChainEpoch(0),
|
|
||||||
LaneStates: arr,
|
|
||||||
})
|
|
||||||
|
|
||||||
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
|
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
|
||||||
mgr, err := newManager(store, mock)
|
mgr, err := newManager(store, mock)
|
||||||
@ -1043,8 +966,8 @@ func testGenerateKeyPair(t *testing.T) ([]byte, []byte) {
|
|||||||
return priv, pub
|
return priv, pub
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTestVoucher(t *testing.T, ch address.Address, voucherLane uint64, nonce uint64, voucherAmount big.Int, key []byte) *paych.SignedVoucher {
|
func createTestVoucher(t *testing.T, ch address.Address, voucherLane uint64, nonce uint64, voucherAmount big.Int, key []byte) *v0paych.SignedVoucher {
|
||||||
sv := &paych.SignedVoucher{
|
sv := &v0paych.SignedVoucher{
|
||||||
ChannelAddr: ch,
|
ChannelAddr: ch,
|
||||||
Lane: voucherLane,
|
Lane: voucherLane,
|
||||||
Nonce: nonce,
|
Nonce: nonce,
|
||||||
@ -1059,13 +982,13 @@ func createTestVoucher(t *testing.T, ch address.Address, voucherLane uint64, non
|
|||||||
return sv
|
return sv
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTestVoucherWithExtra(t *testing.T, ch address.Address, voucherLane uint64, nonce uint64, voucherAmount big.Int, key []byte) *paych.SignedVoucher {
|
func createTestVoucherWithExtra(t *testing.T, ch address.Address, voucherLane uint64, nonce uint64, voucherAmount big.Int, key []byte) *v0paych.SignedVoucher {
|
||||||
sv := &paych.SignedVoucher{
|
sv := &v0paych.SignedVoucher{
|
||||||
ChannelAddr: ch,
|
ChannelAddr: ch,
|
||||||
Lane: voucherLane,
|
Lane: voucherLane,
|
||||||
Nonce: nonce,
|
Nonce: nonce,
|
||||||
Amount: voucherAmount,
|
Amount: voucherAmount,
|
||||||
Extra: &paych.ModVerifyParams{
|
Extra: &v0paych.ModVerifyParams{
|
||||||
Actor: tutils.NewActorAddr(t, "act"),
|
Actor: tutils.NewActorAddr(t, "act"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -1083,13 +1006,13 @@ type mockBestSpendableAPI struct {
|
|||||||
mgr *Manager
|
mgr *Manager
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockBestSpendableAPI) PaychVoucherList(ctx context.Context, ch address.Address) ([]*paych.SignedVoucher, error) {
|
func (m *mockBestSpendableAPI) PaychVoucherList(ctx context.Context, ch address.Address) ([]*v0paych.SignedVoucher, error) {
|
||||||
vi, err := m.mgr.ListVouchers(ctx, ch)
|
vi, err := m.mgr.ListVouchers(ctx, ch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
out := make([]*paych.SignedVoucher, len(vi))
|
out := make([]*v0paych.SignedVoucher, len(vi))
|
||||||
for k, v := range vi {
|
for k, v := range vi {
|
||||||
out[k] = v.Voucher
|
out[k] = v.Voucher
|
||||||
}
|
}
|
||||||
@ -1097,7 +1020,7 @@ func (m *mockBestSpendableAPI) PaychVoucherList(ctx context.Context, ch address.
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockBestSpendableAPI) PaychVoucherCheckSpendable(ctx context.Context, ch address.Address, voucher *paych.SignedVoucher, secret []byte, proof []byte) (bool, error) {
|
func (m *mockBestSpendableAPI) PaychVoucherCheckSpendable(ctx context.Context, ch address.Address, voucher *v0paych.SignedVoucher, secret []byte, proof []byte) (bool, error) {
|
||||||
return m.mgr.CheckVoucherSpendable(ctx, ch, voucher, secret, proof)
|
return m.mgr.CheckVoucherSpendable(ctx, ch, voucher, secret, proof)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,29 +6,22 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin/account"
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/util/adt"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
|
||||||
|
|
||||||
cborrpc "github.com/filecoin-project/go-cbor-util"
|
cborrpc "github.com/filecoin-project/go-cbor-util"
|
||||||
|
|
||||||
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/go-state-types/big"
|
|
||||||
tutils "github.com/filecoin-project/specs-actors/support/testing"
|
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
ds "github.com/ipfs/go-datastore"
|
ds "github.com/ipfs/go-datastore"
|
||||||
ds_sync "github.com/ipfs/go-datastore/sync"
|
ds_sync "github.com/ipfs/go-datastore/sync"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"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/specs-actors/actors/builtin"
|
||||||
|
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
|
||||||
|
tutils "github.com/filecoin-project/specs-actors/support/testing"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
|
||||||
|
paychmock "github.com/filecoin-project/lotus/chain/actors/builtin/paych/mock"
|
||||||
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func testChannelResponse(t *testing.T, ch address.Address) types.MessageReceipt {
|
func testChannelResponse(t *testing.T, ch address.Address) types.MessageReceipt {
|
||||||
@ -976,25 +969,15 @@ func TestPaychAvailableFunds(t *testing.T) {
|
|||||||
require.EqualValues(t, 0, av.VoucherReedeemedAmt.Int64())
|
require.EqualValues(t, 0, av.VoucherReedeemedAmt.Int64())
|
||||||
|
|
||||||
// Create channel in state
|
// Create channel in state
|
||||||
arr, err := adt.MakeEmptyArray(mock.store).Root()
|
mock.setAccountAddress(fromAcct, from)
|
||||||
require.NoError(t, err)
|
mock.setAccountAddress(toAcct, to)
|
||||||
mock.setAccountState(fromAcct, account.State{Address: from})
|
|
||||||
mock.setAccountState(toAcct, account.State{Address: to})
|
|
||||||
act := &types.Actor{
|
act := &types.Actor{
|
||||||
Code: builtin.AccountActorCodeID,
|
Code: builtin.AccountActorCodeID,
|
||||||
Head: cid.Cid{},
|
Head: cid.Cid{},
|
||||||
Nonce: 0,
|
Nonce: 0,
|
||||||
Balance: createAmt,
|
Balance: createAmt,
|
||||||
}
|
}
|
||||||
mock.setPaychState(ch, act, paych.State{
|
mock.setPaychState(ch, act, paychmock.NewMockPayChState(fromAcct, toAcct, abi.ChainEpoch(0), big.NewInt(0), make(map[uint64]paych.LaneState)))
|
||||||
From: fromAcct,
|
|
||||||
To: toAcct,
|
|
||||||
ToSend: big.NewInt(0),
|
|
||||||
SettlingAt: abi.ChainEpoch(0),
|
|
||||||
MinSettleHeight: abi.ChainEpoch(0),
|
|
||||||
LaneStates: arr,
|
|
||||||
})
|
|
||||||
|
|
||||||
// Send create channel response
|
// Send create channel response
|
||||||
response := testChannelResponse(t, ch)
|
response := testChannelResponse(t, ch)
|
||||||
mock.receiveMsgResponse(createMsgCid, response)
|
mock.receiveMsgResponse(createMsgCid, response)
|
||||||
|
@ -6,20 +6,17 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
|
||||||
|
|
||||||
"golang.org/x/sync/errgroup"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/go-state-types/big"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
|
||||||
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
"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/big"
|
||||||
|
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||||
|
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
|
||||||
|
v0paych "github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/api"
|
||||||
"github.com/filecoin-project/lotus/build"
|
"github.com/filecoin-project/lotus/build"
|
||||||
"github.com/filecoin-project/lotus/chain/actors"
|
"github.com/filecoin-project/lotus/chain/actors"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
@ -320,7 +317,7 @@ func (ca *channelAccessor) currentAvailableFunds(channelID string, queuedAmt typ
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, ls := range laneStates {
|
for _, ls := range laneStates {
|
||||||
totalRedeemed = types.BigAdd(totalRedeemed, ls.Redeemed)
|
totalRedeemed = types.BigAdd(totalRedeemed, ls.Redeemed())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,7 +382,7 @@ func (ca *channelAccessor) processTask(ctx context.Context, amt types.BigInt) *p
|
|||||||
|
|
||||||
// createPaych sends a message to create the channel and returns the message cid
|
// createPaych sends a message to create the channel and returns the message cid
|
||||||
func (ca *channelAccessor) createPaych(ctx context.Context, amt types.BigInt) (cid.Cid, error) {
|
func (ca *channelAccessor) createPaych(ctx context.Context, amt types.BigInt) (cid.Cid, error) {
|
||||||
params, aerr := actors.SerializeParams(&paych.ConstructorParams{From: ca.from, To: ca.to})
|
params, aerr := actors.SerializeParams(&v0paych.ConstructorParams{From: ca.from, To: ca.to})
|
||||||
if aerr != nil {
|
if aerr != nil {
|
||||||
return cid.Undef, aerr
|
return cid.Undef, aerr
|
||||||
}
|
}
|
||||||
|
@ -3,13 +3,9 @@ package paychmgr
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/util/adt"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin/account"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -17,14 +13,8 @@ type stateAccessor struct {
|
|||||||
sm stateManagerAPI
|
sm stateManagerAPI
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ca *stateAccessor) loadPaychActorState(ctx context.Context, ch address.Address) (*types.Actor, *paych.State, error) {
|
func (ca *stateAccessor) loadPaychActorState(ctx context.Context, ch address.Address) (*types.Actor, paych.State, error) {
|
||||||
var pcast paych.State
|
return ca.sm.GetPaychState(ctx, ch, nil)
|
||||||
act, err := ca.sm.LoadActorState(ctx, ch, &pcast, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return act, &pcast, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ca *stateAccessor) loadStateChannelInfo(ctx context.Context, ch address.Address, dir uint64) (*ChannelInfo, error) {
|
func (ca *stateAccessor) loadStateChannelInfo(ctx context.Context, ch address.Address, dir uint64) (*ChannelInfo, error) {
|
||||||
@ -33,17 +23,15 @@ func (ca *stateAccessor) loadStateChannelInfo(ctx context.Context, ch address.Ad
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var account account.State
|
// Load channel "From" account actor state
|
||||||
_, err = ca.sm.LoadActorState(ctx, st.From, &account, nil)
|
from, err := ca.sm.ResolveToKeyAddress(ctx, st.From(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
from := account.Address
|
to, err := ca.sm.ResolveToKeyAddress(ctx, st.To(), nil)
|
||||||
_, err = ca.sm.LoadActorState(ctx, st.To, &account, nil)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
to := account.Address
|
|
||||||
|
|
||||||
nextLane, err := ca.nextLaneFromState(ctx, st)
|
nextLane, err := ca.nextLaneFromState(ctx, st)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -67,25 +55,24 @@ func (ca *stateAccessor) loadStateChannelInfo(ctx context.Context, ch address.Ad
|
|||||||
return ci, nil
|
return ci, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ca *stateAccessor) nextLaneFromState(ctx context.Context, st *paych.State) (uint64, error) {
|
func (ca *stateAccessor) nextLaneFromState(ctx context.Context, st paych.State) (uint64, error) {
|
||||||
store := ca.sm.AdtStore(ctx)
|
laneCount, err := st.LaneCount()
|
||||||
laneStates, err := adt.AsArray(store, st.LaneStates)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
if laneStates.Length() == 0 {
|
if laneCount == 0 {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
maxID := int64(0)
|
maxID := uint64(0)
|
||||||
if err := laneStates.ForEach(nil, func(i int64) error {
|
if err := st.ForEachLaneState(func(idx uint64, _ paych.LaneState) error {
|
||||||
if i > maxID {
|
if idx > maxID {
|
||||||
maxID = i
|
maxID = idx
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return uint64(maxID + 1), nil
|
return maxID + 1, nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user