les: lespay API

This commit is contained in:
Zsolt Felfoldi 2019-11-25 16:29:18 +01:00
parent be4fb5757a
commit db4bc521a3
9 changed files with 146 additions and 15 deletions

View file

@ -33,6 +33,7 @@ var Modules = map[string]string{
"swarmfs": SwarmfsJs, "swarmfs": SwarmfsJs,
"txpool": TxpoolJs, "txpool": TxpoolJs,
"les": LESJs, "les": LESJs,
"lespay": LESPAYJs,
} }
const ChequebookJs = ` const ChequebookJs = `
@ -856,3 +857,20 @@ web3._extend({
] ]
}); });
` `
const LESPAYJs = `
web3._extend({
property: 'lespay',
methods:
[
new web3._extend.Method({
name: 'connection',
call: 'lespay_connection',
params: 6
}),
],
properties:
[
]
});
`

View file

@ -17,13 +17,16 @@
package les package les
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
"time" "time"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/mclock" "github.com/ethereum/go-ethereum/common/mclock"
"github.com/ethereum/go-ethereum/p2p/discv5"
"github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/rlp"
) )
var ( var (
@ -349,3 +352,102 @@ func (api *PrivateLightAPI) GetCheckpointContractAddress() (string, error) {
} }
return api.backend.oracle.config.Address.Hex(), nil return api.backend.oracle.config.Address.Hex(), nil
} }
type PrivateLespayAPI struct {
peerSet *peerSet
clientHandler *clientHandler
dht *discv5.Network
tokenSale *tokenSale
}
// NewPrivateLespayAPI creates a new LESPAY API.
func NewPrivateLespayAPI(peerSet *peerSet, clientHandler *clientHandler, dht *discv5.Network, tokenSale *tokenSale) *PrivateLespayAPI {
return &PrivateLespayAPI{
peerSet: peerSet,
clientHandler: clientHandler,
dht: dht,
tokenSale: tokenSale,
}
}
func (api *PrivateLespayAPI) makeCall(ctx context.Context, remote bool, nodeStr string, cmd []byte) ([]byte, error) {
var (
id enode.ID
freeID string
peer *peer
node *enode.Node
)
if nodeStr != "" {
if peer = api.peerSet.Peer(nodeStr); peer != nil {
id = peer.ID()
freeID = peer.freeClientId()
} else {
var err error
if node, err = enode.Parse(enode.ValidSchemes, nodeStr); err == nil {
id = node.ID()
freeID = node.IP().String()
} else {
return nil, err
}
}
}
if remote {
var (
reply []byte
cancelFn func() bool
)
delivered := make(chan struct{})
if peer != nil {
// remote call to a connected peer through LES
if api.clientHandler == nil {
return nil, errors.New("client handler not available")
}
cancelFn = api.clientHandler.makeLespayCall(peer, [][]byte{cmd}, func(replies [][]byte) bool {
if len(replies) == 1 {
reply = replies[0]
}
close(delivered)
return reply != nil
})
} else {
// remote call through UDP TALK
if api.dht == nil {
return nil, errors.New("UDP DHT not available")
}
cancelFn = api.dht.SendTalkRequest(node, "lespay", [][]byte{cmd}, func(payload interface{}) bool {
if replies, ok := payload.([][]byte); ok && len(replies) == 1 {
reply = replies[0]
}
close(delivered)
return reply != nil
})
}
select {
case <-ctx.Done():
cancelFn()
return nil, ctx.Err()
case <-delivered:
return reply, nil
}
} else {
if api.tokenSale == nil {
return nil, errors.New("token sale module not available")
}
// execute call locally
return api.tokenSale.runCommand(cmd, id, freeID), nil
}
}
func (api *PrivateLespayAPI) Connection(ctx context.Context, remote bool, node string, requestedCapacity, stayConnected uint64, paymentModule []string, setCap bool) (results tsConnectionResults, err error) {
params := tsConnectionParams{requestedCapacity, stayConnected, paymentModule, setCap}
enc, _ := rlp.EncodeToBytes(&params)
var resEnc []byte
resEnc, err = api.makeCall(ctx, remote, node, enc)
if err != nil {
return
}
err = rlp.DecodeBytes(resEnc, &results)
return
}

View file

