paych: Update to specs paych code

This commit is contained in:
Łukasz Magiera 2020-02-13 00:52:19 +01:00
parent 255f511abd
commit 5afaca6fa5
4 changed files with 69 additions and 66 deletions

View File

@ -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
}

View File

@ -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)
}
}
}

View File

@ -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),

View File

@ -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
}