WIP: wiring up the payment channel manager to the api
This commit is contained in:
parent
7be7d9137e
commit
6d52abcb2e
@ -101,9 +101,10 @@ type FullNode interface {
|
||||
PaychList(context.Context) ([]address.Address, error)
|
||||
PaychStatus(context.Context, address.Address) (*PaychStatus, error)
|
||||
PaychClose(context.Context, address.Address) error
|
||||
PaychVoucherCheck(context.Context, *types.SignedVoucher) error
|
||||
PaychVoucherCheckValid(context.Context, address.Address, *types.SignedVoucher) error
|
||||
PaychVoucherCheckSpendable(context.Context, address.Address, *types.SignedVoucher, []byte, []byte) (bool, error)
|
||||
PaychVoucherCreate(context.Context, address.Address, types.BigInt, uint64) (*types.SignedVoucher, error)
|
||||
PaychVoucherAdd(context.Context, *types.SignedVoucher) error
|
||||
PaychVoucherAdd(context.Context, address.Address, *types.SignedVoucher) error
|
||||
PaychVoucherList(context.Context, address.Address) ([]*types.SignedVoucher, error)
|
||||
}
|
||||
|
||||
|
@ -73,14 +73,16 @@ type FullNodeStruct struct {
|
||||
StateMinerSectors func(context.Context, address.Address) ([]*SectorInfo, error) `perm:"read"`
|
||||
StateMinerProvingSet func(context.Context, address.Address) ([]*SectorInfo, error) `perm:"read"`
|
||||
|
||||
PaychCreate func(ctx context.Context, from, to address.Address, amt types.BigInt) (address.Address, error) `perm:"sign"`
|
||||
PaychList func(context.Context) ([]address.Address, error) `perm:"read"`
|
||||
PaychStatus func(context.Context, address.Address) (*PaychStatus, error) `perm:"read"`
|
||||
PaychClose func(context.Context, address.Address) error `perm:"sign"`
|
||||
PaychVoucherCheck func(context.Context, *types.SignedVoucher) error `perm:"read"`
|
||||
PaychVoucherAdd func(context.Context, *types.SignedVoucher) error `perm:"write"`
|
||||
PaychVoucherCreate func(context.Context, address.Address, types.BigInt, uint64) (*types.SignedVoucher, error) `perm:"sign"`
|
||||
PaychVoucherList func(context.Context, address.Address) ([]*types.SignedVoucher, error) `perm:"write"`
|
||||
PaychCreate func(ctx context.Context, from, to address.Address, amt types.BigInt) (address.Address, error) `perm:"sign"`
|
||||
PaychList func(context.Context) ([]address.Address, error) `perm:"read"`
|
||||
PaychStatus func(context.Context, address.Address) (*PaychStatus, error) `perm:"read"`
|
||||
PaychClose func(context.Context, address.Address) error `perm:"sign"`
|
||||
PaychVoucherCheck func(context.Context, *types.SignedVoucher) error `perm:"read"`
|
||||
PaychVoucherCheckValid func(context.Context, address.Address, *types.SignedVoucher) error `perm:"read"`
|
||||
PaychVoucherCheckSpendable func(context.Context, address.Address, *types.SignedVoucher, []byte, []byte) (bool, error) `perm:"read"`
|
||||
PaychVoucherAdd func(context.Context, address.Address, *types.SignedVoucher) error `perm:"write"`
|
||||
PaychVoucherCreate func(context.Context, address.Address, types.BigInt, uint64) (*types.SignedVoucher, error) `perm:"sign"`
|
||||
PaychVoucherList func(context.Context, address.Address) ([]*types.SignedVoucher, error) `perm:"write"`
|
||||
}
|
||||
}
|
||||
|
||||
@ -260,12 +262,16 @@ func (c *FullNodeStruct) PaychStatus(ctx context.Context, pch address.Address) (
|
||||
return c.Internal.PaychStatus(ctx, pch)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) PaychVoucherCheck(ctx context.Context, sv *types.SignedVoucher) error {
|
||||
return c.Internal.PaychVoucherCheck(ctx, sv)
|
||||
func (c *FullNodeStruct) PaychVoucherCheckValid(ctx context.Context, addr address.Address, sv *types.SignedVoucher) error {
|
||||
return c.Internal.PaychVoucherCheckValid(ctx, addr, sv)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) PaychVoucherAdd(ctx context.Context, sv *types.SignedVoucher) error {
|
||||
return c.Internal.PaychVoucherAdd(ctx, sv)
|
||||
func (c *FullNodeStruct) PaychVoucherCheckSpendable(ctx context.Context, addr address.Address, sv *types.SignedVoucher, secret []byte, proof []byte) (bool, error) {
|
||||
return c.Internal.PaychVoucherCheckSpendable(ctx, addr, sv, secret, proof)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) PaychVoucherAdd(ctx context.Context, addr address.Address, sv *types.SignedVoucher) error {
|
||||
return c.Internal.PaychVoucherAdd(ctx, addr, sv)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) PaychVoucherCreate(ctx context.Context, pch address.Address, amt types.BigInt, lane uint64) (*types.SignedVoucher, error) {
|
||||
|
@ -33,6 +33,7 @@ import (
|
||||
"github.com/filecoin-project/go-lotus/node/modules/lp2p"
|
||||
"github.com/filecoin-project/go-lotus/node/modules/testing"
|
||||
"github.com/filecoin-project/go-lotus/node/repo"
|
||||
"github.com/filecoin-project/go-lotus/paych"
|
||||
"github.com/filecoin-project/go-lotus/storage"
|
||||
)
|
||||
|
||||
@ -214,6 +215,9 @@ func Online() Option {
|
||||
|
||||
Override(new(*deals.Client), deals.NewClient),
|
||||
Override(RunDealClientKey, modules.RunDealClient),
|
||||
|
||||
Override(new(*paych.Store), modules.PaychStore),
|
||||
Override(new(*paych.Manager), modules.PaymentChannelManager),
|
||||
),
|
||||
|
||||
// Storage miner
|
||||
|
@ -19,6 +19,7 @@ import (
|
||||
"github.com/filecoin-project/go-lotus/chain/wallet"
|
||||
"github.com/filecoin-project/go-lotus/miner"
|
||||
"github.com/filecoin-project/go-lotus/node/client"
|
||||
"github.com/filecoin-project/go-lotus/paych"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/ipfs/go-hamt-ipld"
|
||||
@ -41,6 +42,7 @@ type FullNodeAPI struct {
|
||||
PubSub *pubsub.PubSub
|
||||
Mpool *chain.MessagePool
|
||||
Wallet *wallet.Wallet
|
||||
PaychMgr *paych.Manager
|
||||
}
|
||||
|
||||
func (a *FullNodeAPI) ClientStartDeal(ctx context.Context, data cid.Cid, miner address.Address, price types.BigInt, blocksDuration uint64) (*cid.Cid, error) {
|
||||
@ -516,7 +518,7 @@ func (a *FullNodeAPI) PaychCreate(ctx context.Context, from, to address.Address,
|
||||
}
|
||||
|
||||
func (a *FullNodeAPI) PaychList(ctx context.Context) ([]address.Address, error) {
|
||||
panic("nyi")
|
||||
return a.PaychMgr.ListChannels()
|
||||
}
|
||||
|
||||
func (a *FullNodeAPI) PaychStatus(ctx context.Context, pch address.Address) (*api.PaychStatus, error) {
|
||||
@ -524,15 +526,60 @@ func (a *FullNodeAPI) PaychStatus(ctx context.Context, pch address.Address) (*ap
|
||||
}
|
||||
|
||||
func (a *FullNodeAPI) PaychClose(ctx context.Context, addr address.Address) error {
|
||||
panic("nyi")
|
||||
ci, err := a.PaychMgr.GetChannelInfo(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nonce, err := a.MpoolGetNonce(ctx, ci.ControlAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
msg := &types.Message{
|
||||
To: addr,
|
||||
From: ci.ControlAddr,
|
||||
Value: types.NewInt(0),
|
||||
Method: actors.PCAMethods.Close,
|
||||
Nonce: nonce,
|
||||
|
||||
GasLimit: types.NewInt(500),
|
||||
GasPrice: types.NewInt(0),
|
||||
}
|
||||
|
||||
b, err := msg.Serialize()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sig, err := a.WalletSign(ctx, ci.ControlAddr, b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
smsg := &types.SignedMessage{
|
||||
Message: *msg,
|
||||
Signature: *sig,
|
||||
}
|
||||
|
||||
// TODO: should this block and wait?
|
||||
return a.MpoolPush(ctx, smsg)
|
||||
}
|
||||
|
||||
func (a *FullNodeAPI) PaychVoucherCheck(ctx context.Context, sv *types.SignedVoucher) error {
|
||||
panic("nyi")
|
||||
func (a *FullNodeAPI) PaychVoucherCheckValid(ctx context.Context, ch address.Address, sv *types.SignedVoucher) error {
|
||||
return a.PaychMgr.CheckVoucherValid(ctx, ch, sv)
|
||||
}
|
||||
|
||||
func (a *FullNodeAPI) PaychVoucherAdd(ctx context.Context, sv *types.SignedVoucher) error {
|
||||
panic("nyi")
|
||||
func (a *FullNodeAPI) PaychVoucherCheckSpendable(ctx context.Context, ch address.Address, sv *types.SignedVoucher, secret []byte, proof []byte) (bool, error) {
|
||||
return a.PaychMgr.CheckVoucherSpendable(ctx, ch, sv, secret, proof)
|
||||
}
|
||||
|
||||
func (a *FullNodeAPI) PaychVoucherAdd(ctx context.Context, ch address.Address, sv *types.SignedVoucher) error {
|
||||
if err := a.PaychVoucherCheckValid(ctx, ch, sv); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return a.PaychMgr.AddVoucher(ctx, ch, sv)
|
||||
}
|
||||
|
||||
func (a *FullNodeAPI) PaychVoucherCreate(ctx context.Context, pch address.Address, amt types.BigInt, lane uint64) (*types.SignedVoucher, error) {
|
||||
|
18
node/modules/paych.go
Normal file
18
node/modules/paych.go
Normal file
@ -0,0 +1,18 @@
|
||||
package modules
|
||||
|
||||
import (
|
||||
"github.com/filecoin-project/go-lotus/api"
|
||||
"github.com/filecoin-project/go-lotus/chain/store"
|
||||
"github.com/filecoin-project/go-lotus/node/modules/dtypes"
|
||||
"github.com/filecoin-project/go-lotus/paych"
|
||||
)
|
||||
|
||||
func PaychStore(ds dtypes.MetadataDS) *paych.Store {
|
||||
return paych.NewStore(ds)
|
||||
}
|
||||
|
||||
func PaymentChannelManager(chain *store.ChainStore, store *paych.Store) (*paych.Manager, error) {
|
||||
var api api.FullNode
|
||||
panic("i need a full node api. what do i do")
|
||||
return paych.NewManager(api, chain, store), nil
|
||||
}
|
@ -17,26 +17,56 @@ type paychMgrApi interface {
|
||||
ChainCall(ctx context.Context, msg *types.Message, ts *types.TipSet) (*types.MessageReceipt, error)
|
||||
}
|
||||
|
||||
type PaychManager struct {
|
||||
type Manager struct {
|
||||
chain *store.ChainStore
|
||||
api paychMgrApi
|
||||
store *PaychStore
|
||||
store *Store
|
||||
}
|
||||
|
||||
func NewManager(api paychMgrApi, chain *store.ChainStore, pchstore *PaychStore) *PaychManager {
|
||||
return &PaychManager{
|
||||
func NewManager(api paychMgrApi, chain *store.ChainStore, pchstore *Store) *Manager {
|
||||
return &Manager{
|
||||
api: api,
|
||||
chain: chain,
|
||||
store: pchstore,
|
||||
}
|
||||
}
|
||||
|
||||
func (pm *PaychManager) TrackChannel(ch address.Address) error {
|
||||
return pm.store.TrackChannel(ch)
|
||||
func (pm *Manager) TrackInboundChannel(ctx context.Context, ch address.Address) error {
|
||||
_, st, err := pm.loadPaychState(ctx, ch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return pm.store.TrackChannel(&ChannelInfo{
|
||||
Channel: ch,
|
||||
Direction: DirInbound,
|
||||
ControlAddr: st.To,
|
||||
})
|
||||
}
|
||||
|
||||
func (pm *Manager) TrackOutboundChannel(ctx context.Context, ch address.Address) error {
|
||||
_, st, err := pm.loadPaychState(ctx, ch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return pm.store.TrackChannel(&ChannelInfo{
|
||||
Channel: ch,
|
||||
Direction: DirOutbound,
|
||||
ControlAddr: st.From,
|
||||
})
|
||||
}
|
||||
|
||||
func (pm *Manager) ListChannels() ([]address.Address, error) {
|
||||
return pm.store.ListChannels()
|
||||
}
|
||||
|
||||
func (pm *Manager) GetChannelInfo(addr address.Address) (*ChannelInfo, error) {
|
||||
return pm.store.getChannelInfo(addr)
|
||||
}
|
||||
|
||||
// checks if the given voucher is valid (is or could become spendable at some point)
|
||||
func (pm *PaychManager) CheckVoucherValid(ctx context.Context, ch address.Address, sv *types.SignedVoucher) error {
|
||||
func (pm *Manager) CheckVoucherValid(ctx context.Context, ch address.Address, sv *types.SignedVoucher) error {
|
||||
act, pca, err := pm.loadPaychState(ctx, ch)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -83,7 +113,7 @@ func (pm *PaychManager) CheckVoucherValid(ctx context.Context, ch address.Addres
|
||||
}
|
||||
|
||||
// checks if the given voucher is currently spendable
|
||||
func (pm *PaychManager) CheckVoucherSpendable(ctx context.Context, ch address.Address, sv *types.SignedVoucher, secret []byte, proof []byte) (bool, error) {
|
||||
func (pm *Manager) CheckVoucherSpendable(ctx context.Context, ch address.Address, sv *types.SignedVoucher, secret []byte, proof []byte) (bool, error) {
|
||||
owner, err := pm.getPaychOwner(ctx, ch)
|
||||
if err != nil {
|
||||
return false, err
|
||||
@ -115,7 +145,7 @@ func (pm *PaychManager) CheckVoucherSpendable(ctx context.Context, ch address.Ad
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (pm *PaychManager) loadPaychState(ctx context.Context, ch address.Address) (*types.Actor, *actors.PaymentChannelActorState, error) {
|
||||
func (pm *Manager) loadPaychState(ctx context.Context, ch address.Address) (*types.Actor, *actors.PaymentChannelActorState, error) {
|
||||
st, err := pm.chain.TipSetState(pm.chain.GetHeaviestTipSet().Cids())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@ -140,7 +170,7 @@ func (pm *PaychManager) loadPaychState(ctx context.Context, ch address.Address)
|
||||
return act, &pcast, nil
|
||||
}
|
||||
|
||||
func (pm *PaychManager) getPaychOwner(ctx context.Context, ch address.Address) (address.Address, error) {
|
||||
func (pm *Manager) getPaychOwner(ctx context.Context, ch address.Address) (address.Address, error) {
|
||||
ret, err := pm.api.ChainCall(ctx, &types.Message{
|
||||
From: ch,
|
||||
To: ch,
|
||||
@ -156,3 +186,11 @@ func (pm *PaychManager) getPaychOwner(ctx context.Context, ch address.Address) (
|
||||
|
||||
return address.NewFromBytes(ret.Return)
|
||||
}
|
||||
|
||||
func (pm *Manager) AddVoucher(ctx context.Context, ch address.Address, sv *types.SignedVoucher) error {
|
||||
if err := pm.CheckVoucherValid(ctx, ch, sv); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return pm.store.AddVoucher(ch, sv)
|
||||
}
|
||||
|
103
paych/store.go
103
paych/store.go
@ -1,29 +1,114 @@
|
||||
package paych
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/filecoin-project/go-lotus/chain/address"
|
||||
"github.com/filecoin-project/go-lotus/chain/types"
|
||||
"github.com/ipfs/go-datastore"
|
||||
dsq "github.com/ipfs/go-datastore/query"
|
||||
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
)
|
||||
|
||||
type PaychStore struct {
|
||||
func init() {
|
||||
cbor.RegisterCborType(ChannelInfo{})
|
||||
}
|
||||
|
||||
type Store struct {
|
||||
ds datastore.Batching
|
||||
}
|
||||
|
||||
func NewPaychStore(ds datastore.Batching) *PaychStore {
|
||||
return &PaychStore{
|
||||
func NewStore(ds datastore.Batching) *Store {
|
||||
return &Store{
|
||||
ds: ds,
|
||||
}
|
||||
}
|
||||
|
||||
func (ps *PaychStore) TrackChannel(ch address.Address) error {
|
||||
const (
|
||||
DirInbound = 1
|
||||
DirOutbound = 2
|
||||
)
|
||||
|
||||
type ChannelInfo struct {
|
||||
Channel address.Address
|
||||
ControlAddr address.Address
|
||||
Direction int
|
||||
Vouchers []*types.SignedVoucher
|
||||
}
|
||||
|
||||
func dskeyForChannel(addr address.Address) datastore.Key {
|
||||
return datastore.NewKey("/paych/" + addr.String())
|
||||
}
|
||||
|
||||
func (ps *Store) putChannelInfo(ci *ChannelInfo) error {
|
||||
k := dskeyForChannel(ci.Channel)
|
||||
|
||||
b, err := cbor.DumpObject(ci)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ps.ds.Put(k, b)
|
||||
}
|
||||
|
||||
func (ps *Store) getChannelInfo(addr address.Address) (*ChannelInfo, error) {
|
||||
k := dskeyForChannel(addr)
|
||||
|
||||
b, err := ps.ds.Get(k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ci ChannelInfo
|
||||
if err := cbor.DecodeInto(b, &ci); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ci, nil
|
||||
}
|
||||
|
||||
func (ps *Store) TrackChannel(ch *ChannelInfo) error {
|
||||
_, err := ps.getChannelInfo(ch.Channel)
|
||||
switch err {
|
||||
default:
|
||||
return err
|
||||
case nil:
|
||||
return fmt.Errorf("already tracking channel: %s", ch.Channel)
|
||||
case datastore.ErrNotFound:
|
||||
return ps.putChannelInfo(ch)
|
||||
}
|
||||
}
|
||||
|
||||
func (ps *Store) ListChannels() ([]address.Address, error) {
|
||||
res, err := ps.ds.Query(dsq.Query{Prefix: "/paych/", KeysOnly: true})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var out []address.Address
|
||||
for {
|
||||
res, ok := res.NextSync()
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
|
||||
addr, err := address.NewFromString(strings.TrimPrefix(res.Key, "/paych/"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out = append(out, addr)
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (ps *Store) AddVoucher(ch address.Address, sv *types.SignedVoucher) error {
|
||||
panic("nyi")
|
||||
}
|
||||
|
||||
func (ps *PaychStore) AddVoucher(sv *types.SignedVoucher) error {
|
||||
panic("nyi")
|
||||
}
|
||||
|
||||
func (ps *PaychStore) VouchersForPaych(addr address.Address) ([]*types.SignedVoucher, error) {
|
||||
func (ps *Store) VouchersForPaych(addr address.Address) ([]*types.SignedVoucher, error) {
|
||||
panic("nyi")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user