les: lespay API

This commit is contained in:
Zsolt Felfoldi 2019-11-27 18:47:17 +01:00
parent db4bc521a3
commit 94bf8de547
7 changed files with 88 additions and 29 deletions

View file

@ -20,6 +20,7 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"reflect"
"time" "time"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
@ -376,10 +377,13 @@ func (api *PrivateLespayAPI) makeCall(ctx context.Context, remote bool, nodeStr
freeID string freeID string
peer *peer peer *peer
node *enode.Node node *enode.Node
err error
) )
if nodeStr != "" { if nodeStr != "" {
if peer = api.peerSet.Peer(nodeStr); peer != nil { if id, err = enode.ParseID(nodeStr); err == nil {
id = peer.ID() if peer = api.peerSet.Peer(peerIdToString(id)); peer == nil {
return nil, errors.New("peer not connected")
}
freeID = peer.freeClientId() freeID = peer.freeClientId()
} else { } else {
var err error var err error
@ -416,18 +420,25 @@ func (api *PrivateLespayAPI) makeCall(ctx context.Context, remote bool, nodeStr
return nil, errors.New("UDP DHT not available") return nil, errors.New("UDP DHT not available")
} }
cancelFn = api.dht.SendTalkRequest(node, "lespay", [][]byte{cmd}, func(payload interface{}) bool { cancelFn = api.dht.SendTalkRequest(node, "lespay", [][]byte{cmd}, func(payload interface{}) bool {
if replies, ok := payload.([][]byte); ok && len(replies) == 1 { fmt.Println("dht delivered", payload, reflect.TypeOf(payload))
reply = replies[0] if replies, ok := payload.([]interface{}); ok && len(replies) == 1 {
reply, ok = replies[0].([]byte)
} }
close(delivered) close(delivered)
return reply != nil return reply != nil
}) })
} }
select { select {
case <-time.After(time.Second * 5):
cancelFn()
return nil, errors.New("timeout")
case <-ctx.Done(): case <-ctx.Done():
cancelFn() cancelFn()
return nil, ctx.Err() return nil, ctx.Err()
case <-delivered: case <-delivered:
if len(reply) == 0 {
return nil, errors.New("unknown command")
}
return reply, nil return reply, nil
} }
} else { } else {
@ -444,10 +455,13 @@ func (api *PrivateLespayAPI) Connection(ctx context.Context, remote bool, node s
params := tsConnectionParams{requestedCapacity, stayConnected, paymentModule, setCap} params := tsConnectionParams{requestedCapacity, stayConnected, paymentModule, setCap}
enc, _ := rlp.EncodeToBytes(&params) enc, _ := rlp.EncodeToBytes(&params)
var resEnc []byte var resEnc []byte
resEnc, err = api.makeCall(ctx, remote, node, enc) fmt.Println("makeCall", remote, node, enc)
resEnc, err = api.makeCall(ctx, remote, node, append([]byte{tsConnection}, enc...))
if err != nil { if err != nil {
fmt.Println("makeCall err", err)
return return
} }
err = rlp.DecodeBytes(resEnc, &results) err = rlp.DecodeBytes(resEnc, &results)
fmt.Println("decode err", err)
return return
} }

View file

