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-state-types/abi"
|
||||
"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"
|
||||
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/market"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
||||
"github.com/filecoin-project/specs-actors/actors/util/adt"
|
||||
"github.com/ipfs/go-cid"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
typegen "github.com/whyrusleeping/cbor-gen"
|
||||
|
||||
@ -49,7 +48,7 @@ func NewStatePredicates(api ChainAPI) *StatePredicates {
|
||||
// - err
|
||||
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
|
||||
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) {
|
||||
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
|
||||
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
|
||||
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
|
||||
}
|
||||
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 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)
|
||||
|
||||
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
|
||||
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
|
||||
}
|
||||
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 diffInitActorState(ctx, &oldState, &newState)
|
||||
@ -423,13 +422,13 @@ func (sp *StatePredicates) OnInitActorChange(diffInitActorState DiffInitActorSta
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
}
|
||||
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 diffMinerActorState(ctx, &oldState, &newState)
|
||||
@ -608,20 +607,20 @@ func (sp *StatePredicates) OnMinerPreCommitChange() DiffMinerActorStateFunc {
|
||||
}
|
||||
|
||||
// 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
|
||||
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) {
|
||||
var oldState paych.State
|
||||
if err := sp.cst.Get(ctx, oldActorStateHead, &oldState); err != nil {
|
||||
return sp.OnActorStateChanged(paychAddr, func(ctx context.Context, oldActorState, newActorState *types.Actor) (changed bool, user UserData, err error) {
|
||||
oldState, err := paych.Load(adt.WrapStore(ctx, sp.cst), oldActorState)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
var newState paych.State
|
||||
if err := sp.cst.Get(ctx, newActorStateHead, &newState); err != nil {
|
||||
newState, err := paych.Load(adt.WrapStore(ctx, sp.cst), newActorState)
|
||||
if err != nil {
|
||||
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
|
||||
func (sp *StatePredicates) OnToSendAmountChanges() DiffPaymentChannelStateFunc {
|
||||
return func(ctx context.Context, oldState *paych.State, newState *paych.State) (changed bool, user UserData, err error) {
|
||||
if oldState.ToSend.Equals(newState.ToSend) {
|
||||
return func(ctx context.Context, oldState paych.State, newState paych.State) (changed bool, user UserData, err error) {
|
||||
if oldState.ToSend().Equals(newState.ToSend()) {
|
||||
return false, nil, nil
|
||||
}
|
||||
return true, &PayChToSendChange{
|
||||
OldToSend: oldState.ToSend,
|
||||
NewToSend: newState.ToSend,
|
||||
OldToSend: oldState.ToSend(),
|
||||
NewToSend: newState.ToSend(),
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
@ -221,7 +221,7 @@ func TestMarketPredicates(t *testing.T) {
|
||||
// Test that OnActorStateChanged does not call the callback if the state has not changed
|
||||
mockAddr, err := address.NewFromString("t01")
|
||||
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")
|
||||
return false, nil, nil
|
||||
})
|
||||
|
@ -25,6 +25,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"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/state"
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
@ -1145,3 +1146,21 @@ func (sm *StateManager) GetNtwkVersion(ctx context.Context, height abi.ChainEpoc
|
||||
|
||||
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/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"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
@ -88,7 +89,7 @@ func TestPaymentChannels(t *testing.T) {
|
||||
|
||||
// Wait for the chain to reach the settle height
|
||||
chState := getPaychState(ctx, t, paymentReceiver, chAddr)
|
||||
waitForHeight(ctx, t, paymentReceiver, chState.SettlingAt)
|
||||
waitForHeight(ctx, t, paymentReceiver, chState.SettlingAt())
|
||||
|
||||
// receiver: paych collect <channel>
|
||||
cmd = []string{chAddr.String()}
|
||||
@ -540,8 +541,7 @@ func getPaychState(ctx context.Context, t *testing.T, node test.TestNode, chAddr
|
||||
require.NoError(t, err)
|
||||
|
||||
store := cbor.NewCborStore(apibstore.NewAPIBlockstore(node))
|
||||
var chState paych.State
|
||||
err = store.Get(ctx, act.Head, &chState)
|
||||
chState, err := paych.Load(adt.WrapStore(ctx, store), act)
|
||||
require.NoError(t, err)
|
||||
|
||||
return chState
|
||||
|
@ -4,28 +4,23 @@ import (
|
||||
"context"
|
||||
"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-datastore"
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
"go.uber.org/fx"
|
||||
xerrors "golang.org/x/xerrors"
|
||||
|
||||
"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/types"
|
||||
"github.com/filecoin-project/lotus/node/impl/full"
|
||||
"github.com/filecoin-project/lotus/node/modules/helpers"
|
||||
)
|
||||
|
||||
var log = logging.Logger("paych")
|
||||
@ -40,9 +35,9 @@ type PaychAPI struct {
|
||||
|
||||
// stateManagerAPI defines the methods needed from StateManager
|
||||
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)
|
||||
AdtStore(ctx context.Context) adt.Store
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
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)
|
||||
if err != nil {
|
||||
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).
|
||||
// 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).
|
||||
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
|
||||
ca, err := pm.inboundChannelAccessor(ctx, ch)
|
||||
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
|
||||
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)
|
||||
if err != nil {
|
||||
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.
|
||||
// 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)
|
||||
if err != nil {
|
||||
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.
|
||||
// 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).
|
||||
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
|
||||
ca, err := pm.inboundChannelAccessor(ctx, ch)
|
||||
if err != nil {
|
||||
@ -341,7 +336,7 @@ func (pm *Manager) trackInboundChannel(ctx context.Context, ch address.Address)
|
||||
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)
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
|
@ -2,23 +2,18 @@ package paychmgr
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"errors"
|
||||
"sync"
|
||||
|
||||
"github.com/filecoin-project/lotus/lib/sigs"
|
||||
|
||||
"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/ipfs/go-cid"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/account"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/filecoin-project/lotus/lib/sigs"
|
||||
)
|
||||
|
||||
type mockManagerAPI struct {
|
||||
@ -40,29 +35,23 @@ type mockPchState struct {
|
||||
|
||||
type mockStateManager struct {
|
||||
lk sync.Mutex
|
||||
accountState map[address.Address]account.State
|
||||
accountState map[address.Address]address.Address
|
||||
paychState map[address.Address]mockPchState
|
||||
store adt.Store
|
||||
response *api.InvocResult
|
||||
lastCall *types.Message
|
||||
}
|
||||
|
||||
func newMockStateManager() *mockStateManager {
|
||||
return &mockStateManager{
|
||||
accountState: make(map[address.Address]account.State),
|
||||
accountState: make(map[address.Address]address.Address),
|
||||
paychState: make(map[address.Address]mockPchState),
|
||||
store: adt.WrapStore(context.Background(), cbornode.NewMemCborStore()),
|
||||
}
|
||||
}
|
||||
|
||||
func (sm *mockStateManager) AdtStore(ctx context.Context) adt.Store {
|
||||
return sm.store
|
||||
}
|
||||
|
||||
func (sm *mockStateManager) setAccountState(a address.Address, state account.State) {
|
||||
func (sm *mockStateManager) setAccountAddress(a address.Address, lookup address.Address) {
|
||||
sm.lk.Lock()
|
||||
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) {
|
||||
@ -71,31 +60,24 @@ func (sm *mockStateManager) setPaychState(a address.Address, actor *types.Actor,
|
||||
sm.paychState[a] = mockPchState{actor, state}
|
||||
}
|
||||
|
||||
func (sm *mockStateManager) storeLaneStates(laneStates map[uint64]paych.LaneState) (cid.Cid, 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) {
|
||||
func (sm *mockStateManager) ResolveToKeyAddress(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
|
||||
sm.lk.Lock()
|
||||
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 {
|
||||
*outState = sm.accountState[a]
|
||||
return nil, nil
|
||||
func (sm *mockStateManager) GetPaychState(ctx context.Context, addr address.Address, ts *types.TipSet) (*types.Actor, paych.State, error) {
|
||||
sm.lk.Lock()
|
||||
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 {
|
||||
info := sm.paychState[a]
|
||||
*outState = info.state
|
||||
return info.actor, nil
|
||||
}
|
||||
panic(fmt.Sprintf("unexpected state type %v", out))
|
||||
return info.actor, info.state, nil
|
||||
}
|
||||
|
||||
func (sm *mockStateManager) setCallResponse(response *api.InvocResult) {
|
||||
|
@ -4,9 +4,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
|
@ -5,22 +5,20 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/util/adt"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
cborutil "github.com/filecoin-project/go-cbor-util"
|
||||
"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/builtin/paych"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"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
|
||||
@ -45,6 +43,19 @@ func (e *ErrInsufficientFunds) Shortfall() types.BigInt {
|
||||
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
|
||||
type channelAccessor struct {
|
||||
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.
|
||||
// If there are not enough funds in the channel to create the voucher, returns
|
||||
// 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()
|
||||
defer ca.lk.Unlock()
|
||||
|
||||
@ -151,14 +162,14 @@ func (ca *channelAccessor) nextNonceForLane(ci *ChannelInfo, lane uint64) uint64
|
||||
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()
|
||||
defer ca.lk.Unlock()
|
||||
|
||||
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 {
|
||||
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
|
||||
var actState account.State
|
||||
_, err = ca.api.LoadActorState(ctx, pchState.From, &actState, nil)
|
||||
from, err := ca.api.ResolveToKeyAddress(ctx, pchState.From(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
from := actState.Address
|
||||
|
||||
// verify voucher signature
|
||||
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
|
||||
// nonce for the 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")
|
||||
}
|
||||
|
||||
// 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")
|
||||
}
|
||||
|
||||
@ -230,7 +239,7 @@ func (ca *channelAccessor) checkVoucherValidUnlocked(ctx context.Context, ch add
|
||||
|
||||
// Total required balance = total redeemed + toSend
|
||||
// Must not exceed actor balance
|
||||
newTotal := types.BigAdd(totalRedeemed, pchState.ToSend)
|
||||
newTotal := types.BigAdd(totalRedeemed, pchState.ToSend())
|
||||
if act.Balance.LessThan(newTotal) {
|
||||
return nil, newErrInsufficientFunds(types.BigSub(newTotal, act.Balance))
|
||||
}
|
||||
@ -242,7 +251,7 @@ func (ca *channelAccessor) checkVoucherValidUnlocked(ctx context.Context, ch add
|
||||
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()
|
||||
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,
|
||||
Secret: secret,
|
||||
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) {
|
||||
var state paych.State
|
||||
if _, err := ca.api.LoadActorState(ctx, ch, &state, nil); err != nil {
|
||||
_, state, err := ca.api.GetPaychState(ctx, ch, nil)
|
||||
if err != nil {
|
||||
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()
|
||||
defer ca.lk.Unlock()
|
||||
|
||||
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)
|
||||
if err != nil {
|
||||
return types.BigInt{}, err
|
||||
@ -367,7 +376,7 @@ func (ca *channelAccessor) addVoucherUnlocked(ctx context.Context, ch address.Ad
|
||||
laneState, exists := laneStates[sv.Lane]
|
||||
redeemed := big.NewInt(0)
|
||||
if exists {
|
||||
redeemed = laneState.Redeemed
|
||||
redeemed = laneState.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)
|
||||
}
|
||||
|
||||
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()
|
||||
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,
|
||||
Secret: secret,
|
||||
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
|
||||
// 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
|
||||
// (but technically dont't need to)
|
||||
|
||||
// Get the lane state from the chain
|
||||
store := ca.api.AdtStore(ctx)
|
||||
lsamt, err := adt.AsArray(store, state.LaneStates)
|
||||
laneCount, err := state.LaneCount()
|
||||
if err != nil {
|
||||
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
|
||||
// client sets the lane ID (the index) and potentially they could use a
|
||||
// very large index.
|
||||
var ls paych.LaneState
|
||||
laneStates := make(map[uint64]*paych.LaneState, lsamt.Length())
|
||||
err = lsamt.ForEach(&ls, func(i int64) error {
|
||||
current := ls
|
||||
laneStates[uint64(i)] = ¤t
|
||||
laneStates := make(map[uint64]paych.LaneState, laneCount)
|
||||
err = state.ForEachLaneState(func(idx uint64, ls paych.LaneState) error {
|
||||
laneStates[idx] = ls
|
||||
return 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
|
||||
// create it
|
||||
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
|
||||
}
|
||||
|
||||
ls.Nonce = v.Voucher.Nonce
|
||||
ls.Redeemed = v.Voucher.Amount
|
||||
laneStates[v.Voucher.Lane] = laneState{v.Voucher.Amount, v.Voucher.Nonce}
|
||||
}
|
||||
|
||||
return laneStates, nil
|
||||
}
|
||||
|
||||
// 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
|
||||
if len(sv.Merges) != 0 {
|
||||
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)
|
||||
for _, ls := range laneStates {
|
||||
total = big.Add(total, ls.Redeemed)
|
||||
total = big.Add(total, ls.Redeemed())
|
||||
}
|
||||
|
||||
lane, ok := laneStates[sv.Lane]
|
||||
if ok {
|
||||
// If the voucher is for an existing lane, and the voucher 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
|
||||
// amount to the total
|
||||
delta := big.Sub(sv.Amount, lane.Redeemed)
|
||||
delta := big.Sub(sv.Amount, lane.Redeemed())
|
||||
total = big.Add(total, delta)
|
||||
}
|
||||
} else {
|
||||
|
@ -5,31 +5,24 @@ import (
|
||||
"context"
|
||||
"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/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_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) {
|
||||
@ -46,8 +39,8 @@ func TestCheckVoucherValid(t *testing.T) {
|
||||
toAcct := tutils.NewActorAddr(t, "toAct")
|
||||
|
||||
mock := newMockManagerAPI()
|
||||
mock.setAccountState(fromAcct, account.State{Address: from})
|
||||
mock.setAccountState(toAcct, account.State{Address: to})
|
||||
mock.setAccountAddress(fromAcct, from)
|
||||
mock.setAccountAddress(toAcct, to)
|
||||
|
||||
tcases := []struct {
|
||||
name string
|
||||
@ -96,10 +89,7 @@ func TestCheckVoucherValid(t *testing.T) {
|
||||
voucherLane: 1,
|
||||
voucherNonce: 2,
|
||||
laneStates: map[uint64]paych.LaneState{
|
||||
1: {
|
||||
Redeemed: big.NewInt(2),
|
||||
Nonce: 3,
|
||||
},
|
||||
1: paychmock.NewMockLaneState(big.NewInt(2), 3),
|
||||
},
|
||||
}, {
|
||||
name: "passes when nonce higher",
|
||||
@ -110,10 +100,7 @@ func TestCheckVoucherValid(t *testing.T) {
|
||||
voucherLane: 1,
|
||||
voucherNonce: 3,
|
||||
laneStates: map[uint64]paych.LaneState{
|
||||
1: {
|
||||
Redeemed: big.NewInt(2),
|
||||
Nonce: 2,
|
||||
},
|
||||
1: paychmock.NewMockLaneState(big.NewInt(2), 2),
|
||||
},
|
||||
}, {
|
||||
name: "passes when nonce for different lane",
|
||||
@ -124,10 +111,7 @@ func TestCheckVoucherValid(t *testing.T) {
|
||||
voucherLane: 2,
|
||||
voucherNonce: 2,
|
||||
laneStates: map[uint64]paych.LaneState{
|
||||
1: {
|
||||
Redeemed: big.NewInt(2),
|
||||
Nonce: 3,
|
||||
},
|
||||
1: paychmock.NewMockLaneState(big.NewInt(2), 3),
|
||||
},
|
||||
}, {
|
||||
name: "fails when voucher has higher nonce but lower value than lane state",
|
||||
@ -139,10 +123,7 @@ func TestCheckVoucherValid(t *testing.T) {
|
||||
voucherLane: 1,
|
||||
voucherNonce: 3,
|
||||
laneStates: map[uint64]paych.LaneState{
|
||||
1: {
|
||||
Redeemed: big.NewInt(6),
|
||||
Nonce: 2,
|
||||
},
|
||||
1: paychmock.NewMockLaneState(big.NewInt(6), 2),
|
||||
},
|
||||
}, {
|
||||
name: "fails when voucher + ToSend > balance",
|
||||
@ -168,10 +149,7 @@ func TestCheckVoucherValid(t *testing.T) {
|
||||
voucherNonce: 2,
|
||||
laneStates: map[uint64]paych.LaneState{
|
||||
// Lane 1 (same as voucher lane 1)
|
||||
1: {
|
||||
Redeemed: big.NewInt(4),
|
||||
Nonce: 1,
|
||||
},
|
||||
1: paychmock.NewMockLaneState(big.NewInt(4), 1),
|
||||
},
|
||||
}, {
|
||||
// required balance = toSend + total redeemed
|
||||
@ -188,10 +166,7 @@ func TestCheckVoucherValid(t *testing.T) {
|
||||
voucherNonce: 1,
|
||||
laneStates: map[uint64]paych.LaneState{
|
||||
// Lane 2 (different from voucher lane 1)
|
||||
2: {
|
||||
Redeemed: big.NewInt(4),
|
||||
Nonce: 1,
|
||||
},
|
||||
2: paychmock.NewMockLaneState(big.NewInt(4), 1),
|
||||
},
|
||||
}}
|
||||
|
||||
@ -208,18 +183,8 @@ func TestCheckVoucherValid(t *testing.T) {
|
||||
Balance: tcase.actorBalance,
|
||||
}
|
||||
|
||||
// Set the state of the channel's lanes
|
||||
laneStates, err := mock.storeLaneStates(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,
|
||||
})
|
||||
mock.setPaychState(ch, act, paychmock.NewMockPayChState(
|
||||
fromAcct, toAcct, abi.ChainEpoch(0), tcase.toSend, tcase.laneStates))
|
||||
|
||||
// Create a manager
|
||||
mgr, err := newManager(store, mock)
|
||||
@ -255,22 +220,16 @@ func TestCheckVoucherValidCountingAllLanes(t *testing.T) {
|
||||
minDelta := big.NewInt(0)
|
||||
|
||||
mock := newMockManagerAPI()
|
||||
mock.setAccountState(fromAcct, account.State{Address: from})
|
||||
mock.setAccountState(toAcct, account.State{Address: to})
|
||||
mock.setAccountAddress(fromAcct, from)
|
||||
mock.setAccountAddress(toAcct, to)
|
||||
|
||||
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
|
||||
|
||||
actorBalance := big.NewInt(10)
|
||||
toSend := big.NewInt(1)
|
||||
laneStates := map[uint64]paych.LaneState{
|
||||
1: {
|
||||
Nonce: 1,
|
||||
Redeemed: big.NewInt(3),
|
||||
},
|
||||
2: {
|
||||
Nonce: 1,
|
||||
Redeemed: big.NewInt(4),
|
||||
},
|
||||
1: paychmock.NewMockLaneState(big.NewInt(3), 1),
|
||||
2: paychmock.NewMockLaneState(big.NewInt(4), 1),
|
||||
}
|
||||
|
||||
act := &types.Actor{
|
||||
@ -280,16 +239,7 @@ func TestCheckVoucherValidCountingAllLanes(t *testing.T) {
|
||||
Balance: actorBalance,
|
||||
}
|
||||
|
||||
lsCid, err := mock.storeLaneStates(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,
|
||||
})
|
||||
mock.setPaychState(ch, act, paychmock.NewMockPayChState(fromAcct, toAcct, abi.ChainEpoch(0), toSend, laneStates))
|
||||
|
||||
mgr, err := newManager(store, mock)
|
||||
require.NoError(t, err)
|
||||
@ -389,7 +339,7 @@ func TestCreateVoucher(t *testing.T) {
|
||||
|
||||
// Create a voucher in lane 1
|
||||
voucherLane1Amt := big.NewInt(5)
|
||||
voucher := paych.SignedVoucher{
|
||||
voucher := v0paych.SignedVoucher{
|
||||
Lane: 1,
|
||||
Amount: voucherLane1Amt,
|
||||
}
|
||||
@ -404,7 +354,7 @@ func TestCreateVoucher(t *testing.T) {
|
||||
|
||||
// Create a voucher in lane 1 again, with a higher amount
|
||||
voucherLane1Amt = big.NewInt(8)
|
||||
voucher = paych.SignedVoucher{
|
||||
voucher = v0paych.SignedVoucher{
|
||||
Lane: 1,
|
||||
Amount: voucherLane1Amt,
|
||||
}
|
||||
@ -419,7 +369,7 @@ func TestCreateVoucher(t *testing.T) {
|
||||
// Create a voucher in lane 2 that covers all the remaining funds
|
||||
// in the channel
|
||||
voucherLane2Amt := big.Sub(s.amt, voucherLane1Amt)
|
||||
voucher = paych.SignedVoucher{
|
||||
voucher = v0paych.SignedVoucher{
|
||||
Lane: 2,
|
||||
Amount: voucherLane2Amt,
|
||||
}
|
||||
@ -433,7 +383,7 @@ func TestCreateVoucher(t *testing.T) {
|
||||
// Create a voucher in lane 2 that exceeds the remaining funds in the
|
||||
// channel
|
||||
voucherLane2Amt = big.Add(voucherLane2Amt, big.NewInt(1))
|
||||
voucher = paych.SignedVoucher{
|
||||
voucher = v0paych.SignedVoucher{
|
||||
Lane: 2,
|
||||
Amount: voucherLane2Amt,
|
||||
}
|
||||
@ -567,8 +517,8 @@ func TestAllocateLaneWithExistingLaneState(t *testing.T) {
|
||||
toAcct := tutils.NewActorAddr(t, "toAct")
|
||||
|
||||
mock := newMockManagerAPI()
|
||||
mock.setAccountState(fromAcct, account.State{Address: from})
|
||||
mock.setAccountState(toAcct, account.State{Address: to})
|
||||
mock.setAccountAddress(fromAcct, from)
|
||||
mock.setAccountAddress(toAcct, to)
|
||||
mock.addWalletAddress(to)
|
||||
|
||||
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
|
||||
@ -584,16 +534,7 @@ func TestAllocateLaneWithExistingLaneState(t *testing.T) {
|
||||
Balance: actorBalance,
|
||||
}
|
||||
|
||||
arr, err := adt.MakeEmptyArray(mock.store).Root()
|
||||
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,
|
||||
})
|
||||
mock.setPaychState(ch, act, paychmock.NewMockPayChState(fromAcct, toAcct, abi.ChainEpoch(0), toSend, make(map[uint64]paych.LaneState)))
|
||||
|
||||
mgr, err := newManager(store, mock)
|
||||
require.NoError(t, err)
|
||||
@ -681,19 +622,10 @@ func TestAddVoucherInboundWalletKey(t *testing.T) {
|
||||
}
|
||||
|
||||
mock := newMockManagerAPI()
|
||||
arr, err := adt.MakeEmptyArray(mock.store).Root()
|
||||
require.NoError(t, err)
|
||||
mock.setAccountState(fromAcct, account.State{Address: from})
|
||||
mock.setAccountState(toAcct, account.State{Address: to})
|
||||
mock.setAccountAddress(fromAcct, from)
|
||||
mock.setAccountAddress(toAcct, to)
|
||||
|
||||
mock.setPaychState(ch, act, paych.State{
|
||||
From: fromAcct,
|
||||
To: toAcct,
|
||||
ToSend: types.NewInt(0),
|
||||
SettlingAt: abi.ChainEpoch(0),
|
||||
MinSettleHeight: abi.ChainEpoch(0),
|
||||
LaneStates: arr,
|
||||
})
|
||||
mock.setPaychState(ch, act, paychmock.NewMockPayChState(fromAcct, toAcct, abi.ChainEpoch(0), types.NewInt(0), make(map[uint64]paych.LaneState)))
|
||||
|
||||
// Create a manager
|
||||
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
|
||||
lastCall := s.mock.getLastCall()
|
||||
var p paych.UpdateChannelStateParams
|
||||
var p v0paych.UpdateChannelStateParams
|
||||
err = p.UnmarshalCBOR(bytes.NewReader(lastCall.Params))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, otherProof, p.Proof)
|
||||
@ -854,7 +786,7 @@ func TestCheckSpendable(t *testing.T) {
|
||||
require.True(t, spendable)
|
||||
|
||||
lastCall = s.mock.getLastCall()
|
||||
var p2 paych.UpdateChannelStateParams
|
||||
var p2 v0paych.UpdateChannelStateParams
|
||||
err = p2.UnmarshalCBOR(bytes.NewReader(lastCall.Params))
|
||||
require.NoError(t, err)
|
||||
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
|
||||
msg := s.mock.pushedMessages(submitCid)
|
||||
var p paych.UpdateChannelStateParams
|
||||
var p v0paych.UpdateChannelStateParams
|
||||
err = p.UnmarshalCBOR(bytes.NewReader(msg.Message.Params))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, submitProof, p.Proof)
|
||||
@ -931,7 +863,7 @@ func TestSubmitVoucher(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
msg = s.mock.pushedMessages(submitCid)
|
||||
var p2 paych.UpdateChannelStateParams
|
||||
var p2 v0paych.UpdateChannelStateParams
|
||||
err = p2.UnmarshalCBOR(bytes.NewReader(msg.Message.Params))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, addVoucherProof2, p2.Proof)
|
||||
@ -947,7 +879,7 @@ func TestSubmitVoucher(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
msg = s.mock.pushedMessages(submitCid)
|
||||
var p3 paych.UpdateChannelStateParams
|
||||
var p3 v0paych.UpdateChannelStateParams
|
||||
err = p3.UnmarshalCBOR(bytes.NewReader(msg.Message.Params))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, proof3, p3.Proof)
|
||||
@ -986,10 +918,8 @@ func testSetupMgrWithChannel(ctx context.Context, t *testing.T) *testScaffold {
|
||||
toAcct := tutils.NewActorAddr(t, "toAct")
|
||||
|
||||
mock := newMockManagerAPI()
|
||||
arr, err := adt.MakeEmptyArray(mock.store).Root()
|
||||
require.NoError(t, err)
|
||||
mock.setAccountState(fromAcct, account.State{Address: from})
|
||||
mock.setAccountState(toAcct, account.State{Address: to})
|
||||
mock.setAccountAddress(fromAcct, from)
|
||||
mock.setAccountAddress(toAcct, to)
|
||||
|
||||
// Create channel in state
|
||||
balance := big.NewInt(20)
|
||||
@ -999,14 +929,7 @@ func testSetupMgrWithChannel(ctx context.Context, t *testing.T) *testScaffold {
|
||||
Nonce: 0,
|
||||
Balance: balance,
|
||||
}
|
||||
mock.setPaychState(ch, act, paych.State{
|
||||
From: fromAcct,
|
||||
To: toAcct,
|
||||
ToSend: big.NewInt(0),
|
||||
SettlingAt: abi.ChainEpoch(0),
|
||||
MinSettleHeight: abi.ChainEpoch(0),
|
||||
LaneStates: arr,
|
||||
})
|
||||
mock.setPaychState(ch, act, paychmock.NewMockPayChState(fromAcct, toAcct, abi.ChainEpoch(0), big.NewInt(0), make(map[uint64]paych.LaneState)))
|
||||
|
||||
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
|
||||
mgr, err := newManager(store, mock)
|
||||
@ -1043,8 +966,8 @@ func testGenerateKeyPair(t *testing.T) ([]byte, []byte) {
|
||||
return priv, pub
|
||||
}
|
||||
|
||||
func createTestVoucher(t *testing.T, ch address.Address, voucherLane uint64, nonce uint64, voucherAmount big.Int, key []byte) *paych.SignedVoucher {
|
||||
sv := &paych.SignedVoucher{
|
||||
func createTestVoucher(t *testing.T, ch address.Address, voucherLane uint64, nonce uint64, voucherAmount big.Int, key []byte) *v0paych.SignedVoucher {
|
||||
sv := &v0paych.SignedVoucher{
|
||||
ChannelAddr: ch,
|
||||
Lane: voucherLane,
|
||||
Nonce: nonce,
|
||||
@ -1059,13 +982,13 @@ func createTestVoucher(t *testing.T, ch address.Address, voucherLane uint64, non
|
||||
return sv
|
||||
}
|
||||
|
||||
func createTestVoucherWithExtra(t *testing.T, ch address.Address, voucherLane uint64, nonce uint64, voucherAmount big.Int, key []byte) *paych.SignedVoucher {
|
||||
sv := &paych.SignedVoucher{
|
||||
func createTestVoucherWithExtra(t *testing.T, ch address.Address, voucherLane uint64, nonce uint64, voucherAmount big.Int, key []byte) *v0paych.SignedVoucher {
|
||||
sv := &v0paych.SignedVoucher{
|
||||
ChannelAddr: ch,
|
||||
Lane: voucherLane,
|
||||
Nonce: nonce,
|
||||
Amount: voucherAmount,
|
||||
Extra: &paych.ModVerifyParams{
|
||||
Extra: &v0paych.ModVerifyParams{
|
||||
Actor: tutils.NewActorAddr(t, "act"),
|
||||
},
|
||||
}
|
||||
@ -1083,13 +1006,13 @@ type mockBestSpendableAPI struct {
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out := make([]*paych.SignedVoucher, len(vi))
|
||||
out := make([]*v0paych.SignedVoucher, len(vi))
|
||||
for k, v := range vi {
|
||||
out[k] = v.Voucher
|
||||
}
|
||||
@ -1097,7 +1020,7 @@ func (m *mockBestSpendableAPI) PaychVoucherList(ctx context.Context, ch address.
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -6,29 +6,22 @@ import (
|
||||
"testing"
|
||||
"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"
|
||||
|
||||
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"
|
||||
ds "github.com/ipfs/go-datastore"
|
||||
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/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 {
|
||||
@ -976,25 +969,15 @@ func TestPaychAvailableFunds(t *testing.T) {
|
||||
require.EqualValues(t, 0, av.VoucherReedeemedAmt.Int64())
|
||||
|
||||
// Create channel in state
|
||||
arr, err := adt.MakeEmptyArray(mock.store).Root()
|
||||
require.NoError(t, err)
|
||||
mock.setAccountState(fromAcct, account.State{Address: from})
|
||||
mock.setAccountState(toAcct, account.State{Address: to})
|
||||
mock.setAccountAddress(fromAcct, from)
|
||||
mock.setAccountAddress(toAcct, to)
|
||||
act := &types.Actor{
|
||||
Code: builtin.AccountActorCodeID,
|
||||
Head: cid.Cid{},
|
||||
Nonce: 0,
|
||||
Balance: createAmt,
|
||||
}
|
||||
mock.setPaychState(ch, act, paych.State{
|
||||
From: fromAcct,
|
||||
To: toAcct,
|
||||
ToSend: big.NewInt(0),
|
||||
SettlingAt: abi.ChainEpoch(0),
|
||||
MinSettleHeight: abi.ChainEpoch(0),
|
||||
LaneStates: arr,
|
||||
})
|
||||
|
||||
mock.setPaychState(ch, act, paychmock.NewMockPayChState(fromAcct, toAcct, abi.ChainEpoch(0), big.NewInt(0), make(map[uint64]paych.LaneState)))
|
||||
// Send create channel response
|
||||
response := testChannelResponse(t, ch)
|
||||
mock.receiveMsgResponse(createMsgCid, response)
|
||||
|
@ -6,20 +6,17 @@ import (
|
||||
"fmt"
|
||||
"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"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"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/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
@ -320,7 +317,7 @@ func (ca *channelAccessor) currentAvailableFunds(channelID string, queuedAmt typ
|
||||
}
|
||||
|
||||
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
|
||||
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 {
|
||||
return cid.Undef, aerr
|
||||
}
|
||||
|
@ -3,13 +3,9 @@ package paychmgr
|
||||
import (
|
||||
"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/specs-actors/actors/builtin/paych"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
@ -17,14 +13,8 @@ type stateAccessor struct {
|
||||
sm stateManagerAPI
|
||||
}
|
||||
|
||||
func (ca *stateAccessor) loadPaychActorState(ctx context.Context, ch address.Address) (*types.Actor, *paych.State, error) {
|
||||
var pcast paych.State
|
||||
act, err := ca.sm.LoadActorState(ctx, ch, &pcast, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return act, &pcast, nil
|
||||
func (ca *stateAccessor) loadPaychActorState(ctx context.Context, ch address.Address) (*types.Actor, paych.State, error) {
|
||||
return ca.sm.GetPaychState(ctx, ch, nil)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
var account account.State
|
||||
_, err = ca.sm.LoadActorState(ctx, st.From, &account, nil)
|
||||
// Load channel "From" account actor state
|
||||
from, err := ca.sm.ResolveToKeyAddress(ctx, st.From(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
from := account.Address
|
||||
_, err = ca.sm.LoadActorState(ctx, st.To, &account, nil)
|
||||
to, err := ca.sm.ResolveToKeyAddress(ctx, st.To(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
to := account.Address
|
||||
|
||||
nextLane, err := ca.nextLaneFromState(ctx, st)
|
||||
if err != nil {
|
||||
@ -67,25 +55,24 @@ func (ca *stateAccessor) loadStateChannelInfo(ctx context.Context, ch address.Ad
|
||||
return ci, nil
|
||||
}
|
||||
|
||||
func (ca *stateAccessor) nextLaneFromState(ctx context.Context, st *paych.State) (uint64, error) {
|
||||
store := ca.sm.AdtStore(ctx)
|
||||
laneStates, err := adt.AsArray(store, st.LaneStates)
|
||||
func (ca *stateAccessor) nextLaneFromState(ctx context.Context, st paych.State) (uint64, error) {
|
||||
laneCount, err := st.LaneCount()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if laneStates.Length() == 0 {
|
||||
if laneCount == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
maxID := int64(0)
|
||||
if err := laneStates.ForEach(nil, func(i int64) error {
|
||||
if i > maxID {
|
||||
maxID = i
|
||||
maxID := uint64(0)
|
||||
if err := st.ForEachLaneState(func(idx uint64, _ paych.LaneState) error {
|
||||
if idx > maxID {
|
||||
maxID = idx
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return uint64(maxID + 1), nil
|
||||
return maxID + 1, nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user