@ -48,6 +48,7 @@ import (
type LightEthereum struct { type LightEthereum struct {
lesCommons lesCommons
srvr *p2p.Server
reqDist *requestDistributor reqDist *requestDistributor
retriever *retrieveManager retriever *retrieveManager
odr *LesOdr odr *LesOdr
@ -206,6 +207,12 @@ func (s *LightEthereum) APIs() []rpc.API {
Service: NewPrivateLightAPI(&s.lesCommons), Service: NewPrivateLightAPI(&s.lesCommons),
Public: false, Public: false,
}, },
{
Namespace: "lespay",
Version: "1.0",
Service: NewPrivateLespayAPI(s.lesCommons.peers, s.handler, s.srvr.DiscV5, nil),
Public: false,
},
}...) }...)
} }
@ -235,6 +242,7 @@ func (s *LightEthereum) Protocols() []p2p.Protocol {
// light ethereum protocol implementation. // light ethereum protocol implementation.
func (s *LightEthereum) Start(srvr *p2p.Server) error { func (s *LightEthereum) Start(srvr *p2p.Server) error {
log.Warn("Light client mode is an experimental feature") log.Warn("Light client mode is an experimental feature")
s.srvr = srvr
// Start bloom request workers. // Start bloom request workers.
s.wg.Add(bloomServiceThreads) s.wg.Add(bloomServiceThreads)

View file

@ -352,7 +352,7 @@ func (h *clientHandler) handleMsg(p *peer) error {
return nil return nil
} }
func (h *clientHandler) sendLespayCommands(p *peer, cmds [][]byte, handler func([][]byte) bool) func() bool { func (h *clientHandler) makeLespayCall(p *peer, cmds [][]byte, handler func([][]byte) bool) func() bool {
reqID := genReqID() reqID := genReqID()
if p.SendLespay(reqID, cmds) != nil { if p.SendLespay(reqID, cmds) != nil {
return nil return nil

View file

@ -149,6 +149,12 @@ func (s *LesServer) APIs() []rpc.API {
Service: NewPrivateDebugAPI(s), Service: NewPrivateDebugAPI(s),
Public: false, Public: false,
}, },
{
Namespace: "lespay",
Version: "1.0",
Service: NewPrivateLespayAPI(s.lesCommons.peers, nil, s.srvr.DiscV5, s.tokenSale),
Public: false,
},
} }
} }

View file

@ -981,9 +981,9 @@ func (h *serverHandler) broadcastHeaders() {
} }
} }
func (h *serverHandler) talkRequestHandler(id enode.ID, addr *net.UDPAddr, payload []byte) ([]byte, bool) { func (h *serverHandler) talkRequestHandler(id enode.ID, addr *net.UDPAddr, payload interface{}) (interface{}, bool) {
var cmds [][]byte cmds, ok := payload.([][]byte)
if err := rlp.DecodeBytes(payload, &cmds); err != nil { if !ok {
return nil, false return nil, false
} }
results := h.server.tokenSale.runCommands(cmds, id, addr.IP.String()) results := h.server.tokenSale.runCommands(cmds, id, addr.IP.String())

View file

@ -319,11 +319,6 @@ const (
tsConnection tsConnection
) )
/*func (t *tokenSale) connection(id enode.ID, freeID string, requestedCapacity uint64, stayConnected time.Duration, paymentModule []string, setCap bool) (availableCapacity, tokenBalance, tokensMissing, pcBalance, pcMissing uint64, paymentRequired []uint64, err error) {
func (t *tokenSale) deposit(id enode.ID, paymentModule string, proofOfPayment []byte) (pcValue, pcBalance uint64, err error) {
func (t *tokenSale) buyTokens(id enode.ID, maxSpend, minReceive uint64, spendAll bool) (pcBalance, tokenBalance, spend, receive uint64, success bool) {
func (t *tokenSale) paymentInfo(paymentModule []string) map[string][]byte {*/
type ( type (
tsDepositParams struct { tsDepositParams struct {
PaymentModule string PaymentModule string

View file

@ -87,8 +87,8 @@ type Network struct {
} }
type ( type (
TalkRequestHandler func(enode.ID, *net.UDPAddr, []byte) ([]byte, bool) TalkRequestHandler func(enode.ID, *net.UDPAddr, interface{}) (interface{}, bool)
TalkResponseHandler func([]byte) bool TalkResponseHandler func(interface{}) bool
) )
// transport is implemented by the UDP transport. // transport is implemented by the UDP transport.
@ -116,7 +116,7 @@ type findnodeQuery struct {
type talkQuery struct { type talkQuery struct {
remote *Node remote *Node
talkID string talkID string
payload rlp.RawValue payload interface{}
key string key string
handler TalkResponseHandler handler TalkResponseHandler
} }
@ -1387,7 +1387,7 @@ func (q *talkQuery) deferQuery() {
q.remote.deferQuery(q) q.remote.deferQuery(q)
} }
func (net *Network) SendTalkRequest(to *enode.Node, talkID string, payload []byte, handler TalkResponseHandler) func() bool { func (net *Network) SendTalkRequest(to *enode.Node, talkID string, payload interface{}, handler TalkResponseHandler) func() bool {
var nodeID NodeID var nodeID NodeID
copy(nodeID[:], crypto.FromECDSAPub(to.Pubkey())[1:]) copy(nodeID[:], crypto.FromECDSAPub(to.Pubkey())[1:])
node := net.nodes[nodeID] node := net.nodes[nodeID]

View file

@ -120,11 +120,13 @@ type (
} }
talkRequest struct { talkRequest struct {
TalkID, Payload []byte TalkID []byte
Payload interface{}
} }
talkResponse struct { talkResponse struct {
ReplyTok, Payload []byte ReplyTok []byte
Payload interface{}
} }
rpcNode struct { rpcNode struct {