diff --git a/paych/cbor_gen.go b/paych/cbor_gen.go index b2c2c34d0..c72fb6834 100644 --- a/paych/cbor_gen.go +++ b/paych/cbor_gen.go @@ -6,7 +6,6 @@ import ( "fmt" "io" - "github.com/filecoin-project/lotus/chain/types" cbg "github.com/whyrusleeping/cbor-gen" xerrors "golang.org/x/xerrors" ) @@ -22,7 +21,7 @@ func (t *VoucherInfo) MarshalCBOR(w io.Writer) error { return err } - // t.Voucher (types.SignedVoucher) (struct) + // t.Voucher (paych.SignedVoucher) (struct) if err := t.Voucher.MarshalCBOR(w); err != nil { return err } @@ -56,7 +55,7 @@ func (t *VoucherInfo) UnmarshalCBOR(r io.Reader) error { return fmt.Errorf("cbor input had wrong number of fields") } - // t.Voucher (types.SignedVoucher) (struct) + // t.Voucher (paych.SignedVoucher) (struct) { @@ -70,7 +69,7 @@ func (t *VoucherInfo) UnmarshalCBOR(r io.Reader) error { return err } } else { - t.Voucher = new(types.SignedVoucher) + t.Voucher = new(SignedVoucher) if err := t.Voucher.UnmarshalCBOR(br); err != nil { return err } diff --git a/paych/paych.go b/paych/paych.go index 375fe7395..239847c08 100644 --- a/paych/paych.go +++ b/paych/paych.go @@ -5,14 +5,17 @@ import ( "context" "fmt" "math" - "strconv" + cborutil "github.com/filecoin-project/go-cbor-util" + "github.com/filecoin-project/specs-actors/actors/builtin" + "github.com/filecoin-project/specs-actors/actors/builtin/paych" "golang.org/x/xerrors" logging "github.com/ipfs/go-log/v2" "go.uber.org/fx" "github.com/filecoin-project/go-address" + "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/types" @@ -52,13 +55,9 @@ func NewManager(sm *stmgr.StateManager, pchstore *Store, api ManagerApi) *Manage func maxLaneFromState(st *actors.PaymentChannelActorState) (uint64, error) { maxLane := uint64(math.MaxUint64) - for lane := range st.LaneStates { - ilane, err := strconv.ParseUint(lane, 10, 64) - if err != nil { - return 0, err - } - if ilane+1 > maxLane+1 { - maxLane = ilane + for _, state := range st.LaneStates { + if uint64(state.ID)+1 > maxLane+1 { + maxLane = uint64(state.ID) } } return maxLane, nil @@ -148,13 +147,10 @@ func (pm *Manager) CheckVoucherValid(ctx context.Context, ch address.Address, sv // now check the lane state // TODO: should check against vouchers in our local store too // there might be something conflicting - ls, ok := pca.LaneStates[fmt.Sprint(sv.Lane)] - if !ok { + ls := findLane(pca.LaneStates, uint64(sv.Lane)) + if ls == nil { } else { - if ls.Closed { - return fmt.Errorf("voucher is on a closed lane") - } - if ls.Nonce >= sv.Nonce { + if (ls.Nonce) >= sv.Nonce { return fmt.Errorf("nonce too low") } @@ -188,7 +184,11 @@ func (pm *Manager) CheckVoucherSpendable(ctx context.Context, ch address.Address } for _, v := range known { - if v.Proof != nil && v.Voucher.Equals(sv) { + eq, err := cborutil.Equals(v.Voucher, sv) + if err != nil { + return false, err + } + if v.Proof != nil && eq { log.Info("CheckVoucherSpendable: using stored proof") proof = v.Proof break @@ -199,7 +199,7 @@ func (pm *Manager) CheckVoucherSpendable(ctx context.Context, ch address.Address } } - enc, err := actors.SerializeParams(&actors.PCAUpdateChannelStateParams{ + enc, err := actors.SerializeParams(&paych.UpdateChannelStateParams{ Sv: *sv, Secret: secret, Proof: proof, @@ -211,7 +211,7 @@ func (pm *Manager) CheckVoucherSpendable(ctx context.Context, ch address.Address ret, err := pm.sm.Call(ctx, &types.Message{ From: owner, To: ch, - Method: actors.PCAMethods.UpdateChannelState, + Method: builtin.MethodsPaych.UpdateChannelState, Params: enc, }, nil) if err != nil { @@ -226,20 +226,12 @@ func (pm *Manager) CheckVoucherSpendable(ctx context.Context, ch address.Address } func (pm *Manager) getPaychOwner(ctx context.Context, ch address.Address) (address.Address, error) { - ret, err := pm.sm.Call(ctx, &types.Message{ - From: ch, - To: ch, - Method: actors.PCAMethods.GetOwner, - }, nil) - if err != nil { - return address.Undef, err + var state paych.State + if _, err := pm.sm.LoadActorState(ctx, ch, &state, nil); err != nil { + return address.Address{}, err } - if ret.ExitCode != 0 { - return address.Undef, fmt.Errorf("failed to get payment channel owner (exit code %d)", ret.ExitCode) - } - - return address.NewFromBytes(ret.Return) + return state.From, nil } func (pm *Manager) AddVoucher(ctx context.Context, ch address.Address, sv *types.SignedVoucher, proof []byte, minDelta types.BigInt) (types.BigInt, error) { @@ -255,22 +247,22 @@ func (pm *Manager) AddVoucher(ctx context.Context, ch address.Address, sv *types return types.NewInt(0), err } - laneState, err := pm.laneState(ctx, ch, sv.Lane) + laneState, err := pm.laneState(ctx, ch, uint64(sv.Lane)) if err != nil { return types.NewInt(0), err } - if laneState.Closed { - return types.NewInt(0), xerrors.New("lane closed") - } - if minDelta.GreaterThan(types.NewInt(0)) && laneState.Nonce > sv.Nonce { return types.NewInt(0), xerrors.Errorf("already storing voucher with higher nonce; %d > %d", laneState.Nonce, sv.Nonce) } // look for duplicates for i, v := range ci.Vouchers { - if !sv.Equals(v.Voucher) { + eq, err := cborutil.Equals(sv, v) + if err != nil { + return types.BigInt{}, err + } + if !eq { continue } if v.Proof != nil { @@ -301,8 +293,8 @@ func (pm *Manager) AddVoucher(ctx context.Context, ch address.Address, sv *types Proof: proof, }) - if ci.NextLane <= sv.Lane { - ci.NextLane = sv.Lane + 1 + if ci.NextLane <= uint64(sv.Lane) { + ci.NextLane = uint64(sv.Lane + 1) } return delta, pm.store.putChannelInfo(ci) @@ -338,9 +330,9 @@ func (pm *Manager) NextNonceForLane(ctx context.Context, ch address.Address, lan var maxnonce uint64 for _, v := range vouchers { - if v.Voucher.Lane == lane { - if v.Voucher.Nonce > maxnonce { - maxnonce = v.Voucher.Nonce + if uint64(v.Voucher.Lane) == lane { + if uint64(v.Voucher.Nonce) > maxnonce { + maxnonce = uint64(v.Voucher.Nonce) } } } diff --git a/paych/simple.go b/paych/simple.go index 0c5844545..2f3fe2a43 100644 --- a/paych/simple.go +++ b/paych/simple.go @@ -4,23 +4,27 @@ import ( "context" "fmt" + "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/xerrors" "github.com/filecoin-project/go-address" + "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/types" ) func (pm *Manager) createPaych(ctx context.Context, from, to address.Address, amt types.BigInt) (address.Address, cid.Cid, error) { - params, aerr := actors.SerializeParams(&actors.PCAConstructorParams{To: to}) + params, aerr := actors.SerializeParams(&paych.ConstructorParams{To: to}) if aerr != nil { return address.Undef, cid.Undef, aerr } - enc, aerr := actors.SerializeParams(&actors.ExecParams{ - Params: params, - Code: actors.PaymentChannelCodeCid, + enc, aerr := actors.SerializeParams(&init_.ExecParams{ + CodeCID: actors.PaymentChannelCodeCid, + ConstructorParams: params, }) if aerr != nil { return address.Undef, cid.Undef, aerr @@ -30,7 +34,7 @@ func (pm *Manager) createPaych(ctx context.Context, from, to address.Address, am To: actors.InitAddress, From: from, Value: amt, - Method: actors.IAMethods.Exec, + Method: builtin.MethodsInit.Exec, Params: enc, GasLimit: types.NewInt(1000000), GasPrice: types.NewInt(0), diff --git a/paych/state.go b/paych/state.go index bd9521864..07e03ffab 100644 --- a/paych/state.go +++ b/paych/state.go @@ -2,12 +2,13 @@ package paych import ( "context" - "fmt" "github.com/filecoin-project/go-address" + "github.com/filecoin-project/specs-actors/actors/builtin/paych" + xerrors "golang.org/x/xerrors" + "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/types" - xerrors "golang.org/x/xerrors" ) func (pm *Manager) loadPaychState(ctx context.Context, ch address.Address) (*types.Actor, *actors.PaymentChannelActorState, error) { @@ -20,52 +21,59 @@ func (pm *Manager) loadPaychState(ctx context.Context, ch address.Address) (*typ return act, &pcast, nil } -func (pm *Manager) laneState(ctx context.Context, ch address.Address, lane uint64) (actors.LaneState, error) { +func findLane(states []*paych.LaneState, lane uint64) *paych.LaneState { + var ls *paych.LaneState + for _, laneState := range states { + if uint64(laneState.ID) == lane { + ls = laneState + break + } + } + return ls +} + +func (pm *Manager) laneState(ctx context.Context, ch address.Address, lane uint64) (paych.LaneState, error) { _, state, err := pm.loadPaychState(ctx, ch) if err != nil { - return actors.LaneState{}, err + return paych.LaneState{}, err } // TODO: we probably want to call UpdateChannelState with all vouchers to be fully correct // (but technically dont't need to) // TODO: make sure this is correct - ls, ok := state.LaneStates[fmt.Sprintf("%d", lane)] - if !ok { - ls = &actors.LaneState{ - Closed: false, + ls := findLane(state.LaneStates, lane) + if ls == nil { + ls = &paych.LaneState{ + ID: int64(lane), Redeemed: types.NewInt(0), Nonce: 0, } } - if ls.Closed { - return *ls, nil - } - vouchers, err := pm.store.VouchersForPaych(ch) if err != nil { if err == ErrChannelNotTracked { return *ls, nil } - return actors.LaneState{}, err + return paych.LaneState{}, err } for _, v := range vouchers { for range v.Voucher.Merges { - return actors.LaneState{}, xerrors.Errorf("paych merges not handled yet") + return paych.LaneState{}, xerrors.Errorf("paych merges not handled yet") } - if v.Voucher.Lane != lane { + if uint64(v.Voucher.Lane) != lane { continue } - if v.Voucher.Nonce < ls.Nonce { + if uint64(v.Voucher.Nonce) < uint64(ls.Nonce) { log.Warnf("Found outdated voucher: ch=%s, lane=%d, v.nonce=%d lane.nonce=%d", ch, lane, v.Voucher.Nonce, ls.Nonce) continue } - ls.Nonce = v.Voucher.Nonce + ls.Nonce = int64(v.Voucher.Nonce) ls.Redeemed = v.Voucher.Amount }