@ -17,6 +17,7 @@
package les package les
import ( import (
"fmt"
"math/big" "math/big"
"sync" "sync"
"time" "time"
@ -316,19 +317,24 @@ func (h *clientHandler) handleMsg(p *peer) error {
p.freezeServer(false) p.freezeServer(false)
p.Log().Debug("Service resumed") p.Log().Debug("Service resumed")
case LespayReplyMsg: case LespayReplyMsg:
fmt.Println("LespayReply received")
p.Log().Trace("Received tx status response") p.Log().Trace("Received tx status response")
var resp struct { var resp struct {
ReqID uint64 ReqID uint64
Replies [][]byte Replies [][]byte
} }
if err := msg.Decode(&resp); err != nil { if err := msg.Decode(&resp); err != nil {
fmt.Println("LespayReply decode err", err)
return errResp(ErrDecode, "msg %v: %v", msg, err) return errResp(ErrDecode, "msg %v: %v", msg, err)
} }
fmt.Println("LespayReply decoded", resp)
h.lespayReplyLock.Lock() h.lespayReplyLock.Lock()
if handler := h.lespayReplyHandlers[resp.ReqID]; handler != nil { if handler := h.lespayReplyHandlers[resp.ReqID]; handler != nil {
fmt.Println("handler found")
delete(h.lespayReplyHandlers, resp.ReqID) delete(h.lespayReplyHandlers, resp.ReqID)
responseError = !handler(resp.Replies) responseError = !handler(resp.Replies)
} else { } else {
fmt.Println("handler not found")
responseError = true responseError = true
} }
h.lespayReplyLock.Unlock() h.lespayReplyLock.Unlock()
@ -354,9 +360,16 @@ func (h *clientHandler) handleMsg(p *peer) error {
func (h *clientHandler) makeLespayCall(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()
h.lespayReplyLock.Lock()
h.lespayReplyHandlers[reqID] = handler
h.lespayReplyLock.Unlock()
if p.SendLespay(reqID, cmds) != nil { if p.SendLespay(reqID, cmds) != nil {
h.lespayReplyLock.Lock()
delete(h.lespayReplyHandlers, reqID)
h.lespayReplyLock.Unlock()
return nil return nil
} }
fmt.Println("Lespay sent")
return func() bool { return func() bool {
h.lespayReplyLock.Lock() h.lespayReplyLock.Lock()
cancel := h.lespayReplyHandlers[reqID] != nil cancel := h.lespayReplyHandlers[reqID] != nil

View file

@ -594,10 +594,11 @@ func (f *clientPool) setCapacity(id enode.ID, freeID string, capacity uint64, mi
if missing != 0 { if missing != 0 {
return missing, capacity, errNoPriority return missing, capacity, errNoPriority
} }
if setCap && c == nil {
return missing, capacity, fmt.Errorf("client %064x is not connected", c.id[:])
}
// capacity update is possible // capacity update is possible
if setCap {
if c == nil {
return 0, capacity, fmt.Errorf("client %064x is not connected", c.id[:])
}
f.connectedCap += capacity - c.capacity f.connectedCap += capacity - c.capacity
f.updateFullRatio() f.updateFullRatio()
f.priorityConnected += capacity - c.capacity f.priorityConnected += capacity - c.capacity
@ -607,6 +608,7 @@ func (f *clientPool) setCapacity(id enode.ID, freeID string, capacity uint64, mi
totalConnectedGauge.Update(int64(f.connectedCap)) totalConnectedGauge.Update(int64(f.connectedCap))
updatePriceFactors(&c.balanceTracker, c.posFactors, c.negFactors, c.capacity) updatePriceFactors(&c.balanceTracker, c.posFactors, c.negFactors, c.capacity)
c.peer.updateCapacity(c.capacity) c.peer.updateCapacity(c.capacity)
}
return 0, capacity, nil return 0, capacity, nil
} }

View file

@ -20,7 +20,9 @@ import (
"encoding/binary" "encoding/binary"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt"
"net" "net"
"reflect"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
@ -130,7 +132,7 @@ func (h *serverHandler) handle(p *peer) error {
} }
// Reject light clients if server is not synced. // Reject light clients if server is not synced.
if !h.synced() { if !h.synced() {
return p2p.DiscRequested //return p2p.DiscRequested
} }
defer p.fcClient.Disconnect() defer p.fcClient.Disconnect()
@ -982,11 +984,21 @@ func (h *serverHandler) broadcastHeaders() {
} }
func (h *serverHandler) talkRequestHandler(id enode.ID, addr *net.UDPAddr, payload interface{}) (interface{}, bool) { func (h *serverHandler) talkRequestHandler(id enode.ID, addr *net.UDPAddr, payload interface{}) (interface{}, bool) {
cmds, ok := payload.([][]byte) fmt.Println("talkRequestHandler", id, addr, payload, reflect.TypeOf(payload))
c, ok := payload.([]interface{})
if !ok { if !ok {
return nil, false return nil, false
} }
results := h.server.tokenSale.runCommands(cmds, id, addr.IP.String()) cmds := make([][]byte, len(c))
res, _ := rlp.EncodeToBytes(&results) for i, c := range c {
return res, true cmds[i], ok = c.([]byte)
if !ok {
fmt.Println("type err", reflect.TypeOf(c))
return nil, false
}
}
fmt.Println("ok", ok)
results := h.server.tokenSale.runCommands(cmds, id, addr.IP.String())
fmt.Println("results", results)
return results, true
} }

View file

@ -367,7 +367,9 @@ func (t *tokenSale) runCommand(cmd []byte, id enode.ID, freeID string) []byte {
) )
if err := rlp.DecodeBytes(cmd[1:], &params); err == nil { if err := rlp.DecodeBytes(cmd[1:], &params); err == nil {
results.PcValue, results.PcBalance, err = t.deposit(id, params.PaymentModule, params.ProofOfPayment) results.PcValue, results.PcBalance, err = t.deposit(id, params.PaymentModule, params.ProofOfPayment)
if err != nil {
results.Err = err.Error() results.Err = err.Error()
}
res, _ = rlp.EncodeToBytes(&results) res, _ = rlp.EncodeToBytes(&results)
} }
case tsBuyTokens: case tsBuyTokens:
@ -388,7 +390,9 @@ func (t *tokenSale) runCommand(cmd []byte, id enode.ID, freeID string) []byte {
if err := rlp.DecodeBytes(cmd[1:], &params); err == nil { if err := rlp.DecodeBytes(cmd[1:], &params); err == nil {
results.AvailableCapacity, results.TokenBalance, results.TokensMissing, results.PcBalance, results.PcMissing, results.PaymentRequired, err = results.AvailableCapacity, results.TokenBalance, results.TokensMissing, results.PcBalance, results.PcMissing, results.PaymentRequired, err =
t.connection(id, freeID, params.RequestedCapacity, time.Duration(params.StayConnected)*time.Second, params.PaymentModule, params.SetCap) t.connection(id, freeID, params.RequestedCapacity, time.Duration(params.StayConnected)*time.Second, params.PaymentModule, params.SetCap)
if err != nil {
results.Err = err.Error() results.Err = err.Error()
}
res, _ = rlp.EncodeToBytes(&results) res, _ = rlp.EncodeToBytes(&results)
} }
} }

View file

@ -432,9 +432,11 @@ loop:
// Ingress packet handling. // Ingress packet handling.
case pkt := <-net.read: case pkt := <-net.read:
//fmt.Println("read", pkt.ev)
log.Trace("<-net.read") log.Trace("<-net.read")
n := net.internNode(&pkt) n := net.internNode(&pkt)
if pkt.ev == talkRequestPacket {
fmt.Println("read trp", n.state, pkt)
}
prestate := n.state prestate := n.state
status := "ok" status := "ok"
if err := net.handle(n, pkt.ev, &pkt); err != nil { if err := net.handle(n, pkt.ev, &pkt); err != nil {
@ -722,11 +724,17 @@ func (net *Network) refresh(done chan<- struct{}) {
func (net *Network) internNode(pkt *ingressPacket) *Node { func (net *Network) internNode(pkt *ingressPacket) *Node {
if n := net.nodes[pkt.remoteID]; n != nil { if n := net.nodes[pkt.remoteID]; n != nil {
if pkt.ev == talkRequestPacket {
fmt.Println("node exists")
}
n.IP = pkt.remoteAddr.IP n.IP = pkt.remoteAddr.IP
n.UDP = uint16(pkt.remoteAddr.Port) n.UDP = uint16(pkt.remoteAddr.Port)
n.TCP = uint16(pkt.remoteAddr.Port) n.TCP = uint16(pkt.remoteAddr.Port)
return n return n
} }
if pkt.ev == talkRequestPacket {
fmt.Println("node created")
}
n := NewNode(pkt.remoteID, pkt.remoteAddr.IP, uint16(pkt.remoteAddr.Port), uint16(pkt.remoteAddr.Port)) n := NewNode(pkt.remoteID, pkt.remoteAddr.IP, uint16(pkt.remoteAddr.Port), uint16(pkt.remoteAddr.Port))
n.state = unknown n.state = unknown
net.nodes[pkt.remoteID] = n net.nodes[pkt.remoteID] = n
@ -1061,7 +1069,7 @@ func (net *Network) handle(n *Node, ev nodeEvent, pkt *ingressPacket) error {
//fmt.Println("handle", n.addr().String(), n.state, ev) //fmt.Println("handle", n.addr().String(), n.state, ev)
if pkt != nil { if pkt != nil {
if err := net.checkPacket(n, ev, pkt); err != nil { if err := net.checkPacket(n, ev, pkt); err != nil {
//fmt.Println("check err:", err) //fmt.Println("check err:", err, pkt)
return err return err
} }
// Start the background expiration goroutine after the first // Start the background expiration goroutine after the first
@ -1076,6 +1084,7 @@ func (net *Network) handle(n *Node, ev nodeEvent, pkt *ingressPacket) error {
if n.state == nil { if n.state == nil {
n.state = unknown //??? n.state = unknown //???
} }
//fmt.Println("old state:", n.state)
next, err := n.state.handle(net, n, ev, pkt) next, err := n.state.handle(net, n, ev, pkt)
net.transition(n, next) net.transition(n, next)
//fmt.Println("new state:", n.state) //fmt.Println("new state:", n.state)
@ -1241,8 +1250,10 @@ func (net *Network) handleQueryEvent(n *Node, ev nodeEvent, pkt *ingressPacket)
net.talkRequestSubLock.RLock() net.talkRequestSubLock.RLock()
subFn := net.talkRequestSubs[string(p.TalkID)] subFn := net.talkRequestSubs[string(p.TalkID)]
net.talkRequestSubLock.RUnlock() net.talkRequestSubLock.RUnlock()
fmt.Println("trp", p)
if subFn != nil { if subFn != nil {
resp, ok := subFn(enode.ID(n.sha), n.addr(), p.Payload) resp, ok := subFn(enode.ID(n.sha), n.addr(), p.Payload)
fmt.Println("subFn", ok)
if ok { if ok {
net.conn.send(n, talkResponsePacket, talkResponse{ReplyTok: pkt.hash, Payload: resp}) net.conn.send(n, talkResponsePacket, talkResponse{ReplyTok: pkt.hash, Payload: resp})
} else { } else {
@ -1367,7 +1378,7 @@ func (q *talkQuery) start(net *Network) bool {
q.key = string(q.remote.sha[:]) + string(hash[:]) q.key = string(q.remote.sha[:]) + string(hash[:])
net.talkResponseSubs[q.key] = q.handler net.talkResponseSubs[q.key] = q.handler
net.talkResponseSubLock.Unlock() net.talkResponseSubLock.Unlock()
fmt.Println("sent") fmt.Println("sent", q.remote.state)
return true return true
} }
// If the node is not known yet, it won't accept queries. // If the node is not known yet, it won't accept queries.
@ -1397,6 +1408,9 @@ func (net *Network) SendTalkRequest(to *enode.Node, talkID string, payload inter
net.nodes[nodeID] = node net.nodes[nodeID] = node
} }
q := &talkQuery{remote: node, talkID: talkID, payload: payload, handler: handler} q := &talkQuery{remote: node, talkID: talkID, payload: payload, handler: handler}
if node.state == nil || !node.state.canQuery {
net.ping(node, node.addr())
}
select { select {
case net.queryReq <- q: case net.queryReq <- q:
case <-net.closed: case <-net.closed:

View file

@ -217,7 +217,7 @@ func (n ID) MarshalText() ([]byte, error) {
// UnmarshalText implements the encoding.TextUnmarshaler interface. // UnmarshalText implements the encoding.TextUnmarshaler interface.
func (n *ID) UnmarshalText(text []byte) error { func (n *ID) UnmarshalText(text []byte) error {
id, err := parseID(string(text)) id, err := ParseID(string(text))
if err != nil { if err != nil {
return err return err
} }
@ -229,14 +229,14 @@ func (n *ID) UnmarshalText(text []byte) error {
// The string may be prefixed with 0x. // The string may be prefixed with 0x.
// It panics if the string is not a valid ID. // It panics if the string is not a valid ID.
func HexID(in string) ID { func HexID(in string) ID {
id, err := parseID(in) id, err := ParseID(in)
if err != nil { if err != nil {
panic(err) panic(err)
} }
return id return id
} }
func parseID(in string) (ID, error) { func ParseID(in string) (ID, error) {
var id ID var id ID
b, err := hex.DecodeString(strings.TrimPrefix(in, "0x")) b, err := hex.DecodeString(strings.TrimPrefix(in, "0x"))
if err != nil { if err != nil {